diff --git a/.woodpecker/ui-build.yml b/.woodpecker/ui-build.yml deleted file mode 100644 index 224fc19ad14..00000000000 --- a/.woodpecker/ui-build.yml +++ /dev/null @@ -1,80 +0,0 @@ -variables: - - &sftp-settings - server: ${CACHE_SERVER} - username: user - password: pass - ignore_branch: true - port: 2222 - path: /cache - mount: - - cache - - - &rsync-settings - user: fenecon-docs - hosts: - - ${ARTIFACT_SERVER} - port: 22 - key: - from_secret: ssh_key_intranet - args: '-v' - - - &main-build - - branch: [main, develop] - - evaluate: 'CI_COMMIT_MESSAGE contains "[APP]"' - - path: - include: ['.woodpecker/ui-build.yml'] - on_empty: false - -when: - event: - - push - -matrix: - THEME: - - fenecon - - heckert - -clone: - git: - when: *main-build - image: woodpeckerci/plugin-git - -steps: - restore-cache: - when: *main-build - image: appleboy/drone-sftp-cache - settings: - restore: true - <<: *sftp-settings - - prepare-environment: - when: *main-build - image: openems-bash - commands: - - export CACHE=$CI_WORKSPACE/cache - - mkdir -p $CI_WORKSPACE/cache build/target - - source tools/common.sh - - common_initialize_environment - - common_build_snapshot_version - - common_save_environment $CI_WORKSPACE/.openems-env - depends_on: [restore-cache] - - build-android-app: - when: *main-build - image: openems-android:20.32 - environment: - - THEME=${THEME} - commands: - - source $CI_WORKSPACE/.openems-env - - source tools/common.sh - - common_build_android_app - depends_on: [prepare-environment] - - refresh-dev-android: - when: *main-build - image: woodpeckerci/rsync:latest - settings: - <<: *rsync-settings - source: $CI_WORKSPACE/ui/android/target/ - target: /var/opt/develop/fems-artifacts/html/${CI_COMMIT_BRANCH} - depends_on: [build-android-app] diff --git a/README.md b/README.md index 519047007e3..b1ad40deb8a 100644 --- a/README.md +++ b/README.md @@ -80,14 +80,14 @@ If you use OpenEMS in your scientific research, please use our Zenodo Digital Ob * OpenEMS Edge * OpenEMS Backend -Copyright (C) 2016-2022 OpenEMS Association e.V. +Copyright (C) 2016-2025 OpenEMS Association e.V. This product includes software developed at FENECON GmbH: you can redistribute it and/or modify it under the terms of the [Eclipse Public License version 2.0](LICENSE-EPL-2.0). * OpenEMS UI -Copyright (C) 2016-2022 OpenEMS Association e.V. +Copyright (C) 2016-2025 OpenEMS Association e.V. This product includes software developed at FENECON GmbH: you can redistribute it and/or modify it under the terms of the [GNU Affero General Public License version 3](LICENSE-AGPL-3.0). diff --git a/cnf/pom.xml b/cnf/pom.xml index 191ff3f5c56..7c28736d105 100644 --- a/cnf/pom.xml +++ b/cnf/pom.xml @@ -61,7 +61,7 @@ com.squareup.okio okio-jvm - 3.9.1 + 3.10.2 @@ -231,7 +231,7 @@ org.apache.felix org.apache.felix.http.jetty - 5.1.26 + 5.1.28 @@ -284,14 +284,14 @@ org.bouncycastle bcpkix-jdk18on - 1.79 + 1.80 org.bouncycastle bcprov-jdk18on - 1.79 + 1.80 org.dhatim @@ -337,7 +337,7 @@ org.jetbrains.kotlin kotlin-osgi-bundle - 2.1.0 + 2.1.10 org.jetbrains.kotlinx @@ -403,12 +403,12 @@ org.ops4j.pax.logging pax-logging-api - 2.2.7 + 2.2.8 org.ops4j.pax.logging pax-logging-log4j2 - 2.2.7 + 2.2.8 org.osgi @@ -435,7 +435,7 @@ org.postgresql postgresql - 42.7.4 + 42.7.5 diff --git a/io.openems.backend.alerting/src/io/openems/backend/alerting/scheduler/TimedExecutor.java b/io.openems.backend.alerting/src/io/openems/backend/alerting/scheduler/TimedExecutor.java index debb78c6cbf..ba255e80876 100644 --- a/io.openems.backend.alerting/src/io/openems/backend/alerting/scheduler/TimedExecutor.java +++ b/io.openems.backend.alerting/src/io/openems/backend/alerting/scheduler/TimedExecutor.java @@ -16,7 +16,7 @@ public TimedTask(ZonedDateTime executeAt, Consumer task) { @Override public int compareTo(TimedTask other) { - if (other == null || other.executeAt == null) { + if (other == null || other.executeAt == null) { return 1; } return this.executeAt.compareTo(other.executeAt); diff --git a/io.openems.backend.alerting/test/io/openems/backend/alerting/MessageTest.java b/io.openems.backend.alerting/test/io/openems/backend/alerting/MessageTest.java index d1e2296f3c2..132858e15ab 100644 --- a/io.openems.backend.alerting/test/io/openems/backend/alerting/MessageTest.java +++ b/io.openems.backend.alerting/test/io/openems/backend/alerting/MessageTest.java @@ -35,7 +35,7 @@ public void testMessage() { assertTrue("msg10 should be greater than msg11", msg10.compareTo(msg11) > 0); assertTrue("msg10 should be lower than msg20", msg10.compareTo(msg20) < 0); - + assertTrue("msg10 should be greater than null", msg10.compareTo(null) > 0); } diff --git a/io.openems.backend.application/BackendApp.bndrun b/io.openems.backend.application/BackendApp.bndrun index 2f9caaea57f..fe45707e12c 100644 --- a/io.openems.backend.application/BackendApp.bndrun +++ b/io.openems.backend.application/BackendApp.bndrun @@ -65,7 +65,7 @@ com.google.gson;version='[2.11.0,2.11.1)',\ com.google.guava;version='[33.4.0,33.4.1)',\ com.google.guava.failureaccess;version='[1.0.2,1.0.3)',\ - com.squareup.okio;version='[3.9.1,3.9.2)',\ + com.squareup.okio;version='[3.10.2,3.10.3)',\ com.zaxxer.HikariCP;version='[6.2.1,6.2.2)',\ io.openems.backend.alerting;version=snapshot,\ io.openems.backend.application;version=snapshot,\ @@ -109,22 +109,22 @@ 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.7.4,3.7.5)',\ - org.apache.felix.http.jetty;version='[5.1.26,5.1.27)',\ + org.apache.felix.http.jetty;version='[5.1.28,5.1.29)',\ org.apache.felix.http.servlet-api;version='[3.0.0,3.0.1)',\ org.apache.felix.inventory;version='[2.0.0,2.0.1)',\ org.apache.felix.metatype;version='[1.2.4,1.2.5)',\ org.apache.felix.scr;version='[2.2.12,2.2.13)',\ org.apache.felix.webconsole;version='[5.0.8,5.0.9)',\ org.apache.felix.webconsole.plugins.ds;version='[2.3.0,2.3.1)',\ - org.jetbrains.kotlin.osgi-bundle;version='[2.1.0,2.1.1)',\ + org.jetbrains.kotlin.osgi-bundle;version='[2.1.10,2.1.11)',\ org.jsr-305;version='[3.0.2,3.0.3)',\ - org.ops4j.pax.logging.pax-logging-api;version='[2.2.7,2.2.8)',\ - org.ops4j.pax.logging.pax-logging-log4j2;version='[2.2.7,2.2.8)',\ + org.ops4j.pax.logging.pax-logging-api;version='[2.2.8,2.2.9)',\ + org.ops4j.pax.logging.pax-logging-log4j2;version='[2.2.8,2.2.9)',\ org.osgi.service.component;version='[1.5.1,1.5.2)',\ 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.owasp.encoder;version='[1.3.1,1.3.2)',\ - org.postgresql.jdbc;version='[42.7.4,42.7.5)',\ + org.postgresql.jdbc;version='[42.7.5,42.7.6)',\ reactive-streams;version='[1.0.4,1.0.5)',\ stax2-api;version='[4.2.2,4.2.3)' \ No newline at end of file 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 337da975af9..f5ee2505ae6 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 @@ -197,11 +197,9 @@ private void handleJsonRpc(User user, Request baseRequest, HttpServletRequest ht } // parse JSON-RPC Request var message = JsonrpcMessage.from(json); - if (!(message instanceof JsonrpcRequest)) { + if (!(message instanceof JsonrpcRequest request)) { throw new OpenemsException("Only JSON-RPC Request is supported here."); } - var request = (JsonrpcRequest) message; - // handle the request CompletableFuture responseFuture = this.parent.jsonRpcRequestHandler .handleRequest(this.parent.getName(), user, request); 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 79696ccbde7..eeee757a2de 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 @@ -194,8 +194,8 @@ public static String activeStateChannelsToString( var states = new HashMap>(); for (Entry entry : activeStateChannels.entrySet()) { var detail = entry.getValue().getDetail(); - if (detail instanceof ChannelDetailState) { - var level = ((ChannelDetailState) detail).getLevel(); + if (detail instanceof ChannelDetailState cds) { + var level = cds.getLevel(); var channelsByComponent = states.get(level); if (channelsByComponent == null) { channelsByComponent = HashMultimap.create(); diff --git a/io.openems.backend.core/src/io/openems/backend/core/jsonrpcrequesthandler/CoreJsonRpcRequestHandlerImpl.java b/io.openems.backend.core/src/io/openems/backend/core/jsonrpcrequesthandler/CoreJsonRpcRequestHandlerImpl.java index 275e0af47c8..30e5b4ddeb9 100644 --- a/io.openems.backend.core/src/io/openems/backend/core/jsonrpcrequesthandler/CoreJsonRpcRequestHandlerImpl.java +++ b/io.openems.backend.core/src/io/openems/backend/core/jsonrpcrequesthandler/CoreJsonRpcRequestHandlerImpl.java @@ -98,26 +98,21 @@ private void updateConfig(Config config) { @Override public CompletableFuture handleRequest(String context, User user, JsonrpcRequest request) throws OpenemsNamedException { - switch (request.getMethod()) { - - case EdgeRpcRequest.METHOD: - return this.edgeRpcRequestHandler.handleRequest(user, request.getId(), EdgeRpcRequest.from(request)); - - case GetEdgesStatusRequest.METHOD: - return this.handleGetEdgesStatusRequest(user, request.getId(), GetEdgesStatusRequest.from(request)); - - case GetEdgesChannelsValuesRequest.METHOD: - return this.handleGetEdgesChannelsValuesRequest(user, request.getId(), + return switch (request.getMethod()) { + case EdgeRpcRequest.METHOD // + -> this.edgeRpcRequestHandler.handleRequest(user, request.getId(), EdgeRpcRequest.from(request)); + case GetEdgesStatusRequest.METHOD // + -> this.handleGetEdgesStatusRequest(user, request.getId(), GetEdgesStatusRequest.from(request)); + case GetEdgesChannelsValuesRequest.METHOD // + -> this.handleGetEdgesChannelsValuesRequest(user, request.getId(), GetEdgesChannelsValuesRequest.from(request)); - - case SetGridConnScheduleRequest.METHOD: - return this.handleSetGridConnScheduleRequest(user, request.getId(), - SetGridConnScheduleRequest.from(request)); - - default: + case SetGridConnScheduleRequest.METHOD // + -> this.handleSetGridConnScheduleRequest(user, request.getId(), SetGridConnScheduleRequest.from(request)); + default -> { this.logWarn(context, "Unhandled Request: " + request); throw OpenemsError.JSONRPC_UNHANDLED_METHOD.exception(request.getMethod()); } + }; } /** diff --git a/io.openems.backend.edgewebsocket/src/io/openems/backend/edgewebsocket/OnNotification.java b/io.openems.backend.edgewebsocket/src/io/openems/backend/edgewebsocket/OnNotification.java index 2ccb8cc68a9..d4250287c9e 100644 --- a/io.openems.backend.edgewebsocket/src/io/openems/backend/edgewebsocket/OnNotification.java +++ b/io.openems.backend.edgewebsocket/src/io/openems/backend/edgewebsocket/OnNotification.java @@ -1,5 +1,7 @@ package io.openems.backend.edgewebsocket; +import static io.openems.common.utils.FunctionUtils.doNothing; + import java.util.Map.Entry; import java.util.concurrent.TimeUnit; @@ -118,14 +120,17 @@ private void handleDataNotification(AbstractDataNotification message, WsData wsD var edgeId = wsData.assertEdgeId(message); try { - // TODO java 21 switch case with type - if (message instanceof TimestampedDataNotification timestampNotification) { + switch (message) { + case TimestampedDataNotification timestampNotification -> { wsData.edgeCache.updateCurrentData(timestampNotification); this.parent.timedataManager.write(edgeId, timestampNotification); - } else if (message instanceof AggregatedDataNotification aggregatedNotification) { + } + case AggregatedDataNotification aggregatedNotification -> { wsData.edgeCache.updateAggregatedData(aggregatedNotification); this.parent.timedataManager.write(edgeId, aggregatedNotification); } + case ResendDataNotification resendNotification -> doNothing(); // handled in handleResendDataNotification() + } } catch (IllegalArgumentException e) { e.printStackTrace(); } diff --git a/io.openems.backend.metadata.odoo/src/io/openems/backend/metadata/odoo/Config.java b/io.openems.backend.metadata.odoo/src/io/openems/backend/metadata/odoo/Config.java index 8512870c35e..22712118e26 100644 --- a/io.openems.backend.metadata.odoo/src/io/openems/backend/metadata/odoo/Config.java +++ b/io.openems.backend.metadata.odoo/src/io/openems/backend/metadata/odoo/Config.java @@ -4,6 +4,7 @@ import org.osgi.service.metatype.annotations.ObjectClassDefinition; import io.openems.backend.metadata.odoo.odoo.Protocol; +import io.openems.common.types.DebugMode; @ObjectClassDefinition(// name = "Metadata.Odoo", // diff --git a/io.openems.backend.metadata.odoo/src/io/openems/backend/metadata/odoo/MetadataOdoo.java b/io.openems.backend.metadata.odoo/src/io/openems/backend/metadata/odoo/MetadataOdoo.java index 9f28bc32346..6c16b5f2315 100644 --- a/io.openems.backend.metadata.odoo/src/io/openems/backend/metadata/odoo/MetadataOdoo.java +++ b/io.openems.backend.metadata.odoo/src/io/openems/backend/metadata/odoo/MetadataOdoo.java @@ -71,6 +71,7 @@ import io.openems.common.oem.OpenemsBackendOem; import io.openems.common.session.Language; import io.openems.common.session.Role; +import io.openems.common.types.DebugMode; import io.openems.common.types.EdgeConfig; import io.openems.common.types.EdgeConfigDiff; import io.openems.common.types.SemanticVersion; @@ -319,40 +320,36 @@ public void handleEvent(Event event) { var reader = new EventReader(event); switch (event.getTopic()) { - case Edge.Events.ON_SET_ONLINE: { + case Edge.Events.ON_SET_ONLINE -> { var edgeId = reader.getString(Edge.Events.OnSetOnline.EDGE_ID); var isOnline = reader.getBoolean(Edge.Events.OnSetOnline.IS_ONLINE); this.getEdge(edgeId).ifPresent(edge -> { - if (edge instanceof MyEdge) { + if (edge instanceof MyEdge myEdge) { // Set OpenEMS Is Connected in Odoo/Postgres - this.postgresHandler.getPeriodicWriteWorker().onSetOnline((MyEdge) edge, isOnline); + this.postgresHandler.getPeriodicWriteWorker().onSetOnline(myEdge, isOnline); } }); } - break; - case Edge.Events.ON_SET_CONFIG: - this.onSetConfigEvent(reader); - break; + case Edge.Events.ON_SET_CONFIG // + -> this.onSetConfigEvent(reader); - case Edge.Events.ON_SET_VERSION: { + case Edge.Events.ON_SET_VERSION -> { var edge = (MyEdge) reader.getProperty(Edge.Events.OnSetVersion.EDGE); var version = (SemanticVersion) reader.getProperty(Edge.Events.OnSetVersion.VERSION); // Set Version in Odoo this.odooHandler.writeEdge(edge, new FieldValue<>(Field.EdgeDevice.OPENEMS_VERSION, version.toString())); } - break; - case Edge.Events.ON_SET_LASTMESSAGE: { + case Edge.Events.ON_SET_LASTMESSAGE -> { var edge = (MyEdge) reader.getProperty(Edge.Events.OnSetLastmessage.EDGE); // Set LastMessage timestamp in Odoo/Postgres this.postgresHandler.getPeriodicWriteWorker().onLastMessage(edge); } - break; - case Edge.Events.ON_SET_SUM_STATE: { + case Edge.Events.ON_SET_SUM_STATE -> { var edgeId = reader.getString(Edge.Events.OnSetSumState.EDGE_ID); var sumState = (Level) reader.getProperty(Edge.Events.OnSetSumState.SUM_STATE); @@ -360,9 +357,8 @@ public void handleEvent(Event event) { // Set Sum-State in Odoo/Postgres this.postgresHandler.getPeriodicWriteWorker().onSetSumState(edge, sumState); } - break; - case Edge.Events.ON_SET_PRODUCTTYPE: { + case Edge.Events.ON_SET_PRODUCTTYPE -> { var edge = (MyEdge) reader.getProperty(Edge.Events.OnSetProducttype.EDGE); var producttype = reader.getString(Edge.Events.OnSetProducttype.PRODUCTTYPE); // Set Producttype in Odoo/Postgres @@ -375,8 +371,6 @@ public void handleEvent(Event event) { } }); } - break; - } } @@ -567,10 +561,11 @@ public List getSumStateAlertingSettings(String edgeId) @Override public void setUserAlertingSettings(User user, String edgeId, List settings) throws OpenemsException { - if (user instanceof MyUser odooUser) { - this.odooHandler.setUserAlertingSettings(odooUser, edgeId, settings); - } else { - throw new OpenemsException("User information is from foreign source!!"); + switch (user) { + case MyUser odooUser // + -> this.odooHandler.setUserAlertingSettings(odooUser, edgeId, settings); + default // + -> throw new OpenemsException("User information is from foreign source!!"); } } diff --git a/io.openems.backend.metadata.odoo/src/io/openems/backend/metadata/odoo/odoo/FieldValue.java b/io.openems.backend.metadata.odoo/src/io/openems/backend/metadata/odoo/odoo/FieldValue.java index 3a6b88d5a41..00011462ead 100644 --- a/io.openems.backend.metadata.odoo/src/io/openems/backend/metadata/odoo/odoo/FieldValue.java +++ b/io.openems.backend.metadata.odoo/src/io/openems/backend/metadata/odoo/odoo/FieldValue.java @@ -1,9 +1,10 @@ package io.openems.backend.metadata.odoo.odoo; +import static io.openems.common.utils.StringUtils.toShortString; + import com.google.gson.JsonElement; import io.openems.backend.metadata.odoo.Field; -import io.openems.common.utils.StringUtils; public class FieldValue { private final Field field; @@ -24,14 +25,14 @@ public T getValue() { @Override public String toString() { - String string; - if (this.value instanceof JsonElement) { - string = StringUtils.toShortString((JsonElement) this.value, 100); - } else if (this.value instanceof String) { - string = StringUtils.toShortString((String) this.value, 100); - } else { - string = this.value.toString(); - } + var string = switch (this.value) { + case JsonElement je // + -> toShortString(je, 100); + case String s // + -> toShortString(s, 100); + default // + -> this.value.toString(); + }; string = string.replace("\n", ""); return this.field.id() + ":" + string; } 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 b79cab0cace..1e5e1476595 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 @@ -925,8 +925,8 @@ public Optional getSerialNumberForEdge(Edge edge) { Field.EdgeDevice.STOCK_PRODUCTION_LOT_ID); var serialNumber = serialNumberField.get(Field.EdgeDevice.STOCK_PRODUCTION_LOT_ID.id()); - if (serialNumber instanceof Object[] && ((Object[]) serialNumber).length > 1) { - return getAsOptional(((Object[]) serialNumber)[1], String.class); + if (serialNumber instanceof Object[] sns && sns.length > 1) { + return getAsOptional(sns[1], String.class); } return Optional.empty(); } catch (OpenemsException ex) { diff --git a/io.openems.backend.metadata.odoo/src/io/openems/backend/metadata/odoo/odoo/OdooUtils.java b/io.openems.backend.metadata.odoo/src/io/openems/backend/metadata/odoo/odoo/OdooUtils.java index fd92b4cb783..844be68bfe1 100644 --- a/io.openems.backend.metadata.odoo/src/io/openems/backend/metadata/odoo/odoo/OdooUtils.java +++ b/io.openems.backend.metadata.odoo/src/io/openems/backend/metadata/odoo/odoo/OdooUtils.java @@ -536,10 +536,10 @@ protected static Optional getAsOptional(Object object, Cla * @return the odoo reference id or empty {@link Optional} */ protected static Optional getOdooReferenceId(Object object) { - if (object instanceof Object[] odooReference) { - if (odooReference.length > 0 && odooReference[0] instanceof Integer) { - return Optional.of((Integer) odooReference[0]); - } + if (object instanceof Object[] odooReference // + && odooReference.length > 0 // + && odooReference[0] instanceof Integer i) { + return Optional.of(i); } return Optional.empty(); diff --git a/io.openems.common/src/io/openems/common/OpenemsConstants.java b/io.openems.common/src/io/openems/common/OpenemsConstants.java index 9e7cf71367f..4c13f7bf642 100644 --- a/io.openems.common/src/io/openems/common/OpenemsConstants.java +++ b/io.openems.common/src/io/openems/common/OpenemsConstants.java @@ -22,7 +22,7 @@ public class OpenemsConstants { *

* This is the month of the release. */ - public static final short VERSION_MINOR = 1; + public static final short VERSION_MINOR = 2; /** * The patch version of OpenEMS. diff --git a/io.openems.edge.controller.evcs/src/io/openems/edge/controller/evcs/JSCalendar.java b/io.openems.common/src/io/openems/common/jscalendar/JSCalendar.java similarity index 61% rename from io.openems.edge.controller.evcs/src/io/openems/edge/controller/evcs/JSCalendar.java rename to io.openems.common/src/io/openems/common/jscalendar/JSCalendar.java index ab9fcbf39b9..d96cb19793c 100644 --- a/io.openems.edge.controller.evcs/src/io/openems/edge/controller/evcs/JSCalendar.java +++ b/io.openems.common/src/io/openems/common/jscalendar/JSCalendar.java @@ -1,17 +1,18 @@ -package io.openems.edge.controller.evcs; +package io.openems.common.jscalendar; import static com.google.common.collect.ImmutableList.toImmutableList; import static com.google.common.collect.ImmutableSortedSet.toImmutableSortedSet; import static io.openems.common.utils.JsonUtils.getAsEnum; -import static io.openems.common.utils.JsonUtils.getAsJsonArray; import static io.openems.common.utils.JsonUtils.getAsJsonObject; -import static io.openems.common.utils.JsonUtils.getAsLocalDateTime; +import static io.openems.common.utils.JsonUtils.getAsOptionalJsonArray; +import static io.openems.common.utils.JsonUtils.getAsOptionalJsonObject; +import static io.openems.common.utils.JsonUtils.getAsOptionalString; +import static io.openems.common.utils.JsonUtils.getAsOptionalUUID; +import static io.openems.common.utils.JsonUtils.getAsOptionalZonedDateTime; import static io.openems.common.utils.JsonUtils.getAsString; -import static io.openems.common.utils.JsonUtils.getAsUUID; -import static io.openems.common.utils.JsonUtils.getAsZonedDateTime; +import static io.openems.common.utils.JsonUtils.parseToJsonArray; import static io.openems.common.utils.JsonUtils.stream; import static io.openems.common.utils.JsonUtils.toJsonArray; -import static io.openems.edge.controller.evcs.JSCalendar.RecurrenceFrequency.WEEKLY; import static java.time.DayOfWeek.FRIDAY; import static java.time.DayOfWeek.MONDAY; import static java.time.DayOfWeek.SATURDAY; @@ -19,16 +20,22 @@ import static java.time.DayOfWeek.THURSDAY; import static java.time.DayOfWeek.TUESDAY; import static java.time.DayOfWeek.WEDNESDAY; +import static java.time.LocalDate.EPOCH; import static java.time.format.DateTimeFormatter.ISO_INSTANT; import static java.time.format.DateTimeFormatter.ISO_LOCAL_DATE_TIME; import static java.time.temporal.ChronoField.NANO_OF_DAY; import static java.time.temporal.TemporalAdjusters.nextOrSame; import static java.util.Arrays.stream; -import static java.util.UUID.randomUUID; import java.time.DayOfWeek; +import java.time.Duration; +import java.time.LocalDate; import java.time.LocalDateTime; +import java.time.LocalTime; import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeParseException; +import java.time.temporal.ChronoUnit; import java.util.NoSuchElementException; import java.util.UUID; import java.util.function.Consumer; @@ -47,21 +54,44 @@ import io.openems.common.utils.JsonUtils; /** - * This implementation is based on RFC 8984 "JSCalendar: A JSON Representation - * of Calendar Data". + * Implementation of RFC 8984 "JSCalendar: A JSON Representation of Calendar + * Data". * *

- * - * @link https://www.rfc-editor.org/rfc/rfc8984.html + * See https://www.rfc-editor.org/rfc/rfc8984.html */ // CHECKSTYLE:OFF public class JSCalendar { // CHECKSTYLE:ON - public static record Task(UUID uid, ZonedDateTime updated, LocalDateTime start, + private static final String PROPERTY_PAYLOAD = "openems.io:payload"; + + public static record Task(UUID uid, ZonedDateTime updated, LocalDateTime start, Duration duration, ImmutableList recurrenceRules, PAYLOAD payload) { + /** + * Parse a List of {@link Task}s from a String representing a {@link JsonArray} + * - includes checks for null and empty. + * + * @param the type of the Payload + * @param string the {@link JsonArray} string + * @param payloadParser a parser for a Payload + * @return the List of {@link Task}s + */ + public static ImmutableList> fromStringOrEmpty(String string, + ThrowingFunction payloadParser) { + if (string == null || string.isBlank()) { + return ImmutableList.of(); + } + try { + return fromJson(parseToJsonArray(string), payloadParser); + } catch (OpenemsNamedException e) { + e.printStackTrace(); + return ImmutableList.of(); + } + } + /** * Parse a List of {@link Task}s from a {@link JsonArray}. * @@ -77,7 +107,7 @@ public static ImmutableList> fromJson(JsonArray json, return stream(json) // .map(j -> { try { - return fromJson(JsonUtils.getAsJsonObject(j), payloadParser); + return fromJson(getAsJsonObject(j), payloadParser); } catch (OpenemsNamedException e) { e.printStackTrace(); throw new NoSuchElementException(e.getMessage()); @@ -122,43 +152,40 @@ public static Task fromJson(JsonObject json, if (!type.equalsIgnoreCase("Task")) { throw new OpenemsException("This is not a 'Task': " + type); } - try { - var uid = getAsUUID(json, "uid"); - var updated = getAsZonedDateTime(json, "updated"); - var start = getAsLocalDateTime(json, "start"); - var recurrenceRules = stream(getAsJsonArray(json, "recurrenceRules")) // - .map(r -> { - try { - return RecurrenceRule.fromJson(r); - } catch (OpenemsNamedException e) { - e.printStackTrace(); - throw new NoSuchElementException(e.getMessage()); - } - }) // - .collect(toImmutableList()); - var payload = payloadParser.apply(getAsJsonObject(json, "payload")); - return new Task(uid, updated, start, recurrenceRules, payload); - - } catch (NoSuchElementException e) { - throw new OpenemsException("NoSuchElementException: " + e.getMessage()); - } + var b = Task.create() // + .setUid(getAsOptionalUUID(json, "uid").orElse(null)) // + .setUpdated(getAsOptionalZonedDateTime(json, "updated").orElse(null)) // + .setStart(getAsString(json, "start")) // + .setDuration(getAsOptionalString(json, "duration").orElse(null)); // + getAsOptionalJsonArray(json, "recurrenceRules") // + .ifPresent(j -> stream(j) // + .forEach(r -> b.addRecurrenceRule(r))); + var rawPayload = getAsOptionalJsonObject(json, PROPERTY_PAYLOAD); + b.setPayload(rawPayload.isPresent() // + ? payloadParser.apply(rawPayload.get()) // + : null); + return b.build(); } public static class Builder { - private final UUID uid; - private final ZonedDateTime updated; - + private UUID uid = null; + private ZonedDateTime updated = null; private LocalDateTime start = null; + private Duration duration = null; private ImmutableList.Builder recurrenceRules = ImmutableList.builder(); private PAYLOAD payload = null; protected Builder() { - this(randomUUID(), ZonedDateTime.now()); } - protected Builder(UUID uid, ZonedDateTime updated) { + public Builder setUid(UUID uid) { this.uid = uid; + return this; + } + + public Builder setUpdated(ZonedDateTime updated) { this.updated = updated; + return this; } public Builder setStart(LocalDateTime start) { @@ -166,11 +193,27 @@ public Builder setStart(LocalDateTime start) { return this; } - protected Builder setStart(String start) { - this.setStart(LocalDateTime.parse(start)); + public Builder setStart(LocalTime start) { + return this.setStart(LocalDateTime.of(EPOCH, start)); + } + + protected Builder setStart(String start) throws DateTimeParseException { + try { + return this.setStart(LocalDateTime.parse(start)); + } catch (DateTimeParseException e) { + return this.setStart(LocalTime.parse(start)); + } + } + + public Builder setDuration(Duration duration) { + this.duration = duration; return this; } + protected Builder setDuration(String duration) { + return this.setDuration(duration == null ? null : Duration.parse(duration)); + } + /** * Adds a {@link RecurrenceRule}. * @@ -182,6 +225,21 @@ public Builder addRecurrenceRule(RecurrenceRule recurrenceRule) { return this; } + /** + * Adds a {@link RecurrenceRule}. + * + * @param json the {@link RecurrenceRule} as {@link JsonObject} + * @return myself + */ + public Builder addRecurrenceRule(JsonElement json) throws NoSuchElementException { + try { + return this.addRecurrenceRule(RecurrenceRule.fromJson(json)); + } catch (OpenemsNamedException e) { + e.printStackTrace(); + throw new NoSuchElementException(e.getMessage()); + } + } + /** * Adds a {@link RecurrenceRule}. * @@ -201,8 +259,8 @@ public Builder setPayload(PAYLOAD payload) { } public Task build() { - return new Task(this.uid, this.updated, this.start, this.recurrenceRules.build(), - this.payload); + return new Task(this.uid, this.updated, this.start, this.duration, + this.recurrenceRules.build(), this.payload); } } @@ -224,11 +282,22 @@ public static Builder create() { */ public JsonObject toJson(Function payloadConverter) { var j = JsonUtils.buildJsonObject() // - .addProperty("@type", "Task") // - .addProperty("uid", this.uid.toString()) // - .addProperty("updated", this.updated.format(ISO_INSTANT)); + .addProperty("@type", "Task"); + if (this.uid != null) { + j.addProperty("uid", this.uid.toString()); + } + if (this.updated != null) { + j.addProperty("updated", this.updated.format(ISO_INSTANT)); + } if (this.start != null) { - j.addProperty("start", this.start.format(ISO_LOCAL_DATE_TIME)); + if (LocalDate.from(this.start).equals(EPOCH)) { + j.addProperty("start", this.start.format(DateTimeFormatter.ISO_LOCAL_TIME)); + } else { + j.addProperty("start", this.start.format(ISO_LOCAL_DATE_TIME)); + } + } + if (this.duration != null) { + j.addProperty("duration", this.duration.toString()); } if (!this.recurrenceRules.isEmpty()) { j.add("recurrenceRules", this.recurrenceRules.stream() // @@ -236,21 +305,25 @@ public JsonObject toJson(Function payloadConverter) { .collect(toJsonArray())); } if (this.payload != null) { - j.add("payload", payloadConverter.apply(this.payload)); + j.add(PROPERTY_PAYLOAD, payloadConverter.apply(this.payload)); } return j.build(); } /** - * Gets the next occurence of the {@link Task} at or after a date. + * Gets the next occurence of the {@link Task} (including duration) at or after + * a date. * * @param from the from timestamp * @return a {@link ZonedDateTime} */ public ZonedDateTime getNextOccurence(ZonedDateTime from) { + var f = this.duration == null // + ? from // + : from.minus(this.duration); // query active tasks var start = this.start.atZone(from.getZone()); return this.recurrenceRules.stream() // - .map(rr -> rr.getNextOccurence(from.isBefore(start) ? start : from, start)) // + .map(rr -> rr.getNextOccurence(f.isBefore(start) ? start : f, start)) // .min((o1, o2) -> o1.toInstant().compareTo(o2.toInstant())) // .orElse(null); } @@ -283,18 +356,20 @@ public record RecurrenceRule(RecurrenceFrequency frequency, ImmutableSortedSet switch (JsonUtils.getAsOptionalString(j).orElseThrow()) { - case "mo" -> MONDAY; - case "tu" -> TUESDAY; - case "we" -> WEDNESDAY; - case "th" -> THURSDAY; - case "fr" -> FRIDAY; - case "sa" -> SATURDAY; - case "su" -> SUNDAY; - default -> throw new NoSuchElementException(""); - }) // - .collect(toImmutableSortedSet(Ordering.natural())); + var byDay = getAsOptionalJsonArray(json, "byDay") // + .map(arr -> stream(arr) // + .map(j -> switch (getAsOptionalString(j).orElseThrow()) { + case "mo" -> MONDAY; + case "tu" -> TUESDAY; + case "we" -> WEDNESDAY; + case "th" -> THURSDAY; + case "fr" -> FRIDAY; + case "sa" -> SATURDAY; + case "su" -> SUNDAY; + default -> throw new NoSuchElementException(""); + }) // + .collect(toImmutableSortedSet(Ordering.natural()))) // + .orElse(ImmutableSortedSet.of()); return new RecurrenceRule(frequency, byDay); } @@ -343,21 +418,36 @@ public static Builder create() { * @return a {@link ZonedDateTime} */ public ZonedDateTime getNextOccurence(ZonedDateTime from, ZonedDateTime start) { - if (this.frequency == WEEKLY) { + final var startTime = start.toLocalTime(); + + return switch (this.frequency) { + case DAILY -> { + var resultDay = from.truncatedTo(ChronoUnit.DAYS); + if (from.toLocalTime().isAfter(startTime)) { + resultDay = from.plusDays(1); + } + yield resultDay.with(NANO_OF_DAY, startTime.toNanoOfDay()); + } + case WEEKLY -> { if (!this.byDay.isEmpty()) { - var startTime = start.toLocalTime(); var nextByDay = this.byDay.ceiling(from.toLocalTime().isAfter(startTime) // ? from.getDayOfWeek().plus(1) // next day : from.getDayOfWeek()); // same day if (nextByDay == null) { nextByDay = this.byDay.first(); } - return from // + yield from // .with(nextOrSame(nextByDay)) // .with(NANO_OF_DAY, startTime.toNanoOfDay()); } + // TODO: If frequency is weekly and there is no byDay property, add a byDay + // property with the sole value being the day of the week of the initial + // date-time. + yield null; // not implemented } - return null; + case MONTHLY -> null; // not implemented + case YEARLY -> null; // not implemented + }; } /** diff --git a/io.openems.common/src/io/openems/common/jscalendar/package-info.java b/io.openems.common/src/io/openems/common/jscalendar/package-info.java new file mode 100644 index 00000000000..0d681ebdb59 --- /dev/null +++ b/io.openems.common/src/io/openems/common/jscalendar/package-info.java @@ -0,0 +1,11 @@ +/** + * Implementation of RFC 8984 "JSCalendar: A JSON Representation of Calendar + * Data". + * + *

+ * See https://www.rfc-editor.org/rfc/rfc8984.html + */ +@org.osgi.annotation.versioning.Version("1.0.0") +@org.osgi.annotation.bundle.Export +package io.openems.common.jscalendar; diff --git a/io.openems.common/src/io/openems/common/jsonrpc/base/AbstractJsonrpcRequest.java b/io.openems.common/src/io/openems/common/jsonrpc/base/AbstractJsonrpcRequest.java index 1a7e81baa04..6a1975fd9e4 100644 --- a/io.openems.common/src/io/openems/common/jsonrpc/base/AbstractJsonrpcRequest.java +++ b/io.openems.common/src/io/openems/common/jsonrpc/base/AbstractJsonrpcRequest.java @@ -11,7 +11,7 @@ * @see JSON-RPC * specification */ -public abstract class AbstractJsonrpcRequest extends JsonrpcMessage { +public abstract sealed class AbstractJsonrpcRequest extends JsonrpcMessage permits JsonrpcRequest, JsonrpcNotification { private final String method; diff --git a/io.openems.common/src/io/openems/common/jsonrpc/base/JsonrpcMessage.java b/io.openems.common/src/io/openems/common/jsonrpc/base/JsonrpcMessage.java index 2b4ad440394..2267ec1ccc1 100644 --- a/io.openems.common/src/io/openems/common/jsonrpc/base/JsonrpcMessage.java +++ b/io.openems.common/src/io/openems/common/jsonrpc/base/JsonrpcMessage.java @@ -20,7 +20,7 @@ * @see JSON-RPC * specification */ -public abstract class JsonrpcMessage { +public abstract sealed class JsonrpcMessage permits AbstractJsonrpcRequest, JsonrpcResponse { public static final String JSONRPC_VERSION = "2.0"; diff --git a/io.openems.common/src/io/openems/common/jsonrpc/base/JsonrpcNotification.java b/io.openems.common/src/io/openems/common/jsonrpc/base/JsonrpcNotification.java index 85256cbaf39..5600650a8f4 100644 --- a/io.openems.common/src/io/openems/common/jsonrpc/base/JsonrpcNotification.java +++ b/io.openems.common/src/io/openems/common/jsonrpc/base/JsonrpcNotification.java @@ -14,7 +14,7 @@ * @see JSON-RPC * specification */ -public abstract class JsonrpcNotification extends AbstractJsonrpcRequest { +public abstract non-sealed class JsonrpcNotification extends AbstractJsonrpcRequest { public JsonrpcNotification(String method) { super(method); diff --git a/io.openems.common/src/io/openems/common/jsonrpc/base/JsonrpcRequest.java b/io.openems.common/src/io/openems/common/jsonrpc/base/JsonrpcRequest.java index 5f48be201e6..3d0c5940381 100644 --- a/io.openems.common/src/io/openems/common/jsonrpc/base/JsonrpcRequest.java +++ b/io.openems.common/src/io/openems/common/jsonrpc/base/JsonrpcRequest.java @@ -23,7 +23,7 @@ * @see JSON-RPC * specification */ -public abstract class JsonrpcRequest extends AbstractJsonrpcRequest { +public abstract non-sealed class JsonrpcRequest extends AbstractJsonrpcRequest { public static final int DEFAULT_TIMEOUT_SECONDS = 60; public static final int NO_TIMEOUT = -1; diff --git a/io.openems.common/src/io/openems/common/jsonrpc/base/JsonrpcResponse.java b/io.openems.common/src/io/openems/common/jsonrpc/base/JsonrpcResponse.java index 87bf060e807..acddc648aa7 100644 --- a/io.openems.common/src/io/openems/common/jsonrpc/base/JsonrpcResponse.java +++ b/io.openems.common/src/io/openems/common/jsonrpc/base/JsonrpcResponse.java @@ -23,7 +23,7 @@ * @see JSON-RPC * specification */ -public abstract class JsonrpcResponse extends JsonrpcMessage { +public abstract non-sealed class JsonrpcResponse extends JsonrpcMessage { /** * Parses a JSON String to a {@link JsonrpcResponse}. diff --git a/io.openems.common/src/io/openems/common/jsonrpc/base/JsonrpcResponseSuccess.java b/io.openems.common/src/io/openems/common/jsonrpc/base/JsonrpcResponseSuccess.java index ba731e061cc..f4167e7c44e 100644 --- a/io.openems.common/src/io/openems/common/jsonrpc/base/JsonrpcResponseSuccess.java +++ b/io.openems.common/src/io/openems/common/jsonrpc/base/JsonrpcResponseSuccess.java @@ -32,11 +32,10 @@ public abstract class JsonrpcResponseSuccess extends JsonrpcResponse { * @throws OpenemsNamedException if it was not a Success Response */ public static JsonrpcResponseSuccess from(JsonObject j) throws OpenemsNamedException { - var response = JsonrpcResponse.from(j); - if (!(response instanceof JsonrpcResponseSuccess)) { - throw OpenemsError.GENERIC.exception("Expected a JSON-RPC Success Response"); - } - return (JsonrpcResponseSuccess) response; + return switch (JsonrpcResponse.from(j)) { + case JsonrpcResponseSuccess r -> r; + default -> throw OpenemsError.GENERIC.exception("Expected a JSON-RPC Success Response"); + }; } public JsonrpcResponseSuccess(UUID id) { diff --git a/io.openems.common/src/io/openems/common/jsonrpc/notification/AbstractDataNotification.java b/io.openems.common/src/io/openems/common/jsonrpc/notification/AbstractDataNotification.java index 506ed5037e6..4047811809c 100644 --- a/io.openems.common/src/io/openems/common/jsonrpc/notification/AbstractDataNotification.java +++ b/io.openems.common/src/io/openems/common/jsonrpc/notification/AbstractDataNotification.java @@ -26,8 +26,8 @@ * } * */ -// TODO change to sealed class -public abstract class AbstractDataNotification extends JsonrpcNotification { +public abstract sealed class AbstractDataNotification extends JsonrpcNotification + permits TimestampedDataNotification, AggregatedDataNotification, ResendDataNotification { private final TreeBasedTable data; diff --git a/io.openems.common/src/io/openems/common/jsonrpc/notification/AggregatedDataNotification.java b/io.openems.common/src/io/openems/common/jsonrpc/notification/AggregatedDataNotification.java index a31f44d65b5..366d8a03c81 100644 --- a/io.openems.common/src/io/openems/common/jsonrpc/notification/AggregatedDataNotification.java +++ b/io.openems.common/src/io/openems/common/jsonrpc/notification/AggregatedDataNotification.java @@ -22,7 +22,7 @@ * } * */ -public class AggregatedDataNotification extends AbstractDataNotification { +public final class AggregatedDataNotification extends AbstractDataNotification { public static final String METHOD = "aggregatedData"; diff --git a/io.openems.common/src/io/openems/common/jsonrpc/notification/ResendDataNotification.java b/io.openems.common/src/io/openems/common/jsonrpc/notification/ResendDataNotification.java index 43c9dc0b851..67236d6e650 100644 --- a/io.openems.common/src/io/openems/common/jsonrpc/notification/ResendDataNotification.java +++ b/io.openems.common/src/io/openems/common/jsonrpc/notification/ResendDataNotification.java @@ -21,7 +21,7 @@ * } * */ -public class ResendDataNotification extends AbstractDataNotification { +public final class ResendDataNotification extends AbstractDataNotification { public static final String METHOD = "resendData"; diff --git a/io.openems.common/src/io/openems/common/jsonrpc/notification/TimestampedDataNotification.java b/io.openems.common/src/io/openems/common/jsonrpc/notification/TimestampedDataNotification.java index be703c6cf15..af097e773a9 100644 --- a/io.openems.common/src/io/openems/common/jsonrpc/notification/TimestampedDataNotification.java +++ b/io.openems.common/src/io/openems/common/jsonrpc/notification/TimestampedDataNotification.java @@ -22,7 +22,7 @@ * } * */ -public class TimestampedDataNotification extends AbstractDataNotification { +public final class TimestampedDataNotification extends AbstractDataNotification { public static final String METHOD = "timestampedData"; diff --git a/io.openems.common/src/io/openems/common/oem/DummyOpenemsEdgeOem.java b/io.openems.common/src/io/openems/common/oem/DummyOpenemsEdgeOem.java index f5327adf50d..93c6e17ef6e 100644 --- a/io.openems.common/src/io/openems/common/oem/DummyOpenemsEdgeOem.java +++ b/io.openems.common/src/io/openems/common/oem/DummyOpenemsEdgeOem.java @@ -78,6 +78,8 @@ public SystemUpdateParams getSystemUpdateParams() { .put("App.TimeOfUseTariff.Tibber", "") // .put("App.Api.ModbusTcp.ReadOnly", "") // .put("App.Api.ModbusTcp.ReadWrite", "") // + .put("App.Api.ModbusRtu.ReadOnly", "") // + .put("App.Api.ModbusRtu.ReadWrite", "") // .put("App.Api.RestJson.ReadOnly", "") // .put("App.Api.RestJson.ReadWrite", "") // .put("App.Timedata.InfluxDb", "")// diff --git a/io.openems.common/src/io/openems/common/oem/OpenemsEdgeOem.java b/io.openems.common/src/io/openems/common/oem/OpenemsEdgeOem.java index ef291a2c75c..a4a0c63c948 100644 --- a/io.openems.common/src/io/openems/common/oem/OpenemsEdgeOem.java +++ b/io.openems.common/src/io/openems/common/oem/OpenemsEdgeOem.java @@ -141,7 +141,7 @@ public record OAuthClientRegistration(String clientId, String clientSecret) { public default OAuthClientRegistration getRabotChargeCredentials() { return null; } - + /** * Gets the OEM authorization for Battery.BMW. * diff --git a/io.openems.common/src/io/openems/common/session/Role.java b/io.openems.common/src/io/openems/common/session/Role.java index 6c60d6e8a12..9c561fc03e8 100644 --- a/io.openems.common/src/io/openems/common/session/Role.java +++ b/io.openems.common/src/io/openems/common/session/Role.java @@ -45,17 +45,13 @@ public int getLevel() { * @return the Role */ public static Role getRole(String name) { - switch (name.toLowerCase()) { - case "admin": - return ADMIN; - case "installer": - return INSTALLER; - case "owner": - return OWNER; - case "guest": - default: - return GUEST; - } + return switch (name.toLowerCase()) { + case "admin" -> ADMIN; + case "installer" -> INSTALLER; + case "owner" -> OWNER; + case "guest" -> GUEST; + default -> GUEST; + }; } /** diff --git a/io.openems.common/src/io/openems/common/test/TestUtils.java b/io.openems.common/src/io/openems/common/test/TestUtils.java new file mode 100644 index 00000000000..36ccf762ed7 --- /dev/null +++ b/io.openems.common/src/io/openems/common/test/TestUtils.java @@ -0,0 +1,35 @@ +package io.openems.common.test; + +import java.io.IOException; +import java.net.ServerSocket; +import java.time.Instant; + +public class TestUtils { + + private TestUtils() { + } + + /** + * Creates a {@link TimeLeapClock} for 1st January 2000 00:00. + * + * @return the {@link TimeLeapClock} + */ + public static TimeLeapClock createDummyClock() { + return new TimeLeapClock(Instant.ofEpochSecond(1577836800) /* starts at 1. January 2020 00:00:00 */); + } + + /** + * Finds and returns an open port. + * + *

+ * Source https://stackoverflow.com/a/26644672 + * + * @return an open port + * @throws IOException on error + */ + public static int findRandomOpenPortOnAllLocalInterfaces() throws IOException { + try (var socket = new ServerSocket(0);) { + return socket.getLocalPort(); + } + } +} diff --git a/io.openems.common/src/io/openems/common/timedata/Resolution.java b/io.openems.common/src/io/openems/common/timedata/Resolution.java index 8afcc764ba1..69dee3b500a 100644 --- a/io.openems.common/src/io/openems/common/timedata/Resolution.java +++ b/io.openems.common/src/io/openems/common/timedata/Resolution.java @@ -38,15 +38,12 @@ public ChronoUnit getUnit() { * @return Date without offset */ public ZonedDateTime revertInfluxDbOffset(ZonedDateTime date) { - switch (this.unit) { - case DAYS: - case MONTHS: - return date.minus(this.value, this.unit); - case MINUTES: - case HOURS: - default: - return date; - } + return switch (this.unit) { + case DAYS, MONTHS // + -> date.minus(this.value, this.unit); + default // MINUTES, HOURS, etc. + -> date; + }; } /** diff --git a/io.openems.common/src/io/openems/common/timedata/XlsxExportDetailData.java b/io.openems.common/src/io/openems/common/timedata/XlsxExportDetailData.java index 199bc345846..94e40fafe63 100644 --- a/io.openems.common/src/io/openems/common/timedata/XlsxExportDetailData.java +++ b/io.openems.common/src/io/openems/common/timedata/XlsxExportDetailData.java @@ -11,8 +11,7 @@ public record XlsxExportDetailData(// EnumMap> data, // - CurrencyConfig currency -) { + CurrencyConfig currency) { public Map> getChannelsBySaveType() { return this.data().values().stream().flatMap(List::stream).collect(Collectors.groupingBy( diff --git a/io.openems.common/src/io/openems/common/timedata/XlsxWorksheetWrapper.java b/io.openems.common/src/io/openems/common/timedata/XlsxWorksheetWrapper.java index faec99a684a..a39b7742d6c 100644 --- a/io.openems.common/src/io/openems/common/timedata/XlsxWorksheetWrapper.java +++ b/io.openems.common/src/io/openems/common/timedata/XlsxWorksheetWrapper.java @@ -38,7 +38,7 @@ public void setForRange(int r1, int c1, int r2, int c2, Consumer OpenemsType.LONG; + case AttributeDefinition.INTEGER -> OpenemsType.INTEGER; + case AttributeDefinition.SHORT, AttributeDefinition.BYTE -> OpenemsType.SHORT; + case AttributeDefinition.DOUBLE -> OpenemsType.DOUBLE; + case AttributeDefinition.FLOAT -> OpenemsType.FLOAT; + case AttributeDefinition.BOOLEAN -> OpenemsType.BOOLEAN; + case AttributeDefinition.STRING, AttributeDefinition.CHARACTER, AttributeDefinition.PASSWORD -> + OpenemsType.STRING; + default -> { EdgeConfig.LOG.warn("AttributeDefinition type [" + ad.getType() + "] is unknown!"); - type = OpenemsType.STRING; + yield OpenemsType.STRING; } - + }; var defaultValues = ad.getDefaultValue(); JsonElement defaultValue; if (defaultValues == null) { @@ -769,15 +752,13 @@ public static Property from(AttributeDefinition ad) { var id = ad.getID(); var name = ad.getName(); - final boolean isRequired; - switch (id) { - case "alias": - // Set alias as not-required. If no alias is given it falls back to id. - isRequired = false; - break; - default: - isRequired = ad.getCardinality() == 0; - } + var isRequired = switch (id) { + case "alias" -> // + // Set alias as not-required. If no alias is given it falls back to id + false; + default // + -> ad.getCardinality() == 0; + }; return new Property(id, name, description, type, isRequired, isPassword, defaultValue, schema); } diff --git a/io.openems.common/src/io/openems/common/types/EdgeConfigDiff.java b/io.openems.common/src/io/openems/common/types/EdgeConfigDiff.java index a4b8615b629..6ce49572427 100644 --- a/io.openems.common/src/io/openems/common/types/EdgeConfigDiff.java +++ b/io.openems.common/src/io/openems/common/types/EdgeConfigDiff.java @@ -1,5 +1,7 @@ package io.openems.common.types; +import static io.openems.common.utils.StringUtils.toShortString; + import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; @@ -18,7 +20,6 @@ import io.openems.common.types.EdgeConfig.Component; import io.openems.common.types.EdgeConfigDiff.ComponentDiff.Change; import io.openems.common.types.EdgeConfigDiff.ComponentDiff.OldNewProperty; -import io.openems.common.utils.StringUtils; public class EdgeConfigDiff { @@ -325,30 +326,27 @@ public String getAsText() { final var component = componentEntry.getValue(); var change = component.properties.entrySet().stream() // .filter(e -> { - switch (e.getKey()) { - case "_lastChangeAt": - case "_lastChangeBy": - case "org.ops4j.pax.logging.appender.name": - // ignore - return false; - default: - return true; - } + return switch (e.getKey()) { + case // + "_lastChangeAt", // + "_lastChangeBy", // + "org.ops4j.pax.logging.appender.name" // + -> false; // ignore + default // + -> true; + }; }) // .map(e -> { - String oldValue = StringUtils.toShortString(e.getValue().getOld(), 20); - String newValue = StringUtils.toShortString(e.getValue().getNew(), 20); - - switch (component.change) { - case CREATED: - return e.getKey() + "=" + newValue; - case UPDATED: - return e.getKey() + "=" + newValue + " [was:" + oldValue + "]"; - case DELETED: - return e.getKey() + " [was:" + oldValue + "]"; - } - assert true; - return ""; // can never happen + var oldValue = toShortString(e.getValue().getOld(), 20); + var newValue = toShortString(e.getValue().getNew(), 20); + return switch (component.change) { + case CREATED // + -> e.getKey() + "=" + newValue; + case UPDATED // + -> e.getKey() + "=" + newValue + " [was:" + oldValue + "]"; + case DELETED // + -> e.getKey() + " [was:" + oldValue + "]"; + }; }) // .collect(Collectors.joining(", ")); if (change.isEmpty()) { 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 1ead2112db3..68329dbc164 100644 --- a/io.openems.common/src/io/openems/common/utils/JsonUtils.java +++ b/io.openems.common/src/io/openems/common/utils/JsonUtils.java @@ -23,7 +23,6 @@ import com.google.common.base.Function; import com.google.common.base.Supplier; -import com.google.common.collect.Sets; import com.google.gson.GsonBuilder; import com.google.gson.JsonArray; import com.google.gson.JsonElement; @@ -445,7 +444,7 @@ public static class JsonArrayCollector implements Collector characteristics() { - return Sets.newHashSet().stream().collect(Sets.toImmutableEnumSet()); + return Set.of(); } @Override @@ -461,7 +460,7 @@ public BiConsumer accumulator() { @Override public BinaryOperator combiner() { return (t, u) -> { - u.build().forEach(j -> t.add(j)); + u.build().forEach(t::add); return t; }; } @@ -604,7 +603,6 @@ public static JsonPrimitive getAsPrimitive(JsonElement jElement, String memberNa * @param jElement the {@link JsonElement} * @param memberName the name of the member * @return the {@link Optional} {@link JsonPrimitive} value - * @throws OpenemsNamedException on error */ public static Optional getAsOptionalPrimitive(JsonElement jElement, String memberName) { return Optional.ofNullable(toPrimitive(toSubElement(jElement, memberName))); @@ -634,7 +632,6 @@ public static JsonElement getSubElement(JsonElement jElement, String memberName) * @param jElement the {@link JsonElement} * @param memberName the name of the member * @return the {@link Optional} {@link JsonElement} value - * @throws OpenemsNamedException on error */ public static Optional getOptionalSubElement(JsonElement jElement, String memberName) { return Optional.ofNullable(toSubElement(jElement, memberName)); @@ -677,7 +674,6 @@ public static JsonObject getAsJsonObject(JsonElement jElement, String memberName * * @param jElement the {@link JsonElement} * @return the {@link Optional} {@link JsonObject} value - * @throws OpenemsNamedException on error */ public static Optional getAsOptionalJsonObject(JsonElement jElement) { return Optional.ofNullable(toJsonObject(jElement)); @@ -690,7 +686,6 @@ public static Optional getAsOptionalJsonObject(JsonElement jElement) * @param jElement the {@link JsonElement} * @param memberName the name of the member * @return the {@link Optional} {@link JsonObject} value - * @throws OpenemsNamedException on error */ public static Optional getAsOptionalJsonObject(JsonElement jElement, String memberName) { return Optional.ofNullable(toJsonObject(toSubElement(jElement, memberName))); @@ -733,7 +728,6 @@ public static JsonArray getAsJsonArray(JsonElement jElement, String memberName) * * @param jElement the {@link JsonElement} * @return the {@link Optional} {@link JsonArray} value - * @throws OpenemsNamedException on error */ public static Optional getAsOptionalJsonArray(JsonElement jElement) { return Optional.ofNullable(toJsonArray(jElement)); @@ -746,7 +740,6 @@ public static Optional getAsOptionalJsonArray(JsonElement jElement) { * @param jElement the {@link JsonElement} * @param memberName the name of the member * @return the {@link Optional} {@link JsonArray} value - * @throws OpenemsNamedException on error */ public static Optional getAsOptionalJsonArray(JsonElement jElement, String memberName) { return Optional.ofNullable(toJsonArray(toSubElement(jElement, memberName))); @@ -789,7 +782,6 @@ public static String getAsString(JsonElement jElement, String memberName) throws * * @param jElement the {@link JsonElement} * @return the {@link Optional} {@link String} value - * @throws OpenemsNamedException on error */ public static Optional getAsOptionalString(JsonElement jElement) { return Optional.ofNullable(toString(toPrimitive(jElement))); @@ -802,7 +794,6 @@ public static Optional getAsOptionalString(JsonElement jElement) { * @param jElement the {@link JsonElement} * @param memberName the name of the member * @return the {@link Optional} {@link String} value - * @throws OpenemsNamedException on error */ public static Optional getAsOptionalString(JsonElement jElement, String memberName) { return Optional.ofNullable(toString(toPrimitive(toSubElement(jElement, memberName)))); @@ -851,7 +842,7 @@ public static String[] getAsStringArray(JsonArray json) throws OpenemsNamedExcep public static boolean getAsBoolean(JsonElement jElement) throws OpenemsNamedException { var value = toBoolean(toPrimitive(jElement)); if (value != null) { - return value.booleanValue(); + return value; } throw OpenemsError.JSON_NO_BOOLEAN.exception(jElement.toString().replace("%", "%%")); } @@ -867,7 +858,7 @@ public static boolean getAsBoolean(JsonElement jElement) throws OpenemsNamedExce public static boolean getAsBoolean(JsonElement jElement, String memberName) throws OpenemsNamedException { var value = toBoolean(toPrimitive(toSubElement(jElement, memberName))); if (value != null) { - return value.booleanValue(); + return value; } throw OpenemsError.JSON_NO_BOOLEAN_MEMBER.exception(memberName, jElement.toString().replace("%", "%%")); } @@ -877,7 +868,6 @@ public static boolean getAsBoolean(JsonElement jElement, String memberName) thro * * @param jElement the {@link JsonElement} * @return the {@link Optional} {@link Boolean} value - * @throws OpenemsNamedException on error */ public static Optional getAsOptionalBoolean(JsonElement jElement) { return Optional.ofNullable(toBoolean(toPrimitive(jElement))); @@ -890,7 +880,6 @@ public static Optional getAsOptionalBoolean(JsonElement jElement) { * @param jElement the {@link JsonElement} * @param memberName the name of the member * @return the {@link Optional} {@link Boolean} value - * @throws OpenemsNamedException on error */ public static Optional getAsOptionalBoolean(JsonElement jElement, String memberName) { return Optional.ofNullable(toBoolean(toPrimitive(toSubElement(jElement, memberName)))); @@ -906,7 +895,7 @@ public static Optional getAsOptionalBoolean(JsonElement jElement, Strin public static short getAsShort(JsonElement jElement) throws OpenemsNamedException { var value = toShort(toPrimitive(jElement)); if (value != null) { - return value.shortValue(); + return value; } throw OpenemsError.JSON_NO_SHORT.exception(jElement.toString().replace("%", "%%")); } @@ -932,7 +921,6 @@ public static short getAsShort(JsonElement jElement, String memberName) throws O * * @param jElement the {@link JsonElement} * @return the {@link Optional} {@link Short} value - * @throws OpenemsNamedException on error */ public static Optional getAsOptionalShort(JsonElement jElement) { return Optional.ofNullable(toShort(toPrimitive(jElement))); @@ -945,7 +933,6 @@ public static Optional getAsOptionalShort(JsonElement jElement) { * @param jElement the {@link JsonElement} * @param memberName the name of the member * @return the {@link Optional} {@link Boolean} value - * @throws OpenemsNamedException on error */ public static Optional getAsOptionalShort(JsonElement jElement, String memberName) { return Optional.ofNullable(toShort(toPrimitive(toSubElement(jElement, memberName)))); @@ -961,7 +948,7 @@ public static Optional getAsOptionalShort(JsonElement jElement, String me public static int getAsInt(JsonElement jElement) throws OpenemsNamedException { var value = toInt(toPrimitive(jElement)); if (value != null) { - return value.intValue(); + return value; } throw OpenemsError.JSON_NO_INTEGER.exception(jElement.toString().replace("%", "%%")); } @@ -1002,7 +989,6 @@ public static int getAsInt(JsonArray jArray, int index) throws OpenemsNamedExcep * * @param jElement the {@link JsonElement} * @return the {@link Optional} {@link Integer} value - * @throws OpenemsNamedException on error */ public static Optional getAsOptionalInt(JsonElement jElement) { return Optional.ofNullable(toInt(toPrimitive(jElement))); @@ -1015,7 +1001,6 @@ public static Optional getAsOptionalInt(JsonElement jElement) { * @param jElement the {@link JsonElement} * @param memberName the name of the member * @return the {@link Optional} {@link Integer} value - * @throws OpenemsNamedException on error */ public static Optional getAsOptionalInt(JsonElement jElement, String memberName) { return Optional.ofNullable(toInt(toPrimitive(toSubElement(jElement, memberName)))); @@ -1031,7 +1016,7 @@ public static Optional getAsOptionalInt(JsonElement jElement, String me public static long getAsLong(JsonElement jElement) throws OpenemsNamedException { var value = toLong(toPrimitive(jElement)); if (value != null) { - return value.longValue(); + return value; } throw OpenemsError.JSON_NO_LONG.exception(jElement.toString().replace("%", "%%")); } @@ -1057,7 +1042,6 @@ public static long getAsLong(JsonElement jElement, String memberName) throws Ope * * @param jElement the {@link JsonElement} * @return the {@link Optional} {@link Long} value - * @throws OpenemsNamedException on error */ public static Optional getAsOptionalLong(JsonElement jElement) { return Optional.ofNullable(toLong(toPrimitive(jElement))); @@ -1069,7 +1053,6 @@ public static Optional getAsOptionalLong(JsonElement jElement) { * @param jElement the {@link JsonElement} * @param memberName the name of the member * @return the {@link Optional} {@link Long} value - * @throws OpenemsNamedException on error */ public static Optional getAsOptionalLong(JsonElement jElement, String memberName) { return Optional.ofNullable(toLong(toPrimitive(toSubElement(jElement, memberName)))); @@ -1085,7 +1068,7 @@ public static Optional getAsOptionalLong(JsonElement jElement, String memb public static float getAsFloat(JsonElement jElement) throws OpenemsNamedException { var value = toFloat(toPrimitive(jElement)); if (value != null) { - return value.floatValue(); + return value; } throw OpenemsError.JSON_NO_FLOAT.exception(jElement.toString().replace("%", "%%")); } @@ -1111,7 +1094,6 @@ public static float getAsFloat(JsonElement jElement, String memberName) throws O * * @param jElement the {@link JsonElement} * @return the {@link Optional} {@link Float} value - * @throws OpenemsNamedException on error */ public static Optional getAsOptionalFloat(JsonElement jElement) { return Optional.ofNullable(toFloat(toPrimitive(jElement))); @@ -1123,7 +1105,6 @@ public static Optional getAsOptionalFloat(JsonElement jElement) { * @param jElement the {@link JsonElement} * @param memberName the name of the member * @return the {@link Optional} {@link Float} value - * @throws OpenemsNamedException on error */ public static Optional getAsOptionalFloat(JsonElement jElement, String memberName) { return Optional.ofNullable(toFloat(toPrimitive(toSubElement(jElement, memberName)))); @@ -1139,7 +1120,7 @@ public static Optional getAsOptionalFloat(JsonElement jElement, String me public static double getAsDouble(JsonElement jElement) throws OpenemsNamedException { var value = toDouble(toPrimitive(jElement)); if (value != null) { - return value.doubleValue(); + return value; } throw OpenemsError.JSON_NO_DOUBLE.exception(jElement.toString().replace("%", "%%")); } @@ -1165,7 +1146,6 @@ public static double getAsDouble(JsonElement jElement, String memberName) throws * * @param jElement the {@link JsonElement} * @return the {@link Optional} {@link Double} value - * @throws OpenemsNamedException on error */ public static Optional getAsOptionalDouble(JsonElement jElement) { return Optional.ofNullable(toDouble(toPrimitive(jElement))); @@ -1178,7 +1158,6 @@ public static Optional getAsOptionalDouble(JsonElement jElement) { * @param jElement the {@link JsonElement} * @param memberName the name of the member * @return the {@link Optional} {@link Double} value - * @throws OpenemsNamedException on error */ public static Optional getAsOptionalDouble(JsonElement jElement, String memberName) { return Optional.ofNullable(toDouble(toPrimitive(toSubElement(jElement, memberName)))); @@ -1228,7 +1207,6 @@ public static > E getAsEnum(Class enumType, JsonElement jEl * @param enumType the class of the {@link Enum} * @param jElement the {@link JsonElement} * @return the {@link Optional} {@link Enum} value - * @throws OpenemsNamedException on error */ public static > Optional getAsOptionalEnum(Class enumType, JsonElement jElement) { return Optional.ofNullable(toEnum(enumType, toString(toPrimitive(jElement)))); @@ -1242,7 +1220,6 @@ public static > Optional getAsOptionalEnum(Class enumTyp * @param jElement the {@link JsonElement} * @param memberName the name of the member * @return the {@link Optional} {@link Enum} value - * @throws OpenemsNamedException on error */ public static > Optional getAsOptionalEnum(Class enumType, JsonElement jElement, String memberName) { @@ -1285,7 +1262,6 @@ public static Inet4Address getAsInet4Address(JsonElement jElement, String member * * @param jElement the {@link JsonElement} * @return the {@link Optional} {@link Inet4Address} value - * @throws OpenemsNamedException on error */ public static Optional getAsOptionalInet4Address(JsonElement jElement) { return Optional.ofNullable(InetAddressUtils.parseOrNull(toString(toPrimitive(jElement)))); @@ -1298,7 +1274,6 @@ public static Optional getAsOptionalInet4Address(JsonElement jElem * @param jElement the {@link JsonElement} * @param memberName the name of the member * @return the {@link Optional} {@link Inet4Address} value - * @throws OpenemsNamedException on error */ public static Optional getAsOptionalInet4Address(JsonElement jElement, String memberName) { return Optional.ofNullable(// @@ -1345,7 +1320,6 @@ public static UUID getAsUUID(JsonElement jElement, String memberName) throws Ope * * @param jElement the {@link JsonElement} * @return the {@link Optional} {@link UUID} value - * @throws OpenemsNamedException on error */ // CHECKSTYLE:OFF public static Optional getAsOptionalUUID(JsonElement jElement) { @@ -1359,7 +1333,6 @@ public static Optional getAsOptionalUUID(JsonElement jElement) { * @param jElement the {@link JsonElement} * @param memberName the name of the member * @return the {@link Optional} {@link UUID} value - * @throws OpenemsNamedException on error */ // CHECKSTYLE:OFF public static Optional getAsOptionalUUID(JsonElement jElement, String memberName) { @@ -1379,7 +1352,7 @@ public static Object getAsBestType(JsonElement j) throws OpenemsNamedException { try { if (j.isJsonArray()) { var jA = (JsonArray) j; - if (jA.size() == 0) { + if (jA.isEmpty()) { return new Object[0]; } // identify the array type (boolean, int or String) @@ -1453,132 +1426,88 @@ public static Object getAsBestType(JsonElement j) throws OpenemsNamedException { * @return the {@link JsonElement} */ public static JsonElement getAsJsonElement(Object value) { - // null - if (value == null) { - return JsonNull.INSTANCE; - } // optional - if (value instanceof Optional) { - if (!((Optional) value).isPresent()) { + if (value instanceof Optional opt) { + if (opt.isEmpty()) { return JsonNull.INSTANCE; } - value = ((Optional) value).get(); - } - if (value instanceof Number) { - /* - * Number - */ - return new JsonPrimitive((Number) value); - } - if (value instanceof String) { - /* - * String - */ - return new JsonPrimitive((String) value); - } - if (value instanceof Boolean) { - /* - * Boolean - */ - return new JsonPrimitive((Boolean) value); - } - if (value instanceof Inet4Address) { - /* - * Inet4Address - */ - return new JsonPrimitive(((Inet4Address) value).getHostAddress()); - } - if (value instanceof JsonElement) { - /* - * JsonElement - */ - return (JsonElement) value; - } else if (value instanceof boolean[]) { - /* - * boolean-Array - */ + value = opt.get(); + } + + return switch (value) { + case null -> JsonNull.INSTANCE; + case Number n -> new JsonPrimitive(n); + case String s -> new JsonPrimitive(s); + case Boolean b -> new JsonPrimitive(b); + case Inet4Address inet -> new JsonPrimitive(inet.getHostAddress()); + case JsonElement json -> json; + case boolean[] bool -> { var js = new JsonArray(); - for (boolean b : (boolean[]) value) { + for (boolean b : bool) { js.add(new JsonPrimitive(b)); } - return js; - } else if (value instanceof short[]) { - /* - * short-Array - */ + yield js; + } + case short[] shorts -> { var js = new JsonArray(); - for (short s : (short[]) value) { + for (short s : shorts) { js.add(new JsonPrimitive(s)); } - return js; - } else if (value instanceof int[]) { - /* - * int-Array - */ + yield js; + } + case int[] ints -> { var js = new JsonArray(); - for (int i : (int[]) value) { + for (int i : ints) { js.add(new JsonPrimitive(i)); } - return js; - } else if (value instanceof long[]) { - /* - * long-Array - */ + yield js; + } + case long[] longs -> { var js = new JsonArray(); - for (long l : (long[]) value) { + for (long l : longs) { js.add(new JsonPrimitive(l)); } - return js; - } else if (value instanceof float[]) { - /* - * float-Array - */ + yield js; + } + case float[] floats -> { var js = new JsonArray(); - for (float f : (float[]) value) { + for (float f : floats) { js.add(new JsonPrimitive(f)); } - return js; - } else if (value instanceof double[]) { - /* - * double-Array - */ + yield js; + } + case double[] doubles -> { var js = new JsonArray(); - for (double d : (double[]) value) { - js.add(new JsonPrimitive(d)); + for (double f : doubles) { + js.add(new JsonPrimitive(f)); } - return js; - } else if (value instanceof String[]) { - /* - * String-Array - */ + yield js; + } + case String[] strings -> { var js = new JsonArray(); - var v = (String[]) value; - if (v.length == 1 && v[0].isEmpty()) { + if (strings.length == 1 && strings[0].isEmpty()) { // special case: String-Array with one entry which is an empty String. Return an // empty JsonArray. - return js; + yield js; } - for (String s : v) { + for (String s : strings) { js.add(new JsonPrimitive(s)); } - return js; - } else if (value instanceof Object[]) { - /* - * Object-Array - */ + yield js; + } + case Object[] objects -> { var js = new JsonArray(); - for (Object o : (Object[]) value) { + for (Object o : objects) { js.add(JsonUtils.getAsJsonElement(o)); } - return js; - } else { - /* - * Use toString()-method - */ - JsonUtils.LOG.warn("Converter for [" + value + "]" + " of type [" + value.getClass().getSimpleName() - + "] to JSON is not implemented."); - return new JsonPrimitive(value.toString()); + yield js; } + default -> { + JsonUtils.LOG.warn("Converter for [{}] of type [{}] to JSON is not implemented.", // + value, value.getClass().getSimpleName()); + yield new JsonPrimitive(value.toString()); + } + }; } /** @@ -1631,11 +1560,11 @@ public static Object getAsType(Class type, JsonElement j) throws NotImplement */ return j.getAsJsonArray(); } else if (type.isArray()) { - /** + /* * Asking for Array */ if (Long.class.isAssignableFrom(type.getComponentType())) { - /** + /* * Asking for ArrayOfLong */ if (j.isJsonArray()) { @@ -1671,22 +1600,15 @@ public static T getAsType(OpenemsType type, JsonElement j) throws OpenemsNam } if (j.isJsonPrimitive()) { - switch (type) { - case BOOLEAN: - return (T) Boolean.valueOf(JsonUtils.getAsBoolean(j)); - case DOUBLE: - return (T) Double.valueOf(JsonUtils.getAsDouble(j)); - case FLOAT: - return (T) Float.valueOf(JsonUtils.getAsFloat(j)); - case INTEGER: - return (T) Integer.valueOf(JsonUtils.getAsInt(j)); - case LONG: - return (T) Long.valueOf(JsonUtils.getAsLong(j)); - case SHORT: - return (T) Short.valueOf(JsonUtils.getAsShort(j)); - case STRING: - return (T) JsonUtils.getAsString(j); - } + return switch (type) { + case BOOLEAN -> (T) Boolean.valueOf(JsonUtils.getAsBoolean(j)); + case DOUBLE -> (T) Double.valueOf(JsonUtils.getAsDouble(j)); + case FLOAT -> (T) Float.valueOf(JsonUtils.getAsFloat(j)); + case INTEGER -> (T) Integer.valueOf(JsonUtils.getAsInt(j)); + case LONG -> (T) Long.valueOf(JsonUtils.getAsLong(j)); + case SHORT -> (T) Short.valueOf(JsonUtils.getAsShort(j)); + case STRING -> (T) JsonUtils.getAsString(j); + }; } if (j.isJsonObject() || j.isJsonArray()) { @@ -1715,7 +1637,7 @@ public static T getAsType(OpenemsType type, JsonElement j) throws OpenemsNam * @return an Object of the given type */ public static Object getAsType(Optional> typeOptional, JsonElement j) throws NotImplementedException { - if (!typeOptional.isPresent()) { + if (typeOptional.isEmpty()) { throw new NotImplementedException( "Type of Channel was not set: " + (j == null ? "UNDEFINED" : j.getAsString())); } @@ -1759,6 +1681,19 @@ public static LocalDateTime getAsLocalDateTime(JsonElement jElement, String memb return DateUtils.parseLocalDateTimeOrError(toString(toPrimitive(toSubElement(jElement, memberName)))); } + /** + * Takes a JSON in the form '2020-01-01T00:00:00' and converts it to a + * {@link LocalDateTime}. + * + * @param jElement the {@link JsonElement} + * @param memberName the name of the member of the JsonObject + * @return the {@link ZonedDateTime} + */ + public static Optional getAsOptionalLocalDateTime(JsonElement jElement, String memberName) { + return JsonUtils.getAsOptionalString(jElement, memberName)// + .map(DateUtils::parseLocalDateTimeOrNull); + } + /** * Takes a JSON in the form '2020-01-01T00:00:00Z' and converts it to a * {@link ZonedDateTime}. @@ -1867,7 +1802,7 @@ public static String prettyToString(JsonElement j) { public static boolean isEmptyJsonObject(JsonElement j) { if (j != null && j.isJsonObject()) { var object = j.getAsJsonObject(); - return object.size() == 0; + return object.isEmpty(); } return false; @@ -1882,7 +1817,7 @@ public static boolean isEmptyJsonObject(JsonElement j) { public static boolean isEmptyJsonArray(JsonElement j) { if (j != null && j.isJsonArray()) { var array = j.getAsJsonArray(); - return array.size() == 0; + return array.isEmpty(); } return false; @@ -1907,7 +1842,7 @@ public static boolean isNumber(JsonElement j) { */ public static Stream stream(JsonArray jsonArray) { return IntStream.range(0, jsonArray.size()) // - .mapToObj(index -> jsonArray.get(index)); + .mapToObj(jsonArray::get); } private static JsonObject toJsonObject(JsonElement jElement) { diff --git a/io.openems.common/src/io/openems/common/utils/ObjectUtils.java b/io.openems.common/src/io/openems/common/utils/ObjectUtils.java index 55b76a66366..4a751a514c3 100644 --- a/io.openems.common/src/io/openems/common/utils/ObjectUtils.java +++ b/io.openems.common/src/io/openems/common/utils/ObjectUtils.java @@ -12,11 +12,10 @@ public class ObjectUtils { * @return a {@link String} or null */ public static String getAsString(Object object) { - if (object instanceof String) { - return (String) object; - } - - return null; + return switch (object) { + case String s -> s; + case null, default -> null; + }; } /** @@ -37,11 +36,10 @@ public static Optional getAsOptionalString(Object object) { * @return a {@link Integer} or null */ public static Integer getAsInteger(Object object) { - if (object instanceof Integer) { - return (Integer) object; - } - - return null; + return switch (object) { + case Integer i -> i; + case null, default -> null; + }; } /** @@ -52,11 +50,9 @@ public static Integer getAsInteger(Object object) { * @return a {@link Object} array or empty array */ public static Object[] getAsObjectArrray(Object object) { - if (object instanceof Object[]) { - return (Object[]) object; - } - - return new Object[] {}; + return switch (object) { + case Object[] os -> os; + case null, default -> null; + }; } - } diff --git a/io.openems.common/src/io/openems/common/utils/StreamUtils.java b/io.openems.common/src/io/openems/common/utils/StreamUtils.java new file mode 100644 index 00000000000..9a831452028 --- /dev/null +++ b/io.openems.common/src/io/openems/common/utils/StreamUtils.java @@ -0,0 +1,25 @@ +package io.openems.common.utils; + +import java.util.Collections; +import java.util.Dictionary; +import java.util.Enumeration; +import java.util.Map; +import java.util.Map.Entry; +import java.util.stream.Stream; + +public class StreamUtils { + + /** + * Converts a Dictionary to a Stream of Map entries. + * + * @param dictionary the Dictionary to be converted + * @param the type of keys in the Dictionary + * @param the type of values in the Dictionary + * @return a Stream containing all the key-value pairs from the Dictionary as + * Map entries + */ + public static Stream> dictionaryToStream(Dictionary dictionary) { + Enumeration keys = dictionary.keys(); + return Collections.list(keys).stream().map(key -> Map.entry(key, dictionary.get(key))); + } +} diff --git a/io.openems.common/src/io/openems/common/websocket/AbstractWebsocketServer.java b/io.openems.common/src/io/openems/common/websocket/AbstractWebsocketServer.java index 64a90b1bda4..6b872b19fa6 100644 --- a/io.openems.common/src/io/openems/common/websocket/AbstractWebsocketServer.java +++ b/io.openems.common/src/io/openems/common/websocket/AbstractWebsocketServer.java @@ -162,10 +162,11 @@ public Map debugMetrics() { @Override protected OnInternalError getOnInternalError() { return (t, wsDataString) -> { - if (t instanceof BindException) { - this.logError(this.log, "Unable to Bind to port [" + this.port + "]"); - } else { - this.logError(this.log, new StringBuilder() // + switch (t) { + case BindException be // + -> this.logError(this.log, "Unable to Bind to port [" + this.port + "]"); + default // + -> this.logError(this.log, new StringBuilder() // .append("OnInternalError for ").append(wsDataString).append(". ") // .append(t.getClass()).append(": ") // .append(t.getMessage()).toString()); diff --git a/io.openems.common/src/io/openems/common/websocket/MyDraft6455.java b/io.openems.common/src/io/openems/common/websocket/MyDraft6455.java index 4c4968114c6..9759e53cb25 100644 --- a/io.openems.common/src/io/openems/common/websocket/MyDraft6455.java +++ b/io.openems.common/src/io/openems/common/websocket/MyDraft6455.java @@ -698,16 +698,16 @@ private boolean isFrameSizeValid(int maxpacketsize, int realpacketsize) { * @return byte that represents which RSV bit is set. */ private byte getRsvByte(int rsv) { - switch (rsv) { - case 1: // 0100 0000 - return 0x40; - case 2: // 0010 0000 - return 0x20; - case 3: // 0001 0000 - return 0x10; - default: - return 0; - } + return switch (rsv) { + case 1 // + -> 0x40; // 0100 0000 + case 2 // + -> 0x20; // 0010 0000 + case 3 // + -> 0x10; // 0001 0000 + default // + -> 0; + }; } /** @@ -864,41 +864,26 @@ private byte[] toByteArray(long val, int bytecount) { } private byte fromOpcode(Opcode opcode) { - if (opcode == Opcode.CONTINUOUS) { - return 0; - } else if (opcode == Opcode.TEXT) { - return 1; - } else if (opcode == Opcode.BINARY) { - return 2; - } else if (opcode == Opcode.CLOSING) { - return 8; - } else if (opcode == Opcode.PING) { - return 9; - } else if (opcode == Opcode.PONG) { - return 10; - } - throw new IllegalArgumentException("Don't know how to handle " + opcode.toString()); + return switch (opcode) { + case Opcode.CONTINUOUS -> 0; + case Opcode.TEXT -> 1; + case Opcode.BINARY -> 2; + case Opcode.CLOSING -> 8; + case Opcode.PING -> 9; + case Opcode.PONG -> 10; + }; } private Opcode toOpcode(byte opcode) throws InvalidFrameException { - switch (opcode) { - case 0: - return Opcode.CONTINUOUS; - case 1: - return Opcode.TEXT; - case 2: - return Opcode.BINARY; - // 3-7 are not yet defined - case 8: - return Opcode.CLOSING; - case 9: - return Opcode.PING; - case 10: - return Opcode.PONG; - // 11-15 are not yet defined - default: - throw new InvalidFrameException("Unknown opcode " + (short) opcode); - } + return switch (opcode) { + case 0 -> Opcode.CONTINUOUS; + case 1 -> Opcode.TEXT; + case 2 -> Opcode.BINARY; + case 8 -> Opcode.CLOSING; + case 9 -> Opcode.PING; + case 10 -> Opcode.PONG; + default -> throw new InvalidFrameException("Unknown opcode " + (short) opcode); + }; } @Override @@ -1059,8 +1044,7 @@ private void processFrameIsNotFin(Framedata frame) throws InvalidDataException { private void processFrameClosing(WebSocketImpl webSocketImpl, Framedata frame) { int code = CloseFrame.NOCODE; String reason = ""; - if (frame instanceof CloseFrame) { - CloseFrame cf = (CloseFrame) frame; + if (frame instanceof CloseFrame cf) { code = cf.getCloseCode(); reason = cf.getMessage(); } diff --git a/io.openems.common/src/io/openems/common/websocket/OnMessageHandler.java b/io.openems.common/src/io/openems/common/websocket/OnMessageHandler.java index 9efe41ba425..400237e914a 100644 --- a/io.openems.common/src/io/openems/common/websocket/OnMessageHandler.java +++ b/io.openems.common/src/io/openems/common/websocket/OnMessageHandler.java @@ -56,16 +56,13 @@ public OnMessageHandler(// @Override public final void run() { try { - var message = JsonrpcMessage.from(this.message); - - if (message instanceof JsonrpcRequest request) { - this.handleJsonrpcRequest(this.ws, request); - - } else if (message instanceof JsonrpcResponse response) { - this.handleJsonrpcResponse(this.ws, response); - - } else if (message instanceof JsonrpcNotification notification) { - this.handleJsonrpcNotification(this.ws, notification); + switch (JsonrpcMessage.from(this.message)) { + case JsonrpcRequest request // + -> this.handleJsonrpcRequest(this.ws, request); + case JsonrpcResponse response // + -> this.handleJsonrpcResponse(this.ws, response); + case JsonrpcNotification notification // + -> this.handleJsonrpcNotification(this.ws, notification); } } catch (OpenemsNamedException e) { @@ -142,11 +139,12 @@ private void handleJsonrpcRequestException(WebSocket ws, JsonrpcRequest request, this.logWarn.accept(this.log, log.toString()); // Get JSON-RPC Response Error - if (t instanceof OpenemsNamedException one) { - this.sendMessage.test(ws, new JsonrpcResponseError(request.getId(), one)); - } else { - this.sendMessage.test(ws, new JsonrpcResponseError(request.getId(), t.getMessage())); - } + this.sendMessage.test(ws, switch (t) { + case OpenemsNamedException one // + -> new JsonrpcResponseError(request.getId(), one); + default // + -> new JsonrpcResponseError(request.getId(), t.getMessage()); + }); } /** diff --git a/io.openems.common/src/io/openems/common/websocket/WsData.java b/io.openems.common/src/io/openems/common/websocket/WsData.java index 852b4290125..9c3c02809b3 100644 --- a/io.openems.common/src/io/openems/common/websocket/WsData.java +++ b/io.openems.common/src/io/openems/common/websocket/WsData.java @@ -119,21 +119,18 @@ public void handleJsonrpcResponse(JsonrpcResponse response) throws OpenemsNamedE throw OpenemsError.JSONRPC_RESPONSE_WITHOUT_REQUEST.exception(response.toJsonObject()); } // this was a response on a request - if (response instanceof JsonrpcResponseSuccess) { + switch (response) { + case JsonrpcResponseSuccess success -> // Success Response -> complete future - future.complete((JsonrpcResponseSuccess) response); - - } else if (response instanceof JsonrpcResponseError) { + future.complete(success); + case JsonrpcResponseError error -> // Named OpenEMS-Error Response -> cancel future - var error = (JsonrpcResponseError) response; - var exception = new OpenemsNamedException(error.getOpenemsError(), error.getParamsAsObjectArray()); - future.completeExceptionally(exception); - - } else { + future.completeExceptionally( + new OpenemsNamedException(error.getOpenemsError(), error.getParamsAsObjectArray())); + default -> // Undefined Error Response -> cancel future - var exception = new OpenemsNamedException(OpenemsError.GENERIC, - "Response is neither JsonrpcResponseSuccess nor JsonrpcResponseError: " + response.toString()); - future.completeExceptionally(exception); + future.completeExceptionally(new OpenemsNamedException(OpenemsError.GENERIC, + "Response is neither JsonrpcResponseSuccess nor JsonrpcResponseError: " + response.toString())); } } diff --git a/io.openems.edge.controller.evcs/test/io/openems/edge/controller/evcs/JSCalendarTest.java b/io.openems.common/test/io/openems/common/jscalendar/JSCalendarTest.java similarity index 59% rename from io.openems.edge.controller.evcs/test/io/openems/edge/controller/evcs/JSCalendarTest.java rename to io.openems.common/test/io/openems/common/jscalendar/JSCalendarTest.java index defe0bf80cb..689368466fd 100644 --- a/io.openems.edge.controller.evcs/test/io/openems/edge/controller/evcs/JSCalendarTest.java +++ b/io.openems.common/test/io/openems/common/jscalendar/JSCalendarTest.java @@ -1,10 +1,11 @@ -package io.openems.edge.controller.evcs; +package io.openems.common.jscalendar; +import static io.openems.common.jscalendar.JSCalendar.RecurrenceFrequency.DAILY; +import static io.openems.common.jscalendar.JSCalendar.RecurrenceFrequency.WEEKLY; +import static io.openems.common.test.TestUtils.createDummyClock; +import static io.openems.common.utils.JsonUtils.buildJsonArray; import static io.openems.common.utils.JsonUtils.buildJsonObject; import static io.openems.common.utils.JsonUtils.prettyToString; -import static io.openems.common.utils.UuidUtils.getNilUuid; -import static io.openems.edge.common.test.TestUtils.createDummyClock; -import static io.openems.edge.controller.evcs.JSCalendar.RecurrenceFrequency.WEEKLY; import static java.time.DayOfWeek.FRIDAY; import static java.time.DayOfWeek.MONDAY; import static java.time.DayOfWeek.SATURDAY; @@ -27,11 +28,46 @@ public class JSCalendarTest { // CHECKSTYLE:ON + @Test + public void testDaily() throws OpenemsNamedException { + var clock = createDummyClock(); + var sut = JSCalendar.Task.create() // + .setStart("07:00:00") // + .addRecurrenceRule(b -> b // + .setFrequency(DAILY)) // + .build(); + + var next = sut.getNextOccurence(ZonedDateTime.now(clock)); + assertEquals("2020-01-01T07:00Z", next.toString()); + next = sut.getNextOccurence(next.plusSeconds(1)); + assertEquals("2020-01-02T07:00Z", next.toString()); + next = sut.getNextOccurence(next.plusSeconds(1)); + assertEquals("2020-01-03T07:00Z", next.toString()); + } + + @Test + public void testDailyParse() throws OpenemsNamedException { + var sut = JSCalendar.Task.fromStringOrEmpty(""" + [ + { + "@type":"Task", + "start":"19:00:00", + "duration":"PT12H", + "recurrenceRules":[ + { + "frequency":"daily" + } + ] + } + ]""", j -> j); + assertEquals(1, sut.size()); + } + @Test public void testWeekday() throws OpenemsNamedException { var clock = createDummyClock(); - var sut = new JSCalendar.Task.Builder(getNilUuid(), ZonedDateTime.now(clock)) // - .setStart("2024-06-17T07:00:00") // + var sut = JSCalendar.Task.create() // + .setStart("07:00:00") // .addRecurrenceRule(b -> b // .setFrequency(WEEKLY) // .addByDay(MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY)) // @@ -39,12 +75,11 @@ public void testWeekday() throws OpenemsNamedException { .addProperty("sessionEnergy", 10000) // .build()) // .build(); + assertEquals(""" { "@type": "Task", - "uid": "00000000-0000-0000-0000-000000000000", - "updated": "2020-01-01T00:00:00Z", - "start": "2024-06-17T07:00:00", + "start": "07:00:00", "recurrenceRules": [ { "frequency": "weekly", @@ -57,35 +92,37 @@ public void testWeekday() throws OpenemsNamedException { ] } ], - "payload": { + "openems.io:payload": { "sessionEnergy": 10000 } }""", prettyToString(sut.toJson(identity()))); var next = sut.getNextOccurence(ZonedDateTime.now(clock)); - assertEquals("2024-06-17T07:00Z", next.toString()); + assertEquals("2020-01-01T07:00Z", next.toString()); + next = sut.getNextOccurence(next.plusSeconds(1)); + assertEquals("2020-01-02T07:00Z", next.toString()); next = sut.getNextOccurence(next.plusSeconds(1)); - assertEquals("2024-06-18T07:00Z", next.toString()); + assertEquals("2020-01-03T07:00Z", next.toString()); next = sut.getNextOccurence(next.plusSeconds(1)); - assertEquals("2024-06-19T07:00Z", next.toString()); + assertEquals("2020-01-06T07:00Z", next.toString()); // next week next = sut.getNextOccurence(next.plusSeconds(1)); - assertEquals("2024-06-20T07:00Z", next.toString()); + assertEquals("2020-01-07T07:00Z", next.toString()); next = sut.getNextOccurence(next.plusSeconds(1)); - assertEquals("2024-06-21T07:00Z", next.toString()); - next = sut.getNextOccurence(next.plusSeconds(1)); // next week - assertEquals("2024-06-24T07:00Z", next.toString()); + assertEquals("2020-01-08T07:00Z", next.toString()); next = sut.getNextOccurence(next); - assertEquals("2024-06-24T07:00Z", next.toString()); // same + assertEquals("2020-01-08T07:00Z", next.toString()); // same // Parse JSON - var fromJson = JSCalendar.Task.fromJson(sut.toJson(identity()), identity()); - assertEquals(sut.toJson(identity()), fromJson.toJson(identity())); + var fromJson = JSCalendar.Task.fromJson(buildJsonArray() // + .add(sut.toJson(identity())) // + .build(), j -> j); + assertEquals(sut.toJson(identity()), fromJson.get(0).toJson(identity())); } @Test public void testWeekend() throws OpenemsNamedException { var clock = createDummyClock(); - var sut = new JSCalendar.Task.Builder(getNilUuid(), ZonedDateTime.now(clock)) // + var sut = JSCalendar.Task.create() // .setStart("2024-06-17T00:00:00") // .addRecurrenceRule(b -> b // .setFrequency(WEEKLY) // @@ -97,8 +134,6 @@ public void testWeekend() throws OpenemsNamedException { assertEquals(""" { "@type": "Task", - "uid": "00000000-0000-0000-0000-000000000000", - "updated": "2020-01-01T00:00:00Z", "start": "2024-06-17T00:00:00", "recurrenceRules": [ { @@ -109,7 +144,7 @@ public void testWeekend() throws OpenemsNamedException { ] } ], - "payload": { + "openems.io:payload": { "sessionEnergy": 10001 } }""", prettyToString(sut.toJson(identity()))); diff --git a/io.openems.common/test/io/openems/common/test/TimeLeapClockTest.java b/io.openems.common/test/io/openems/common/test/TimeLeapClockTest.java index 3609efce3a5..6c7485a35ce 100644 --- a/io.openems.common/test/io/openems/common/test/TimeLeapClockTest.java +++ b/io.openems.common/test/io/openems/common/test/TimeLeapClockTest.java @@ -52,7 +52,7 @@ public void testMillis() { @Test public void testLeap() { - var dateTime = ZonedDateTime.now(); + var dateTime = ZonedDateTime.of(2023, 1, 2, 3, 4, 5, 6, ZoneId.of("UTC")); final var instant = dateTime.toInstant(); final var zone = dateTime.getZone(); diff --git a/io.openems.common/test/io/openems/common/utils/JsonUtilsTest.java b/io.openems.common/test/io/openems/common/utils/JsonUtilsTest.java index de06b6e2bd3..37f25ae848b 100644 --- a/io.openems.common/test/io/openems/common/utils/JsonUtilsTest.java +++ b/io.openems.common/test/io/openems/common/utils/JsonUtilsTest.java @@ -54,10 +54,12 @@ import static io.openems.common.utils.JsonUtils.getAsOptionalInt; import static io.openems.common.utils.JsonUtils.getAsOptionalJsonArray; import static io.openems.common.utils.JsonUtils.getAsOptionalJsonObject; +import static io.openems.common.utils.JsonUtils.getAsOptionalLocalDateTime; import static io.openems.common.utils.JsonUtils.getAsOptionalLong; import static io.openems.common.utils.JsonUtils.getAsOptionalShort; import static io.openems.common.utils.JsonUtils.getAsOptionalString; import static io.openems.common.utils.JsonUtils.getAsOptionalUUID; +import static io.openems.common.utils.JsonUtils.getAsOptionalZonedDateTime; import static io.openems.common.utils.JsonUtils.getAsPrimitive; import static io.openems.common.utils.JsonUtils.getAsShort; import static io.openems.common.utils.JsonUtils.getAsString; @@ -688,11 +690,17 @@ public void testGetAsZonedDateTime() throws OpenemsNamedException { ); assertEquals("1900-01-01T00:00Z", getAsZonedDateTime(JSON_OBJECT, "ZonedDateTime").toString()); + + assertTrue(getAsOptionalZonedDateTime(JSON_OBJECT, "foo").isEmpty()); } @Test public void testGetAsLocalDateTime() throws OpenemsNamedException { assertEquals("1900-01-01T00:00", getAsLocalDateTime(JSON_OBJECT, "LocalDateTime").toString()); + + assertEquals("1900-01-01T00:00", getAsOptionalLocalDateTime(JSON_OBJECT, "LocalDateTime").get().toString()); + + assertTrue(getAsOptionalLocalDateTime(JSON_OBJECT, "foo").isEmpty()); } @Test diff --git a/io.openems.common/test/io/openems/common/utils/ObjectUtilsTest.java b/io.openems.common/test/io/openems/common/utils/ObjectUtilsTest.java new file mode 100644 index 00000000000..a2f6744ca76 --- /dev/null +++ b/io.openems.common/test/io/openems/common/utils/ObjectUtilsTest.java @@ -0,0 +1,42 @@ +package io.openems.common.utils; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +import java.util.Optional; + +import org.junit.Test; + +public class ObjectUtilsTest { + + @Test + public void testGetAsString() { + assertNull(ObjectUtils.getAsString(null)); + assertNull(ObjectUtils.getAsString(new Object())); + assertEquals("string", ObjectUtils.getAsString("string")); + } + + @Test + public void testGetAsOptionalString() { + assertEquals(Optional.empty(), ObjectUtils.getAsOptionalString(null)); + assertEquals(Optional.empty(), ObjectUtils.getAsOptionalString(new Object())); + assertEquals(Optional.of("string"), ObjectUtils.getAsOptionalString("string")); + } + + @Test + public void testGetAsInteger() { + assertNull(ObjectUtils.getAsInteger(null)); + assertNull(ObjectUtils.getAsInteger(new Object())); + assertEquals((Integer) 1337, ObjectUtils.getAsInteger(1337)); + } + + @Test + public void testGetAsObjectArrray() { + assertNull(ObjectUtils.getAsObjectArrray(null)); + assertNull(ObjectUtils.getAsObjectArrray(new Object())); + final var array = new Object[] {}; + assertArrayEquals(array, ObjectUtils.getAsObjectArrray(array)); + } + +} diff --git a/io.openems.edge.application/EdgeApp.bndrun b/io.openems.edge.application/EdgeApp.bndrun index 5ac61e56d48..e997fc82ca9 100644 --- a/io.openems.edge.application/EdgeApp.bndrun +++ b/io.openems.edge.application/EdgeApp.bndrun @@ -96,6 +96,7 @@ bnd.identity;id='io.openems.edge.controller.io.analog',\ bnd.identity;id='io.openems.edge.controller.io.channelsinglethreshold',\ bnd.identity;id='io.openems.edge.controller.io.fixdigitaloutput',\ + bnd.identity;id='io.openems.edge.controller.io.heating.room',\ bnd.identity;id='io.openems.edge.controller.io.heatingelement',\ bnd.identity;id='io.openems.edge.controller.io.heatpump.sgready',\ bnd.identity;id='io.openems.edge.controller.pvinverter.fixpowerlimit',\ @@ -142,6 +143,7 @@ bnd.identity;id='io.openems.edge.io.offgridswitch',\ bnd.identity;id='io.openems.edge.io.revpi',\ bnd.identity;id='io.openems.edge.io.shelly',\ + bnd.identity;id='io.openems.edge.io.siemenslogo',\ bnd.identity;id='io.openems.edge.io.wago',\ bnd.identity;id='io.openems.edge.io.weidmueller',\ bnd.identity;id='io.openems.edge.kaco.blueplanet.hybrid10',\ @@ -198,16 +200,16 @@ -runbundles: \ Java-WebSocket;version='[1.5.4,1.5.5)',\ - bcpkix;version='[1.79.0,1.79.1)',\ - bcprov;version='[1.79.0,1.79.1)',\ - bcutil;version='[1.79.0,1.79.1)',\ + bcpkix;version='[1.80.0,1.80.1)',\ + bcprov;version='[1.80.0,1.80.1)',\ + bcutil;version='[1.80.0,1.80.1)',\ com.fasterxml.aalto-xml;version='[1.3.3,1.3.4)',\ com.fazecast.jSerialComm;version='[2.10.4,2.10.5)',\ com.ghgande.j2mod;version='[3.2.1,3.2.2)',\ com.google.gson;version='[2.11.0,2.11.1)',\ com.google.guava;version='[33.4.0,33.4.1)',\ com.google.guava.failureaccess;version='[1.0.2,1.0.3)',\ - com.squareup.okio;version='[3.9.1,3.9.2)',\ + com.squareup.okio;version='[3.10.2,3.10.3)',\ com.sun.jna;version='[5.16.0,5.16.1)',\ io.openems.common;version=snapshot,\ io.openems.edge.application;version=snapshot,\ @@ -271,6 +273,7 @@ io.openems.edge.controller.io.analog;version=snapshot,\ io.openems.edge.controller.io.channelsinglethreshold;version=snapshot,\ io.openems.edge.controller.io.fixdigitaloutput;version=snapshot,\ + io.openems.edge.controller.io.heating.room;version=snapshot,\ io.openems.edge.controller.io.heatingelement;version=snapshot,\ io.openems.edge.controller.io.heatpump.sgready;version=snapshot,\ io.openems.edge.controller.pvinverter.fixpowerlimit;version=snapshot,\ @@ -321,6 +324,7 @@ io.openems.edge.io.offgridswitch;version=snapshot,\ io.openems.edge.io.revpi;version=snapshot,\ io.openems.edge.io.shelly;version=snapshot,\ + io.openems.edge.io.siemenslogo;version=snapshot,\ io.openems.edge.io.wago;version=snapshot,\ io.openems.edge.io.weidmueller;version=snapshot,\ io.openems.edge.kaco.blueplanet.hybrid10;version=snapshot,\ @@ -412,7 +416,7 @@ 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.7.4,3.7.5)',\ - org.apache.felix.http.jetty;version='[5.1.26,5.1.27)',\ + org.apache.felix.http.jetty;version='[5.1.28,5.1.29)',\ org.apache.felix.http.servlet-api;version='[3.0.0,3.0.1)',\ org.apache.felix.inventory;version='[2.0.0,2.0.1)',\ org.apache.felix.metatype;version='[1.2.4,1.2.5)',\ @@ -424,13 +428,13 @@ 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='[2.1.0,2.1.1)',\ + org.jetbrains.kotlin.osgi-bundle;version='[2.1.10,2.1.11)',\ org.jsoup;version='[1.18.3,1.18.4)',\ org.jsr-305;version='[3.0.2,3.0.3)',\ org.openmuc.jmbus;version='[3.3.0,3.3.1)',\ org.openmuc.jrxtx;version='[1.0.1,1.0.2)',\ - org.ops4j.pax.logging.pax-logging-api;version='[2.2.7,2.2.8)',\ - org.ops4j.pax.logging.pax-logging-log4j2;version='[2.2.7,2.2.8)',\ + org.ops4j.pax.logging.pax-logging-api;version='[2.2.8,2.2.9)',\ + org.ops4j.pax.logging.pax-logging-log4j2;version='[2.2.8,2.2.9)',\ org.osgi.service.component;version='[1.5.1,1.5.2)',\ org.osgi.util.function;version='[1.2.0,1.2.1)',\ org.osgi.util.promise;version='[1.3.0,1.3.1)',\ diff --git a/io.openems.edge.battery.api/src/io/openems/edge/battery/protection/currenthandler/AbstractMaxCurrentHandler.java b/io.openems.edge.battery.api/src/io/openems/edge/battery/protection/currenthandler/AbstractMaxCurrentHandler.java index e5406842d18..6e5793685df 100644 --- a/io.openems.edge.battery.api/src/io/openems/edge/battery/protection/currenthandler/AbstractMaxCurrentHandler.java +++ b/io.openems.edge.battery.api/src/io/openems/edge/battery/protection/currenthandler/AbstractMaxCurrentHandler.java @@ -422,19 +422,16 @@ protected Double getForceCurrent(Integer minCellVoltage, Integer maxCellVoltage) } // Evaluate force charge/discharge current from current state - switch (state) { - case UNDEFINED: - case WAIT_FOR_FORCE_MODE: - return null; - case FORCE_MODE: + return switch (state) { + case UNDEFINED, WAIT_FOR_FORCE_MODE // + -> null; + case FORCE_MODE -> // TODO Plan is making the value adaptive, i.e. start with 1 A; if voltage still // decreases, then slowly increase force charge current. - return -2.; - case BLOCK_MODE: - return 0.; - } - // will never happen - return null; + -2.; + case BLOCK_MODE // + -> 0.; + }; } /** diff --git a/io.openems.edge.battery.api/src/io/openems/edge/battery/protection/force/AbstractForceChargeDischarge.java b/io.openems.edge.battery.api/src/io/openems/edge/battery/protection/force/AbstractForceChargeDischarge.java index 9c9c4282b86..f7100c6b41d 100644 --- a/io.openems.edge.battery.api/src/io/openems/edge/battery/protection/force/AbstractForceChargeDischarge.java +++ b/io.openems.edge.battery.api/src/io/openems/edge/battery/protection/force/AbstractForceChargeDischarge.java @@ -74,51 +74,43 @@ public AbstractForceChargeDischarge() { @Override public StateHandler getStateHandler(State state) { - switch (state) { - case UNDEFINED: - return new StateHandler<>() { - @Override - protected State runAndGetNextState(Context context) throws OpenemsNamedException { - return AbstractForceChargeDischarge.this.handleUndefinedState(context.minCellVoltage, - context.maxCellVoltage); - } - }; - - case WAIT_FOR_FORCE_MODE: - return new StateHandler<>() { - private Instant enteredAt = Instant.MAX; - - @Override - protected void onEntry(Context context) throws OpenemsNamedException { - this.enteredAt = context.now(); - } - - @Override - protected State runAndGetNextState(Context context) throws OpenemsNamedException { - return AbstractForceChargeDischarge.this.handleWaitForForceModeState(context.minCellVoltage, - context.maxCellVoltage, Duration.between(this.enteredAt, context.now())); - } - }; - - case FORCE_MODE: - return new StateHandler<>() { - @Override - protected State runAndGetNextState(Context context) throws OpenemsNamedException { - return AbstractForceChargeDischarge.this.handleForceModeState(context.minCellVoltage, - context.maxCellVoltage); - } - }; - - case BLOCK_MODE: - return new StateHandler<>() { - @Override - protected State runAndGetNextState(Context context) throws OpenemsNamedException { - return AbstractForceChargeDischarge.this.handleBlockModeState(context.minCellVoltage, - context.maxCellVoltage); - } - }; - } - throw new IllegalArgumentException("Unknown State [" + state + "]"); + return switch (state) { + case UNDEFINED -> new StateHandler<>() { + @Override + protected State runAndGetNextState(Context context) throws OpenemsNamedException { + return AbstractForceChargeDischarge.this.handleUndefinedState(context.minCellVoltage, + context.maxCellVoltage); + } + }; + case WAIT_FOR_FORCE_MODE -> new StateHandler<>() { + private Instant enteredAt = Instant.MAX; + + @Override + protected void onEntry(Context context) throws OpenemsNamedException { + this.enteredAt = context.now(); + } + + @Override + protected State runAndGetNextState(Context context) throws OpenemsNamedException { + return AbstractForceChargeDischarge.this.handleWaitForForceModeState(context.minCellVoltage, + context.maxCellVoltage, Duration.between(this.enteredAt, context.now())); + } + }; + case FORCE_MODE -> new StateHandler<>() { + @Override + protected State runAndGetNextState(Context context) throws OpenemsNamedException { + return AbstractForceChargeDischarge.this.handleForceModeState(context.minCellVoltage, + context.maxCellVoltage); + } + }; + case BLOCK_MODE -> new StateHandler<>() { + @Override + protected State runAndGetNextState(Context context) throws OpenemsNamedException { + return AbstractForceChargeDischarge.this.handleBlockModeState(context.minCellVoltage, + context.maxCellVoltage); + } + }; + }; } protected abstract State handleUndefinedState(int minCellVoltage, int maxCellVoltage); diff --git a/io.openems.edge.battery.bmw/src/io/openems/edge/battery/bmw/statemachine/StateMachine.java b/io.openems.edge.battery.bmw/src/io/openems/edge/battery/bmw/statemachine/StateMachine.java index d0e027ebc25..648baf28665 100644 --- a/io.openems.edge.battery.bmw/src/io/openems/edge/battery/bmw/statemachine/StateMachine.java +++ b/io.openems.edge.battery.bmw/src/io/openems/edge/battery/bmw/statemachine/StateMachine.java @@ -51,20 +51,13 @@ public StateMachine(State initialState) { @Override public StateHandler getStateHandler(State state) { - switch (state) { - case UNDEFINED: - return new UndefinedHandler(); - case GO_RUNNING: - return new GoRunningHandler(); - case RUNNING: - return new RunningHandler(); - case GO_STOPPED: - return new GoStoppedHandler(); - case STOPPED: - return new StoppedHandler(); - case ERROR: - return new ErrorHandler(); - } - throw new IllegalArgumentException("Unknown State [" + state + "]"); + return switch (state) { + case UNDEFINED -> new UndefinedHandler(); + case GO_RUNNING -> new GoRunningHandler(); + case RUNNING -> new RunningHandler(); + case GO_STOPPED -> new GoStoppedHandler(); + case STOPPED -> new StoppedHandler(); + case ERROR -> new ErrorHandler(); + }; } } \ No newline at end of file diff --git a/io.openems.edge.battery.bydcommercial/src/io/openems/edge/battery/bydcommercial/BydBatteryBoxCommercialC130Impl.java b/io.openems.edge.battery.bydcommercial/src/io/openems/edge/battery/bydcommercial/BydBatteryBoxCommercialC130Impl.java index b838288b319..865326e9ce6 100644 --- a/io.openems.edge.battery.bydcommercial/src/io/openems/edge/battery/bydcommercial/BydBatteryBoxCommercialC130Impl.java +++ b/io.openems.edge.battery.bydcommercial/src/io/openems/edge/battery/bydcommercial/BydBatteryBoxCommercialC130Impl.java @@ -928,22 +928,11 @@ public void setStartStop(StartStop value) { @Override public StartStop getStartStopTarget() { - switch (this.config.startStop()) { - case AUTO: - // read StartStop-Channel - return this.startStopTarget.get(); - - case START: - // force START - return StartStop.START; - - case STOP: - // force STOP - return StartStop.STOP; - } - - assert false; - return StartStop.UNDEFINED; // can never happen + return switch (this.config.startStop()) { + case AUTO -> this.startStopTarget.get(); // read StartStop-Channel + case START -> StartStop.START; // force START + case STOP -> StartStop.STOP; // force STOP + }; } /* diff --git a/io.openems.edge.battery.bydcommercial/src/io/openems/edge/battery/bydcommercial/statemachine/StateMachine.java b/io.openems.edge.battery.bydcommercial/src/io/openems/edge/battery/bydcommercial/statemachine/StateMachine.java index 929bf195f56..d2b1bf5ab5b 100644 --- a/io.openems.edge.battery.bydcommercial/src/io/openems/edge/battery/bydcommercial/statemachine/StateMachine.java +++ b/io.openems.edge.battery.bydcommercial/src/io/openems/edge/battery/bydcommercial/statemachine/StateMachine.java @@ -51,20 +51,13 @@ public StateMachine(State initialState) { @Override public StateHandler getStateHandler(State state) { - switch (state) { - case UNDEFINED: - return new UndefinedHandler(); - case GO_RUNNING: - return new GoRunningHandler(); - case RUNNING: - return new RunningHandler(); - case GO_STOPPED: - return new GoStoppedHandler(); - case STOPPED: - return new StoppedHandler(); - case ERROR: - return new ErrorHandler(); - } - throw new IllegalArgumentException("Unknown State [" + state + "]"); + return switch (state) { + case UNDEFINED -> new UndefinedHandler(); + case GO_RUNNING -> new GoRunningHandler(); + case RUNNING -> new RunningHandler(); + case GO_STOPPED -> new GoStoppedHandler(); + case STOPPED -> new StoppedHandler(); + case ERROR -> new ErrorHandler(); + }; } } diff --git a/io.openems.edge.battery.bydcommercial/src/io/openems/edge/battery/bydcommercial/statemachine/UndefinedHandler.java b/io.openems.edge.battery.bydcommercial/src/io/openems/edge/battery/bydcommercial/statemachine/UndefinedHandler.java index a6524f535d2..83150414f11 100644 --- a/io.openems.edge.battery.bydcommercial/src/io/openems/edge/battery/bydcommercial/statemachine/UndefinedHandler.java +++ b/io.openems.edge.battery.bydcommercial/src/io/openems/edge/battery/bydcommercial/statemachine/UndefinedHandler.java @@ -9,28 +9,20 @@ public class UndefinedHandler extends StateHandler { public State runAndGetNextState(Context context) { var battery = context.getParent(); - switch (battery.getStartStopTarget()) { - case UNDEFINED: - // Stuck in UNDEFINED State - return State.UNDEFINED; - - case START: - // force START - if (battery.hasFaults()) { - // Has Faults -> error handling - return State.ERROR; - } else { - // No Faults -> start - return State.GO_RUNNING; - } - - case STOP: - // force STOP - return State.GO_STOPPED; - } - - assert false; - return State.UNDEFINED; // can never happen + return switch (battery.getStartStopTarget()) { + case UNDEFINED // Stuck in UNDEFINED State + -> State.UNDEFINED; + + case START // force START + -> battery.hasFaults() // + // Has Faults -> error handling + ? State.ERROR + // No Faults -> start + : State.GO_RUNNING; + + case STOP // force STOP + -> State.GO_STOPPED; + }; } } diff --git a/io.openems.edge.battery.fenecon.commercial/src/io/openems/edge/battery/fenecon/commercial/BatteryFeneconCommercialImpl.java b/io.openems.edge.battery.fenecon.commercial/src/io/openems/edge/battery/fenecon/commercial/BatteryFeneconCommercialImpl.java index 869077dbe64..16aa7e05552 100644 --- a/io.openems.edge.battery.fenecon.commercial/src/io/openems/edge/battery/fenecon/commercial/BatteryFeneconCommercialImpl.java +++ b/io.openems.edge.battery.fenecon.commercial/src/io/openems/edge/battery/fenecon/commercial/BatteryFeneconCommercialImpl.java @@ -1303,21 +1303,10 @@ public void setStartStop(StartStop value) { @Override public StartStop getStartStopTarget() { - switch (this.config.startStop()) { - case AUTO: - // read StartStop-Channel - return this.startStopTarget.get(); - - case START: - // force START - return StartStop.START; - - case STOP: - // force STOP - return StartStop.STOP; - } - - assert false; - return StartStop.UNDEFINED; // can never happen + return switch (this.config.startStop()) { + case AUTO -> this.startStopTarget.get(); // read StartStop-Channel + case START -> StartStop.START; // force START + case STOP -> StartStop.STOP; // force STOP + }; } } diff --git a/io.openems.edge.battery.fenecon.commercial/src/io/openems/edge/battery/fenecon/commercial/IgnoreZeroConverter.java b/io.openems.edge.battery.fenecon.commercial/src/io/openems/edge/battery/fenecon/commercial/IgnoreZeroConverter.java index b1ae6528904..5467953f365 100644 --- a/io.openems.edge.battery.fenecon.commercial/src/io/openems/edge/battery/fenecon/commercial/IgnoreZeroConverter.java +++ b/io.openems.edge.battery.fenecon.commercial/src/io/openems/edge/battery/fenecon/commercial/IgnoreZeroConverter.java @@ -36,10 +36,10 @@ private IgnoreZeroConverter(BatteryFeneconCommercialImpl parent) { return null; } // If the battery is not started and the value is not zero -> return the value, - if (value instanceof Integer && (Integer) value != 0) { + if (value instanceof Integer i && i != 0) { return value; } - if (value instanceof Long && (Long) value != 0L) { + if (value instanceof Long l && l != 0L) { return value; } // Is battery status not available or battery not started? diff --git a/io.openems.edge.battery.fenecon.commercial/src/io/openems/edge/battery/fenecon/commercial/statemachine/StateMachine.java b/io.openems.edge.battery.fenecon.commercial/src/io/openems/edge/battery/fenecon/commercial/statemachine/StateMachine.java index 010ee574776..f6775bb8bcc 100644 --- a/io.openems.edge.battery.fenecon.commercial/src/io/openems/edge/battery/fenecon/commercial/statemachine/StateMachine.java +++ b/io.openems.edge.battery.fenecon.commercial/src/io/openems/edge/battery/fenecon/commercial/statemachine/StateMachine.java @@ -54,20 +54,13 @@ public StateMachine(State initialState) { @Override public StateHandler getStateHandler(State state) { - switch (state) { - case UNDEFINED: - return new UndefinedHandler(); - case GO_RUNNING: - return new GoRunningHandler(); - case RUNNING: - return new RunningHandler(); - case GO_STOPPED: - return new GoStoppedHandler(); - case STOPPED: - return new StoppedHandler(); - case ERROR: - return new ErrorHandler(); - } - throw new IllegalArgumentException("Unknown State [" + state + "]"); + return switch (state) { + case UNDEFINED -> new UndefinedHandler(); + case GO_RUNNING -> new GoRunningHandler(); + case RUNNING -> new RunningHandler(); + case GO_STOPPED -> new GoStoppedHandler(); + case STOPPED -> new StoppedHandler(); + case ERROR -> new ErrorHandler(); + }; } } \ No newline at end of file diff --git a/io.openems.edge.battery.fenecon.commercial/src/io/openems/edge/battery/fenecon/commercial/statemachine/UndefinedHandler.java b/io.openems.edge.battery.fenecon.commercial/src/io/openems/edge/battery/fenecon/commercial/statemachine/UndefinedHandler.java index 1c08a0b67f2..085b9f5f30f 100644 --- a/io.openems.edge.battery.fenecon.commercial/src/io/openems/edge/battery/fenecon/commercial/statemachine/UndefinedHandler.java +++ b/io.openems.edge.battery.fenecon.commercial/src/io/openems/edge/battery/fenecon/commercial/statemachine/UndefinedHandler.java @@ -8,28 +8,20 @@ public class UndefinedHandler extends StateHandler { @Override public State runAndGetNextState(Context context) { var battery = context.getParent(); - switch (battery.getStartStopTarget()) { - case UNDEFINED: - // Stuck in UNDEFINED State - return State.UNDEFINED; + return switch (battery.getStartStopTarget()) { + case UNDEFINED // Stuck in UNDEFINED State + -> State.UNDEFINED; - case START: - // force START - if (battery.hasFaults()) { - // Has Faults -> error handling - return State.ERROR; - } else { - // No Faults -> start - return State.GO_RUNNING; - } + case START // force START + -> battery.hasFaults() // + // Has Faults -> error handling + ? State.ERROR + // No Faults -> start + : State.GO_RUNNING; - case STOP: - // force STOP - return State.GO_STOPPED; - } - - assert false; - return State.UNDEFINED; // can never happen + case STOP // force STOP + -> State.GO_STOPPED; + }; } } diff --git a/io.openems.edge.battery.fenecon.commercial/test/io/openems/edge/battery/fenecon/commercial/BatteryFeneconCommercialImplTest.java b/io.openems.edge.battery.fenecon.commercial/test/io/openems/edge/battery/fenecon/commercial/BatteryFeneconCommercialImplTest.java index 8fec9839f16..17038a5c183 100644 --- a/io.openems.edge.battery.fenecon.commercial/test/io/openems/edge/battery/fenecon/commercial/BatteryFeneconCommercialImplTest.java +++ b/io.openems.edge.battery.fenecon.commercial/test/io/openems/edge/battery/fenecon/commercial/BatteryFeneconCommercialImplTest.java @@ -1,5 +1,6 @@ package io.openems.edge.battery.fenecon.commercial; +import static io.openems.common.test.TestUtils.createDummyClock; import static io.openems.edge.battery.api.Battery.ChannelId.CHARGE_MAX_CURRENT; import static io.openems.edge.battery.api.Battery.ChannelId.DISCHARGE_MAX_CURRENT; import static io.openems.edge.battery.api.Battery.ChannelId.SOC; @@ -7,7 +8,6 @@ import static io.openems.edge.battery.fenecon.commercial.BatteryFeneconCommercial.ChannelId.RUNNING; import static io.openems.edge.battery.fenecon.commercial.BatteryFeneconCommercial.ChannelId.STATE_MACHINE; import static io.openems.edge.common.startstop.StartStoppable.ChannelId.START_STOP; -import static io.openems.edge.common.test.TestUtils.createDummyClock; import static io.openems.edge.io.test.DummyInputOutput.ChannelId.INPUT_OUTPUT7; import org.junit.Test; diff --git a/io.openems.edge.battery.fenecon.home/src/io/openems/edge/battery/fenecon/home/BatteryFeneconHomeImpl.java b/io.openems.edge.battery.fenecon.home/src/io/openems/edge/battery/fenecon/home/BatteryFeneconHomeImpl.java index 3130b3ba4fc..b5cbecfad37 100644 --- a/io.openems.edge.battery.fenecon.home/src/io/openems/edge/battery/fenecon/home/BatteryFeneconHomeImpl.java +++ b/io.openems.edge.battery.fenecon.home/src/io/openems/edge/battery/fenecon/home/BatteryFeneconHomeImpl.java @@ -812,7 +812,7 @@ private synchronized void initializeTowerModulesChannels(int numberOfTowers, int // Create Voltage Channel var channelId = new ChannelIdImpl(// generateSingleCellPrefix(tower, module, cell) + "_VOLTAGE", - Doc.of(OpenemsType.INTEGER).unit(Unit.VOLT)); + Doc.of(OpenemsType.INTEGER).unit(Unit.MILLIVOLT)); this.addChannel(channelId); // Create Modbus-Mapping for Voltages diff --git a/io.openems.edge.battery.fenecon.home/test/io/openems/edge/battery/fenecon/home/BatteryFeneconHomeImplTest.java b/io.openems.edge.battery.fenecon.home/test/io/openems/edge/battery/fenecon/home/BatteryFeneconHomeImplTest.java index b0029262635..77062d93093 100644 --- a/io.openems.edge.battery.fenecon.home/test/io/openems/edge/battery/fenecon/home/BatteryFeneconHomeImplTest.java +++ b/io.openems.edge.battery.fenecon.home/test/io/openems/edge/battery/fenecon/home/BatteryFeneconHomeImplTest.java @@ -1,5 +1,6 @@ package io.openems.edge.battery.fenecon.home; +import static io.openems.common.test.TestUtils.createDummyClock; import static io.openems.edge.battery.api.Battery.ChannelId.CHARGE_MAX_CURRENT; import static io.openems.edge.battery.api.Battery.ChannelId.CURRENT; import static io.openems.edge.battery.api.Battery.ChannelId.MAX_CELL_VOLTAGE; @@ -22,7 +23,6 @@ import static io.openems.edge.battery.protection.BatteryProtection.ChannelId.BP_CHARGE_BMS; import static io.openems.edge.battery.protection.BatteryProtection.ChannelId.BP_CHARGE_MAX_SOC; import static io.openems.edge.bridge.modbus.api.ModbusComponent.ChannelId.MODBUS_COMMUNICATION_FAILED; -import static io.openems.edge.common.test.TestUtils.createDummyClock; import static io.openems.edge.io.test.DummyInputOutput.ChannelId.INPUT_OUTPUT4; import static java.lang.Math.round; import static java.time.temporal.ChronoUnit.SECONDS; diff --git a/io.openems.edge.battery.soltaro/src/io/openems/edge/battery/soltaro/cluster/versionb/SingleRack.java b/io.openems.edge.battery.soltaro/src/io/openems/edge/battery/soltaro/cluster/versionb/SingleRack.java index 02835194b33..e5d4529f972 100644 --- a/io.openems.edge.battery.soltaro/src/io/openems/edge/battery/soltaro/cluster/versionb/SingleRack.java +++ b/io.openems.edge.battery.soltaro/src/io/openems/edge/battery/soltaro/cluster/versionb/SingleRack.java @@ -1,5 +1,14 @@ package io.openems.edge.battery.soltaro.cluster.versionb; +import static io.openems.common.channel.AccessMode.READ_WRITE; +import static io.openems.common.channel.Level.OK; +import static io.openems.common.channel.Level.WARNING; +import static io.openems.common.channel.Unit.DEZIDEGREE_CELSIUS; +import static io.openems.common.channel.Unit.MILLIAMPERE; +import static io.openems.common.channel.Unit.MILLIVOLT; +import static io.openems.common.channel.Unit.NONE; +import static io.openems.common.channel.Unit.PERCENT; +import static io.openems.common.types.OpenemsType.INTEGER; import static io.openems.edge.bridge.modbus.api.ElementToChannelConverter.SCALE_FACTOR_2; import static io.openems.edge.bridge.modbus.api.ElementToChannelConverter.SCALE_FACTOR_MINUS_1; @@ -9,10 +18,6 @@ import java.util.Map; import java.util.Optional; -import io.openems.common.channel.AccessMode; -import io.openems.common.channel.Level; -import io.openems.common.channel.Unit; -import io.openems.common.types.OpenemsType; import io.openems.edge.battery.soltaro.common.enums.ChargeIndication; import io.openems.edge.bridge.modbus.api.AbstractOpenemsModbusComponent; import io.openems.edge.bridge.modbus.api.element.BitsWordElement; @@ -426,104 +431,102 @@ private Map> createChannelMap() { private Map createChannelIdMap() { Map map = new HashMap<>(); - this.addEntry(map, KEY_VOLTAGE, new IntegerDoc().unit(Unit.MILLIVOLT)); - this.addEntry(map, KEY_CURRENT, new IntegerDoc().unit(Unit.MILLIAMPERE)); + this.addEntry(map, KEY_VOLTAGE, new IntegerDoc().unit(MILLIVOLT)); + this.addEntry(map, KEY_CURRENT, new IntegerDoc().unit(MILLIAMPERE)); this.addEntry(map, KEY_CHARGE_INDICATION, Doc.of(ChargeIndication.values())); - this.addEntry(map, KEY_SOC, new IntegerDoc().unit(Unit.PERCENT)); - this.addEntry(map, KEY_SOH, new IntegerDoc().unit(Unit.PERCENT)); - this.addEntry(map, KEY_MAX_CELL_VOLTAGE_ID, new IntegerDoc().unit(Unit.NONE)); - this.addEntry(map, KEY_MAX_CELL_VOLTAGE, new IntegerDoc().unit(Unit.MILLIVOLT)); - this.addEntry(map, KEY_MIN_CELL_VOLTAGE_ID, new IntegerDoc().unit(Unit.NONE)); - this.addEntry(map, KEY_MIN_CELL_VOLTAGE, new IntegerDoc().unit(Unit.MILLIVOLT)); - this.addEntry(map, KEY_MAX_CELL_TEMPERATURE_ID, new IntegerDoc().unit(Unit.NONE)); - this.addEntry(map, KEY_MAX_CELL_TEMPERATURE, new IntegerDoc().unit(Unit.DEZIDEGREE_CELSIUS)); - this.addEntry(map, KEY_MIN_CELL_TEMPERATURE_ID, new IntegerDoc().unit(Unit.NONE)); - this.addEntry(map, KEY_MIN_CELL_TEMPERATURE, new IntegerDoc().unit(Unit.DEZIDEGREE_CELSIUS)); - this.addEntry(map, KEY_ALARM_LEVEL_2_CELL_DISCHA_TEMP_LOW, Doc.of(Level.WARNING) + this.addEntry(map, KEY_SOC, new IntegerDoc().unit(PERCENT)); + this.addEntry(map, KEY_SOH, new IntegerDoc().unit(PERCENT)); + this.addEntry(map, KEY_MAX_CELL_VOLTAGE_ID, new IntegerDoc().unit(NONE)); + this.addEntry(map, KEY_MAX_CELL_VOLTAGE, new IntegerDoc().unit(MILLIVOLT)); + this.addEntry(map, KEY_MIN_CELL_VOLTAGE_ID, new IntegerDoc().unit(NONE)); + this.addEntry(map, KEY_MIN_CELL_VOLTAGE, new IntegerDoc().unit(MILLIVOLT)); + this.addEntry(map, KEY_MAX_CELL_TEMPERATURE_ID, new IntegerDoc().unit(NONE)); + this.addEntry(map, KEY_MAX_CELL_TEMPERATURE, new IntegerDoc().unit(DEZIDEGREE_CELSIUS)); + this.addEntry(map, KEY_MIN_CELL_TEMPERATURE_ID, new IntegerDoc().unit(NONE)); + this.addEntry(map, KEY_MIN_CELL_TEMPERATURE, new IntegerDoc().unit(DEZIDEGREE_CELSIUS)); + this.addEntry(map, KEY_ALARM_LEVEL_2_CELL_DISCHA_TEMP_LOW, Doc.of(WARNING) .text("Rack" + this.rackNumber + " Cell Discharge Temperature Low Alarm Level 2")); /* Bit 15 */ - this.addEntry(map, KEY_ALARM_LEVEL_2_CELL_DISCHA_TEMP_HIGH, Doc.of(Level.WARNING) + this.addEntry(map, KEY_ALARM_LEVEL_2_CELL_DISCHA_TEMP_HIGH, Doc.of(WARNING) .text("Rack" + this.rackNumber + " Cell Discharge Temperature High Alarm Level 2")); /* Bit 14 */ this.addEntry(map, KEY_ALARM_LEVEL_2_GR_TEMPERATURE_HIGH, - Doc.of(Level.WARNING).text("Rack" + this.rackNumber + " GR Temperature High Alarm Level 2")); /* Bit 10 */ - this.addEntry(map, KEY_ALARM_LEVEL_2_CELL_CHA_TEMP_LOW, Doc.of(Level.WARNING) + Doc.of(WARNING).text("Rack" + this.rackNumber + " GR Temperature High Alarm Level 2")); /* Bit 10 */ + this.addEntry(map, KEY_ALARM_LEVEL_2_CELL_CHA_TEMP_LOW, Doc.of(WARNING) .text("Rack" + this.rackNumber + " Cell Charge Temperature Low Alarm Level 2")); /* Bit 7 */ - this.addEntry(map, KEY_ALARM_LEVEL_2_CELL_CHA_TEMP_HIGH, Doc.of(Level.WARNING) + this.addEntry(map, KEY_ALARM_LEVEL_2_CELL_CHA_TEMP_HIGH, Doc.of(WARNING) .text("Rack" + this.rackNumber + " Cell Charge Temperature High Alarm Level 2")); /* Bit 6 */ - this.addEntry(map, KEY_ALARM_LEVEL_2_DISCHA_CURRENT_HIGH, Doc.of(Level.WARNING) - .text("Rack" + this.rackNumber + " Discharge Current High Alarm Level 2")); /* Bit 5 */ + this.addEntry(map, KEY_ALARM_LEVEL_2_DISCHA_CURRENT_HIGH, + Doc.of(WARNING).text("Rack" + this.rackNumber + " Discharge Current High Alarm Level 2")); /* Bit 5 */ this.addEntry(map, KEY_ALARM_LEVEL_2_TOTAL_VOLTAGE_LOW, - Doc.of(Level.WARNING).text("Rack" + this.rackNumber + " Total Voltage Low Alarm Level 2")); /* Bit 4 */ + Doc.of(WARNING).text("Rack" + this.rackNumber + " Total Voltage Low Alarm Level 2")); /* Bit 4 */ this.addEntry(map, KEY_ALARM_LEVEL_2_CELL_VOLTAGE_LOW, - Doc.of(Level.WARNING).text("Cluster 1 Cell Voltage Low Alarm Level 2")); /* Bit 3 */ + Doc.of(WARNING).text("Cluster 1 Cell Voltage Low Alarm Level 2")); /* Bit 3 */ this.addEntry(map, KEY_ALARM_LEVEL_2_CHA_CURRENT_HIGH, - Doc.of(Level.WARNING).text("Rack" + this.rackNumber + " Charge Current High Alarm Level 2")); /* Bit 2 */ + Doc.of(WARNING).text("Rack" + this.rackNumber + " Charge Current High Alarm Level 2")); /* Bit 2 */ this.addEntry(map, KEY_ALARM_LEVEL_2_TOTAL_VOLTAGE_HIGH, - Doc.of(Level.WARNING).text("Rack" + this.rackNumber + " Total Voltage High Alarm Level 2")); /* Bit 1 */ + Doc.of(WARNING).text("Rack" + this.rackNumber + " Total Voltage High Alarm Level 2")); /* Bit 1 */ this.addEntry(map, KEY_ALARM_LEVEL_2_CELL_VOLTAGE_HIGH, - Doc.of(Level.WARNING).text("Rack" + this.rackNumber + " Cell Voltage High Alarm Level 2")); /* Bit 0 */ - this.addEntry(map, KEY_ALARM_LEVEL_1_CELL_DISCHA_TEMP_LOW, Doc.of(Level.WARNING) + Doc.of(WARNING).text("Rack" + this.rackNumber + " Cell Voltage High Alarm Level 2")); /* Bit 0 */ + this.addEntry(map, KEY_ALARM_LEVEL_1_CELL_DISCHA_TEMP_LOW, Doc.of(WARNING) .text("Rack" + this.rackNumber + " Cell Discharge Temperature Low Alarm Level 1")); /* Bit 15 */ - this.addEntry(map, KEY_ALARM_LEVEL_1_CELL_DISCHA_TEMP_HIGH, Doc.of(Level.WARNING) + this.addEntry(map, KEY_ALARM_LEVEL_1_CELL_DISCHA_TEMP_HIGH, Doc.of(WARNING) .text("Rack" + this.rackNumber + " Cell Discharge Temperature High Alarm Level 1")); /* Bit 14 */ - this.addEntry(map, KEY_ALARM_LEVEL_1_TOTAL_VOLTAGE_DIFF_HIGH, Doc.of(Level.WARNING) - .text("Rack" + this.rackNumber + " Total Voltage Diff High Alarm Level 1")); /* Bit 13 */ - this.addEntry(map, KEY_ALARM_LEVEL_1_CELL_VOLTAGE_DIFF_HIGH, Doc.of(Level.WARNING) - .text("Rack" + this.rackNumber + " Cell Voltage Diff High Alarm Level 1")); /* Bit 11 */ - this.addEntry(map, KEY_ALARM_LEVEL_1_GR_TEMPERATURE_HIGH, Doc.of(Level.WARNING) - .text("Rack" + this.rackNumber + " GR Temperature High Alarm Level 1")); /* Bit 10 */ - this.addEntry(map, KEY_ALARM_LEVEL_1_CELL_TEMP_DIFF_HIGH, Doc.of(Level.WARNING) + this.addEntry(map, KEY_ALARM_LEVEL_1_TOTAL_VOLTAGE_DIFF_HIGH, + Doc.of(WARNING).text("Rack" + this.rackNumber + " Total Voltage Diff High Alarm Level 1")); /* Bit 13 */ + this.addEntry(map, KEY_ALARM_LEVEL_1_CELL_VOLTAGE_DIFF_HIGH, + Doc.of(WARNING).text("Rack" + this.rackNumber + " Cell Voltage Diff High Alarm Level 1")); /* Bit 11 */ + this.addEntry(map, KEY_ALARM_LEVEL_1_GR_TEMPERATURE_HIGH, + Doc.of(WARNING).text("Rack" + this.rackNumber + " GR Temperature High Alarm Level 1")); /* Bit 10 */ + this.addEntry(map, KEY_ALARM_LEVEL_1_CELL_TEMP_DIFF_HIGH, Doc.of(WARNING) .text("Rack" + this.rackNumber + " Cell temperature Diff High Alarm Level 1")); /* Bit 9 */ this.addEntry(map, KEY_ALARM_LEVEL_1_SOC_LOW, - Doc.of(Level.WARNING).text("Rack" + this.rackNumber + " SOC Low Alarm Level 1")); /* Bit 8 */ - this.addEntry(map, KEY_ALARM_LEVEL_1_CELL_CHA_TEMP_LOW, Doc.of(Level.WARNING) + Doc.of(WARNING).text("Rack" + this.rackNumber + " SOC Low Alarm Level 1")); /* Bit 8 */ + this.addEntry(map, KEY_ALARM_LEVEL_1_CELL_CHA_TEMP_LOW, Doc.of(WARNING) .text("Rack" + this.rackNumber + " Cell Charge Temperature Low Alarm Level 1")); /* Bit 7 */ - this.addEntry(map, KEY_ALARM_LEVEL_1_CELL_CHA_TEMP_HIGH, Doc.of(Level.WARNING) + this.addEntry(map, KEY_ALARM_LEVEL_1_CELL_CHA_TEMP_HIGH, Doc.of(WARNING) .text("Rack" + this.rackNumber + " Cell Charge Temperature High Alarm Level 1")); /* Bit 6 */ - this.addEntry(map, KEY_ALARM_LEVEL_1_DISCHA_CURRENT_HIGH, Doc.of(Level.WARNING) - .text("Rack" + this.rackNumber + " Discharge Current High Alarm Level 1")); /* Bit 5 */ + this.addEntry(map, KEY_ALARM_LEVEL_1_DISCHA_CURRENT_HIGH, + Doc.of(WARNING).text("Rack" + this.rackNumber + " Discharge Current High Alarm Level 1")); /* Bit 5 */ this.addEntry(map, KEY_ALARM_LEVEL_1_TOTAL_VOLTAGE_LOW, - Doc.of(Level.WARNING).text("Rack" + this.rackNumber + " Total Voltage Low Alarm Level 1")); /* Bit 4 */ + Doc.of(WARNING).text("Rack" + this.rackNumber + " Total Voltage Low Alarm Level 1")); /* Bit 4 */ this.addEntry(map, KEY_ALARM_LEVEL_1_CELL_VOLTAGE_LOW, - Doc.of(Level.WARNING).text("Rack" + this.rackNumber + " Cell Voltage Low Alarm Level 1")); /* Bit 3 */ - this.addEntry(map, KEY_ALARM_LEVEL_1_CHA_CURRENT_HIGH, Doc.of(Level.WARNING) - .text("Rack" + this.rackNumber + " Charge Current High Alarm Level 1")); /* Bit 2 */ + Doc.of(WARNING).text("Rack" + this.rackNumber + " Cell Voltage Low Alarm Level 1")); /* Bit 3 */ + this.addEntry(map, KEY_ALARM_LEVEL_1_CHA_CURRENT_HIGH, + Doc.of(WARNING).text("Rack" + this.rackNumber + " Charge Current High Alarm Level 1")); /* Bit 2 */ this.addEntry(map, KEY_ALARM_LEVEL_1_TOTAL_VOLTAGE_HIGH, - Doc.of(Level.WARNING).text("Rack" + this.rackNumber + " Total Voltage High Alarm Level 1")); /* Bit 1 */ + Doc.of(WARNING).text("Rack" + this.rackNumber + " Total Voltage High Alarm Level 1")); /* Bit 1 */ this.addEntry(map, KEY_ALARM_LEVEL_1_CELL_VOLTAGE_HIGH, - Doc.of(Level.WARNING).text("Rack" + this.rackNumber + " Cell Voltage High Alarm Level 1")); /* Bit 0 */ + Doc.of(WARNING).text("Rack" + this.rackNumber + " Cell Voltage High Alarm Level 1")); /* Bit 0 */ this.addEntry(map, KEY_RUN_STATE, Doc.of(Enums.ClusterRunState.values())); // - this.addEntry(map, KEY_FAILURE_INITIALIZATION, Doc.of(Level.WARNING).text("Initialization failure")); /* Bit */ - this.addEntry(map, KEY_FAILURE_EEPROM, Doc.of(Level.WARNING).text("EEPROM fault")); /* Bit 11 */ + this.addEntry(map, KEY_FAILURE_INITIALIZATION, Doc.of(WARNING).text("Initialization failure")); /* Bit */ + this.addEntry(map, KEY_FAILURE_EEPROM, Doc.of(WARNING).text("EEPROM fault")); /* Bit 11 */ this.addEntry(map, KEY_FAILURE_INTRANET_COMMUNICATION, - Doc.of(Level.WARNING).text("Internal communication fault")); /* Bit 10 */ + Doc.of(WARNING).text("Internal communication fault")); /* Bit 10 */ this.addEntry(map, KEY_FAILURE_TEMPERATURE_SENSOR_CABLE, - Doc.of(Level.WARNING).text("Temperature sensor cable fault")); /* Bit 9 */ - this.addEntry(map, KEY_FAILURE_BALANCING_MODULE, Doc.of(Level.OK).text("Balancing module fault")); /* Bit 8 */ - this.addEntry(map, KEY_FAILURE_TEMPERATURE_PCB, Doc.of(Level.WARNING).text("Temperature PCB error")); /* Bit 7 */ - this.addEntry(map, KEY_FAILURE_GR_TEMPERATURE, Doc.of(Level.WARNING).text("GR Temperature error")); /* Bit 6 */ - this.addEntry(map, KEY_FAILURE_TEMP_SENSOR, Doc.of(Level.WARNING).text("Temperature sensor fault")); /* Bit 5 */ - this.addEntry(map, KEY_FAILURE_TEMP_SAMPLING, - Doc.of(Level.WARNING).text("Temperature sampling fault")); /* Bit 4 */ - this.addEntry(map, KEY_FAILURE_VOLTAGE_SAMPLING, - Doc.of(Level.WARNING).text("Voltage sampling fault")); /* Bit 3 */ - this.addEntry(map, KEY_FAILURE_LTC6803, Doc.of(Level.WARNING).text("LTC6803 fault")); /* Bit 2 */ - this.addEntry(map, KEY_FAILURE_CONNECTOR_WIRE, Doc.of(Level.WARNING).text("connector wire fault")); /* Bit 1 */ - this.addEntry(map, KEY_FAILURE_SAMPLING_WIRE, Doc.of(Level.WARNING).text("sampling wire fault")); /* Bit 0 */ - this.addEntry(map, KEY_SLEEP, Doc.of(OpenemsType.INTEGER).accessMode(AccessMode.READ_WRITE)); - this.addEntry(map, KEY_RESET, Doc.of(OpenemsType.INTEGER).accessMode(AccessMode.READ_WRITE)); + Doc.of(WARNING).text("Temperature sensor cable fault")); /* Bit 9 */ + this.addEntry(map, KEY_FAILURE_BALANCING_MODULE, Doc.of(OK).text("Balancing module fault")); /* Bit 8 */ + this.addEntry(map, KEY_FAILURE_TEMPERATURE_PCB, Doc.of(WARNING).text("Temperature PCB error")); /* Bit 7 */ + this.addEntry(map, KEY_FAILURE_GR_TEMPERATURE, Doc.of(WARNING).text("GR Temperature error")); /* Bit 6 */ + this.addEntry(map, KEY_FAILURE_TEMP_SENSOR, Doc.of(WARNING).text("Temperature sensor fault")); /* Bit 5 */ + this.addEntry(map, KEY_FAILURE_TEMP_SAMPLING, Doc.of(WARNING).text("Temperature sampling fault")); /* Bit 4 */ + this.addEntry(map, KEY_FAILURE_VOLTAGE_SAMPLING, Doc.of(WARNING).text("Voltage sampling fault")); /* Bit 3 */ + this.addEntry(map, KEY_FAILURE_LTC6803, Doc.of(WARNING).text("LTC6803 fault")); /* Bit 2 */ + this.addEntry(map, KEY_FAILURE_CONNECTOR_WIRE, Doc.of(WARNING).text("connector wire fault")); /* Bit 1 */ + this.addEntry(map, KEY_FAILURE_SAMPLING_WIRE, Doc.of(WARNING).text("sampling wire fault")); /* Bit 0 */ + this.addEntry(map, KEY_SLEEP, Doc.of(INTEGER).accessMode(READ_WRITE)); + this.addEntry(map, KEY_RESET, Doc.of(INTEGER).accessMode(READ_WRITE)); // Cell voltages formatted like: "RACK_1_BATTERY_000_VOLTAGE" for (var i = 0; i < this.numberOfSlaves; i++) { for (var j = i * VOLTAGE_SENSORS_PER_MODULE; j < (i + 1) * VOLTAGE_SENSORS_PER_MODULE; j++) { var key = this.getSingleCellPrefix(j) + "_" + VOLTAGE; - this.addEntry(map, key, new IntegerDoc().unit(Unit.MILLIVOLT)); + this.addEntry(map, key, new IntegerDoc().unit(MILLIVOLT)); } } // Cell temperatures formatted like : "RACK_1_BATTERY_000_TEMPERATURE" for (var i = 0; i < this.numberOfSlaves; i++) { for (var j = i * TEMPERATURE_SENSORS_PER_MODULE; j < (i + 1) * TEMPERATURE_SENSORS_PER_MODULE; j++) { var key = this.getSingleCellPrefix(j) + "_" + TEMPERATURE; - this.addEntry(map, key, new IntegerDoc().unit(Unit.DEZIDEGREE_CELSIUS)); + this.addEntry(map, key, new IntegerDoc().unit(DEZIDEGREE_CELSIUS)); } } diff --git a/io.openems.edge.battery.soltaro/src/io/openems/edge/battery/soltaro/cluster/versionc/BatterySoltaroClusterVersionCImpl.java b/io.openems.edge.battery.soltaro/src/io/openems/edge/battery/soltaro/cluster/versionc/BatterySoltaroClusterVersionCImpl.java index 6b493c42f7a..324d01e6b0c 100644 --- a/io.openems.edge.battery.soltaro/src/io/openems/edge/battery/soltaro/cluster/versionc/BatterySoltaroClusterVersionCImpl.java +++ b/io.openems.edge.battery.soltaro/src/io/openems/edge/battery/soltaro/cluster/versionc/BatterySoltaroClusterVersionCImpl.java @@ -1057,22 +1057,10 @@ public void setStartStop(StartStop value) { @Override public StartStop getStartStopTarget() { - switch (this.config.startStop()) { - case AUTO: - // read StartStop-Channel - return this.startStopTarget.get(); - - case START: - // force START - return StartStop.START; - - case STOP: - // force STOP - return StartStop.STOP; - } - - assert false; - return StartStop.UNDEFINED; // can never happen + return switch (this.config.startStop()) { + case AUTO -> this.startStopTarget.get(); // read StartStop-Channel + case START -> StartStop.START; // force START + case STOP -> StartStop.STOP; // force STOP + }; } - } diff --git a/io.openems.edge.battery.soltaro/src/io/openems/edge/battery/soltaro/cluster/versionc/statemachine/StateMachine.java b/io.openems.edge.battery.soltaro/src/io/openems/edge/battery/soltaro/cluster/versionc/statemachine/StateMachine.java index 8320231a603..9713db3a9f8 100644 --- a/io.openems.edge.battery.soltaro/src/io/openems/edge/battery/soltaro/cluster/versionc/statemachine/StateMachine.java +++ b/io.openems.edge.battery.soltaro/src/io/openems/edge/battery/soltaro/cluster/versionc/statemachine/StateMachine.java @@ -51,20 +51,13 @@ public StateMachine(State initialState) { @Override public StateHandler getStateHandler(State state) { - switch (state) { - case UNDEFINED: - return new UndefinedHandler(); - case GO_RUNNING: - return new GoRunningHandler(); - case RUNNING: - return new RunningHandler(); - case GO_STOPPED: - return new GoStoppedHandler(); - case STOPPED: - return new StoppedHandler(); - case ERROR: - return new ErrorHandler(); - } - throw new IllegalArgumentException("Unknown State [" + state + "]"); + return switch (state) { + case UNDEFINED -> new UndefinedHandler(); + case GO_RUNNING -> new GoRunningHandler(); + case RUNNING -> new RunningHandler(); + case GO_STOPPED -> new GoStoppedHandler(); + case STOPPED -> new StoppedHandler(); + case ERROR -> new ErrorHandler(); + }; } } \ No newline at end of file diff --git a/io.openems.edge.battery.soltaro/src/io/openems/edge/battery/soltaro/cluster/versionc/statemachine/UndefinedHandler.java b/io.openems.edge.battery.soltaro/src/io/openems/edge/battery/soltaro/cluster/versionc/statemachine/UndefinedHandler.java index 510731f605b..bd8f3168f3a 100644 --- a/io.openems.edge.battery.soltaro/src/io/openems/edge/battery/soltaro/cluster/versionc/statemachine/UndefinedHandler.java +++ b/io.openems.edge.battery.soltaro/src/io/openems/edge/battery/soltaro/cluster/versionc/statemachine/UndefinedHandler.java @@ -9,28 +9,20 @@ public class UndefinedHandler extends StateHandler { public State runAndGetNextState(Context context) { var battery = context.getParent(); - switch (battery.getStartStopTarget()) { - case UNDEFINED: - // Stuck in UNDEFINED State - return State.UNDEFINED; - - case START: - // force START - if (battery.hasFaults()) { - // Has Faults -> error handling - return State.ERROR; - } else { - // No Faults -> start - return State.GO_RUNNING; - } - - case STOP: - // force STOP - return State.GO_STOPPED; - } - - assert false; - return State.UNDEFINED; // can never happen + return switch (battery.getStartStopTarget()) { + case UNDEFINED // Stuck in UNDEFINED State + -> State.UNDEFINED; + + case START // force START + -> battery.hasFaults() // + // Has Faults -> error handling + ? State.ERROR + // No Faults -> start + : State.GO_RUNNING; + + case STOP // force STOP + -> State.GO_STOPPED; + }; } } diff --git a/io.openems.edge.battery.soltaro/src/io/openems/edge/battery/soltaro/single/versionb/BatterySoltaroSingleRackVersionBImpl.java b/io.openems.edge.battery.soltaro/src/io/openems/edge/battery/soltaro/single/versionb/BatterySoltaroSingleRackVersionBImpl.java index a87a7fe5106..1af9cb7d0da 100644 --- a/io.openems.edge.battery.soltaro/src/io/openems/edge/battery/soltaro/single/versionb/BatterySoltaroSingleRackVersionBImpl.java +++ b/io.openems.edge.battery.soltaro/src/io/openems/edge/battery/soltaro/single/versionb/BatterySoltaroSingleRackVersionBImpl.java @@ -208,22 +208,11 @@ public void setStartStop(StartStop value) { @Override public StartStop getStartStopTarget() { - switch (this.config.startStop()) { - case AUTO: - // read StartStop-Channel - return this.startStopTarget.get(); - - case START: - // force START - return StartStop.START; - - case STOP: - // force STOP - return StartStop.STOP; - } - - assert false; - return StartStop.UNDEFINED; // can never happen + return switch (this.config.startStop()) { + case AUTO -> this.startStopTarget.get(); // read StartStop-Channel + case START -> StartStop.START; // force START + case STOP -> StartStop.STOP; // force STOP + }; } @Override diff --git a/io.openems.edge.battery.soltaro/src/io/openems/edge/battery/soltaro/single/versionb/statemachine/StateMachine.java b/io.openems.edge.battery.soltaro/src/io/openems/edge/battery/soltaro/single/versionb/statemachine/StateMachine.java index f1c2da278c7..e32f1901040 100644 --- a/io.openems.edge.battery.soltaro/src/io/openems/edge/battery/soltaro/single/versionb/statemachine/StateMachine.java +++ b/io.openems.edge.battery.soltaro/src/io/openems/edge/battery/soltaro/single/versionb/statemachine/StateMachine.java @@ -52,20 +52,13 @@ public StateMachine(State initialState) { @Override public StateHandler getStateHandler(State state) { - switch (state) { - case UNDEFINED: - return new UndefinedHandler(); - case GO_RUNNING: - return new GoRunningHandler(); - case RUNNING: - return new RunningHandler(); - case GO_STOPPED: - return new GoStoppedHandler(); - case STOPPED: - return new StoppedHandler(); - case ERROR: - return new ErrorHandler(); - } - throw new IllegalArgumentException("Unknown State [" + state + "]"); + return switch (state) { + case UNDEFINED -> new UndefinedHandler(); + case GO_RUNNING -> new GoRunningHandler(); + case RUNNING -> new RunningHandler(); + case GO_STOPPED -> new GoStoppedHandler(); + case STOPPED -> new StoppedHandler(); + case ERROR -> new ErrorHandler(); + }; } } \ No newline at end of file diff --git a/io.openems.edge.battery.soltaro/src/io/openems/edge/battery/soltaro/single/versionb/statemachine/UndefinedHandler.java b/io.openems.edge.battery.soltaro/src/io/openems/edge/battery/soltaro/single/versionb/statemachine/UndefinedHandler.java index 9ffd3d28954..52ef94b620c 100644 --- a/io.openems.edge.battery.soltaro/src/io/openems/edge/battery/soltaro/single/versionb/statemachine/UndefinedHandler.java +++ b/io.openems.edge.battery.soltaro/src/io/openems/edge/battery/soltaro/single/versionb/statemachine/UndefinedHandler.java @@ -10,28 +10,20 @@ public class UndefinedHandler extends StateHandler { protected State runAndGetNextState(Context context) throws OpenemsNamedException { var battery = context.getParent(); - switch (battery.getStartStopTarget()) { - case UNDEFINED: - // Stuck in UNDEFINED State - return State.UNDEFINED; - - case START: - // force START - if (battery.hasFaults()) { - // Has Faults -> error handling - return State.ERROR; - } else { - // No Faults -> start - return State.GO_RUNNING; - } - - case STOP: - // force STOP - return State.GO_STOPPED; - } - - assert false; - return State.UNDEFINED; // can never happen + return switch (battery.getStartStopTarget()) { + case UNDEFINED // Stuck in UNDEFINED State + -> State.UNDEFINED; + + case START // force START + -> battery.hasFaults() // + // Has Faults -> error handling + ? State.ERROR + // No Faults -> start + : State.GO_RUNNING; + + case STOP // force STOP + -> State.GO_STOPPED; + }; } } diff --git a/io.openems.edge.battery.soltaro/src/io/openems/edge/battery/soltaro/single/versionc/BatterySoltaroSingleRackVersionCImpl.java b/io.openems.edge.battery.soltaro/src/io/openems/edge/battery/soltaro/single/versionc/BatterySoltaroSingleRackVersionCImpl.java index 988a530da27..c2e7f9b00ae 100644 --- a/io.openems.edge.battery.soltaro/src/io/openems/edge/battery/soltaro/single/versionc/BatterySoltaroSingleRackVersionCImpl.java +++ b/io.openems.edge.battery.soltaro/src/io/openems/edge/battery/soltaro/single/versionc/BatterySoltaroSingleRackVersionCImpl.java @@ -749,22 +749,10 @@ public void setStartStop(StartStop value) { @Override public StartStop getStartStopTarget() { - switch (this.config.startStop()) { - case AUTO: - // read StartStop-Channel - return this.startStopTarget.get(); - - case START: - // force START - return StartStop.START; - - case STOP: - // force STOP - return StartStop.STOP; - } - - assert false; - return StartStop.UNDEFINED; // can never happen + return switch (this.config.startStop()) { + case AUTO -> this.startStopTarget.get(); // read StartStop-Channel + case START -> StartStop.START; // force START + case STOP -> StartStop.STOP; // force STOP + }; } - } diff --git a/io.openems.edge.battery.soltaro/src/io/openems/edge/battery/soltaro/single/versionc/statemachine/StateMachine.java b/io.openems.edge.battery.soltaro/src/io/openems/edge/battery/soltaro/single/versionc/statemachine/StateMachine.java index 914c58eda06..c1c5d96c425 100644 --- a/io.openems.edge.battery.soltaro/src/io/openems/edge/battery/soltaro/single/versionc/statemachine/StateMachine.java +++ b/io.openems.edge.battery.soltaro/src/io/openems/edge/battery/soltaro/single/versionc/statemachine/StateMachine.java @@ -51,20 +51,13 @@ public StateMachine(State initialState) { @Override public StateHandler getStateHandler(State state) { - switch (state) { - case UNDEFINED: - return new UndefinedHandler(); - case GO_RUNNING: - return new GoRunningHandler(); - case RUNNING: - return new RunningHandler(); - case GO_STOPPED: - return new GoStoppedHandler(); - case STOPPED: - return new StoppedHandler(); - case ERROR: - return new ErrorHandler(); - } - throw new IllegalArgumentException("Unknown State [" + state + "]"); + return switch (state) { + case UNDEFINED -> new UndefinedHandler(); + case GO_RUNNING -> new GoRunningHandler(); + case RUNNING -> new RunningHandler(); + case GO_STOPPED -> new GoStoppedHandler(); + case STOPPED -> new StoppedHandler(); + case ERROR -> new ErrorHandler(); + }; } } \ No newline at end of file diff --git a/io.openems.edge.battery.soltaro/src/io/openems/edge/battery/soltaro/single/versionc/statemachine/UndefinedHandler.java b/io.openems.edge.battery.soltaro/src/io/openems/edge/battery/soltaro/single/versionc/statemachine/UndefinedHandler.java index 2f2bd1687b3..855a1e13e10 100644 --- a/io.openems.edge.battery.soltaro/src/io/openems/edge/battery/soltaro/single/versionc/statemachine/UndefinedHandler.java +++ b/io.openems.edge.battery.soltaro/src/io/openems/edge/battery/soltaro/single/versionc/statemachine/UndefinedHandler.java @@ -8,28 +8,20 @@ public class UndefinedHandler extends StateHandler { @Override public State runAndGetNextState(Context context) { var battery = context.getParent(); - switch (battery.getStartStopTarget()) { - case UNDEFINED: - // Stuck in UNDEFINED State - return State.UNDEFINED; + return switch (battery.getStartStopTarget()) { + case UNDEFINED // Stuck in UNDEFINED State + -> State.UNDEFINED; - case START: - // force START - if (battery.hasFaults()) { - // Has Faults -> error handling - return State.ERROR; - } else { - // No Faults -> start - return State.GO_RUNNING; - } + case START// force START + -> battery.hasFaults() // + // Has Faults -> error handling + ? State.ERROR + // No Faults -> start + : State.GO_RUNNING; - case STOP: - // force STOP - return State.GO_STOPPED; - } - - assert false; - return State.UNDEFINED; // can never happen + case STOP // force STOP + -> State.GO_STOPPED; + }; } } diff --git a/io.openems.edge.batteryinverter.api/src/io/openems/edge/batteryinverter/api/SymmetricBatteryInverter.java b/io.openems.edge.batteryinverter.api/src/io/openems/edge/batteryinverter/api/SymmetricBatteryInverter.java index 32aa035b4f1..8e731a87612 100644 --- a/io.openems.edge.batteryinverter.api/src/io/openems/edge/batteryinverter/api/SymmetricBatteryInverter.java +++ b/io.openems.edge.batteryinverter.api/src/io/openems/edge/batteryinverter/api/SymmetricBatteryInverter.java @@ -135,6 +135,20 @@ public enum ChannelId implements io.openems.edge.common.channel.ChannelId { DC_MAX_VOLTAGE(Doc.of(OpenemsType.INTEGER) // .unit(Unit.VOLT) // .persistencePriority(PersistencePriority.HIGH) // + ), // + + /** + * Inverter Cabinet Temperature. + * + *

    + *
  • Interface: SymmetricBatteryInverter + *
  • Type: Integer + *
  • Unit: C + *
+ */ + TEMPERATURE_CABINET(Doc.of(OpenemsType.INTEGER) // + .unit(Unit.DEGREE_CELSIUS) // + .persistencePriority(PersistencePriority.HIGH) // ); private final Doc doc; @@ -463,4 +477,23 @@ public default void _setDcMaxVoltage(Integer value) { public default void _setDcMaxVoltage(int value) { this.getDcMaxVoltageChannel().setNextValue(value); } + + /** + * Gets the Channel for {@link ChannelId#TEMPERATURE_CABINET}. + * + * @return the Channel + */ + public default IntegerReadChannel getTemperatureCabinetChannel() { + return this.channel(ChannelId.TEMPERATURE_CABINET); + } + + /** + * Gets the Inverters Cabinet temperature in [C]. See + * {@link ChannelId#TEMPERATURE_CABINET}. + * + * @return the Channel {@link Value} + */ + public default Value getTemperatureCabinet() { + return this.getTemperatureCabinetChannel().value(); + } } diff --git a/io.openems.edge.batteryinverter.kaco.blueplanetgridsave/src/io/openems/edge/batteryinverter/kaco/blueplanetgridsave/KacoSunSpecModel.java b/io.openems.edge.batteryinverter.kaco.blueplanetgridsave/src/io/openems/edge/batteryinverter/kaco/blueplanetgridsave/KacoSunSpecModel.java index 88974aeedf0..751aed62757 100644 --- a/io.openems.edge.batteryinverter.kaco.blueplanetgridsave/src/io/openems/edge/batteryinverter/kaco/blueplanetgridsave/KacoSunSpecModel.java +++ b/io.openems.edge.batteryinverter.kaco.blueplanetgridsave/src/io/openems/edge/batteryinverter/kaco/blueplanetgridsave/KacoSunSpecModel.java @@ -106,8 +106,7 @@ public static enum S64201 implements SunSpecPoint { V_AR(new ScaledValuePoint("S64201_V_AR", "AC Reactive Power", "", // ValuePoint.Type.INT16, true, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE, "V_AR_SF")), // HZ(new ScaledValuePoint("S64201_HZ", "Line Frequency", "", // - ValuePoint.Type.UINT16, true, AccessMode.READ_ONLY, Unit.HERTZ, "Hz_SF") - ), // + ValuePoint.Type.UINT16, true, AccessMode.READ_ONLY, Unit.HERTZ, "Hz_SF")), // RESERVED_36(new ReservedPoint("S64201_RESERVED_36")), // RESERVED_37(new ReservedPoint("S64201_RESERVED_37")), // RESERVED_38(new ReservedPoint("S64201_RESERVED_38")), // diff --git a/io.openems.edge.batteryinverter.kaco.blueplanetgridsave/test/io/openems/edge/batteryinverter/kaco/blueplanetgridsave/BatteryInverterKacoBlueplanetGridsaveImplTest.java b/io.openems.edge.batteryinverter.kaco.blueplanetgridsave/test/io/openems/edge/batteryinverter/kaco/blueplanetgridsave/BatteryInverterKacoBlueplanetGridsaveImplTest.java index fc68eda27ec..d3d8025f5e1 100644 --- a/io.openems.edge.batteryinverter.kaco.blueplanetgridsave/test/io/openems/edge/batteryinverter/kaco/blueplanetgridsave/BatteryInverterKacoBlueplanetGridsaveImplTest.java +++ b/io.openems.edge.batteryinverter.kaco.blueplanetgridsave/test/io/openems/edge/batteryinverter/kaco/blueplanetgridsave/BatteryInverterKacoBlueplanetGridsaveImplTest.java @@ -1,5 +1,6 @@ package io.openems.edge.batteryinverter.kaco.blueplanetgridsave; +import static io.openems.common.test.TestUtils.createDummyClock; import static io.openems.edge.batteryinverter.api.SymmetricBatteryInverter.ChannelId.MAX_APPARENT_POWER; import static io.openems.edge.batteryinverter.kaco.blueplanetgridsave.BatteryInverterKacoBlueplanetGridsave.WATCHDOG_TIMEOUT_SECONDS; import static io.openems.edge.batteryinverter.kaco.blueplanetgridsave.BatteryInverterKacoBlueplanetGridsave.WATCHDOG_TRIGGER_SECONDS; @@ -27,7 +28,6 @@ import io.openems.edge.common.test.ComponentTest; import io.openems.edge.common.test.DummyComponentManager; import io.openems.edge.common.test.DummyConfigurationAdmin; -import io.openems.edge.common.test.TestUtils; public class BatteryInverterKacoBlueplanetGridsaveImplTest { @@ -49,17 +49,16 @@ protected void handleEvent(String topic) throws Exception { } - private static TimeLeapClock clock; + private static final TimeLeapClock CLOCK = createDummyClock(); private static ComponentTest test; @Before public void prepareTest() throws Exception { - clock = TestUtils.createDummyClock(); var sut = new BatteryInverterKacoBlueplanetGridsaveImpl(); test = new MyComponentTest(sut) // .addReference("cm", new DummyConfigurationAdmin()) // - .addReference("componentManager", new DummyComponentManager(clock)) // + .addReference("componentManager", new DummyComponentManager(CLOCK)) // .addReference("setModbus", new DummyModbusBridge("modbus0")); // TODO implement proper Dummy-Modbus-Bridge with SunSpec support. Till then... @@ -97,10 +96,10 @@ public void testStart() throws Exception { .input(MAX_APPARENT_POWER, 50_000) // .output(STATE_MACHINE, State.UNDEFINED)) // .next(new TestCase() // - .timeleap(clock, 4, SECONDS) // + .timeleap(CLOCK, 4, SECONDS) // .output(STATE_MACHINE, State.GO_RUNNING)) // .next(new TestCase() // - .timeleap(clock, 1, SECONDS) // + .timeleap(CLOCK, 1, SECONDS) // .input(CURRENT_STATE.getChannelId(), S64201CurrentState.GRID_CONNECTED) // .output(WATCHDOG.getChannelId(), WATCHDOG_TIMEOUT_SECONDS)) // .next(new TestCase() // @@ -114,10 +113,10 @@ public void testWatchdog() throws Exception { .next(new TestCase() // .output(WATCHDOG.getChannelId(), WATCHDOG_TIMEOUT_SECONDS)) // .next(new TestCase() // - .timeleap(clock, WATCHDOG_TRIGGER_SECONDS - 1, SECONDS) // + .timeleap(CLOCK, WATCHDOG_TRIGGER_SECONDS - 1, SECONDS) // .output(WATCHDOG.getChannelId(), null /* waiting till next watchdog trigger */)) // .next(new TestCase() // - .timeleap(clock, 1, SECONDS) // + .timeleap(CLOCK, 1, SECONDS) // .output(WATCHDOG.getChannelId(), WATCHDOG_TIMEOUT_SECONDS)) // ; } diff --git a/io.openems.edge.batteryinverter.refu88k/src/io/openems/edge/batteryinverter/refu88k/BatteryInverterRefuStore88kImpl.java b/io.openems.edge.batteryinverter.refu88k/src/io/openems/edge/batteryinverter/refu88k/BatteryInverterRefuStore88kImpl.java index a63d14f76fd..3a66adce7a3 100644 --- a/io.openems.edge.batteryinverter.refu88k/src/io/openems/edge/batteryinverter/refu88k/BatteryInverterRefuStore88kImpl.java +++ b/io.openems.edge.batteryinverter.refu88k/src/io/openems/edge/batteryinverter/refu88k/BatteryInverterRefuStore88kImpl.java @@ -490,22 +490,11 @@ public void setStartStop(StartStop value) { @Override public StartStop getStartStopTarget() { - switch (this.config.startStop()) { - case AUTO: - // read StartStop-Channel - return this.startStopTarget.get(); - - case START: - // force START - return StartStop.START; - - case STOP: - // force STOP - return StartStop.STOP; - } - - assert false; - return StartStop.UNDEFINED; // can never happen + return switch (this.config.startStop()) { + case AUTO -> this.startStopTarget.get(); // read StartStop-Channel + case START -> StartStop.START; // force START + case STOP -> StartStop.STOP; // force STOP + }; } /** diff --git a/io.openems.edge.batteryinverter.refu88k/src/io/openems/edge/batteryinverter/refu88k/statemachine/GoRunningHandler.java b/io.openems.edge.batteryinverter.refu88k/src/io/openems/edge/batteryinverter/refu88k/statemachine/GoRunningHandler.java index 4e28a0ab7fe..c76b73e045f 100644 --- a/io.openems.edge.batteryinverter.refu88k/src/io/openems/edge/batteryinverter/refu88k/statemachine/GoRunningHandler.java +++ b/io.openems.edge.batteryinverter.refu88k/src/io/openems/edge/batteryinverter/refu88k/statemachine/GoRunningHandler.java @@ -22,31 +22,22 @@ public State runAndGetNextState(Context context) throws OpenemsNamedException { return State.UNDEFINED; } - switch (inverter.getOperatingState()) { - - case STARTING: - return State.GO_RUNNING; - case MPPT: - case STARTED: - case THROTTLED: + return switch (inverter.getOperatingState()) { + case STARTING // + -> State.GO_RUNNING; + case MPPT, STARTED, THROTTLED -> // // if inverter is throttled, full power is not available, but the device // is still working - return State.RUNNING; - case STANDBY: + State.RUNNING; + case STANDBY -> { inverter.exitStandbyMode(); - return State.GO_RUNNING; - // if inverter is throttled, full power is not available, but the device - // is still working - case FAULT: - return State.ERROR; - case OFF: - case SLEEPING: - case SHUTTING_DOWN: - - case UNDEFINED: - return State.UNDEFINED; + yield State.GO_RUNNING; } - return State.UNDEFINED; + case FAULT // + -> State.ERROR; + case OFF, SLEEPING, SHUTTING_DOWN, UNDEFINED // + -> State.UNDEFINED; + }; } } diff --git a/io.openems.edge.batteryinverter.refu88k/src/io/openems/edge/batteryinverter/refu88k/statemachine/GoStoppedHandler.java b/io.openems.edge.batteryinverter.refu88k/src/io/openems/edge/batteryinverter/refu88k/statemachine/GoStoppedHandler.java index c40457bc2f2..b8f7d44c34e 100644 --- a/io.openems.edge.batteryinverter.refu88k/src/io/openems/edge/batteryinverter/refu88k/statemachine/GoStoppedHandler.java +++ b/io.openems.edge.batteryinverter.refu88k/src/io/openems/edge/batteryinverter/refu88k/statemachine/GoStoppedHandler.java @@ -10,23 +10,15 @@ public class GoStoppedHandler extends StateHandler { public State runAndGetNextState(Context context) throws OpenemsNamedException { var inverter = context.getParent(); - switch (inverter.getOperatingState()) { - case STARTING: - case MPPT: - case THROTTLED: - case STARTED: + return switch (inverter.getOperatingState()) { + case STARTING, MPPT, THROTTLED, STARTED -> { inverter.stopInverter(); - return State.GO_STOPPED; - case FAULT: - case STANDBY: - return State.STOPPED; - case SHUTTING_DOWN: - case OFF: - case SLEEPING: - case UNDEFINED: - return State.UNDEFINED; + yield State.GO_STOPPED; } - - return State.UNDEFINED; + case FAULT, STANDBY // + -> State.STOPPED; + case SHUTTING_DOWN, OFF, SLEEPING, UNDEFINED // + -> State.UNDEFINED; + }; } } diff --git a/io.openems.edge.batteryinverter.refu88k/src/io/openems/edge/batteryinverter/refu88k/statemachine/RunningHandler.java b/io.openems.edge.batteryinverter.refu88k/src/io/openems/edge/batteryinverter/refu88k/statemachine/RunningHandler.java index 13e6ace900f..89a47b7315a 100644 --- a/io.openems.edge.batteryinverter.refu88k/src/io/openems/edge/batteryinverter/refu88k/statemachine/RunningHandler.java +++ b/io.openems.edge.batteryinverter.refu88k/src/io/openems/edge/batteryinverter/refu88k/statemachine/RunningHandler.java @@ -26,28 +26,19 @@ public State runAndGetNextState(Context context) throws OpenemsNamedException { return State.UNDEFINED; } - switch (inverter.getOperatingState()) { - - case STARTED: - case THROTTLED: - case MPPT: + return switch (inverter.getOperatingState()) { + case STARTED, THROTTLED, MPPT -> { // Mark as started inverter._setStartStop(StartStop.START); // Apply Active and Reactive Power Set-Points this.applyPower(context); - return State.RUNNING; - case FAULT: - return State.ERROR; - case OFF: - case SLEEPING: - case STARTING: - case SHUTTING_DOWN: - case STANDBY: - case UNDEFINED: - return State.UNDEFINED; + yield State.RUNNING; } - - return State.UNDEFINED; + case FAULT // + -> State.ERROR; + case OFF, SLEEPING, STARTING, SHUTTING_DOWN, STANDBY, UNDEFINED // + -> State.UNDEFINED; + }; } /** diff --git a/io.openems.edge.batteryinverter.refu88k/src/io/openems/edge/batteryinverter/refu88k/statemachine/StateMachine.java b/io.openems.edge.batteryinverter.refu88k/src/io/openems/edge/batteryinverter/refu88k/statemachine/StateMachine.java index 17e940975a2..04c64c3e00a 100644 --- a/io.openems.edge.batteryinverter.refu88k/src/io/openems/edge/batteryinverter/refu88k/statemachine/StateMachine.java +++ b/io.openems.edge.batteryinverter.refu88k/src/io/openems/edge/batteryinverter/refu88k/statemachine/StateMachine.java @@ -51,20 +51,13 @@ public StateMachine(State initialState) { @Override public StateHandler getStateHandler(State state) { - switch (state) { - case UNDEFINED: - return new UndefinedHandler(); - case GO_RUNNING: - return new GoRunningHandler(); - case RUNNING: - return new RunningHandler(); - case GO_STOPPED: - return new GoStoppedHandler(); - case STOPPED: - return new StoppedHandler(); - case ERROR: - return new ErrorHandler(); - } - throw new IllegalArgumentException("Unknown State [" + state + "]"); + return switch (state) { + case UNDEFINED -> new UndefinedHandler(); + case GO_RUNNING -> new GoRunningHandler(); + case RUNNING -> new RunningHandler(); + case GO_STOPPED -> new GoStoppedHandler(); + case STOPPED -> new StoppedHandler(); + case ERROR -> new ErrorHandler(); + }; } } \ No newline at end of file diff --git a/io.openems.edge.batteryinverter.refu88k/src/io/openems/edge/batteryinverter/refu88k/statemachine/UndefinedHandler.java b/io.openems.edge.batteryinverter.refu88k/src/io/openems/edge/batteryinverter/refu88k/statemachine/UndefinedHandler.java index 7a0c4b26780..d38ff233e04 100644 --- a/io.openems.edge.batteryinverter.refu88k/src/io/openems/edge/batteryinverter/refu88k/statemachine/UndefinedHandler.java +++ b/io.openems.edge.batteryinverter.refu88k/src/io/openems/edge/batteryinverter/refu88k/statemachine/UndefinedHandler.java @@ -8,29 +8,19 @@ public class UndefinedHandler extends StateHandler { @Override public State runAndGetNextState(Context context) { var inverter = context.getParent(); - - switch (inverter.getStartStopTarget()) { - case UNDEFINED: - // Stuck in UNDEFINED State - return State.UNDEFINED; - - case START: - // force START - if (inverter.hasFaults()) { - // Has Faults -> error handling - return State.ERROR; - } else { - // No Faults -> start - return State.GO_RUNNING; - } - - case STOP: - // force STOP - return State.GO_STOPPED; - } - - assert false; - return State.UNDEFINED; // can never happen + return switch (inverter.getStartStopTarget()) { + case UNDEFINED // Stuck in UNDEFINED State + -> State.UNDEFINED; + + case START // force START + -> inverter.hasFaults() // + // Has Faults -> error handling + ? State.ERROR + // No Faults -> start + : State.GO_RUNNING; + + case STOP // force STOP + -> State.GO_STOPPED; + }; } - } diff --git a/io.openems.edge.batteryinverter.sinexcel/src/io/openems/edge/batteryinverter/sinexcel/BatteryInverterSinexcelImpl.java b/io.openems.edge.batteryinverter.sinexcel/src/io/openems/edge/batteryinverter/sinexcel/BatteryInverterSinexcelImpl.java index 5a65149220b..cfface51a1b 100644 --- a/io.openems.edge.batteryinverter.sinexcel/src/io/openems/edge/batteryinverter/sinexcel/BatteryInverterSinexcelImpl.java +++ b/io.openems.edge.batteryinverter.sinexcel/src/io/openems/edge/batteryinverter/sinexcel/BatteryInverterSinexcelImpl.java @@ -333,22 +333,11 @@ public void setStartStop(StartStop value) { * @return {@link StartStop} */ public StartStop getStartStopTarget() { - switch (this.config.startStop()) { - case AUTO: - // read StartStop-Channel - return this.startStopTarget.get(); - - case START: - // force START - return StartStop.START; - - case STOP: - // force STOP - return StartStop.STOP; - } - - assert false; - return StartStop.UNDEFINED; // can never happen + return switch (this.config.startStop()) { + case AUTO -> this.startStopTarget.get(); // read StartStop-Channel + case START -> StartStop.START; // force START + case STOP -> StartStop.STOP; // force STOP + }; } protected final AtomicReference targetGridMode = new AtomicReference<>(TargetGridMode.GO_ON_GRID); diff --git a/io.openems.edge.batteryinverter.sinexcel/src/io/openems/edge/batteryinverter/sinexcel/statemachine/StateMachine.java b/io.openems.edge.batteryinverter.sinexcel/src/io/openems/edge/batteryinverter/sinexcel/statemachine/StateMachine.java index 372a69a8287..723d3285112 100644 --- a/io.openems.edge.batteryinverter.sinexcel/src/io/openems/edge/batteryinverter/sinexcel/statemachine/StateMachine.java +++ b/io.openems.edge.batteryinverter.sinexcel/src/io/openems/edge/batteryinverter/sinexcel/statemachine/StateMachine.java @@ -51,20 +51,13 @@ public StateMachine(State initialState) { @Override public StateHandler getStateHandler(State state) { - switch (state) { - case UNDEFINED: - return new UndefinedHandler(); - case GO_RUNNING: - return new GoRunningHandler(); - case RUNNING: - return new RunningHandler(); - case GO_STOPPED: - return new GoStoppedHandler(); - case STOPPED: - return new StoppedHandler(); - case ERROR: - return new ErrorHandler(); - } - throw new IllegalArgumentException("Unknown State [" + state + "]"); + return switch (state) { + case UNDEFINED -> new UndefinedHandler(); + case GO_RUNNING -> new GoRunningHandler(); + case RUNNING -> new RunningHandler(); + case GO_STOPPED -> new GoStoppedHandler(); + case STOPPED -> new StoppedHandler(); + case ERROR -> new ErrorHandler(); + }; } } diff --git a/io.openems.edge.batteryinverter.sinexcel/src/io/openems/edge/batteryinverter/sinexcel/statemachine/UndefinedHandler.java b/io.openems.edge.batteryinverter.sinexcel/src/io/openems/edge/batteryinverter/sinexcel/statemachine/UndefinedHandler.java index cb2346bc3fe..409482e87ab 100644 --- a/io.openems.edge.batteryinverter.sinexcel/src/io/openems/edge/batteryinverter/sinexcel/statemachine/UndefinedHandler.java +++ b/io.openems.edge.batteryinverter.sinexcel/src/io/openems/edge/batteryinverter/sinexcel/statemachine/UndefinedHandler.java @@ -9,28 +9,20 @@ public class UndefinedHandler extends StateHandler { @Override public State runAndGetNextState(Context context) throws OpenemsNamedException { final var inverter = context.getParent(); - switch (inverter.getStartStopTarget()) { - case UNDEFINED: - // Stuck in UNDEFINED State - return State.UNDEFINED; + return switch (inverter.getStartStopTarget()) { + case UNDEFINED // Stuck in UNDEFINED State + -> State.UNDEFINED; - case START: - // force START - if (inverter.hasFaults()) { - // Has Faults -> error handling - return State.ERROR; - } else { - // No Faults -> start - return State.GO_RUNNING; - } + case START // force START + -> inverter.hasFaults() // + // Has Faults -> error handling + ? State.ERROR + // No Faults -> start + : State.GO_RUNNING; - case STOP: - // force STOP - return State.GO_STOPPED; - } - - assert false; - return State.UNDEFINED; // can never happen + case STOP// force STOP + -> State.GO_STOPPED; + }; } } diff --git a/io.openems.edge.bridge.http/src/io/openems/edge/bridge/http/BridgeHttpImpl.java b/io.openems.edge.bridge.http/src/io/openems/edge/bridge/http/BridgeHttpImpl.java index 460236c183c..c12bcb9afd3 100644 --- a/io.openems.edge.bridge.http/src/io/openems/edge/bridge/http/BridgeHttpImpl.java +++ b/io.openems.edge.bridge.http/src/io/openems/edge/bridge/http/BridgeHttpImpl.java @@ -1,5 +1,7 @@ package io.openems.edge.bridge.http; +import static io.openems.common.utils.FunctionUtils.doNothing; + import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; @@ -20,6 +22,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import io.openems.common.types.DebugMode; import io.openems.common.utils.FunctionUtils; import io.openems.edge.bridge.http.api.BridgeHttp; import io.openems.edge.bridge.http.api.BridgeHttpExecutor; @@ -145,6 +148,8 @@ public void shutdown() { private final Set timeEndpoints = ConcurrentHashMap.newKeySet(); + private DebugMode debugMode = DebugMode.OFF; + @Activate public BridgeHttpImpl(// @Reference final CycleSubscriber cycleSubscriber, // @@ -170,6 +175,11 @@ public void deactivate() { this.timeEndpoints.clear(); } + @Override + public void setDebugMode(DebugMode debugMode) { + this.debugMode = debugMode; + } + @Override public CycleEndpoint subscribeCycle(CycleEndpoint endpoint) { Objects.requireNonNull(endpoint, "CycleEndpoint is not allowed to be null!"); @@ -189,11 +199,14 @@ public TimeEndpoint subscribeTime(TimeEndpoint endpoint) { this.timeEndpoints.add(endpointCountdown); final var delay = endpoint.delayTimeProvider().onFirstRunDelay(); - // TODO change in java 21 to switch case - if (delay instanceof Delay.DurationDelay durationDelay) { + switch (delay) { + case Delay.InfiniteDelay infiniteDelay // + -> doNothing(); + case Delay.DurationDelay durationDelay -> { final var future = this.pool.schedule(this.createTask(endpointCountdown), durationDelay); endpointCountdown.setShutdownCurrentTask(() -> future.cancel(false)); } + } return endpoint; } @@ -202,7 +215,7 @@ public CompletableFuture> request(Endpoint endpoint) { final var future = new CompletableFuture>(); this.pool.execute(() -> { try { - final var result = this.urlFetcher.fetchEndpoint(endpoint); + final var result = this.urlFetcher.fetchEndpoint(endpoint, this.debugMode); future.complete(result); } catch (HttpError e) { future.completeExceptionally(e); @@ -252,7 +265,8 @@ private void handleEvent(Event event) { private Runnable createTask(CycleEndpointCountdown endpointItem) { return () -> { try { - final var result = this.urlFetcher.fetchEndpoint(endpointItem.getCycleEndpoint().endpoint().get()); + final var result = this.urlFetcher.fetchEndpoint(endpointItem.getCycleEndpoint().endpoint().get(), + this.debugMode); endpointItem.getCycleEndpoint().onResult().accept(result); } catch (HttpError e) { endpointItem.getCycleEndpoint().onError().accept(e); @@ -275,7 +289,8 @@ private Runnable createTask(TimeEndpointCountdown endpointCountdown) { HttpResponse result = null; HttpError error = null; try { - result = this.urlFetcher.fetchEndpoint(endpointCountdown.getTimeEndpoint().endpoint().get()); + result = this.urlFetcher.fetchEndpoint(endpointCountdown.getTimeEndpoint().endpoint().get(), + this.debugMode); endpointCountdown.getTimeEndpoint().onResult().accept(result); } catch (HttpError e) { endpointCountdown.getTimeEndpoint().onError().accept(e); @@ -298,14 +313,14 @@ private Runnable createTask(TimeEndpointCountdown endpointCountdown) { nextDelay = endpointCountdown.getTimeEndpoint().delayTimeProvider().onSuccessRunDelay(result); } - // TODO change in java 21 to switch case - if (nextDelay instanceof Delay.InfiniteDelay) { - // do not queue again - return; - } else if (nextDelay instanceof Delay.DurationDelay durationDelay) { + switch (nextDelay) { + case Delay.InfiniteDelay infiniteDelay // + -> doNothing(); + case Delay.DurationDelay durationDelay -> { final var future = this.pool.schedule(this.createTask(endpointCountdown), durationDelay); endpointCountdown.setShutdownCurrentTask(() -> future.cancel(false)); } + } } catch (Exception e) { if (this.pool.isShutdown()) { diff --git a/io.openems.edge.bridge.http/src/io/openems/edge/bridge/http/NetworkEndpointFetcher.java b/io.openems.edge.bridge.http/src/io/openems/edge/bridge/http/NetworkEndpointFetcher.java index 3a751cd7ffc..4d19f500373 100644 --- a/io.openems.edge.bridge.http/src/io/openems/edge/bridge/http/NetworkEndpointFetcher.java +++ b/io.openems.edge.bridge.http/src/io/openems/edge/bridge/http/NetworkEndpointFetcher.java @@ -10,18 +10,24 @@ import java.net.URI; import org.osgi.service.component.annotations.Component; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import io.openems.common.types.DebugMode; import io.openems.common.types.HttpStatus; import io.openems.edge.bridge.http.api.BridgeHttp.Endpoint; import io.openems.edge.bridge.http.api.EndpointFetcher; import io.openems.edge.bridge.http.api.HttpError; import io.openems.edge.bridge.http.api.HttpResponse; +import io.openems.edge.bridge.http.dummy.DummyEndpointFetcher; @Component public class NetworkEndpointFetcher implements EndpointFetcher { + private final Logger log = LoggerFactory.getLogger(DummyEndpointFetcher.class); + @Override - public HttpResponse fetchEndpoint(final Endpoint endpoint) throws HttpError { + public HttpResponse fetchEndpoint(final Endpoint endpoint, DebugMode mode) throws HttpError { try { var url = URI.create(endpoint.url()).toURL(); var con = (HttpURLConnection) url.openConnection(); @@ -53,6 +59,12 @@ public HttpResponse fetchEndpoint(final Endpoint endpoint) throws HttpEr if (status.isError()) { throw new HttpError.ResponseError(status, body); } + if (mode.equals(DebugMode.DETAILED)) { + this.log.debug("Fetched Endpoint for request: " + endpoint.url() + "\n" // + + "method: " + endpoint.method().name() + "\n" // + + "result: " + body // + ); + } return new HttpResponse<>(status, body); } catch (IOException e) { throw new HttpError.UnknownError(e); diff --git a/io.openems.edge.bridge.http/src/io/openems/edge/bridge/http/api/BridgeHttp.java b/io.openems.edge.bridge.http/src/io/openems/edge/bridge/http/api/BridgeHttp.java index 52e198f75f8..d3cbf4352e9 100644 --- a/io.openems.edge.bridge.http/src/io/openems/edge/bridge/http/api/BridgeHttp.java +++ b/io.openems.edge.bridge.http/src/io/openems/edge/bridge/http/api/BridgeHttp.java @@ -10,6 +10,7 @@ import io.openems.common.exceptions.OpenemsError.OpenemsNamedException; import io.openems.common.function.ThrowingFunction; +import io.openems.common.types.DebugMode; import io.openems.common.utils.JsonUtils; /** @@ -73,6 +74,8 @@ public record Endpoint(// } + public void setDebugMode(DebugMode debugMode); + /** * Fetches the url once with {@link HttpMethod#GET}. * diff --git a/io.openems.edge.bridge.http/src/io/openems/edge/bridge/http/api/EndpointFetcher.java b/io.openems.edge.bridge.http/src/io/openems/edge/bridge/http/api/EndpointFetcher.java index c2467110749..e0d1bb54235 100644 --- a/io.openems.edge.bridge.http/src/io/openems/edge/bridge/http/api/EndpointFetcher.java +++ b/io.openems.edge.bridge.http/src/io/openems/edge/bridge/http/api/EndpointFetcher.java @@ -1,6 +1,7 @@ package io.openems.edge.bridge.http.api; import io.openems.common.exceptions.OpenemsError.OpenemsNamedException; +import io.openems.common.types.DebugMode; import io.openems.edge.bridge.http.api.BridgeHttp.Endpoint; public interface EndpointFetcher { @@ -9,10 +10,11 @@ public interface EndpointFetcher { * Creates a {@link Runnable} to execute a request with the given parameters. * * @param endpoint the {@link Endpoint} to fetch + * @param mode the {@link DebugMode} * * @return the result of the {@link Endpoint} * @throws OpenemsNamedException on error */ - public HttpResponse fetchEndpoint(Endpoint endpoint) throws HttpError; + public HttpResponse fetchEndpoint(Endpoint endpoint, DebugMode mode) throws HttpError; } diff --git a/io.openems.edge.bridge.http/src/io/openems/edge/bridge/http/dummy/DummyBridgeHttp.java b/io.openems.edge.bridge.http/src/io/openems/edge/bridge/http/dummy/DummyBridgeHttp.java index 99040297ca2..647c1d3e6be 100644 --- a/io.openems.edge.bridge.http/src/io/openems/edge/bridge/http/dummy/DummyBridgeHttp.java +++ b/io.openems.edge.bridge.http/src/io/openems/edge/bridge/http/dummy/DummyBridgeHttp.java @@ -6,6 +6,7 @@ import java.util.concurrent.CompletableFuture; import java.util.function.Predicate; +import io.openems.common.types.DebugMode; import io.openems.edge.bridge.http.api.BridgeHttp; import io.openems.edge.bridge.http.api.HttpResponse; @@ -55,4 +56,9 @@ public Collection removeTimeEndpointIf(Predicate con return emptyList(); } + @Override + public void setDebugMode(DebugMode debugMode) { + // do nothing + } + } diff --git a/io.openems.edge.bridge.http/src/io/openems/edge/bridge/http/dummy/DummyBridgeHttpExecutor.java b/io.openems.edge.bridge.http/src/io/openems/edge/bridge/http/dummy/DummyBridgeHttpExecutor.java index cf1d07df092..71b7370b2fb 100644 --- a/io.openems.edge.bridge.http/src/io/openems/edge/bridge/http/dummy/DummyBridgeHttpExecutor.java +++ b/io.openems.edge.bridge.http/src/io/openems/edge/bridge/http/dummy/DummyBridgeHttpExecutor.java @@ -1,6 +1,6 @@ package io.openems.edge.bridge.http.dummy; -import static io.openems.edge.common.test.TestUtils.createDummyClock; +import static io.openems.common.test.TestUtils.createDummyClock; import java.time.Clock; import java.time.Duration; diff --git a/io.openems.edge.bridge.http/src/io/openems/edge/bridge/http/dummy/DummyEndpointFetcher.java b/io.openems.edge.bridge.http/src/io/openems/edge/bridge/http/dummy/DummyEndpointFetcher.java index 907c714f0d5..269148dd1a9 100644 --- a/io.openems.edge.bridge.http/src/io/openems/edge/bridge/http/dummy/DummyEndpointFetcher.java +++ b/io.openems.edge.bridge.http/src/io/openems/edge/bridge/http/dummy/DummyEndpointFetcher.java @@ -7,6 +7,7 @@ import org.slf4j.LoggerFactory; import io.openems.common.function.ThrowingFunction; +import io.openems.common.types.DebugMode; import io.openems.common.utils.FunctionUtils; import io.openems.edge.bridge.http.api.BridgeHttp.Endpoint; import io.openems.edge.bridge.http.api.EndpointFetcher; @@ -29,7 +30,8 @@ public record DummyHandler(// @Override public HttpResponse fetchEndpoint(// - final Endpoint endpoint // + final Endpoint endpoint, // + DebugMode mode // ) throws HttpError { try { for (final var iterator = this.urlHandler.iterator(); iterator.hasNext();) { @@ -89,5 +91,4 @@ public void addSingleUseEndpointHandler(ThrowingFunction new DurationDelay(this.duration.plus(durationDelay.getDuration())); + case InfiniteDelay infiniteDelay // + -> delay.plus(this); + }; } @Override diff --git a/io.openems.edge.bridge.http/test/io/openems/edge/bridge/http/api/BridgeHttpTimeTest.java b/io.openems.edge.bridge.http/test/io/openems/edge/bridge/http/api/BridgeHttpTimeTest.java index db098dab702..203f1f8ceb7 100644 --- a/io.openems.edge.bridge.http/test/io/openems/edge/bridge/http/api/BridgeHttpTimeTest.java +++ b/io.openems.edge.bridge.http/test/io/openems/edge/bridge/http/api/BridgeHttpTimeTest.java @@ -1,7 +1,7 @@ package io.openems.edge.bridge.http.api; +import static io.openems.common.test.TestUtils.createDummyClock; import static io.openems.edge.bridge.http.time.DelayTimeProviderChain.fixedDelay; -import static io.openems.edge.common.test.TestUtils.createDummyClock; import static org.junit.Assert.assertEquals; import java.time.Duration; diff --git a/io.openems.edge.bridge.modbus/src/io/openems/edge/bridge/modbus/api/AbstractOpenemsModbusComponent.java b/io.openems.edge.bridge.modbus/src/io/openems/edge/bridge/modbus/api/AbstractOpenemsModbusComponent.java index 80c29c5f234..2162ecc794c 100644 --- a/io.openems.edge.bridge.modbus/src/io/openems/edge/bridge/modbus/api/AbstractOpenemsModbusComponent.java +++ b/io.openems.edge.bridge.modbus/src/io/openems/edge/bridge/modbus/api/AbstractOpenemsModbusComponent.java @@ -354,7 +354,8 @@ public ELEMENT build() { // dynamically get the Converter; this allows the converter to be changed var converter = this.channelMaps.get(channel); var convertedValue = converter.channelToElement(value); - if (this.element instanceof ModbusRegisterElement registerElement) { + switch (this.element) { + case ModbusRegisterElement registerElement -> { try { registerElement.setNextWriteValueFromObject(convertedValue); } catch (IllegalArgumentException e) { @@ -369,8 +370,9 @@ public ELEMENT build() { e.printStackTrace(); } } + } - } else if (this.element instanceof CoilElement coilElement) { + case CoilElement coilElement -> { try { coilElement.setNextWriteValue(TypeUtils.getAsType(OpenemsType.BOOLEAN, convertedValue)); } catch (IllegalArgumentException e) { @@ -378,9 +380,10 @@ public ELEMENT build() { "Unable to write to ModbusCoilElement " // + "[" + this.element.startAddress + "]: " + e.getMessage()); } + } - } else { - AbstractOpenemsModbusComponent.this.logWarn(AbstractOpenemsModbusComponent.this.log, + default // + -> AbstractOpenemsModbusComponent.this.logWarn(AbstractOpenemsModbusComponent.this.log, "Unable to write to Element " // + "[" + this.element.startAddress + "]: it is not a ModbusElement"); } diff --git a/io.openems.edge.bridge.modbus/src/io/openems/edge/bridge/modbus/api/ElementToChannelConverter.java b/io.openems.edge.bridge.modbus/src/io/openems/edge/bridge/modbus/api/ElementToChannelConverter.java index 87a9c0eb0bb..17de9f9ea32 100644 --- a/io.openems.edge.bridge.modbus/src/io/openems/edge/bridge/modbus/api/ElementToChannelConverter.java +++ b/io.openems.edge.bridge.modbus/src/io/openems/edge/bridge/modbus/api/ElementToChannelConverter.java @@ -441,47 +441,41 @@ private static Object apply(// Function floatFactor, // Function doubleFactor // ) { - if (value == null) { - return null; - } - if (value instanceof Boolean) { - return (boolean) value; - } - if (value instanceof Short s) { + return switch (value) { + case null -> null; + case Boolean b -> b; + case Short s -> { long result = shortFactor.apply(s); if (result >= Short.MIN_VALUE && result <= Short.MAX_VALUE) { - return Short.valueOf((short) result); - } - if (result > Integer.MIN_VALUE && result < Integer.MAX_VALUE) { - return Integer.valueOf((int) result); - } else { - return Long.valueOf(result); + yield Short.valueOf((short) result); + } else if (result > Integer.MIN_VALUE && result < Integer.MAX_VALUE) { + yield Integer.valueOf((int) result); } + yield Long.valueOf(result); } - if (value instanceof Integer i) { + case Integer i -> { long result = integerFactor.apply(i); if (result >= Integer.MIN_VALUE && result <= Integer.MAX_VALUE) { - return Integer.valueOf((int) result); + yield Integer.valueOf((int) result); } - return Long.valueOf(result); - } - if (value instanceof Long l) { - return longFactor.apply(l); + yield Long.valueOf(result); } - if (value instanceof Float f) { + case Long l // + -> longFactor.apply(l); + case Float f -> { double result = floatFactor.apply(f); if (result >= Float.MIN_VALUE && result <= Float.MAX_VALUE) { - return Float.valueOf((float) result); + yield Float.valueOf((float) result); } - return Double.valueOf(result); + yield Double.valueOf(result); } - if (value instanceof Double d) { - return doubleFactor.apply(d); - } - if (value instanceof String) { - return value; - } - throw new IllegalArgumentException( - "Type [" + value.getClass().getName() + "] not supported by OFFSET converter"); + case Double d // + -> doubleFactor.apply(d); + case String s // + -> s; + default // + -> throw new IllegalArgumentException( + "Type [" + value.getClass().getName() + "] not supported by OFFSET converter"); + }; } } diff --git a/io.openems.edge.bridge.modbus/src/io/openems/edge/bridge/modbus/api/ElementToChannelScaleFactorConverter.java b/io.openems.edge.bridge.modbus/src/io/openems/edge/bridge/modbus/api/ElementToChannelScaleFactorConverter.java index cf558a53d99..3cce387c0e0 100644 --- a/io.openems.edge.bridge.modbus/src/io/openems/edge/bridge/modbus/api/ElementToChannelScaleFactorConverter.java +++ b/io.openems.edge.bridge.modbus/src/io/openems/edge/bridge/modbus/api/ElementToChannelScaleFactorConverter.java @@ -64,48 +64,43 @@ public ElementToChannelScaleFactorConverter(int scaleFactor) { private static Object apply(Object value, int scaleFactor) { var factor = Math.pow(10, scaleFactor * -1); - if (value == null) { - return null; - } - if (value instanceof Boolean) { - return (boolean) value; - } - if (value instanceof Short) { - var result = (Short) value * factor; + return switch (value) { + case null -> null; + case Boolean b -> b; + case Short s -> { + var result = s * factor; if (result >= Short.MIN_VALUE && result <= Short.MAX_VALUE) { - return Short.valueOf((short) result); - } - if (result > Integer.MIN_VALUE && result < Integer.MAX_VALUE) { - return Integer.valueOf((int) result); - } else { - return Double.valueOf(Math.round(result)); + yield Short.valueOf((short) result); + } else if (result > Integer.MIN_VALUE && result < Integer.MAX_VALUE) { + yield Integer.valueOf((int) result); } + yield Double.valueOf(Math.round(result)); } - if (value instanceof Integer) { - var result = (Integer) value * factor; + case Integer i -> { + var result = i * factor; if (result >= Integer.MIN_VALUE && result <= Integer.MAX_VALUE) { - return Integer.valueOf((int) result); + yield Integer.valueOf((int) result); } - return Double.valueOf(Math.round(result)); + yield Double.valueOf(Math.round(result)); } - if (value instanceof Long) { - var result = (Long) value * factor; - return Math.round(result); + case Long l -> { + var result = l * factor; + yield Math.round(result); } - if (value instanceof Float) { - var result = (Float) value * factor; + case Float f -> { + var result = f * factor; if (result >= Float.MIN_VALUE && result <= Float.MAX_VALUE) { - return Float.valueOf((float) result); + yield Float.valueOf((float) result); } - return Double.valueOf(result); - } - if (value instanceof Double) { - return Double.valueOf((Double) value * factor); - } - if (value instanceof String) { - return value; + yield Double.valueOf(result); } - throw new IllegalArgumentException( - "Type [" + value.getClass().getName() + "] not supported by SCALE_FACTOR converter"); + case Double d // + -> Double.valueOf(d * factor); + case String s // + -> s; + default // + -> throw new IllegalArgumentException( + "Type [" + value.getClass().getName() + "] not supported by SCALE_FACTOR converter"); + }; } } diff --git a/io.openems.edge.bridge.modbus/src/io/openems/edge/bridge/modbus/api/task/AbstractTask.java b/io.openems.edge.bridge.modbus/src/io/openems/edge/bridge/modbus/api/task/AbstractTask.java index 35c419f539e..0393ace47e1 100644 --- a/io.openems.edge.bridge.modbus/src/io/openems/edge/bridge/modbus/api/task/AbstractTask.java +++ b/io.openems.edge.bridge.modbus/src/io/openems/edge/bridge/modbus/api/task/AbstractTask.java @@ -1,5 +1,7 @@ package io.openems.edge.bridge.modbus.api.task; +import static io.openems.common.utils.FunctionUtils.doNothing; + import java.util.Arrays; import java.util.concurrent.TimeUnit; import java.util.function.BiConsumer; @@ -309,8 +311,8 @@ protected final String toLogMessage(LogVerbosity logVerbosity, int startAddress, .append(";ref=").append(startAddress).append("/0x").append(Integer.toHexString(startAddress)) // .append(";length=").append(length); // switch (logVerbosity) { - case NONE, DEBUG_LOG, READS_AND_WRITES, READS_AND_WRITES_DURATION, READS_AND_WRITES_DURATION_TRACE_EVENTS -> { - } + case NONE, DEBUG_LOG, READS_AND_WRITES, READS_AND_WRITES_DURATION, READS_AND_WRITES_DURATION_TRACE_EVENTS // + -> doNothing(); case READS_AND_WRITES_VERBOSE -> { if (request != null) { var hexString = this.payloadToString(request); diff --git a/io.openems.edge.bridge.modbus/src/io/openems/edge/bridge/modbus/api/task/FC16WriteRegistersTask.java b/io.openems.edge.bridge.modbus/src/io/openems/edge/bridge/modbus/api/task/FC16WriteRegistersTask.java index 7767f54674b..726a4dccb32 100644 --- a/io.openems.edge.bridge.modbus/src/io/openems/edge/bridge/modbus/api/task/FC16WriteRegistersTask.java +++ b/io.openems.edge.bridge.modbus/src/io/openems/edge/bridge/modbus/api/task/FC16WriteRegistersTask.java @@ -85,7 +85,8 @@ protected static List mergeWriteRegisters(ModbusElement[] Consumer logWarn) { final var writes = new ArrayList(); for (var element : elements) { - if (element instanceof ModbusRegisterElement e) { + switch (element) { + case ModbusRegisterElement e -> { var registers = e.getNextWriteValueAndReset(); if (registers != null) { // found value registers -> add to 'writes' @@ -107,7 +108,8 @@ protected static List mergeWriteRegisters(ModbusElement[] } write.add(registers); } - } else { + } + default -> // logWarn.accept( "Unable to execute Write for ModbusElement [" + element + "]: No ModbusRegisterElement!"); } diff --git a/io.openems.edge.bridge.modbus/src/io/openems/edge/bridge/modbus/api/worker/ModbusWorker.java b/io.openems.edge.bridge.modbus/src/io/openems/edge/bridge/modbus/api/worker/ModbusWorker.java index 2558852fc4d..d9ad7008a9c 100644 --- a/io.openems.edge.bridge.modbus/src/io/openems/edge/bridge/modbus/api/worker/ModbusWorker.java +++ b/io.openems.edge.bridge.modbus/src/io/openems/edge/bridge/modbus/api/worker/ModbusWorker.java @@ -1,5 +1,7 @@ package io.openems.edge.bridge.modbus.api.worker; +import static io.openems.common.utils.FunctionUtils.doNothing; + import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Supplier; @@ -74,21 +76,19 @@ protected void forever() throws InterruptedException { // execute the task var result = this.execute.apply(task); - // NOTE: with Java 21 LTS this can be refactored to a pattern matching switch - // statement - if (result instanceof ExecuteState.Ok) { + switch (result) { + case ExecuteState.Ok es -> // no exception & at least one sub-task executed this.markComponentAsDefective(task.getParent(), false); - - } else if (result instanceof ExecuteState.NoOp) { + case ExecuteState.NoOp es -> // did not execute anything - - } else if (result instanceof ExecuteState.Error) { + doNothing(); + case ExecuteState.Error es -> { this.markComponentAsDefective(task.getParent(), true); - // invalidate elements of this task this.invalidate.accept(task.getElements()); } + } } /** diff --git a/io.openems.edge.bridge.modbus/src/io/openems/edge/bridge/modbus/sunspec/AbstractOpenemsSunSpecComponent.java b/io.openems.edge.bridge.modbus/src/io/openems/edge/bridge/modbus/sunspec/AbstractOpenemsSunSpecComponent.java index 42e57c330b4..b64f0a62f48 100644 --- a/io.openems.edge.bridge.modbus/src/io/openems/edge/bridge/modbus/sunspec/AbstractOpenemsSunSpecComponent.java +++ b/io.openems.edge.bridge.modbus/src/io/openems/edge/bridge/modbus/sunspec/AbstractOpenemsSunSpecComponent.java @@ -346,25 +346,26 @@ protected void addBlock(int startAddress, SunSpecModel model, Priority priority) */ protected List addModbusElementAndChannels(int startAddress, SunSpecModel model, SunSpecPoint ssp) { final var p = ssp.get(); - // TODO migrate to Java 21 Switch Pattern Matching - if (p instanceof BitFieldPoint bfp) { + return switch (p) { + case BitFieldPoint bfp -> { // Channels are added and mapped internally var alternativeBitPoints = this.getBitPoints(bfp); - return bfp.generateModbusElements(this, channelId -> this.addChannel(channelId), startAddress, + yield bfp.generateModbusElements(this, channelId -> this.addChannel(channelId), startAddress, alternativeBitPoints); } - if (p instanceof ModbusElementPoint mep) { + case ModbusElementPoint mep -> { final var element = mep.generateModbusElement(startAddress); if (p instanceof ChannelIdPoint cp) { var channelId = cp.channelId; this.addChannel(channelId); this.m(channelId, element, this.generateElementToChannelConverter(model, p)); } - return List.of(element); + yield List.of(element); } - return List.of(); + case ChannelIdPoint cip -> List.of(); + }; } /** @@ -429,11 +430,10 @@ protected ElementToChannelConverter generateElementToChannelConverter(SunSpecMod /* Channel -> Element */ value -> value); // Generate Scale-Factor converter (possibly null) - ElementToChannelConverter scaleFactorConverter = null; - - if (point instanceof ScaledValuePoint svp) { + var scaleFactorConverter = switch (point) { + case ScaledValuePoint svp -> { final var scaleFactorName = toUpperUnderscore(svp.scaleFactor); - scaleFactorConverter = Stream.of(model.points()) // + yield Stream.of(model.points()) // .filter(p -> p.name().equals(scaleFactorName)) // .map(SunSpecPoint::get) // .filter(ScaleFactorPoint.class::isInstance) // @@ -454,6 +454,8 @@ protected ElementToChannelConverter generateElementToChannelConverter(SunSpecMod } }); // } + default -> null; + }; if (scaleFactorConverter != null) { return ElementToChannelConverter.chain(valueIsDefinedConverter, scaleFactorConverter); @@ -470,17 +472,16 @@ protected ElementToChannelConverter generateElementToChannelConverter(SunSpecMod * @return the optional {@link Channel} */ protected > Optional getSunSpecChannel(SunSpecPoint ssp) { - var point = ssp.get(); - if (point instanceof ChannelIdPoint cp) { + return switch (ssp.get()) { + case ChannelIdPoint cp -> { try { - return Optional.ofNullable(this.channel(cp.channelId)); + yield Optional.ofNullable(this.channel(cp.channelId)); } catch (IllegalArgumentException e) { - // Ignore + yield Optional.empty(); } - } else { - // Ignore } - return Optional.empty(); + default -> Optional.empty(); + }; } /** diff --git a/io.openems.edge.bridge.modbus/src/io/openems/edge/bridge/modbus/sunspec/DefaultSunSpecModel.java b/io.openems.edge.bridge.modbus/src/io/openems/edge/bridge/modbus/sunspec/DefaultSunSpecModel.java index 8911c6ee34e..7d5a31e4c8d 100644 --- a/io.openems.edge.bridge.modbus/src/io/openems/edge/bridge/modbus/sunspec/DefaultSunSpecModel.java +++ b/io.openems.edge.bridge.modbus/src/io/openems/edge/bridge/modbus/sunspec/DefaultSunSpecModel.java @@ -2,7 +2,29 @@ package io.openems.edge.bridge.modbus.sunspec; -import io.openems.common.channel.AccessMode; +import static io.openems.common.channel.AccessMode.READ_ONLY; +import static io.openems.common.channel.AccessMode.READ_WRITE; +import static io.openems.edge.bridge.modbus.sunspec.Point.BitFieldPoint.Type.BITFIELD16; +import static io.openems.edge.bridge.modbus.sunspec.Point.BitFieldPoint.Type.BITFIELD32; +import static io.openems.edge.bridge.modbus.sunspec.Point.EnumPoint.Type.ENUM16; +import static io.openems.edge.bridge.modbus.sunspec.Point.EnumPoint.Type.ENUM32; +import static io.openems.edge.bridge.modbus.sunspec.Point.ValuePoint.Type.ACC32; +import static io.openems.edge.bridge.modbus.sunspec.Point.ValuePoint.Type.ACC64; +import static io.openems.edge.bridge.modbus.sunspec.Point.ValuePoint.Type.FLOAT32; +import static io.openems.edge.bridge.modbus.sunspec.Point.ValuePoint.Type.INT16; +import static io.openems.edge.bridge.modbus.sunspec.Point.ValuePoint.Type.INT32; +import static io.openems.edge.bridge.modbus.sunspec.Point.ValuePoint.Type.STRING16; +import static io.openems.edge.bridge.modbus.sunspec.Point.ValuePoint.Type.STRING2; +import static io.openems.edge.bridge.modbus.sunspec.Point.ValuePoint.Type.STRING20; +import static io.openems.edge.bridge.modbus.sunspec.Point.ValuePoint.Type.STRING32; +import static io.openems.edge.bridge.modbus.sunspec.Point.ValuePoint.Type.STRING4; +import static io.openems.edge.bridge.modbus.sunspec.Point.ValuePoint.Type.STRING5; +import static io.openems.edge.bridge.modbus.sunspec.Point.ValuePoint.Type.STRING6; +import static io.openems.edge.bridge.modbus.sunspec.Point.ValuePoint.Type.STRING8; +import static io.openems.edge.bridge.modbus.sunspec.Point.ValuePoint.Type.UINT16; +import static io.openems.edge.bridge.modbus.sunspec.Point.ValuePoint.Type.UINT32; +import static io.openems.edge.bridge.modbus.sunspec.Point.ValuePoint.Type.UINT64; + import io.openems.common.channel.Level; import io.openems.common.channel.Unit; import io.openems.common.types.OptionsEnum; @@ -166,25 +188,25 @@ public enum DefaultSunSpecModel implements SunSpecModel { public static enum S1 implements SunSpecPoint { MN(new ValuePoint("S1_MN", "Manufacturer", // "Well known value registered with SunSpec for compliance", // - ValuePoint.Type.STRING16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // + STRING16, true /* mandatory? */, READ_ONLY, Unit.NONE)), // MD(new ValuePoint("S1_MD", "Model", // "Manufacturer specific value (32 chars)", // - ValuePoint.Type.STRING16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // + STRING16, true /* mandatory? */, READ_ONLY, Unit.NONE)), // OPT(new ValuePoint("S1_OPT", "Options", // "Manufacturer specific value (16 chars)", // - ValuePoint.Type.STRING8, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // + STRING8, false /* mandatory? */, READ_ONLY, Unit.NONE)), // VR(new ValuePoint("S1_VR", "Version", // "Manufacturer specific value (16 chars)", // - ValuePoint.Type.STRING8, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // + STRING8, false /* mandatory? */, READ_ONLY, Unit.NONE)), // SN(new ValuePoint("S1_SN", "Serial Number", // "Manufacturer specific value (32 chars)", // - ValuePoint.Type.STRING16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // + STRING16, true /* mandatory? */, READ_ONLY, Unit.NONE)), // DA(new ValuePoint("S1_DA", "Device Address", // "Modbus device address", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_WRITE, Unit.NONE)), // + UINT16, false /* mandatory? */, READ_WRITE, Unit.NONE)), // PAD(new ValuePoint("S1_PAD", "", // "Force even alignment", // - ValuePoint.Type.PAD, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)); + ValuePoint.Type.PAD, false /* mandatory? */, READ_ONLY, Unit.NONE)); private final Point point; @@ -201,34 +223,34 @@ public Point get() { public static enum S2 implements SunSpecPoint { AID(new ValuePoint("S2_AID", "AID", // "Aggregated model id", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // + UINT16, true /* mandatory? */, READ_ONLY, Unit.NONE)), // N(new ValuePoint("S2_N", "N", // "Number of aggregated models", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // + UINT16, true /* mandatory? */, READ_ONLY, Unit.NONE)), // UN(new ValuePoint("S2_UN", "UN", // "Update Number. Incrementing number each time the mapping is changed. If the number is not changed from the last reading the direct access to a specific offset will result in reading the same logical model as before. Otherwise the entire model must be read to refresh the changes", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // + UINT16, true /* mandatory? */, READ_ONLY, Unit.NONE)), // ST(new EnumPoint("S2_ST", "Status", // "Enumerated status code", // - EnumPoint.Type.ENUM16, true /* mandatory? */, AccessMode.READ_ONLY, S2_St.values())), // + ENUM16, true /* mandatory? */, READ_ONLY, S2_St.values())), // ST_VND(new EnumPoint("S2_ST_VND", "Vendor Status", // "Vendor specific status code", // - EnumPoint.Type.ENUM16, false /* mandatory? */, AccessMode.READ_ONLY, new OptionsEnum[0])), // + ENUM16, false /* mandatory? */, READ_ONLY, new OptionsEnum[0])), // EVT(new BitFieldPoint("S2_EVT", "Event Code", // "Bitmask event code", // - BitFieldPoint.Type.BITFIELD32, true /* mandatory? */, AccessMode.READ_ONLY, S2_Evt.values())), // + BITFIELD32, true /* mandatory? */, READ_ONLY, S2_Evt.values())), // EVT_VND(new BitFieldPoint("S2_EVT_VND", "Vendor Event Code", // "Vendor specific event code", // - BitFieldPoint.Type.BITFIELD32, false /* mandatory? */, AccessMode.READ_ONLY, new SunSpecBitPoint[0])), // + BITFIELD32, false /* mandatory? */, READ_ONLY, new SunSpecBitPoint[0])), // CTL(new EnumPoint("S2_CTL", "Control", // "Control register for all aggregated devices", // - EnumPoint.Type.ENUM16, false /* mandatory? */, AccessMode.READ_ONLY, S2_Ctl.values())), // + ENUM16, false /* mandatory? */, READ_ONLY, S2_Ctl.values())), // CTL_VND(new EnumPoint("S2_CTL_VND", "Vendor Control", // "Vendor control register for all aggregated devices", // - EnumPoint.Type.ENUM32, false /* mandatory? */, AccessMode.READ_ONLY, new OptionsEnum[0])), // + ENUM32, false /* mandatory? */, READ_ONLY, new OptionsEnum[0])), // CTL_VL(new EnumPoint("S2_CTL_VL", "Control Value", // "Numerical value used as a parameter to the control", // - EnumPoint.Type.ENUM32, false /* mandatory? */, AccessMode.READ_ONLY, new OptionsEnum[0])); + ENUM32, false /* mandatory? */, READ_ONLY, new OptionsEnum[0])); private final Point point; @@ -343,42 +365,42 @@ public OptionsEnum getUndefined() { public static enum S15 implements SunSpecPoint { CLR(new ValuePoint("S15_CLR", "Clear", // "Write a \"1\" to clear all counters", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_WRITE, Unit.NONE)), // + UINT16, false /* mandatory? */, READ_WRITE, Unit.NONE)), // IN_CNT(new ValuePoint("S15_IN_CNT", "Input Count", // "Number of bytes received", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // + ACC32, false /* mandatory? */, READ_ONLY, Unit.NONE)), // IN_UC_CNT(new ValuePoint("S15_IN_UC_CNT", "Input Unicast Count", // "Number of Unicast packets received", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // + ACC32, false /* mandatory? */, READ_ONLY, Unit.NONE)), // IN_N_UC_CNT(new ValuePoint("S15_IN_N_UC_CNT", "Input Non-Unicast Count", // "Number of non-Unicast packets received", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // + ACC32, false /* mandatory? */, READ_ONLY, Unit.NONE)), // IN_DSC_CNT(new ValuePoint("S15_IN_DSC_CNT", "Input Discarded Count", // "Number of inbound packets received on the interface but discarded", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // + ACC32, false /* mandatory? */, READ_ONLY, Unit.NONE)), // IN_ERR_CNT(new ValuePoint("S15_IN_ERR_CNT", "Input Error Count", // "Number of inbound packets that contain errors (excluding discards)", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // + ACC32, false /* mandatory? */, READ_ONLY, Unit.NONE)), // IN_UNK_CNT(new ValuePoint("S15_IN_UNK_CNT", "Input Unknown Count", // "Number of inbound packets with unknown protocol", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // + ACC32, false /* mandatory? */, READ_ONLY, Unit.NONE)), // OUT_CNT(new ValuePoint("S15_OUT_CNT", "Output Count", // "Total number of bytes transmitted on this interface", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // + ACC32, false /* mandatory? */, READ_ONLY, Unit.NONE)), // OUT_UC_CNT(new ValuePoint("S15_OUT_UC_CNT", "Output Unicast Count", // "Number of Unicast packets transmitted", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // + ACC32, false /* mandatory? */, READ_ONLY, Unit.NONE)), // OUT_N_UC_CNT(new ValuePoint("S15_OUT_N_UC_CNT", "Output Non-Unicast Count", // "Number of Non-Unicast packets transmitted", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // + ACC32, false /* mandatory? */, READ_ONLY, Unit.NONE)), // OUT_DSC_CNT(new ValuePoint("S15_OUT_DSC_CNT", "Output Discarded Count", // "Number of Discarded output packets", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // + ACC32, false /* mandatory? */, READ_ONLY, Unit.NONE)), // OUT_ERR_CNT(new ValuePoint("S15_OUT_ERR_CNT", "Output Error Count", // "Number of outbound error packets", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // + ACC32, false /* mandatory? */, READ_ONLY, Unit.NONE)), // PAD(new ValuePoint("S15_PAD", "", "", // - ValuePoint.Type.PAD, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)); + ValuePoint.Type.PAD, false /* mandatory? */, READ_ONLY, Unit.NONE)); private final Point point; @@ -395,19 +417,19 @@ public Point get() { public static enum S18 implements SunSpecPoint { NAM(new ValuePoint("S18_NAM", "Name", // "Interface name", // - ValuePoint.Type.STRING4, false /* mandatory? */, AccessMode.READ_WRITE, Unit.NONE)), // + STRING4, false /* mandatory? */, READ_WRITE, Unit.NONE)), // IMEI(new ValuePoint("S18_IMEI", "IMEI", // "International Mobile Equipment Identifier for the interface", // - ValuePoint.Type.UINT32, false /* mandatory? */, AccessMode.READ_WRITE, Unit.NONE)), // + UINT32, false /* mandatory? */, READ_WRITE, Unit.NONE)), // APN(new ValuePoint("S18_APN", "APN", // "Access Point Name for the interface", // - ValuePoint.Type.STRING4, false /* mandatory? */, AccessMode.READ_WRITE, Unit.NONE)), // + STRING4, false /* mandatory? */, READ_WRITE, Unit.NONE)), // NUM(new ValuePoint("S18_NUM", "Number", // "Phone number for the interface", // - ValuePoint.Type.STRING6, false /* mandatory? */, AccessMode.READ_WRITE, Unit.NONE)), // + STRING6, false /* mandatory? */, READ_WRITE, Unit.NONE)), // PIN(new ValuePoint("S18_PIN", "PIN", // "Personal Identification Number for the interface", // - ValuePoint.Type.STRING6, false /* mandatory? */, AccessMode.READ_WRITE, Unit.NONE)); + STRING6, false /* mandatory? */, READ_WRITE, Unit.NONE)); private final Point point; @@ -424,109 +446,109 @@ public Point get() { public static enum S101 implements SunSpecPoint { A(new ScaledValuePoint("S101_A", "Amps", // "AC Current", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.AMPERE, "A_SF")), // + UINT16, true /* mandatory? */, READ_ONLY, Unit.AMPERE, "A_SF")), // APH_A(new ScaledValuePoint("S101_APH_A", "Amps PhaseA", // "Phase A Current", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.AMPERE, "A_SF")), // + UINT16, true /* mandatory? */, READ_ONLY, Unit.AMPERE, "A_SF")), // APH_B(new ScaledValuePoint("S101_APH_B", "Amps PhaseB", // "Phase B Current", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.AMPERE, "A_SF")), // + UINT16, false /* mandatory? */, READ_ONLY, Unit.AMPERE, "A_SF")), // APH_C(new ScaledValuePoint("S101_APH_C", "Amps PhaseC", // "Phase C Current", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.AMPERE, "A_SF")), // + UINT16, false /* mandatory? */, READ_ONLY, Unit.AMPERE, "A_SF")), // A_SF(new ScaleFactorPoint("S101_A_SF", "", "")), // P_P_VPH_A_B(new ScaledValuePoint("S101_P_P_VPH_A_B", "Phase Voltage AB", // "Phase Voltage AB", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT, "V_SF")), // + UINT16, false /* mandatory? */, READ_ONLY, Unit.VOLT, "V_SF")), // P_P_VPH_B_C(new ScaledValuePoint("S101_P_P_VPH_B_C", "Phase Voltage BC", // "Phase Voltage BC", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT, "V_SF")), // + UINT16, false /* mandatory? */, READ_ONLY, Unit.VOLT, "V_SF")), // P_P_VPH_C_A(new ScaledValuePoint("S101_P_P_VPH_C_A", "Phase Voltage CA", // "Phase Voltage CA", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT, "V_SF")), // + UINT16, false /* mandatory? */, READ_ONLY, Unit.VOLT, "V_SF")), // PH_VPH_A(new ScaledValuePoint("S101_PH_VPH_A", "Phase Voltage AN", // "Phase Voltage AN", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT, "V_SF")), // + UINT16, true /* mandatory? */, READ_ONLY, Unit.VOLT, "V_SF")), // PH_VPH_B(new ScaledValuePoint("S101_PH_VPH_B", "Phase Voltage BN", // "Phase Voltage BN", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT, "V_SF")), // + UINT16, false /* mandatory? */, READ_ONLY, Unit.VOLT, "V_SF")), // PH_VPH_C(new ScaledValuePoint("S101_PH_VPH_C", "Phase Voltage CN", // "Phase Voltage CN", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT, "V_SF")), // + UINT16, false /* mandatory? */, READ_ONLY, Unit.VOLT, "V_SF")), // V_SF(new ScaleFactorPoint("S101_V_SF", "", "")), // W(new ScaledValuePoint("S101_W", "Watts", // "AC Power", // - ValuePoint.Type.INT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.WATT, "W_SF")), // + INT16, true /* mandatory? */, READ_ONLY, Unit.WATT, "W_SF")), // W_SF(new ScaleFactorPoint("S101_W_SF", "", "")), // HZ(new ScaledValuePoint("S101_HZ", "Hz", // "Line Frequency", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.HERTZ, "Hz_SF")), // + UINT16, true /* mandatory? */, READ_ONLY, Unit.HERTZ, "Hz_SF")), // HZ_S_F(new ScaleFactorPoint("S101_HZ_S_F", "", "")), // VA(new ScaledValuePoint("S101_VA", "VA", // "AC Apparent Power", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE, "VA_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE, "VA_SF")), // VA_SF(new ScaleFactorPoint("S101_VA_SF", "", "")), // V_AR(new ScaledValuePoint("S101_V_AR", "VAr", // "AC Reactive Power", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE, "VAr_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE, "VAr_SF")), // V_AR_S_F(new ScaleFactorPoint("S101_V_AR_S_F", "", "")), // PF(new ScaledValuePoint("S101_PF", "PF", // "AC Power Factor", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE, "PF_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.NONE, "PF_SF")), // PF_SF(new ScaleFactorPoint("S101_PF_SF", "", "")), // WH(new ScaledValuePoint("S101_WH", "WattHours", // "AC Energy", // - ValuePoint.Type.ACC32, true /* mandatory? */, AccessMode.READ_ONLY, Unit.CUMULATED_WATT_HOURS, "WH_SF")), // + ACC32, true /* mandatory? */, READ_ONLY, Unit.CUMULATED_WATT_HOURS, "WH_SF")), // WH_SF(new ScaleFactorPoint("S101_WH_SF", "", "")), // DCA(new ScaledValuePoint("S101_DCA", "DC Amps", // "DC Current", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.AMPERE, "DCA_SF")), // + UINT16, false /* mandatory? */, READ_ONLY, Unit.AMPERE, "DCA_SF")), // DCA_SF(new ScaleFactorPoint("S101_DCA_SF", "", "")), // DCV(new ScaledValuePoint("S101_DCV", "DC Voltage", // "DC Voltage", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT, "DCV_SF")), // + UINT16, false /* mandatory? */, READ_ONLY, Unit.VOLT, "DCV_SF")), // DCV_SF(new ScaleFactorPoint("S101_DCV_SF", "", "")), // DCW(new ScaledValuePoint("S101_DCW", "DC Watts", // "DC Power", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.WATT, "DCW_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.WATT, "DCW_SF")), // DCW_SF(new ScaleFactorPoint("S101_DCW_SF", "", "")), // TMP_CAB(new ScaledValuePoint("S101_TMP_CAB", "Cabinet Temperature", // "Cabinet Temperature", // - ValuePoint.Type.INT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.DEGREE_CELSIUS, "Tmp_SF")), // + INT16, true /* mandatory? */, READ_ONLY, Unit.DEGREE_CELSIUS, "Tmp_SF")), // TMP_SNK(new ScaledValuePoint("S101_TMP_SNK", "Heat Sink Temperature", // "Heat Sink Temperature", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.DEGREE_CELSIUS, "Tmp_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.DEGREE_CELSIUS, "Tmp_SF")), // TMP_TRNS(new ScaledValuePoint("S101_TMP_TRNS", "Transformer Temperature", // "Transformer Temperature", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.DEGREE_CELSIUS, "Tmp_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.DEGREE_CELSIUS, "Tmp_SF")), // TMP_OT(new ScaledValuePoint("S101_TMP_OT", "Other Temperature", // "Other Temperature", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.DEGREE_CELSIUS, "Tmp_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.DEGREE_CELSIUS, "Tmp_SF")), // TMP_S_F(new ScaleFactorPoint("S101_TMP_S_F", "", "")), // ST(new EnumPoint("S101_ST", "Operating State", // "Enumerated value. Operating state", // - EnumPoint.Type.ENUM16, true /* mandatory? */, AccessMode.READ_ONLY, S101_St.values())), // + ENUM16, true /* mandatory? */, READ_ONLY, S101_St.values())), // ST_VND(new EnumPoint("S101_ST_VND", "Vendor Operating State", // "Vendor specific operating state code", // - EnumPoint.Type.ENUM16, false /* mandatory? */, AccessMode.READ_ONLY, new OptionsEnum[0])), // + ENUM16, false /* mandatory? */, READ_ONLY, new OptionsEnum[0])), // EVT1(new BitFieldPoint("S101_EVT1", "Event1", // "Bitmask value. Event fields", // - BitFieldPoint.Type.BITFIELD32, true /* mandatory? */, AccessMode.READ_ONLY, S101_Evt1.values())), // + BITFIELD32, true /* mandatory? */, READ_ONLY, S101_Evt1.values())), // EVT2(new BitFieldPoint("S101_EVT2", "Event Bitfield 2", // "Reserved for future use", // - BitFieldPoint.Type.BITFIELD32, true /* mandatory? */, AccessMode.READ_ONLY, new SunSpecBitPoint[0])), // + BITFIELD32, true /* mandatory? */, READ_ONLY, new SunSpecBitPoint[0])), // EVT_VND1(new BitFieldPoint("S101_EVT_VND1", "Vendor Event Bitfield 1", // "Vendor defined events", // - BitFieldPoint.Type.BITFIELD32, false /* mandatory? */, AccessMode.READ_ONLY, new SunSpecBitPoint[0])), // + BITFIELD32, false /* mandatory? */, READ_ONLY, new SunSpecBitPoint[0])), // EVT_VND2(new BitFieldPoint("S101_EVT_VND2", "Vendor Event Bitfield 2", // "Vendor defined events", // - BitFieldPoint.Type.BITFIELD32, false /* mandatory? */, AccessMode.READ_ONLY, new SunSpecBitPoint[0])), // + BITFIELD32, false /* mandatory? */, READ_ONLY, new SunSpecBitPoint[0])), // EVT_VND3(new BitFieldPoint("S101_EVT_VND3", "Vendor Event Bitfield 3", // "Vendor defined events", // - BitFieldPoint.Type.BITFIELD32, false /* mandatory? */, AccessMode.READ_ONLY, new SunSpecBitPoint[0])), // + BITFIELD32, false /* mandatory? */, READ_ONLY, new SunSpecBitPoint[0])), // EVT_VND4(new BitFieldPoint("S101_EVT_VND4", "Vendor Event Bitfield 4", // "Vendor defined events", // - BitFieldPoint.Type.BITFIELD32, false /* mandatory? */, AccessMode.READ_ONLY, new SunSpecBitPoint[0])); + BITFIELD32, false /* mandatory? */, READ_ONLY, new SunSpecBitPoint[0])); private final Point point; @@ -608,109 +630,109 @@ public BitPoint get() { public static enum S102 implements SunSpecPoint { A(new ScaledValuePoint("S102_A", "Amps", // "AC Current", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.AMPERE, "A_SF")), // + UINT16, true /* mandatory? */, READ_ONLY, Unit.AMPERE, "A_SF")), // APH_A(new ScaledValuePoint("S102_APH_A", "Amps PhaseA", // "Phase A Current", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.AMPERE, "A_SF")), // + UINT16, true /* mandatory? */, READ_ONLY, Unit.AMPERE, "A_SF")), // APH_B(new ScaledValuePoint("S102_APH_B", "Amps PhaseB", // "Phase B Current", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.AMPERE, "A_SF")), // + UINT16, true /* mandatory? */, READ_ONLY, Unit.AMPERE, "A_SF")), // APH_C(new ScaledValuePoint("S102_APH_C", "Amps PhaseC", // "Phase C Current", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.AMPERE, "A_SF")), // + UINT16, false /* mandatory? */, READ_ONLY, Unit.AMPERE, "A_SF")), // A_SF(new ScaleFactorPoint("S102_A_SF", "", "")), // P_P_VPH_A_B(new ScaledValuePoint("S102_P_P_VPH_A_B", "Phase Voltage AB", // "Phase Voltage AB", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT, "V_SF")), // + UINT16, false /* mandatory? */, READ_ONLY, Unit.VOLT, "V_SF")), // P_P_VPH_B_C(new ScaledValuePoint("S102_P_P_VPH_B_C", "Phase Voltage BC", // "Phase Voltage BC", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT, "V_SF")), // + UINT16, false /* mandatory? */, READ_ONLY, Unit.VOLT, "V_SF")), // P_P_VPH_C_A(new ScaledValuePoint("S102_P_P_VPH_C_A", "Phase Voltage CA", // "Phase Voltage CA", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT, "V_SF")), // + UINT16, false /* mandatory? */, READ_ONLY, Unit.VOLT, "V_SF")), // PH_VPH_A(new ScaledValuePoint("S102_PH_VPH_A", "Phase Voltage AN", // "Phase Voltage AN", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT, "V_SF")), // + UINT16, true /* mandatory? */, READ_ONLY, Unit.VOLT, "V_SF")), // PH_VPH_B(new ScaledValuePoint("S102_PH_VPH_B", "Phase Voltage BN", // "Phase Voltage BN", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT, "V_SF")), // + UINT16, true /* mandatory? */, READ_ONLY, Unit.VOLT, "V_SF")), // PH_VPH_C(new ScaledValuePoint("S102_PH_VPH_C", "Phase Voltage CN", // "Phase Voltage CN", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT, "V_SF")), // + UINT16, false /* mandatory? */, READ_ONLY, Unit.VOLT, "V_SF")), // V_SF(new ScaleFactorPoint("S102_V_SF", "", "")), // W(new ScaledValuePoint("S102_W", "Watts", // "AC Power", // - ValuePoint.Type.INT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.WATT, "W_SF")), // + INT16, true /* mandatory? */, READ_ONLY, Unit.WATT, "W_SF")), // W_SF(new ScaleFactorPoint("S102_W_SF", "", "")), // HZ(new ScaledValuePoint("S102_HZ", "Hz", // "Line Frequency", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.HERTZ, "Hz_SF")), // + UINT16, true /* mandatory? */, READ_ONLY, Unit.HERTZ, "Hz_SF")), // HZ_S_F(new ScaleFactorPoint("S102_HZ_S_F", "", "")), // VA(new ScaledValuePoint("S102_VA", "VA", // "AC Apparent Power", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE, "VA_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE, "VA_SF")), // VA_SF(new ScaleFactorPoint("S102_VA_SF", "", "")), // V_AR(new ScaledValuePoint("S102_V_AR", "VAr", // "AC Reactive Power", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE, "VAr_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE, "VAr_SF")), // V_AR_S_F(new ScaleFactorPoint("S102_V_AR_S_F", "", "")), // PF(new ScaledValuePoint("S102_PF", "PF", // "AC Power Factor", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE, "PF_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.NONE, "PF_SF")), // PF_SF(new ScaleFactorPoint("S102_PF_SF", "", "")), // WH(new ScaledValuePoint("S102_WH", "WattHours", // "AC Energy", // - ValuePoint.Type.ACC32, true /* mandatory? */, AccessMode.READ_ONLY, Unit.CUMULATED_WATT_HOURS, "WH_SF")), // + ACC32, true /* mandatory? */, READ_ONLY, Unit.CUMULATED_WATT_HOURS, "WH_SF")), // WH_SF(new ScaleFactorPoint("S102_WH_SF", "", "")), // DCA(new ScaledValuePoint("S102_DCA", "DC Amps", // "DC Current", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.AMPERE, "DCA_SF")), // + UINT16, false /* mandatory? */, READ_ONLY, Unit.AMPERE, "DCA_SF")), // DCA_SF(new ScaleFactorPoint("S102_DCA_SF", "", "")), // DCV(new ScaledValuePoint("S102_DCV", "DC Voltage", // "DC Voltage", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT, "DCV_SF")), // + UINT16, false /* mandatory? */, READ_ONLY, Unit.VOLT, "DCV_SF")), // DCV_SF(new ScaleFactorPoint("S102_DCV_SF", "", "")), // DCW(new ScaledValuePoint("S102_DCW", "DC Watts", // "DC Power", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.WATT, "DCW_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.WATT, "DCW_SF")), // DCW_SF(new ScaleFactorPoint("S102_DCW_SF", "", "")), // TMP_CAB(new ScaledValuePoint("S102_TMP_CAB", "Cabinet Temperature", // "Cabinet Temperature", // - ValuePoint.Type.INT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.DEGREE_CELSIUS, "Tmp_SF")), // + INT16, true /* mandatory? */, READ_ONLY, Unit.DEGREE_CELSIUS, "Tmp_SF")), // TMP_SNK(new ScaledValuePoint("S102_TMP_SNK", "Heat Sink Temperature", // "Heat Sink Temperature", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.DEGREE_CELSIUS, "Tmp_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.DEGREE_CELSIUS, "Tmp_SF")), // TMP_TRNS(new ScaledValuePoint("S102_TMP_TRNS", "Transformer Temperature", // "Transformer Temperature", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.DEGREE_CELSIUS, "Tmp_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.DEGREE_CELSIUS, "Tmp_SF")), // TMP_OT(new ScaledValuePoint("S102_TMP_OT", "Other Temperature", // "Other Temperature", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.DEGREE_CELSIUS, "Tmp_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.DEGREE_CELSIUS, "Tmp_SF")), // TMP_S_F(new ScaleFactorPoint("S102_TMP_S_F", "", "")), // ST(new EnumPoint("S102_ST", "Operating State", // "Enumerated value. Operating state", // - EnumPoint.Type.ENUM16, true /* mandatory? */, AccessMode.READ_ONLY, S102_St.values())), // + ENUM16, true /* mandatory? */, READ_ONLY, S102_St.values())), // ST_VND(new EnumPoint("S102_ST_VND", "Vendor Operating State", // "Vendor specific operating state code", // - EnumPoint.Type.ENUM16, false /* mandatory? */, AccessMode.READ_ONLY, new OptionsEnum[0])), // + ENUM16, false /* mandatory? */, READ_ONLY, new OptionsEnum[0])), // EVT1(new BitFieldPoint("S102_EVT1", "Event1", // "Bitmask value. Event fields", // - BitFieldPoint.Type.BITFIELD32, true /* mandatory? */, AccessMode.READ_ONLY, S102_Evt1.values())), // + BITFIELD32, true /* mandatory? */, READ_ONLY, S102_Evt1.values())), // EVT2(new BitFieldPoint("S102_EVT2", "Event Bitfield 2", // "Reserved for future use", // - BitFieldPoint.Type.BITFIELD32, true /* mandatory? */, AccessMode.READ_ONLY, new SunSpecBitPoint[0])), // + BITFIELD32, true /* mandatory? */, READ_ONLY, new SunSpecBitPoint[0])), // EVT_VND1(new BitFieldPoint("S102_EVT_VND1", "Vendor Event Bitfield 1", // "Vendor defined events", // - BitFieldPoint.Type.BITFIELD32, false /* mandatory? */, AccessMode.READ_ONLY, new SunSpecBitPoint[0])), // + BITFIELD32, false /* mandatory? */, READ_ONLY, new SunSpecBitPoint[0])), // EVT_VND2(new BitFieldPoint("S102_EVT_VND2", "Vendor Event Bitfield 2", // "Vendor defined events", // - BitFieldPoint.Type.BITFIELD32, false /* mandatory? */, AccessMode.READ_ONLY, new SunSpecBitPoint[0])), // + BITFIELD32, false /* mandatory? */, READ_ONLY, new SunSpecBitPoint[0])), // EVT_VND3(new BitFieldPoint("S102_EVT_VND3", "Vendor Event Bitfield 3", // "Vendor defined events", // - BitFieldPoint.Type.BITFIELD32, false /* mandatory? */, AccessMode.READ_ONLY, new SunSpecBitPoint[0])), // + BITFIELD32, false /* mandatory? */, READ_ONLY, new SunSpecBitPoint[0])), // EVT_VND4(new BitFieldPoint("S102_EVT_VND4", "Vendor Event Bitfield 4", // "Vendor defined events", // - BitFieldPoint.Type.BITFIELD32, false /* mandatory? */, AccessMode.READ_ONLY, new SunSpecBitPoint[0])); + BITFIELD32, false /* mandatory? */, READ_ONLY, new SunSpecBitPoint[0])); private final Point point; @@ -792,109 +814,109 @@ public BitPoint get() { public static enum S103 implements SunSpecPoint { A(new ScaledValuePoint("S103_A", "Amps", // "AC Current", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.AMPERE, "A_SF")), // + UINT16, true /* mandatory? */, READ_ONLY, Unit.AMPERE, "A_SF")), // APH_A(new ScaledValuePoint("S103_APH_A", "Amps PhaseA", // "Phase A Current", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.AMPERE, "A_SF")), // + UINT16, true /* mandatory? */, READ_ONLY, Unit.AMPERE, "A_SF")), // APH_B(new ScaledValuePoint("S103_APH_B", "Amps PhaseB", // "Phase B Current", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.AMPERE, "A_SF")), // + UINT16, true /* mandatory? */, READ_ONLY, Unit.AMPERE, "A_SF")), // APH_C(new ScaledValuePoint("S103_APH_C", "Amps PhaseC", // "Phase C Current", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.AMPERE, "A_SF")), // + UINT16, true /* mandatory? */, READ_ONLY, Unit.AMPERE, "A_SF")), // A_SF(new ScaleFactorPoint("S103_A_SF", "", "")), // P_P_VPH_A_B(new ScaledValuePoint("S103_P_P_VPH_A_B", "Phase Voltage AB", // "Phase Voltage AB", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT, "V_SF")), // + UINT16, false /* mandatory? */, READ_ONLY, Unit.VOLT, "V_SF")), // P_P_VPH_B_C(new ScaledValuePoint("S103_P_P_VPH_B_C", "Phase Voltage BC", // "Phase Voltage BC", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT, "V_SF")), // + UINT16, false /* mandatory? */, READ_ONLY, Unit.VOLT, "V_SF")), // P_P_VPH_C_A(new ScaledValuePoint("S103_P_P_VPH_C_A", "Phase Voltage CA", // "Phase Voltage CA", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT, "V_SF")), // + UINT16, false /* mandatory? */, READ_ONLY, Unit.VOLT, "V_SF")), // PH_VPH_A(new ScaledValuePoint("S103_PH_VPH_A", "Phase Voltage AN", // "Phase Voltage AN", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT, "V_SF")), // + UINT16, true /* mandatory? */, READ_ONLY, Unit.VOLT, "V_SF")), // PH_VPH_B(new ScaledValuePoint("S103_PH_VPH_B", "Phase Voltage BN", // "Phase Voltage BN", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT, "V_SF")), // + UINT16, true /* mandatory? */, READ_ONLY, Unit.VOLT, "V_SF")), // PH_VPH_C(new ScaledValuePoint("S103_PH_VPH_C", "Phase Voltage CN", // "Phase Voltage CN", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT, "V_SF")), // + UINT16, true /* mandatory? */, READ_ONLY, Unit.VOLT, "V_SF")), // V_SF(new ScaleFactorPoint("S103_V_SF", "", "")), // W(new ScaledValuePoint("S103_W", "Watts", // "AC Power", // - ValuePoint.Type.INT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.WATT, "W_SF")), // + INT16, true /* mandatory? */, READ_ONLY, Unit.WATT, "W_SF")), // W_SF(new ScaleFactorPoint("S103_W_SF", "", "")), // HZ(new ScaledValuePoint("S103_HZ", "Hz", // "Line Frequency", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.HERTZ, "Hz_SF")), // + UINT16, true /* mandatory? */, READ_ONLY, Unit.HERTZ, "Hz_SF")), // HZ_S_F(new ScaleFactorPoint("S103_HZ_S_F", "", "")), // VA(new ScaledValuePoint("S103_VA", "VA", // "AC Apparent Power", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE, "VA_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE, "VA_SF")), // VA_SF(new ScaleFactorPoint("S103_VA_SF", "", "")), // V_AR(new ScaledValuePoint("S103_V_AR", "VAr", // "AC Reactive Power", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE, "VAr_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE, "VAr_SF")), // V_AR_S_F(new ScaleFactorPoint("S103_V_AR_S_F", "", "")), // PF(new ScaledValuePoint("S103_PF", "PF", // "AC Power Factor", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE, "PF_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.NONE, "PF_SF")), // PF_SF(new ScaleFactorPoint("S103_PF_SF", "", "")), // WH(new ScaledValuePoint("S103_WH", "WattHours", // "AC Energy", // - ValuePoint.Type.ACC32, true /* mandatory? */, AccessMode.READ_ONLY, Unit.CUMULATED_WATT_HOURS, "WH_SF")), // + ACC32, true /* mandatory? */, READ_ONLY, Unit.CUMULATED_WATT_HOURS, "WH_SF")), // WH_SF(new ScaleFactorPoint("S103_WH_SF", "", "")), // DCA(new ScaledValuePoint("S103_DCA", "DC Amps", // "DC Current", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.AMPERE, "DCA_SF")), // + UINT16, false /* mandatory? */, READ_ONLY, Unit.AMPERE, "DCA_SF")), // DCA_SF(new ScaleFactorPoint("S103_DCA_SF", "", "")), // DCV(new ScaledValuePoint("S103_DCV", "DC Voltage", // "DC Voltage", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT, "DCV_SF")), // + UINT16, false /* mandatory? */, READ_ONLY, Unit.VOLT, "DCV_SF")), // DCV_SF(new ScaleFactorPoint("S103_DCV_SF", "", "")), // DCW(new ScaledValuePoint("S103_DCW", "DC Watts", // "DC Power", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.WATT, "DCW_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.WATT, "DCW_SF")), // DCW_SF(new ScaleFactorPoint("S103_DCW_SF", "", "")), // TMP_CAB(new ScaledValuePoint("S103_TMP_CAB", "Cabinet Temperature", // "Cabinet Temperature", // - ValuePoint.Type.INT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.DEGREE_CELSIUS, "Tmp_SF")), // + INT16, true /* mandatory? */, READ_ONLY, Unit.DEGREE_CELSIUS, "Tmp_SF")), // TMP_SNK(new ScaledValuePoint("S103_TMP_SNK", "Heat Sink Temperature", // "Heat Sink Temperature", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.DEGREE_CELSIUS, "Tmp_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.DEGREE_CELSIUS, "Tmp_SF")), // TMP_TRNS(new ScaledValuePoint("S103_TMP_TRNS", "Transformer Temperature", // "Transformer Temperature", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.DEGREE_CELSIUS, "Tmp_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.DEGREE_CELSIUS, "Tmp_SF")), // TMP_OT(new ScaledValuePoint("S103_TMP_OT", "Other Temperature", // "Other Temperature", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.DEGREE_CELSIUS, "Tmp_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.DEGREE_CELSIUS, "Tmp_SF")), // TMP_S_F(new ScaleFactorPoint("S103_TMP_S_F", "", "")), // ST(new EnumPoint("S103_ST", "Operating State", // "Enumerated value. Operating state", // - EnumPoint.Type.ENUM16, true /* mandatory? */, AccessMode.READ_ONLY, S103_St.values())), // + ENUM16, true /* mandatory? */, READ_ONLY, S103_St.values())), // ST_VND(new EnumPoint("S103_ST_VND", "Vendor Operating State", // "Vendor specific operating state code", // - EnumPoint.Type.ENUM16, false /* mandatory? */, AccessMode.READ_ONLY, new OptionsEnum[0])), // + ENUM16, false /* mandatory? */, READ_ONLY, new OptionsEnum[0])), // EVT1(new BitFieldPoint("S103_EVT1", "Event1", // "Bitmask value. Event fields", // - BitFieldPoint.Type.BITFIELD32, true /* mandatory? */, AccessMode.READ_ONLY, S103_Evt1.values())), // + BITFIELD32, true /* mandatory? */, READ_ONLY, S103_Evt1.values())), // EVT2(new BitFieldPoint("S103_EVT2", "Event Bitfield 2", // "Reserved for future use", // - BitFieldPoint.Type.BITFIELD32, true /* mandatory? */, AccessMode.READ_ONLY, new SunSpecBitPoint[0])), // + BITFIELD32, true /* mandatory? */, READ_ONLY, new SunSpecBitPoint[0])), // EVT_VND1(new BitFieldPoint("S103_EVT_VND1", "Vendor Event Bitfield 1", // "Vendor defined events", // - BitFieldPoint.Type.BITFIELD32, false /* mandatory? */, AccessMode.READ_ONLY, new SunSpecBitPoint[0])), // + BITFIELD32, false /* mandatory? */, READ_ONLY, new SunSpecBitPoint[0])), // EVT_VND2(new BitFieldPoint("S103_EVT_VND2", "Vendor Event Bitfield 2", // "Vendor defined events", // - BitFieldPoint.Type.BITFIELD32, false /* mandatory? */, AccessMode.READ_ONLY, new SunSpecBitPoint[0])), // + BITFIELD32, false /* mandatory? */, READ_ONLY, new SunSpecBitPoint[0])), // EVT_VND3(new BitFieldPoint("S103_EVT_VND3", "Vendor Event Bitfield 3", // "Vendor defined events", // - BitFieldPoint.Type.BITFIELD32, false /* mandatory? */, AccessMode.READ_ONLY, new SunSpecBitPoint[0])), // + BITFIELD32, false /* mandatory? */, READ_ONLY, new SunSpecBitPoint[0])), // EVT_VND4(new BitFieldPoint("S103_EVT_VND4", "Vendor Event Bitfield 4", // "Vendor defined events", // - BitFieldPoint.Type.BITFIELD32, false /* mandatory? */, AccessMode.READ_ONLY, new SunSpecBitPoint[0])); + BITFIELD32, false /* mandatory? */, READ_ONLY, new SunSpecBitPoint[0])); private final Point point; @@ -976,97 +998,97 @@ public BitPoint get() { public static enum S111 implements SunSpecPoint { A(new ValuePoint("S111_A", "Amps", // "AC Current", // - ValuePoint.Type.FLOAT32, true /* mandatory? */, AccessMode.READ_ONLY, Unit.AMPERE)), // + FLOAT32, true /* mandatory? */, READ_ONLY, Unit.AMPERE)), // APH_A(new ValuePoint("S111_APH_A", "Amps PhaseA", // "Phase A Current", // - ValuePoint.Type.FLOAT32, true /* mandatory? */, AccessMode.READ_ONLY, Unit.AMPERE)), // + FLOAT32, true /* mandatory? */, READ_ONLY, Unit.AMPERE)), // APH_B(new ValuePoint("S111_APH_B", "Amps PhaseB", // "Phase B Current", // - ValuePoint.Type.FLOAT32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.AMPERE)), // + FLOAT32, false /* mandatory? */, READ_ONLY, Unit.AMPERE)), // APH_C(new ValuePoint("S111_APH_C", "Amps PhaseC", // "Phase C Current", // - ValuePoint.Type.FLOAT32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.AMPERE)), // + FLOAT32, false /* mandatory? */, READ_ONLY, Unit.AMPERE)), // P_P_VPH_A_B(new ValuePoint("S111_P_P_VPH_A_B", "Phase Voltage AB", // "Phase Voltage AB", // - ValuePoint.Type.FLOAT32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT)), // + FLOAT32, false /* mandatory? */, READ_ONLY, Unit.VOLT)), // P_P_VPH_B_C(new ValuePoint("S111_P_P_VPH_B_C", "Phase Voltage BC", // "Phase Voltage BC", // - ValuePoint.Type.FLOAT32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT)), // + FLOAT32, false /* mandatory? */, READ_ONLY, Unit.VOLT)), // P_P_VPH_C_A(new ValuePoint("S111_P_P_VPH_C_A", "Phase Voltage CA", // "Phase Voltage CA", // - ValuePoint.Type.FLOAT32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT)), // + FLOAT32, false /* mandatory? */, READ_ONLY, Unit.VOLT)), // PH_VPH_A(new ValuePoint("S111_PH_VPH_A", "Phase Voltage AN", // "Phase Voltage AN", // - ValuePoint.Type.FLOAT32, true /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT)), // + FLOAT32, true /* mandatory? */, READ_ONLY, Unit.VOLT)), // PH_VPH_B(new ValuePoint("S111_PH_VPH_B", "Phase Voltage BN", // "Phase Voltage BN", // - ValuePoint.Type.FLOAT32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT)), // + FLOAT32, false /* mandatory? */, READ_ONLY, Unit.VOLT)), // PH_VPH_C(new ValuePoint("S111_PH_VPH_C", "Phase Voltage CN", // "Phase Voltage CN", // - ValuePoint.Type.FLOAT32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT)), // + FLOAT32, false /* mandatory? */, READ_ONLY, Unit.VOLT)), // W(new ValuePoint("S111_W", "Watts", // "AC Power", // - ValuePoint.Type.FLOAT32, true /* mandatory? */, AccessMode.READ_ONLY, Unit.WATT)), // + FLOAT32, true /* mandatory? */, READ_ONLY, Unit.WATT)), // HZ(new ValuePoint("S111_HZ", "Hz", // "Line Frequency", // - ValuePoint.Type.FLOAT32, true /* mandatory? */, AccessMode.READ_ONLY, Unit.HERTZ)), // + FLOAT32, true /* mandatory? */, READ_ONLY, Unit.HERTZ)), // VA(new ValuePoint("S111_VA", "VA", // "AC Apparent Power", // - ValuePoint.Type.FLOAT32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE)), // + FLOAT32, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE)), // V_AR(new ValuePoint("S111_V_AR", "VAr", // "AC Reactive Power", // - ValuePoint.Type.FLOAT32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE)), // + FLOAT32, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE)), // PF(new ValuePoint("S111_PF", "PF", // "AC Power Factor", // - ValuePoint.Type.FLOAT32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // + FLOAT32, false /* mandatory? */, READ_ONLY, Unit.NONE)), // WH(new ValuePoint("S111_WH", "WattHours", // "AC Energy", // - ValuePoint.Type.FLOAT32, true /* mandatory? */, AccessMode.READ_ONLY, Unit.CUMULATED_WATT_HOURS)), // + FLOAT32, true /* mandatory? */, READ_ONLY, Unit.CUMULATED_WATT_HOURS)), // DCA(new ValuePoint("S111_DCA", "DC Amps", // "DC Current", // - ValuePoint.Type.FLOAT32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.AMPERE)), // + FLOAT32, false /* mandatory? */, READ_ONLY, Unit.AMPERE)), // DCV(new ValuePoint("S111_DCV", "DC Voltage", // "DC Voltage", // - ValuePoint.Type.FLOAT32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT)), // + FLOAT32, false /* mandatory? */, READ_ONLY, Unit.VOLT)), // DCW(new ValuePoint("S111_DCW", "DC Watts", // "DC Power", // - ValuePoint.Type.FLOAT32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.WATT)), // + FLOAT32, false /* mandatory? */, READ_ONLY, Unit.WATT)), // TMP_CAB(new ValuePoint("S111_TMP_CAB", "Cabinet Temperature", // "Cabinet Temperature", // - ValuePoint.Type.FLOAT32, true /* mandatory? */, AccessMode.READ_ONLY, Unit.DEGREE_CELSIUS)), // + FLOAT32, true /* mandatory? */, READ_ONLY, Unit.DEGREE_CELSIUS)), // TMP_SNK(new ValuePoint("S111_TMP_SNK", "Heat Sink Temperature", // "Heat Sink Temperature", // - ValuePoint.Type.FLOAT32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.DEGREE_CELSIUS)), // + FLOAT32, false /* mandatory? */, READ_ONLY, Unit.DEGREE_CELSIUS)), // TMP_TRNS(new ValuePoint("S111_TMP_TRNS", "Transformer Temperature", // "Transformer Temperature", // - ValuePoint.Type.FLOAT32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.DEGREE_CELSIUS)), // + FLOAT32, false /* mandatory? */, READ_ONLY, Unit.DEGREE_CELSIUS)), // TMP_OT(new ValuePoint("S111_TMP_OT", "Other Temperature", // "Other Temperature", // - ValuePoint.Type.FLOAT32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.DEGREE_CELSIUS)), // + FLOAT32, false /* mandatory? */, READ_ONLY, Unit.DEGREE_CELSIUS)), // ST(new EnumPoint("S111_ST", "Operating State", // "Enumerated value. Operating state", // - EnumPoint.Type.ENUM16, true /* mandatory? */, AccessMode.READ_ONLY, S111_St.values())), // + ENUM16, true /* mandatory? */, READ_ONLY, S111_St.values())), // ST_VND(new EnumPoint("S111_ST_VND", "Vendor Operating State", // "Vendor specific operating state code", // - EnumPoint.Type.ENUM16, false /* mandatory? */, AccessMode.READ_ONLY, new OptionsEnum[0])), // + ENUM16, false /* mandatory? */, READ_ONLY, new OptionsEnum[0])), // EVT1(new BitFieldPoint("S111_EVT1", "Event1", // "Bitmask value. Event fields", // - BitFieldPoint.Type.BITFIELD32, true /* mandatory? */, AccessMode.READ_ONLY, S111_Evt1.values())), // + BITFIELD32, true /* mandatory? */, READ_ONLY, S111_Evt1.values())), // EVT2(new BitFieldPoint("S111_EVT2", "Event Bitfield 2", // "Reserved for future use", // - BitFieldPoint.Type.BITFIELD32, true /* mandatory? */, AccessMode.READ_ONLY, new SunSpecBitPoint[0])), // + BITFIELD32, true /* mandatory? */, READ_ONLY, new SunSpecBitPoint[0])), // EVT_VND1(new BitFieldPoint("S111_EVT_VND1", "Vendor Event Bitfield 1", // "Vendor defined events", // - BitFieldPoint.Type.BITFIELD32, false /* mandatory? */, AccessMode.READ_ONLY, new SunSpecBitPoint[0])), // + BITFIELD32, false /* mandatory? */, READ_ONLY, new SunSpecBitPoint[0])), // EVT_VND2(new BitFieldPoint("S111_EVT_VND2", "Vendor Event Bitfield 2", // "Vendor defined events", // - BitFieldPoint.Type.BITFIELD32, false /* mandatory? */, AccessMode.READ_ONLY, new SunSpecBitPoint[0])), // + BITFIELD32, false /* mandatory? */, READ_ONLY, new SunSpecBitPoint[0])), // EVT_VND3(new BitFieldPoint("S111_EVT_VND3", "Vendor Event Bitfield 3", // "Vendor defined events", // - BitFieldPoint.Type.BITFIELD32, false /* mandatory? */, AccessMode.READ_ONLY, new SunSpecBitPoint[0])), // + BITFIELD32, false /* mandatory? */, READ_ONLY, new SunSpecBitPoint[0])), // EVT_VND4(new BitFieldPoint("S111_EVT_VND4", "Vendor Event Bitfield 4", // "Vendor defined events", // - BitFieldPoint.Type.BITFIELD32, false /* mandatory? */, AccessMode.READ_ONLY, new SunSpecBitPoint[0])); + BITFIELD32, false /* mandatory? */, READ_ONLY, new SunSpecBitPoint[0])); private final Point point; @@ -1148,97 +1170,97 @@ public BitPoint get() { public static enum S112 implements SunSpecPoint { A(new ValuePoint("S112_A", "Amps", // "AC Current", // - ValuePoint.Type.FLOAT32, true /* mandatory? */, AccessMode.READ_ONLY, Unit.AMPERE)), // + FLOAT32, true /* mandatory? */, READ_ONLY, Unit.AMPERE)), // APH_A(new ValuePoint("S112_APH_A", "Amps PhaseA", // "Phase A Current", // - ValuePoint.Type.FLOAT32, true /* mandatory? */, AccessMode.READ_ONLY, Unit.AMPERE)), // + FLOAT32, true /* mandatory? */, READ_ONLY, Unit.AMPERE)), // APH_B(new ValuePoint("S112_APH_B", "Amps PhaseB", // "Phase B Current", // - ValuePoint.Type.FLOAT32, true /* mandatory? */, AccessMode.READ_ONLY, Unit.AMPERE)), // + FLOAT32, true /* mandatory? */, READ_ONLY, Unit.AMPERE)), // APH_C(new ValuePoint("S112_APH_C", "Amps PhaseC", // "Phase C Current", // - ValuePoint.Type.FLOAT32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.AMPERE)), // + FLOAT32, false /* mandatory? */, READ_ONLY, Unit.AMPERE)), // P_P_VPH_A_B(new ValuePoint("S112_P_P_VPH_A_B", "Phase Voltage AB", // "Phase Voltage AB", // - ValuePoint.Type.FLOAT32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT)), // + FLOAT32, false /* mandatory? */, READ_ONLY, Unit.VOLT)), // P_P_VPH_B_C(new ValuePoint("S112_P_P_VPH_B_C", "Phase Voltage BC", // "Phase Voltage BC", // - ValuePoint.Type.FLOAT32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT)), // + FLOAT32, false /* mandatory? */, READ_ONLY, Unit.VOLT)), // P_P_VPH_C_A(new ValuePoint("S112_P_P_VPH_C_A", "Phase Voltage CA", // "Phase Voltage CA", // - ValuePoint.Type.FLOAT32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT)), // + FLOAT32, false /* mandatory? */, READ_ONLY, Unit.VOLT)), // PH_VPH_A(new ValuePoint("S112_PH_VPH_A", "Phase Voltage AN", // "Phase Voltage AN", // - ValuePoint.Type.FLOAT32, true /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT)), // + FLOAT32, true /* mandatory? */, READ_ONLY, Unit.VOLT)), // PH_VPH_B(new ValuePoint("S112_PH_VPH_B", "Phase Voltage BN", // "Phase Voltage BN", // - ValuePoint.Type.FLOAT32, true /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT)), // + FLOAT32, true /* mandatory? */, READ_ONLY, Unit.VOLT)), // PH_VPH_C(new ValuePoint("S112_PH_VPH_C", "Phase Voltage CN", // "Phase Voltage CN", // - ValuePoint.Type.FLOAT32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT)), // + FLOAT32, false /* mandatory? */, READ_ONLY, Unit.VOLT)), // W(new ValuePoint("S112_W", "Watts", // "AC Power", // - ValuePoint.Type.FLOAT32, true /* mandatory? */, AccessMode.READ_ONLY, Unit.WATT)), // + FLOAT32, true /* mandatory? */, READ_ONLY, Unit.WATT)), // HZ(new ValuePoint("S112_HZ", "Hz", // "Line Frequency", // - ValuePoint.Type.FLOAT32, true /* mandatory? */, AccessMode.READ_ONLY, Unit.HERTZ)), // + FLOAT32, true /* mandatory? */, READ_ONLY, Unit.HERTZ)), // VA(new ValuePoint("S112_VA", "VA", // "AC Apparent Power", // - ValuePoint.Type.FLOAT32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE)), // + FLOAT32, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE)), // V_AR(new ValuePoint("S112_V_AR", "VAr", // "AC Reactive Power", // - ValuePoint.Type.FLOAT32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE)), // + FLOAT32, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE)), // PF(new ValuePoint("S112_PF", "PF", // "AC Power Factor", // - ValuePoint.Type.FLOAT32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // + FLOAT32, false /* mandatory? */, READ_ONLY, Unit.NONE)), // WH(new ValuePoint("S112_WH", "WattHours", // "AC Energy", // - ValuePoint.Type.FLOAT32, true /* mandatory? */, AccessMode.READ_ONLY, Unit.CUMULATED_WATT_HOURS)), // + FLOAT32, true /* mandatory? */, READ_ONLY, Unit.CUMULATED_WATT_HOURS)), // DCA(new ValuePoint("S112_DCA", "DC Amps", // "DC Current", // - ValuePoint.Type.FLOAT32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.AMPERE)), // + FLOAT32, false /* mandatory? */, READ_ONLY, Unit.AMPERE)), // DCV(new ValuePoint("S112_DCV", "DC Voltage", // "DC Voltage", // - ValuePoint.Type.FLOAT32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT)), // + FLOAT32, false /* mandatory? */, READ_ONLY, Unit.VOLT)), // DCW(new ValuePoint("S112_DCW", "DC Watts", // "DC Power", // - ValuePoint.Type.FLOAT32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.WATT)), // + FLOAT32, false /* mandatory? */, READ_ONLY, Unit.WATT)), // TMP_CAB(new ValuePoint("S112_TMP_CAB", "Cabinet Temperature", // "Cabinet Temperature", // - ValuePoint.Type.FLOAT32, true /* mandatory? */, AccessMode.READ_ONLY, Unit.DEGREE_CELSIUS)), // + FLOAT32, true /* mandatory? */, READ_ONLY, Unit.DEGREE_CELSIUS)), // TMP_SNK(new ValuePoint("S112_TMP_SNK", "Heat Sink Temperature", // "Heat Sink Temperature", // - ValuePoint.Type.FLOAT32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.DEGREE_CELSIUS)), // + FLOAT32, false /* mandatory? */, READ_ONLY, Unit.DEGREE_CELSIUS)), // TMP_TRNS(new ValuePoint("S112_TMP_TRNS", "Transformer Temperature", // "Transformer Temperature", // - ValuePoint.Type.FLOAT32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.DEGREE_CELSIUS)), // + FLOAT32, false /* mandatory? */, READ_ONLY, Unit.DEGREE_CELSIUS)), // TMP_OT(new ValuePoint("S112_TMP_OT", "Other Temperature", // "Other Temperature", // - ValuePoint.Type.FLOAT32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.DEGREE_CELSIUS)), // + FLOAT32, false /* mandatory? */, READ_ONLY, Unit.DEGREE_CELSIUS)), // ST(new EnumPoint("S112_ST", "Operating State", // "Enumerated value. Operating state", // - EnumPoint.Type.ENUM16, true /* mandatory? */, AccessMode.READ_ONLY, S112_St.values())), // + ENUM16, true /* mandatory? */, READ_ONLY, S112_St.values())), // ST_VND(new EnumPoint("S112_ST_VND", "Vendor Operating State", // "Vendor specific operating state code", // - EnumPoint.Type.ENUM16, false /* mandatory? */, AccessMode.READ_ONLY, new OptionsEnum[0])), // + ENUM16, false /* mandatory? */, READ_ONLY, new OptionsEnum[0])), // EVT1(new BitFieldPoint("S112_EVT1", "Event1", // "Bitmask value. Event fields", // - BitFieldPoint.Type.BITFIELD32, true /* mandatory? */, AccessMode.READ_ONLY, S112_Evt1.values())), // + BITFIELD32, true /* mandatory? */, READ_ONLY, S112_Evt1.values())), // EVT2(new BitFieldPoint("S112_EVT2", "Event Bitfield 2", // "Reserved for future use", // - BitFieldPoint.Type.BITFIELD32, true /* mandatory? */, AccessMode.READ_ONLY, new SunSpecBitPoint[0])), // + BITFIELD32, true /* mandatory? */, READ_ONLY, new SunSpecBitPoint[0])), // EVT_VND1(new BitFieldPoint("S112_EVT_VND1", "Vendor Event Bitfield 1", // "Vendor defined events", // - BitFieldPoint.Type.BITFIELD32, false /* mandatory? */, AccessMode.READ_ONLY, new SunSpecBitPoint[0])), // + BITFIELD32, false /* mandatory? */, READ_ONLY, new SunSpecBitPoint[0])), // EVT_VND2(new BitFieldPoint("S112_EVT_VND2", "Vendor Event Bitfield 2", // "Vendor defined events", // - BitFieldPoint.Type.BITFIELD32, false /* mandatory? */, AccessMode.READ_ONLY, new SunSpecBitPoint[0])), // + BITFIELD32, false /* mandatory? */, READ_ONLY, new SunSpecBitPoint[0])), // EVT_VND3(new BitFieldPoint("S112_EVT_VND3", "Vendor Event Bitfield 3", // "Vendor defined events", // - BitFieldPoint.Type.BITFIELD32, false /* mandatory? */, AccessMode.READ_ONLY, new SunSpecBitPoint[0])), // + BITFIELD32, false /* mandatory? */, READ_ONLY, new SunSpecBitPoint[0])), // EVT_VND4(new BitFieldPoint("S112_EVT_VND4", "Vendor Event Bitfield 4", // "Vendor defined events", // - BitFieldPoint.Type.BITFIELD32, false /* mandatory? */, AccessMode.READ_ONLY, new SunSpecBitPoint[0])); + BITFIELD32, false /* mandatory? */, READ_ONLY, new SunSpecBitPoint[0])); private final Point point; @@ -1320,97 +1342,97 @@ public BitPoint get() { public static enum S113 implements SunSpecPoint { A(new ValuePoint("S113_A", "Amps", // "AC Current", // - ValuePoint.Type.FLOAT32, true /* mandatory? */, AccessMode.READ_ONLY, Unit.AMPERE)), // + FLOAT32, true /* mandatory? */, READ_ONLY, Unit.AMPERE)), // APH_A(new ValuePoint("S113_APH_A", "Amps PhaseA", // "Phase A Current", // - ValuePoint.Type.FLOAT32, true /* mandatory? */, AccessMode.READ_ONLY, Unit.AMPERE)), // + FLOAT32, true /* mandatory? */, READ_ONLY, Unit.AMPERE)), // APH_B(new ValuePoint("S113_APH_B", "Amps PhaseB", // "Phase B Current", // - ValuePoint.Type.FLOAT32, true /* mandatory? */, AccessMode.READ_ONLY, Unit.AMPERE)), // + FLOAT32, true /* mandatory? */, READ_ONLY, Unit.AMPERE)), // APH_C(new ValuePoint("S113_APH_C", "Amps PhaseC", // "Phase C Current", // - ValuePoint.Type.FLOAT32, true /* mandatory? */, AccessMode.READ_ONLY, Unit.AMPERE)), // + FLOAT32, true /* mandatory? */, READ_ONLY, Unit.AMPERE)), // P_P_VPH_A_B(new ValuePoint("S113_P_P_VPH_A_B", "Phase Voltage AB", // "Phase Voltage AB", // - ValuePoint.Type.FLOAT32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT)), // + FLOAT32, false /* mandatory? */, READ_ONLY, Unit.VOLT)), // P_P_VPH_B_C(new ValuePoint("S113_P_P_VPH_B_C", "Phase Voltage BC", // "Phase Voltage BC", // - ValuePoint.Type.FLOAT32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT)), // + FLOAT32, false /* mandatory? */, READ_ONLY, Unit.VOLT)), // P_P_VPH_C_A(new ValuePoint("S113_P_P_VPH_C_A", "Phase Voltage CA", // "Phase Voltage CA", // - ValuePoint.Type.FLOAT32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT)), // + FLOAT32, false /* mandatory? */, READ_ONLY, Unit.VOLT)), // PH_VPH_A(new ValuePoint("S113_PH_VPH_A", "Phase Voltage AN", // "Phase Voltage AN", // - ValuePoint.Type.FLOAT32, true /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT)), // + FLOAT32, true /* mandatory? */, READ_ONLY, Unit.VOLT)), // PH_VPH_B(new ValuePoint("S113_PH_VPH_B", "Phase Voltage BN", // "Phase Voltage BN", // - ValuePoint.Type.FLOAT32, true /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT)), // + FLOAT32, true /* mandatory? */, READ_ONLY, Unit.VOLT)), // PH_VPH_C(new ValuePoint("S113_PH_VPH_C", "Phase Voltage CN", // "Phase Voltage CN", // - ValuePoint.Type.FLOAT32, true /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT)), // + FLOAT32, true /* mandatory? */, READ_ONLY, Unit.VOLT)), // W(new ValuePoint("S113_W", "Watts", // "AC Power", // - ValuePoint.Type.FLOAT32, true /* mandatory? */, AccessMode.READ_ONLY, Unit.WATT)), // + FLOAT32, true /* mandatory? */, READ_ONLY, Unit.WATT)), // HZ(new ValuePoint("S113_HZ", "Hz", // "Line Frequency", // - ValuePoint.Type.FLOAT32, true /* mandatory? */, AccessMode.READ_ONLY, Unit.HERTZ)), // + FLOAT32, true /* mandatory? */, READ_ONLY, Unit.HERTZ)), // VA(new ValuePoint("S113_VA", "VA", // "AC Apparent Power", // - ValuePoint.Type.FLOAT32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE)), // + FLOAT32, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE)), // V_AR(new ValuePoint("S113_V_AR", "VAr", // "AC Reactive Power", // - ValuePoint.Type.FLOAT32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE)), // + FLOAT32, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE)), // PF(new ValuePoint("S113_PF", "PF", // "AC Power Factor", // - ValuePoint.Type.FLOAT32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // + FLOAT32, false /* mandatory? */, READ_ONLY, Unit.NONE)), // WH(new ValuePoint("S113_WH", "WattHours", // "AC Energy", // - ValuePoint.Type.FLOAT32, true /* mandatory? */, AccessMode.READ_ONLY, Unit.CUMULATED_WATT_HOURS)), // + FLOAT32, true /* mandatory? */, READ_ONLY, Unit.CUMULATED_WATT_HOURS)), // DCA(new ValuePoint("S113_DCA", "DC Amps", // "DC Current", // - ValuePoint.Type.FLOAT32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.AMPERE)), // + FLOAT32, false /* mandatory? */, READ_ONLY, Unit.AMPERE)), // DCV(new ValuePoint("S113_DCV", "DC Voltage", // "DC Voltage", // - ValuePoint.Type.FLOAT32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT)), // + FLOAT32, false /* mandatory? */, READ_ONLY, Unit.VOLT)), // DCW(new ValuePoint("S113_DCW", "DC Watts", // "DC Power", // - ValuePoint.Type.FLOAT32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.WATT)), // + FLOAT32, false /* mandatory? */, READ_ONLY, Unit.WATT)), // TMP_CAB(new ValuePoint("S113_TMP_CAB", "Cabinet Temperature", // "Cabinet Temperature", // - ValuePoint.Type.FLOAT32, true /* mandatory? */, AccessMode.READ_ONLY, Unit.DEGREE_CELSIUS)), // + FLOAT32, true /* mandatory? */, READ_ONLY, Unit.DEGREE_CELSIUS)), // TMP_SNK(new ValuePoint("S113_TMP_SNK", "Heat Sink Temperature", // "Heat Sink Temperature", // - ValuePoint.Type.FLOAT32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.DEGREE_CELSIUS)), // + FLOAT32, false /* mandatory? */, READ_ONLY, Unit.DEGREE_CELSIUS)), // TMP_TRNS(new ValuePoint("S113_TMP_TRNS", "Transformer Temperature", // "Transformer Temperature", // - ValuePoint.Type.FLOAT32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.DEGREE_CELSIUS)), // + FLOAT32, false /* mandatory? */, READ_ONLY, Unit.DEGREE_CELSIUS)), // TMP_OT(new ValuePoint("S113_TMP_OT", "Other Temperature", // "Other Temperature", // - ValuePoint.Type.FLOAT32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.DEGREE_CELSIUS)), // + FLOAT32, false /* mandatory? */, READ_ONLY, Unit.DEGREE_CELSIUS)), // ST(new EnumPoint("S113_ST", "Operating State", // "Enumerated value. Operating state", // - EnumPoint.Type.ENUM16, true /* mandatory? */, AccessMode.READ_ONLY, S113_St.values())), // + ENUM16, true /* mandatory? */, READ_ONLY, S113_St.values())), // ST_VND(new EnumPoint("S113_ST_VND", "Vendor Operating State", // "Vendor specific operating state code", // - EnumPoint.Type.ENUM16, false /* mandatory? */, AccessMode.READ_ONLY, new OptionsEnum[0])), // + ENUM16, false /* mandatory? */, READ_ONLY, new OptionsEnum[0])), // EVT1(new BitFieldPoint("S113_EVT1", "Event1", // "Bitmask value. Event fields", // - BitFieldPoint.Type.BITFIELD32, true /* mandatory? */, AccessMode.READ_ONLY, S113_Evt1.values())), // + BITFIELD32, true /* mandatory? */, READ_ONLY, S113_Evt1.values())), // EVT2(new BitFieldPoint("S113_EVT2", "Event Bitfield 2", // "Reserved for future use", // - BitFieldPoint.Type.BITFIELD32, true /* mandatory? */, AccessMode.READ_ONLY, new SunSpecBitPoint[0])), // + BITFIELD32, true /* mandatory? */, READ_ONLY, new SunSpecBitPoint[0])), // EVT_VND1(new BitFieldPoint("S113_EVT_VND1", "Vendor Event Bitfield 1", // "Vendor defined events", // - BitFieldPoint.Type.BITFIELD32, false /* mandatory? */, AccessMode.READ_ONLY, new SunSpecBitPoint[0])), // + BITFIELD32, false /* mandatory? */, READ_ONLY, new SunSpecBitPoint[0])), // EVT_VND2(new BitFieldPoint("S113_EVT_VND2", "Vendor Event Bitfield 2", // "Vendor defined events", // - BitFieldPoint.Type.BITFIELD32, false /* mandatory? */, AccessMode.READ_ONLY, new SunSpecBitPoint[0])), // + BITFIELD32, false /* mandatory? */, READ_ONLY, new SunSpecBitPoint[0])), // EVT_VND3(new BitFieldPoint("S113_EVT_VND3", "Vendor Event Bitfield 3", // "Vendor defined events", // - BitFieldPoint.Type.BITFIELD32, false /* mandatory? */, AccessMode.READ_ONLY, new SunSpecBitPoint[0])), // + BITFIELD32, false /* mandatory? */, READ_ONLY, new SunSpecBitPoint[0])), // EVT_VND4(new BitFieldPoint("S113_EVT_VND4", "Vendor Event Bitfield 4", // "Vendor defined events", // - BitFieldPoint.Type.BITFIELD32, false /* mandatory? */, AccessMode.READ_ONLY, new SunSpecBitPoint[0])); + BITFIELD32, false /* mandatory? */, READ_ONLY, new SunSpecBitPoint[0])); private final Point point; @@ -1492,73 +1514,73 @@ public BitPoint get() { public static enum S120 implements SunSpecPoint { D_E_R_TYP(new EnumPoint("S120_D_E_R_TYP", "DERTyp", // "Type of DER device. Default value is 4 to indicate PV device.", // - EnumPoint.Type.ENUM16, true /* mandatory? */, AccessMode.READ_ONLY, S120_DERTyp.values())), // + ENUM16, true /* mandatory? */, READ_ONLY, S120_DERTyp.values())), // W_RTG(new ScaledValuePoint("S120_W_RTG", "WRtg", // "Continuous power output capability of the inverter.", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.WATT, "WRtg_SF")), // + UINT16, true /* mandatory? */, READ_ONLY, Unit.WATT, "WRtg_SF")), // W_RTG_S_F(new ScaleFactorPoint("S120_W_RTG_S_F", "WRtg_SF", // "Scale factor")), // V_A_RTG(new ScaledValuePoint("S120_V_A_RTG", "VARtg", // "Continuous Volt-Ampere capability of the inverter.", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE, "VARtg_SF")), // + UINT16, true /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE, "VARtg_SF")), // V_A_RTG_S_F(new ScaleFactorPoint("S120_V_A_RTG_S_F", "VARtg_SF", // "Scale factor")), // V_AR_RTG_Q1(new ScaledValuePoint("S120_V_AR_RTG_Q1", "VArRtgQ1", // "Continuous VAR capability of the inverter in quadrant 1.", // - ValuePoint.Type.INT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE, "VArRtg_SF")), // + INT16, true /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE, "VArRtg_SF")), // V_AR_RTG_Q2(new ScaledValuePoint("S120_V_AR_RTG_Q2", "VArRtgQ2", // "Continuous VAR capability of the inverter in quadrant 2.", // - ValuePoint.Type.INT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE, "VArRtg_SF")), // + INT16, true /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE, "VArRtg_SF")), // V_AR_RTG_Q3(new ScaledValuePoint("S120_V_AR_RTG_Q3", "VArRtgQ3", // "Continuous VAR capability of the inverter in quadrant 3.", // - ValuePoint.Type.INT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE, "VArRtg_SF")), // + INT16, true /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE, "VArRtg_SF")), // V_AR_RTG_Q4(new ScaledValuePoint("S120_V_AR_RTG_Q4", "VArRtgQ4", // "Continuous VAR capability of the inverter in quadrant 4.", // - ValuePoint.Type.INT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE, "VArRtg_SF")), // + INT16, true /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE, "VArRtg_SF")), // V_AR_RTG_S_F(new ScaleFactorPoint("S120_V_AR_RTG_S_F", "VArRtg_SF", // "Scale factor")), // A_RTG(new ScaledValuePoint("S120_A_RTG", "ARtg", // "Maximum RMS AC current level capability of the inverter.", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.AMPERE, "ARtg_SF")), // + UINT16, true /* mandatory? */, READ_ONLY, Unit.AMPERE, "ARtg_SF")), // A_RTG_S_F(new ScaleFactorPoint("S120_A_RTG_S_F", "ARtg_SF", // "Scale factor")), // P_F_RTG_Q1(new ScaledValuePoint("S120_P_F_RTG_Q1", "PFRtgQ1", // "Minimum power factor capability of the inverter in quadrant 1.", // - ValuePoint.Type.INT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE, "PFRtg_SF")), // + INT16, true /* mandatory? */, READ_ONLY, Unit.NONE, "PFRtg_SF")), // P_F_RTG_Q2(new ScaledValuePoint("S120_P_F_RTG_Q2", "PFRtgQ2", // "Minimum power factor capability of the inverter in quadrant 2.", // - ValuePoint.Type.INT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE, "PFRtg_SF")), // + INT16, true /* mandatory? */, READ_ONLY, Unit.NONE, "PFRtg_SF")), // P_F_RTG_Q3(new ScaledValuePoint("S120_P_F_RTG_Q3", "PFRtgQ3", // "Minimum power factor capability of the inverter in quadrant 3.", // - ValuePoint.Type.INT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE, "PFRtg_SF")), // + INT16, true /* mandatory? */, READ_ONLY, Unit.NONE, "PFRtg_SF")), // P_F_RTG_Q4(new ScaledValuePoint("S120_P_F_RTG_Q4", "PFRtgQ4", // "Minimum power factor capability of the inverter in quadrant 4.", // - ValuePoint.Type.INT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE, "PFRtg_SF")), // + INT16, true /* mandatory? */, READ_ONLY, Unit.NONE, "PFRtg_SF")), // P_F_RTG_S_F(new ScaleFactorPoint("S120_P_F_RTG_S_F", "PFRtg_SF", // "Scale factor")), // W_H_RTG(new ScaledValuePoint("S120_W_H_RTG", "WHRtg", // "Nominal energy rating of storage device.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.CUMULATED_WATT_HOURS, "WHRtg_SF")), // + UINT16, false /* mandatory? */, READ_ONLY, Unit.CUMULATED_WATT_HOURS, "WHRtg_SF")), // W_H_RTG_S_F(new ScaleFactorPoint("S120_W_H_RTG_S_F", "WHRtg_SF", // "Scale factor")), // AHR_RTG(new ScaledValuePoint("S120_AHR_RTG", "AhrRtg", // "The usable capacity of the battery. Maximum charge minus minimum charge from a technology capability perspective (Amp-hour capacity rating).", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.AMPERE_HOURS, "AhrRtg_SF")), // + UINT16, false /* mandatory? */, READ_ONLY, Unit.AMPERE_HOURS, "AhrRtg_SF")), // AHR_RTG_S_F(new ScaleFactorPoint("S120_AHR_RTG_S_F", "AhrRtg_SF", // "Scale factor for amp-hour rating.")), // MAX_CHA_RTE(new ScaledValuePoint("S120_MAX_CHA_RTE", "MaxChaRte", // "Maximum rate of energy transfer into the storage device.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.WATT, "MaxChaRte_SF")), // + UINT16, false /* mandatory? */, READ_ONLY, Unit.WATT, "MaxChaRte_SF")), // MAX_CHA_RTE_S_F(new ScaleFactorPoint("S120_MAX_CHA_RTE_S_F", "MaxChaRte_SF", // "Scale factor")), // MAX_DIS_CHA_RTE(new ScaledValuePoint("S120_MAX_DIS_CHA_RTE", "MaxDisChaRte", // "Maximum rate of energy transfer out of the storage device.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.WATT, "MaxDisChaRte_SF")), // + UINT16, false /* mandatory? */, READ_ONLY, Unit.WATT, "MaxDisChaRte_SF")), // MAX_DIS_CHA_RTE_S_F(new ScaleFactorPoint("S120_MAX_DIS_CHA_RTE_S_F", "MaxDisChaRte_SF", // "Scale factor")), // PAD(new ValuePoint("S120_PAD", "Pad", // "Pad register.", // - ValuePoint.Type.PAD, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)); + ValuePoint.Type.PAD, false /* mandatory? */, READ_ONLY, Unit.NONE)); private final Point point; @@ -1604,64 +1626,64 @@ public OptionsEnum getUndefined() { public static enum S121 implements SunSpecPoint { W_MAX(new ScaledValuePoint("S121_W_MAX", "WMax", // "Setting for maximum power output. Default to WRtg.", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_WRITE, Unit.WATT, "WMax_SF")), // + UINT16, true /* mandatory? */, READ_WRITE, Unit.WATT, "WMax_SF")), // V_REF(new ScaledValuePoint("S121_V_REF", "VRef", // "Voltage at the PCC.", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_WRITE, Unit.VOLT, "VRef_SF")), // + UINT16, true /* mandatory? */, READ_WRITE, Unit.VOLT, "VRef_SF")), // V_REF_OFS(new ScaledValuePoint("S121_V_REF_OFS", "VRefOfs", // "Offset from PCC to inverter.", // - ValuePoint.Type.INT16, true /* mandatory? */, AccessMode.READ_WRITE, Unit.VOLT, "VRefOfs_SF")), // + INT16, true /* mandatory? */, READ_WRITE, Unit.VOLT, "VRefOfs_SF")), // V_MAX(new ScaledValuePoint("S121_V_MAX", "VMax", // "Setpoint for maximum voltage.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_WRITE, Unit.VOLT, "VMinMax_SF")), // + UINT16, false /* mandatory? */, READ_WRITE, Unit.VOLT, "VMinMax_SF")), // V_MIN(new ScaledValuePoint("S121_V_MIN", "VMin", // "Setpoint for minimum voltage.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_WRITE, Unit.VOLT, "VMinMax_SF")), // + UINT16, false /* mandatory? */, READ_WRITE, Unit.VOLT, "VMinMax_SF")), // V_A_MAX(new ScaledValuePoint("S121_V_A_MAX", "VAMax", // "Setpoint for maximum apparent power. Default to VARtg.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_WRITE, Unit.VOLT_AMPERE, "VAMax_SF")), // + UINT16, false /* mandatory? */, READ_WRITE, Unit.VOLT_AMPERE, "VAMax_SF")), // V_AR_MAX_Q1(new ScaledValuePoint("S121_V_AR_MAX_Q1", "VArMaxQ1", // "Setting for maximum reactive power in quadrant 1. Default to VArRtgQ1.", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_WRITE, Unit.VOLT_AMPERE_REACTIVE, "VArMax_SF")), // + INT16, false /* mandatory? */, READ_WRITE, Unit.VOLT_AMPERE_REACTIVE, "VArMax_SF")), // V_AR_MAX_Q2(new ScaledValuePoint("S121_V_AR_MAX_Q2", "VArMaxQ2", // "Setting for maximum reactive power in quadrant 2. Default to VArRtgQ2.", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_WRITE, Unit.VOLT_AMPERE_REACTIVE, "VArMax_SF")), // + INT16, false /* mandatory? */, READ_WRITE, Unit.VOLT_AMPERE_REACTIVE, "VArMax_SF")), // V_AR_MAX_Q3(new ScaledValuePoint("S121_V_AR_MAX_Q3", "VArMaxQ3", // "Setting for maximum reactive power in quadrant 3. Default to VArRtgQ3.", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_WRITE, Unit.VOLT_AMPERE_REACTIVE, "VArMax_SF")), // + INT16, false /* mandatory? */, READ_WRITE, Unit.VOLT_AMPERE_REACTIVE, "VArMax_SF")), // V_AR_MAX_Q4(new ScaledValuePoint("S121_V_AR_MAX_Q4", "VArMaxQ4", // "Setting for maximum reactive power in quadrant 4. Default to VArRtgQ4.", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_WRITE, Unit.VOLT_AMPERE_REACTIVE, "VArMax_SF")), // + INT16, false /* mandatory? */, READ_WRITE, Unit.VOLT_AMPERE_REACTIVE, "VArMax_SF")), // W_GRA(new ScaledValuePoint("S121_W_GRA", "WGra", // "Default ramp rate of change of active power due to command or internal action.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_WRITE, Unit.PERCENT, "WGra_SF")), // + UINT16, false /* mandatory? */, READ_WRITE, Unit.PERCENT, "WGra_SF")), // P_F_MIN_Q1(new ScaledValuePoint("S121_P_F_MIN_Q1", "PFMinQ1", // "Setpoint for minimum power factor value in quadrant 1. Default to PFRtgQ1.", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_WRITE, Unit.NONE, "PFMin_SF")), // + INT16, false /* mandatory? */, READ_WRITE, Unit.NONE, "PFMin_SF")), // P_F_MIN_Q2(new ScaledValuePoint("S121_P_F_MIN_Q2", "PFMinQ2", // "Setpoint for minimum power factor value in quadrant 2. Default to PFRtgQ2.", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_WRITE, Unit.NONE, "PFMin_SF")), // + INT16, false /* mandatory? */, READ_WRITE, Unit.NONE, "PFMin_SF")), // P_F_MIN_Q3(new ScaledValuePoint("S121_P_F_MIN_Q3", "PFMinQ3", // "Setpoint for minimum power factor value in quadrant 3. Default to PFRtgQ3.", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_WRITE, Unit.NONE, "PFMin_SF")), // + INT16, false /* mandatory? */, READ_WRITE, Unit.NONE, "PFMin_SF")), // P_F_MIN_Q4(new ScaledValuePoint("S121_P_F_MIN_Q4", "PFMinQ4", // "Setpoint for minimum power factor value in quadrant 4. Default to PFRtgQ4.", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_WRITE, Unit.NONE, "PFMin_SF")), // + INT16, false /* mandatory? */, READ_WRITE, Unit.NONE, "PFMin_SF")), // V_AR_ACT(new EnumPoint("S121_V_AR_ACT", "VArAct", // "VAR action on change between charging and discharging: 1=switch 2=maintain VAR characterization.", // - EnumPoint.Type.ENUM16, false /* mandatory? */, AccessMode.READ_WRITE, S121_VArAct.values())), // + ENUM16, false /* mandatory? */, READ_WRITE, S121_VArAct.values())), // CLC_TOT_V_A(new EnumPoint("S121_CLC_TOT_V_A", "ClcTotVA", // "Calculation method for total apparent power. 1=vector 2=arithmetic.", // - EnumPoint.Type.ENUM16, false /* mandatory? */, AccessMode.READ_WRITE, S121_ClcTotVA.values())), // + ENUM16, false /* mandatory? */, READ_WRITE, S121_ClcTotVA.values())), // MAX_RMP_RTE(new ScaledValuePoint("S121_MAX_RMP_RTE", "MaxRmpRte", // "Setpoint for maximum ramp rate as percentage of nominal maximum ramp rate. This setting will limit the rate that watts delivery to the grid can increase or decrease in response to intermittent PV generation.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_WRITE, Unit.PERCENT, "MaxRmpRte_SF")), // + UINT16, false /* mandatory? */, READ_WRITE, Unit.PERCENT, "MaxRmpRte_SF")), // E_C_P_NOM_HZ(new ScaledValuePoint("S121_E_C_P_NOM_HZ", "ECPNomHz", // "Setpoint for nominal frequency at the ECP.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_WRITE, Unit.HERTZ, "ECPNomHz_SF")), // + UINT16, false /* mandatory? */, READ_WRITE, Unit.HERTZ, "ECPNomHz_SF")), // CONN_PH(new EnumPoint("S121_CONN_PH", "ConnPh", // "Identity of connected phase for single phase inverters. A=1 B=2 C=3.", // - EnumPoint.Type.ENUM16, false /* mandatory? */, AccessMode.READ_WRITE, S121_ConnPh.values())), // + ENUM16, false /* mandatory? */, READ_WRITE, S121_ConnPh.values())), // W_MAX_S_F(new ScaleFactorPoint("S121_W_MAX_S_F", "WMax_SF", // "Scale factor for real power.")), // V_REF_S_F(new ScaleFactorPoint("S121_V_REF_S_F", "VRef_SF", // @@ -1786,59 +1808,59 @@ public OptionsEnum getUndefined() { public static enum S122 implements SunSpecPoint { P_V_CONN(new BitFieldPoint("S122_P_V_CONN", "PVConn", // "PV inverter present/available status. Enumerated value.", // - BitFieldPoint.Type.BITFIELD16, true /* mandatory? */, AccessMode.READ_ONLY, S122_PVConn.values())), // + BITFIELD16, true /* mandatory? */, READ_ONLY, S122_PVConn.values())), // STOR_CONN(new BitFieldPoint("S122_STOR_CONN", "StorConn", // "Storage inverter present/available status. Enumerated value.", // - BitFieldPoint.Type.BITFIELD16, true /* mandatory? */, AccessMode.READ_ONLY, S122_StorConn.values())), // + BITFIELD16, true /* mandatory? */, READ_ONLY, S122_StorConn.values())), // E_C_P_CONN(new BitFieldPoint("S122_E_C_P_CONN", "ECPConn", // "ECP connection status: disconnected=0 connected=1.", // - BitFieldPoint.Type.BITFIELD16, true /* mandatory? */, AccessMode.READ_ONLY, S122_ECPConn.values())), // + BITFIELD16, true /* mandatory? */, READ_ONLY, S122_ECPConn.values())), // ACT_WH(new ValuePoint("S122_ACT_WH", "ActWh", // "AC lifetime active (real) energy output.", // - ValuePoint.Type.ACC64, false /* mandatory? */, AccessMode.READ_ONLY, Unit.CUMULATED_WATT_HOURS)), // + ACC64, false /* mandatory? */, READ_ONLY, Unit.CUMULATED_WATT_HOURS)), // ACT_V_AH(new ValuePoint("S122_ACT_V_AH", "ActVAh", // "AC lifetime apparent energy output.", // - ValuePoint.Type.ACC64, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_HOURS)), // + ACC64, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_HOURS)), // ACT_V_ARH_Q1(new ValuePoint("S122_ACT_V_ARH_Q1", "ActVArhQ1", // "AC lifetime reactive energy output in quadrant 1.", // - ValuePoint.Type.ACC64, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS)), // + ACC64, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS)), // ACT_V_ARH_Q2(new ValuePoint("S122_ACT_V_ARH_Q2", "ActVArhQ2", // "AC lifetime reactive energy output in quadrant 2.", // - ValuePoint.Type.ACC64, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS)), // + ACC64, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS)), // ACT_V_ARH_Q3(new ValuePoint("S122_ACT_V_ARH_Q3", "ActVArhQ3", // "AC lifetime negative energy output in quadrant 3.", // - ValuePoint.Type.ACC64, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS)), // + ACC64, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS)), // ACT_V_ARH_Q4(new ValuePoint("S122_ACT_V_ARH_Q4", "ActVArhQ4", // "AC lifetime reactive energy output in quadrant 4.", // - ValuePoint.Type.ACC64, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS)), // + ACC64, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS)), // V_AR_AVAL(new ScaledValuePoint("S122_V_AR_AVAL", "VArAval", // "Amount of VARs available without impacting watts output.", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE, "VArAval_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE, "VArAval_SF")), // V_AR_AVAL_S_F(new ScaleFactorPoint("S122_V_AR_AVAL_S_F", "VArAval_SF", // "Scale factor for available VARs.")), // W_AVAL(new ScaledValuePoint("S122_W_AVAL", "WAval", // "Amount of Watts available.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE, "WAval_SF")), // + UINT16, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE, "WAval_SF")), // W_AVAL_S_F(new ScaleFactorPoint("S122_W_AVAL_S_F", "WAval_SF", // "Scale factor for available Watts.")), // ST_SET_LIM_MSK(new BitFieldPoint("S122_ST_SET_LIM_MSK", "StSetLimMsk", // "Bit Mask indicating setpoint limit(s) reached.", // - BitFieldPoint.Type.BITFIELD32, false /* mandatory? */, AccessMode.READ_ONLY, S122_StSetLimMsk.values())), // + BITFIELD32, false /* mandatory? */, READ_ONLY, S122_StSetLimMsk.values())), // ST_ACT_CTL(new BitFieldPoint("S122_ST_ACT_CTL", "StActCtl", // "Bit Mask indicating which inverter controls are currently active.", // - BitFieldPoint.Type.BITFIELD32, false /* mandatory? */, AccessMode.READ_ONLY, S122_StActCtl.values())), // + BITFIELD32, false /* mandatory? */, READ_ONLY, S122_StActCtl.values())), // TM_SRC(new ValuePoint("S122_TM_SRC", "TmSrc", // "Source of time synchronization.", // - ValuePoint.Type.STRING4, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // + STRING4, false /* mandatory? */, READ_ONLY, Unit.NONE)), // TMS(new ValuePoint("S122_TMS", "Tms", // "Seconds since 01-01-2000 00:00 UTC", // - ValuePoint.Type.UINT32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.SECONDS)), // + UINT32, false /* mandatory? */, READ_ONLY, Unit.SECONDS)), // RT_ST(new BitFieldPoint("S122_RT_ST", "RtSt", // "Bit Mask indicating active ride-through status.", // - BitFieldPoint.Type.BITFIELD16, false /* mandatory? */, AccessMode.READ_ONLY, S122_RtSt.values())), // + BITFIELD16, false /* mandatory? */, READ_ONLY, S122_RtSt.values())), // RIS(new ScaledValuePoint("S122_RIS", "Ris", // "Isolation resistance.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE, "Ris_SF")), // + UINT16, false /* mandatory? */, READ_ONLY, Unit.NONE, "Ris_SF")), // RIS_S_F(new ScaleFactorPoint("S122_RIS_S_F", "Ris_SF", // "Scale factor for isolation resistance.")); @@ -1979,67 +2001,67 @@ public BitPoint get() { public static enum S123 implements SunSpecPoint { CONN_WIN_TMS(new ValuePoint("S123_CONN_WIN_TMS", "Conn_WinTms", // "Time window for connect/disconnect.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_WRITE, Unit.SECONDS)), // + UINT16, false /* mandatory? */, READ_WRITE, Unit.SECONDS)), // CONN_RVRT_TMS(new ValuePoint("S123_CONN_RVRT_TMS", "Conn_RvrtTms", // "Timeout period for connect/disconnect.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_WRITE, Unit.SECONDS)), // + UINT16, false /* mandatory? */, READ_WRITE, Unit.SECONDS)), // CONN(new EnumPoint("S123_CONN", "Conn", // "Enumerated valued. Connection control.", // - EnumPoint.Type.ENUM16, true /* mandatory? */, AccessMode.READ_WRITE, S123_Conn.values())), // + ENUM16, true /* mandatory? */, READ_WRITE, S123_Conn.values())), // W_MAX_LIM_PCT(new ScaledValuePoint("S123_W_MAX_LIM_PCT", "WMaxLimPct", // "Set power output to specified level.", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_WRITE, Unit.PERCENT, "WMaxLimPct_SF")), // + UINT16, true /* mandatory? */, READ_WRITE, Unit.PERCENT, "WMaxLimPct_SF")), // W_MAX_LIM_PCT_WIN_TMS(new ValuePoint("S123_W_MAX_LIM_PCT_WIN_TMS", "WMaxLimPct_WinTms", // "Time window for power limit change.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_WRITE, Unit.SECONDS)), // + UINT16, false /* mandatory? */, READ_WRITE, Unit.SECONDS)), // W_MAX_LIM_PCT_RVRT_TMS(new ValuePoint("S123_W_MAX_LIM_PCT_RVRT_TMS", "WMaxLimPct_RvrtTms", // "Timeout period for power limit.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_WRITE, Unit.SECONDS)), // + UINT16, false /* mandatory? */, READ_WRITE, Unit.SECONDS)), // W_MAX_LIM_PCT_RMP_TMS(new ValuePoint("S123_W_MAX_LIM_PCT_RMP_TMS", "WMaxLimPct_RmpTms", // "Ramp time for moving from current setpoint to new setpoint.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_WRITE, Unit.SECONDS)), // + UINT16, false /* mandatory? */, READ_WRITE, Unit.SECONDS)), // W_MAX_LIM_ENA(new EnumPoint("S123_W_MAX_LIM_ENA", "WMaxLim_Ena", // "Enumerated valued. Throttle enable/disable control.", // - EnumPoint.Type.ENUM16, true /* mandatory? */, AccessMode.READ_WRITE, S123_WMaxLim_Ena.values())), // + ENUM16, true /* mandatory? */, READ_WRITE, S123_WMaxLim_Ena.values())), // OUT_P_F_SET(new ScaledValuePoint("S123_OUT_P_F_SET", "OutPFSet", // "Set power factor to specific value - cosine of angle.", // - ValuePoint.Type.INT16, true /* mandatory? */, AccessMode.READ_WRITE, Unit.NONE, "OutPFSet_SF")), // + INT16, true /* mandatory? */, READ_WRITE, Unit.NONE, "OutPFSet_SF")), // OUT_P_F_SET_WIN_TMS(new ValuePoint("S123_OUT_P_F_SET_WIN_TMS", "OutPFSet_WinTms", // "Time window for power factor change.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_WRITE, Unit.SECONDS)), // + UINT16, false /* mandatory? */, READ_WRITE, Unit.SECONDS)), // OUT_P_F_SET_RVRT_TMS(new ValuePoint("S123_OUT_P_F_SET_RVRT_TMS", "OutPFSet_RvrtTms", // "Timeout period for power factor.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_WRITE, Unit.SECONDS)), // + UINT16, false /* mandatory? */, READ_WRITE, Unit.SECONDS)), // OUT_P_F_SET_RMP_TMS(new ValuePoint("S123_OUT_P_F_SET_RMP_TMS", "OutPFSet_RmpTms", // "Ramp time for moving from current setpoint to new setpoint.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_WRITE, Unit.SECONDS)), // + UINT16, false /* mandatory? */, READ_WRITE, Unit.SECONDS)), // OUT_P_F_SET_ENA(new EnumPoint("S123_OUT_P_F_SET_ENA", "OutPFSet_Ena", // "Enumerated valued. Fixed power factor enable/disable control.", // - EnumPoint.Type.ENUM16, true /* mandatory? */, AccessMode.READ_WRITE, S123_OutPFSet_Ena.values())), // + ENUM16, true /* mandatory? */, READ_WRITE, S123_OutPFSet_Ena.values())), // V_AR_W_MAX_PCT(new ScaledValuePoint("S123_V_AR_W_MAX_PCT", "VArWMaxPct", // "Reactive power in percent of WMax.", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_WRITE, Unit.PERCENT, "VArPct_SF")), // + INT16, false /* mandatory? */, READ_WRITE, Unit.PERCENT, "VArPct_SF")), // V_AR_MAX_PCT(new ScaledValuePoint("S123_V_AR_MAX_PCT", "VArMaxPct", // "Reactive power in percent of VArMax.", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_WRITE, Unit.PERCENT, "VArPct_SF")), // + INT16, false /* mandatory? */, READ_WRITE, Unit.PERCENT, "VArPct_SF")), // V_AR_AVAL_PCT(new ScaledValuePoint("S123_V_AR_AVAL_PCT", "VArAvalPct", // "Reactive power in percent of VArAval.", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_WRITE, Unit.PERCENT, "VArPct_SF")), // + INT16, false /* mandatory? */, READ_WRITE, Unit.PERCENT, "VArPct_SF")), // V_AR_PCT_WIN_TMS(new ValuePoint("S123_V_AR_PCT_WIN_TMS", "VArPct_WinTms", // "Time window for VAR limit change.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_WRITE, Unit.SECONDS)), // + UINT16, false /* mandatory? */, READ_WRITE, Unit.SECONDS)), // V_AR_PCT_RVRT_TMS(new ValuePoint("S123_V_AR_PCT_RVRT_TMS", "VArPct_RvrtTms", // "Timeout period for VAR limit.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_WRITE, Unit.SECONDS)), // + UINT16, false /* mandatory? */, READ_WRITE, Unit.SECONDS)), // V_AR_PCT_RMP_TMS(new ValuePoint("S123_V_AR_PCT_RMP_TMS", "VArPct_RmpTms", // "Ramp time for moving from current setpoint to new setpoint.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_WRITE, Unit.SECONDS)), // + UINT16, false /* mandatory? */, READ_WRITE, Unit.SECONDS)), // V_AR_PCT_MOD(new EnumPoint("S123_V_AR_PCT_MOD", "VArPct_Mod", // "Enumerated value. VAR percent limit mode.", // - EnumPoint.Type.ENUM16, false /* mandatory? */, AccessMode.READ_WRITE, S123_VArPct_Mod.values())), // + ENUM16, false /* mandatory? */, READ_WRITE, S123_VArPct_Mod.values())), // V_AR_PCT_ENA(new EnumPoint("S123_V_AR_PCT_ENA", "VArPct_Ena", // "Enumerated valued. Percent limit VAr enable/disable control.", // - EnumPoint.Type.ENUM16, true /* mandatory? */, AccessMode.READ_WRITE, S123_VArPct_Ena.values())), // + ENUM16, true /* mandatory? */, READ_WRITE, S123_VArPct_Ena.values())), // W_MAX_LIM_PCT_S_F(new ScaleFactorPoint("S123_W_MAX_LIM_PCT_S_F", "WMaxLimPct_SF", // "Scale factor for power output percent.")), // OUT_P_F_SET_S_F(new ScaleFactorPoint("S123_OUT_P_F_SET_S_F", "OutPFSet_SF", // @@ -2209,51 +2231,51 @@ public OptionsEnum getUndefined() { public static enum S124 implements SunSpecPoint { W_CHA_MAX(new ScaledValuePoint("S124_W_CHA_MAX", "WChaMax", // "Setpoint for maximum charge.", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_WRITE, Unit.WATT, "WChaMax_SF")), // + UINT16, true /* mandatory? */, READ_WRITE, Unit.WATT, "WChaMax_SF")), // W_CHA_GRA(new ScaledValuePoint("S124_W_CHA_GRA", "WChaGra", // "Setpoint for maximum charging rate. Default is MaxChaRte.", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_WRITE, Unit.PERCENT, "WChaDisChaGra_SF")), // + UINT16, true /* mandatory? */, READ_WRITE, Unit.PERCENT, "WChaDisChaGra_SF")), // W_DIS_CHA_GRA(new ScaledValuePoint("S124_W_DIS_CHA_GRA", "WDisChaGra", // "Setpoint for maximum discharge rate. Default is MaxDisChaRte.", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_WRITE, Unit.PERCENT, "WChaDisChaGra_SF")), // + UINT16, true /* mandatory? */, READ_WRITE, Unit.PERCENT, "WChaDisChaGra_SF")), // STOR_CTL_MOD(new BitFieldPoint("S124_STOR_CTL_MOD", "StorCtl_Mod", // "Activate hold/discharge/charge storage control mode. Bitfield value.", // - BitFieldPoint.Type.BITFIELD16, true /* mandatory? */, AccessMode.READ_WRITE, S124_StorCtl_Mod.values())), // + BITFIELD16, true /* mandatory? */, READ_WRITE, S124_StorCtl_Mod.values())), // V_A_CHA_MAX(new ScaledValuePoint("S124_V_A_CHA_MAX", "VAChaMax", // "Setpoint for maximum charging VA.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_WRITE, Unit.VOLT_AMPERE, "VAChaMax_SF")), // + UINT16, false /* mandatory? */, READ_WRITE, Unit.VOLT_AMPERE, "VAChaMax_SF")), // MIN_RSV_PCT(new ScaledValuePoint("S124_MIN_RSV_PCT", "MinRsvPct", // "Setpoint for minimum reserve for storage as a percentage of the nominal maximum storage.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_WRITE, Unit.PERCENT, "MinRsvPct_SF")), // + UINT16, false /* mandatory? */, READ_WRITE, Unit.PERCENT, "MinRsvPct_SF")), // CHA_STATE(new ScaledValuePoint("S124_CHA_STATE", "ChaState", // "Currently available energy as a percent of the capacity rating.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.PERCENT, "ChaState_SF")), // + UINT16, false /* mandatory? */, READ_ONLY, Unit.PERCENT, "ChaState_SF")), // STOR_AVAL(new ScaledValuePoint("S124_STOR_AVAL", "StorAval", // "State of charge (ChaState) minus storage reserve (MinRsvPct) times capacity rating (AhrRtg).", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.AMPERE_HOURS, "StorAval_SF")), // + UINT16, false /* mandatory? */, READ_ONLY, Unit.AMPERE_HOURS, "StorAval_SF")), // IN_BAT_V(new ScaledValuePoint("S124_IN_BAT_V", "InBatV", // "Internal battery voltage.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT, "InBatV_SF")), // + UINT16, false /* mandatory? */, READ_ONLY, Unit.VOLT, "InBatV_SF")), // CHA_ST(new EnumPoint("S124_CHA_ST", "ChaSt", // "Charge status of storage device. Enumerated value.", // - EnumPoint.Type.ENUM16, false /* mandatory? */, AccessMode.READ_ONLY, S124_ChaSt.values())), // + ENUM16, false /* mandatory? */, READ_ONLY, S124_ChaSt.values())), // OUT_W_RTE(new ScaledValuePoint("S124_OUT_W_RTE", "OutWRte", // "Percent of max discharge rate.", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_WRITE, Unit.PERCENT, "InOutWRte_SF")), // + INT16, false /* mandatory? */, READ_WRITE, Unit.PERCENT, "InOutWRte_SF")), // IN_W_RTE(new ScaledValuePoint("S124_IN_W_RTE", "InWRte", // "Percent of max charging rate.", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_WRITE, Unit.PERCENT, "InOutWRte_SF")), // + INT16, false /* mandatory? */, READ_WRITE, Unit.PERCENT, "InOutWRte_SF")), // IN_OUT_W_RTE_WIN_TMS(new ValuePoint("S124_IN_OUT_W_RTE_WIN_TMS", "InOutWRte_WinTms", // "Time window for charge/discharge rate change.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_WRITE, Unit.SECONDS)), // + UINT16, false /* mandatory? */, READ_WRITE, Unit.SECONDS)), // IN_OUT_W_RTE_RVRT_TMS(new ValuePoint("S124_IN_OUT_W_RTE_RVRT_TMS", "InOutWRte_RvrtTms", // "Timeout period for charge/discharge rate.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_WRITE, Unit.SECONDS)), // + UINT16, false /* mandatory? */, READ_WRITE, Unit.SECONDS)), // IN_OUT_W_RTE_RMP_TMS(new ValuePoint("S124_IN_OUT_W_RTE_RMP_TMS", "InOutWRte_RmpTms", // "Ramp time for moving from current setpoint to new setpoint.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_WRITE, Unit.SECONDS)), // + UINT16, false /* mandatory? */, READ_WRITE, Unit.SECONDS)), // CHA_GRI_SET(new EnumPoint("S124_CHA_GRI_SET", "", "", // - EnumPoint.Type.ENUM16, false /* mandatory? */, AccessMode.READ_WRITE, S124_ChaGriSet.values())), // + ENUM16, false /* mandatory? */, READ_WRITE, S124_ChaGriSet.values())), // W_CHA_MAX_S_F(new ScaleFactorPoint("S124_W_CHA_MAX_S_F", "WChaMax_SF", // "Scale factor for maximum charge.")), // W_CHA_DIS_CHA_GRA_S_F(new ScaleFactorPoint("S124_W_CHA_DIS_CHA_GRA_S_F", "WChaDisChaGra_SF", // @@ -2365,26 +2387,26 @@ public OptionsEnum getUndefined() { public static enum S125 implements SunSpecPoint { MOD_ENA(new BitFieldPoint("S125_MOD_ENA", "ModEna", // "Is price-based charge/discharge mode active?", // - BitFieldPoint.Type.BITFIELD16, true /* mandatory? */, AccessMode.READ_WRITE, S125_ModEna.values())), // + BITFIELD16, true /* mandatory? */, READ_WRITE, S125_ModEna.values())), // SIG_TYPE(new EnumPoint("S125_SIG_TYPE", "SigType", // "Meaning of the pricing signal. When a Price schedule is used, type must match the schedule range variable description.", // - EnumPoint.Type.ENUM16, false /* mandatory? */, AccessMode.READ_WRITE, S125_SigType.values())), // + ENUM16, false /* mandatory? */, READ_WRITE, S125_SigType.values())), // SIG(new ScaledValuePoint("S125_SIG", "Sig", // "Utility/ESP specific pricing signal. Content depends on pricing signal type. When H/M/L type is specified. Low=0; Med=1; High=2.", // - ValuePoint.Type.INT16, true /* mandatory? */, AccessMode.READ_WRITE, Unit.NONE, "Sig_SF")), // + INT16, true /* mandatory? */, READ_WRITE, Unit.NONE, "Sig_SF")), // WIN_TMS(new ValuePoint("S125_WIN_TMS", "WinTms", // "Time window for charge/discharge pricing change.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_WRITE, Unit.SECONDS)), // + UINT16, false /* mandatory? */, READ_WRITE, Unit.SECONDS)), // RVT_TMS(new ValuePoint("S125_RVT_TMS", "RvtTms", // "Timeout period for charge/discharge pricing change.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_WRITE, Unit.SECONDS)), // + UINT16, false /* mandatory? */, READ_WRITE, Unit.SECONDS)), // RMP_TMS(new ValuePoint("S125_RMP_TMS", "RmpTms", // "Ramp time for moving from current charge or discharge level to new level.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_WRITE, Unit.SECONDS)), // + UINT16, false /* mandatory? */, READ_WRITE, Unit.SECONDS)), // SIG_S_F(new ScaleFactorPoint("S125_SIG_S_F", "Sig_SF", // "Pricing signal scale factor.")), // PAD(new ValuePoint("S125_PAD", "", "", // - ValuePoint.Type.PAD, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)); + ValuePoint.Type.PAD, false /* mandatory? */, READ_ONLY, Unit.NONE)); private final Point point; @@ -2448,22 +2470,22 @@ public OptionsEnum getUndefined() { public static enum S127 implements SunSpecPoint { W_GRA(new ScaledValuePoint("S127_W_GRA", "WGra", // "The slope of the reduction in the maximum allowed watts output as a function of frequency.", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_WRITE, Unit.PERCENT, "WGra_SF")), // + UINT16, true /* mandatory? */, READ_WRITE, Unit.PERCENT, "WGra_SF")), // HZ_STR(new ScaledValuePoint("S127_HZ_STR", "HzStr", // "The frequency deviation from nominal frequency (ECPNomHz) at which a snapshot of the instantaneous power output is taken to act as the CAPPED power level (PM) and above which reduction in power output occurs.", // - ValuePoint.Type.INT16, true /* mandatory? */, AccessMode.READ_WRITE, Unit.HERTZ, "HzStrStop_SF")), // + INT16, true /* mandatory? */, READ_WRITE, Unit.HERTZ, "HzStrStop_SF")), // HZ_STOP(new ScaledValuePoint("S127_HZ_STOP", "HzStop", // "The frequency deviation from nominal frequency (ECPNomHz) at which curtailed power output may return to normal and the cap on the power level value is removed.", // - ValuePoint.Type.INT16, true /* mandatory? */, AccessMode.READ_WRITE, Unit.HERTZ, "HzStrStop_SF")), // + INT16, true /* mandatory? */, READ_WRITE, Unit.HERTZ, "HzStrStop_SF")), // HYS_ENA(new BitFieldPoint("S127_HYS_ENA", "HysEna", // "Enable hysteresis", // - BitFieldPoint.Type.BITFIELD16, true /* mandatory? */, AccessMode.READ_WRITE, S127_HysEna.values())), // + BITFIELD16, true /* mandatory? */, READ_WRITE, S127_HysEna.values())), // MOD_ENA(new BitFieldPoint("S127_MOD_ENA", "ModEna", // "Is Parameterized Frequency-Watt control active.", // - BitFieldPoint.Type.BITFIELD16, true /* mandatory? */, AccessMode.READ_WRITE, S127_ModEna.values())), // + BITFIELD16, true /* mandatory? */, READ_WRITE, S127_ModEna.values())), // HZ_STOP_W_GRA(new ScaledValuePoint("S127_HZ_STOP_W_GRA", "HzStopWGra", // "The maximum time-based rate of change at which power output returns to normal after having been capped by an over frequency event.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_WRITE, Unit.PERCENT, "RmpIncDec_SF")), // + UINT16, false /* mandatory? */, READ_WRITE, Unit.PERCENT, "RmpIncDec_SF")), // W_GRA_S_F(new ScaleFactorPoint("S127_W_GRA_S_F", "WGra_SF", // "Scale factor for output gradient.")), // HZ_STR_STOP_S_F(new ScaleFactorPoint("S127_HZ_STR_STOP_S_F", "HzStrStop_SF", // @@ -2471,7 +2493,7 @@ public static enum S127 implements SunSpecPoint { RMP_INC_DEC_S_F(new ScaleFactorPoint("S127_RMP_INC_DEC_S_F", "RmpIncDec_SF", // "Scale factor for increment and decrement ramps.")), // PAD(new ValuePoint("S127_PAD", "", "", // - ValuePoint.Type.PAD, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)); + ValuePoint.Type.PAD, false /* mandatory? */, READ_ONLY, Unit.NONE)); private final Point point; @@ -2518,43 +2540,43 @@ public BitPoint get() { public static enum S128 implements SunSpecPoint { AR_GRA_MOD(new EnumPoint("S128_AR_GRA_MOD", "ArGraMod", // "Indicates if gradients trend toward zero at the edges of the deadband or trend toward zero at the center of the deadband.", // - EnumPoint.Type.ENUM16, true /* mandatory? */, AccessMode.READ_WRITE, S128_ArGraMod.values())), // + ENUM16, true /* mandatory? */, READ_WRITE, S128_ArGraMod.values())), // AR_GRA_SAG(new ScaledValuePoint("S128_AR_GRA_SAG", "ArGraSag", // "The gradient used to increase capacitive dynamic current. A value of 0 indicates no additional reactive current support.", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_WRITE, Unit.NONE, "ArGra_SF")), // + UINT16, true /* mandatory? */, READ_WRITE, Unit.NONE, "ArGra_SF")), // AR_GRA_SWELL(new ScaledValuePoint("S128_AR_GRA_SWELL", "ArGraSwell", // "The gradient used to increase inductive dynamic current. A value of 0 indicates no additional reactive current support.", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_WRITE, Unit.NONE, "ArGra_SF")), // + UINT16, true /* mandatory? */, READ_WRITE, Unit.NONE, "ArGra_SF")), // MOD_ENA(new BitFieldPoint("S128_MOD_ENA", "ModEna", // "Activate dynamic reactive current model", // - BitFieldPoint.Type.BITFIELD16, true /* mandatory? */, AccessMode.READ_WRITE, S128_ModEna.values())), // + BITFIELD16, true /* mandatory? */, READ_WRITE, S128_ModEna.values())), // FIL_TMS(new ValuePoint("S128_FIL_TMS", "FilTms", // "The time window used to calculate the moving average voltage.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_WRITE, Unit.SECONDS)), // + UINT16, false /* mandatory? */, READ_WRITE, Unit.SECONDS)), // DB_V_MIN(new ScaledValuePoint("S128_DB_V_MIN", "DbVMin", // "The lower delta voltage limit for which negative voltage deviations less than this value no dynamic vars are produced.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_WRITE, Unit.PERCENT, "VRefPct_SF")), // + UINT16, false /* mandatory? */, READ_WRITE, Unit.PERCENT, "VRefPct_SF")), // DB_V_MAX(new ScaledValuePoint("S128_DB_V_MAX", "DbVMax", // "The upper delta voltage limit for which positive voltage deviations less than this value no dynamic current produced.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_WRITE, Unit.PERCENT, "VRefPct_SF")), // + UINT16, false /* mandatory? */, READ_WRITE, Unit.PERCENT, "VRefPct_SF")), // BLK_ZN_V(new ScaledValuePoint("S128_BLK_ZN_V", "BlkZnV", // "Block zone voltage which defines a lower voltage boundary below which no dynamic current is produced.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_WRITE, Unit.PERCENT, "VRefPct_SF")), // + UINT16, false /* mandatory? */, READ_WRITE, Unit.PERCENT, "VRefPct_SF")), // HYS_BLK_ZN_V(new ScaledValuePoint("S128_HYS_BLK_ZN_V", "HysBlkZnV", // "Hysteresis voltage used with BlkZnV.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_WRITE, Unit.PERCENT, "VRefPct_SF")), // + UINT16, false /* mandatory? */, READ_WRITE, Unit.PERCENT, "VRefPct_SF")), // BLK_ZN_TMMS(new ValuePoint("S128_BLK_ZN_TMMS", "BlkZnTmms", // "Block zone time the time before which reactive current support remains active regardless of how low the voltage drops.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_WRITE, Unit.MILLISECONDS)), // + UINT16, false /* mandatory? */, READ_WRITE, Unit.MILLISECONDS)), // HOLD_TMMS(new ValuePoint("S128_HOLD_TMMS", "HoldTmms", // "Hold time during which reactive current support continues after the average voltage has entered the dead zone.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_WRITE, Unit.MILLISECONDS)), // + UINT16, false /* mandatory? */, READ_WRITE, Unit.MILLISECONDS)), // AR_GRA_S_F(new ScaleFactorPoint("S128_AR_GRA_S_F", "ArGra_SF", // "Scale factor for the gradients.")), // V_REF_PCT_S_F(new ScaleFactorPoint("S128_V_REF_PCT_S_F", "VRefPct_SF", // "Scale factor for the voltage zone and limit settings.")), // PAD(new ValuePoint("S128_PAD", "", "", // - ValuePoint.Type.PAD, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)); + ValuePoint.Type.PAD, false /* mandatory? */, READ_ONLY, Unit.NONE)); private final Point point; @@ -2615,25 +2637,25 @@ public BitPoint get() { public static enum S145 implements SunSpecPoint { NOM_RMP_UP_RTE(new ScaledValuePoint("S145_NOM_RMP_UP_RTE", "Ramp Up Rate", // "Ramp up rate as a percentage of max current.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_WRITE, Unit.NONE, "Rmp_SF")), // + UINT16, false /* mandatory? */, READ_WRITE, Unit.NONE, "Rmp_SF")), // NOM_RMP_DN_RTE(new ScaledValuePoint("S145_NOM_RMP_DN_RTE", "NomRmpDnRte", // "Ramp down rate as a percentage of max current.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_WRITE, Unit.NONE, "Rmp_SF")), // + UINT16, false /* mandatory? */, READ_WRITE, Unit.NONE, "Rmp_SF")), // EMG_RMP_UP_RTE(new ScaledValuePoint("S145_EMG_RMP_UP_RTE", "Emergency Ramp Up Rate", // "Emergency ramp up rate as a percentage of max current.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_WRITE, Unit.NONE, "Rmp_SF")), // + UINT16, false /* mandatory? */, READ_WRITE, Unit.NONE, "Rmp_SF")), // EMG_RMP_DN_RTE(new ScaledValuePoint("S145_EMG_RMP_DN_RTE", "Emergency Ramp Down Rate", // "Emergency ramp down rate as a percentage of max current.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_WRITE, Unit.NONE, "Rmp_SF")), // + UINT16, false /* mandatory? */, READ_WRITE, Unit.NONE, "Rmp_SF")), // CONN_RMP_UP_RTE(new ScaledValuePoint("S145_CONN_RMP_UP_RTE", "Connect Ramp Up Rate", // "Connect ramp up rate as a percentage of max current.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_WRITE, Unit.NONE, "Rmp_SF")), // + UINT16, false /* mandatory? */, READ_WRITE, Unit.NONE, "Rmp_SF")), // CONN_RMP_DN_RTE(new ScaledValuePoint("S145_CONN_RMP_DN_RTE", "Connect Ramp Down Rate", // "Connect ramp down rate as a percentage of max current.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_WRITE, Unit.NONE, "Rmp_SF")), // + UINT16, false /* mandatory? */, READ_WRITE, Unit.NONE, "Rmp_SF")), // A_GRA(new ScaledValuePoint("S145_A_GRA", "Default Ramp Rate", // "Ramp rate specified in percent of max current.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_WRITE, Unit.NONE, "Rmp_SF")), // + UINT16, false /* mandatory? */, READ_WRITE, Unit.NONE, "Rmp_SF")), // RMP_S_F(new ScaleFactorPoint("S145_RMP_S_F", "Ramp Rate Scale Factor", // "Ramp Rate Scale Factor")); @@ -2652,174 +2674,186 @@ public Point get() { public static enum S201 implements SunSpecPoint { A(new ScaledValuePoint("S201_A", "Amps", // "Total AC Current", // - ValuePoint.Type.INT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.AMPERE, "A_SF")), // + INT16, true /* mandatory? */, READ_ONLY, Unit.AMPERE, "A_SF")), // APH_A(new ScaledValuePoint("S201_APH_A", "Amps PhaseA", // "Phase A Current", // - ValuePoint.Type.INT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.AMPERE, "A_SF")), // + INT16, true /* mandatory? */, READ_ONLY, Unit.AMPERE, "A_SF")), // APH_B(new ScaledValuePoint("S201_APH_B", "Amps PhaseB", // "Phase B Current", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.AMPERE, "A_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.AMPERE, "A_SF")), // APH_C(new ScaledValuePoint("S201_APH_C", "Amps PhaseC", // "Phase C Current", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.AMPERE, "A_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.AMPERE, "A_SF")), // A_SF(new ScaleFactorPoint("S201_A_SF", "", // "Current scale factor")), // PH_V(new ScaledValuePoint("S201_PH_V", "Voltage LN", // "Line to Neutral AC Voltage (average of active phases)", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT, "V_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.VOLT, "V_SF")), // PH_VPH_A(new ScaledValuePoint("S201_PH_VPH_A", "Phase Voltage AN", // "Phase Voltage AN", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT, "V_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.VOLT, "V_SF")), // PH_VPH_B(new ScaledValuePoint("S201_PH_VPH_B", "Phase Voltage BN", // "Phase Voltage BN", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT, "V_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.VOLT, "V_SF")), // PH_VPH_C(new ScaledValuePoint("S201_PH_VPH_C", "Phase Voltage CN", // "Phase Voltage CN", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT, "V_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.VOLT, "V_SF")), // PPV(new ScaledValuePoint("S201_PPV", "Voltage LL", // "Line to Line AC Voltage (average of active phases)", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT, "V_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.VOLT, "V_SF")), // P_P_VPH_A_B(new ScaledValuePoint("S201_P_P_VPH_A_B", "Phase Voltage AB", // "Phase Voltage AB", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT, "V_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.VOLT, "V_SF")), // P_P_VPH_B_C(new ScaledValuePoint("S201_P_P_VPH_B_C", "Phase Voltage BC", // "Phase Voltage BC", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT, "V_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.VOLT, "V_SF")), // P_P_VPH_C_A(new ScaledValuePoint("S201_P_P_VPH_C_A", "Phase Voltage CA", // "Phase Voltage CA", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT, "V_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.VOLT, "V_SF")), // V_SF(new ScaleFactorPoint("S201_V_SF", "", // "Voltage scale factor")), // HZ(new ScaledValuePoint("S201_HZ", "Hz", // "Frequency", // - ValuePoint.Type.INT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.HERTZ, "Hz_SF")), // + INT16, true /* mandatory? */, READ_ONLY, Unit.HERTZ, "Hz_SF")), // HZ_S_F(new ScaleFactorPoint("S201_HZ_S_F", "", // "Frequency scale factor")), // W(new ScaledValuePoint("S201_W", "Watts", // "Total Real Power", // - ValuePoint.Type.INT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.WATT, "W_SF")), // + INT16, true /* mandatory? */, READ_ONLY, Unit.WATT, "W_SF")), // WPH_A(new ScaledValuePoint("S201_WPH_A", "Watts phase A", "", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.WATT, "W_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.WATT, "W_SF")), // WPH_B(new ScaledValuePoint("S201_WPH_B", "Watts phase B", "", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.WATT, "W_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.WATT, "W_SF")), // WPH_C(new ScaledValuePoint("S201_WPH_C", "Watts phase C", "", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.WATT, "W_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.WATT, "W_SF")), // W_SF(new ScaleFactorPoint("S201_W_SF", "", // "Real Power scale factor")), // VA(new ScaledValuePoint("S201_VA", "VA", // "AC Apparent Power", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE, "VA_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE, "VA_SF")), // V_APH_A(new ScaledValuePoint("S201_V_APH_A", "VA phase A", "", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE, "VA_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE, "VA_SF")), // V_APH_B(new ScaledValuePoint("S201_V_APH_B", "VA phase B", "", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE, "VA_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE, "VA_SF")), // V_APH_C(new ScaledValuePoint("S201_V_APH_C", "VA phase C", "", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE, "VA_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE, "VA_SF")), // VA_SF(new ScaleFactorPoint("S201_VA_SF", "", // "Apparent Power scale factor")), // VAR(new ScaledValuePoint("S201_VAR", "VAR", // "Reactive Power", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE, "VAR_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE, "VAR_SF")), // V_A_RPH_A(new ScaledValuePoint("S201_V_A_RPH_A", "VAR phase A", "", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE, "VAR_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE, "VAR_SF")), // V_A_RPH_B(new ScaledValuePoint("S201_V_A_RPH_B", "VAR phase B", "", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE, "VAR_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE, "VAR_SF")), // V_A_RPH_C(new ScaledValuePoint("S201_V_A_RPH_C", "VAR phase C", "", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE, "VAR_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE, "VAR_SF")), // VAR_SF(new ScaleFactorPoint("S201_VAR_SF", "", // "Reactive Power scale factor")), // PF(new ScaledValuePoint("S201_PF", "PF", // "Power Factor", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE, "PF_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.NONE, "PF_SF")), // P_FPH_A(new ScaledValuePoint("S201_P_FPH_A", "PF phase A", "", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE, "PF_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.NONE, "PF_SF")), // P_FPH_B(new ScaledValuePoint("S201_P_FPH_B", "PF phase B", "", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE, "PF_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.NONE, "PF_SF")), // P_FPH_C(new ScaledValuePoint("S201_P_FPH_C", "PF phase C", "", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE, "PF_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.NONE, "PF_SF")), // PF_SF(new ScaleFactorPoint("S201_PF_SF", "", // "Power Factor scale factor")), // TOT_WH_EXP(new ScaledValuePoint("S201_TOT_WH_EXP", "Total Watt-hours Exported", // "Total Real Energy Exported", // - ValuePoint.Type.ACC32, true /* mandatory? */, AccessMode.READ_ONLY, Unit.CUMULATED_WATT_HOURS, "TotWh_SF")), // + ACC32, true /* mandatory? */, READ_ONLY, Unit.CUMULATED_WATT_HOURS, "TotWh_SF")), // TOT_WH_EXP_PH_A(new ScaledValuePoint("S201_TOT_WH_EXP_PH_A", "Total Watt-hours Exported phase A", "", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.CUMULATED_WATT_HOURS, "TotWh_SF")), // + ACC32, false /* mandatory? */, READ_ONLY, Unit.CUMULATED_WATT_HOURS, "TotWh_SF")), // TOT_WH_EXP_PH_B(new ScaledValuePoint("S201_TOT_WH_EXP_PH_B", "Total Watt-hours Exported phase B", "", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.CUMULATED_WATT_HOURS, "TotWh_SF")), // + ACC32, false /* mandatory? */, READ_ONLY, Unit.CUMULATED_WATT_HOURS, "TotWh_SF")), // TOT_WH_EXP_PH_C(new ScaledValuePoint("S201_TOT_WH_EXP_PH_C", "Total Watt-hours Exported phase C", "", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.CUMULATED_WATT_HOURS, "TotWh_SF")), // + ACC32, false /* mandatory? */, READ_ONLY, Unit.CUMULATED_WATT_HOURS, "TotWh_SF")), // TOT_WH_IMP(new ScaledValuePoint("S201_TOT_WH_IMP", "Total Watt-hours Imported", // "Total Real Energy Imported", // - ValuePoint.Type.ACC32, true /* mandatory? */, AccessMode.READ_ONLY, Unit.CUMULATED_WATT_HOURS, "TotWh_SF")), // + ACC32, true /* mandatory? */, READ_ONLY, Unit.CUMULATED_WATT_HOURS, "TotWh_SF")), // TOT_WH_IMP_PH_A(new ScaledValuePoint("S201_TOT_WH_IMP_PH_A", "Total Watt-hours Imported phase A", "", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.CUMULATED_WATT_HOURS, "TotWh_SF")), // + ACC32, false /* mandatory? */, READ_ONLY, Unit.CUMULATED_WATT_HOURS, "TotWh_SF")), // TOT_WH_IMP_PH_B(new ScaledValuePoint("S201_TOT_WH_IMP_PH_B", "Total Watt-hours Imported phase B", "", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.CUMULATED_WATT_HOURS, "TotWh_SF")), // + ACC32, false /* mandatory? */, READ_ONLY, Unit.CUMULATED_WATT_HOURS, "TotWh_SF")), // TOT_WH_IMP_PH_C(new ScaledValuePoint("S201_TOT_WH_IMP_PH_C", "Total Watt-hours Imported phase C", "", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.CUMULATED_WATT_HOURS, "TotWh_SF")), // + ACC32, false /* mandatory? */, READ_ONLY, Unit.CUMULATED_WATT_HOURS, "TotWh_SF")), // TOT_WH_S_F(new ScaleFactorPoint("S201_TOT_WH_S_F", "", // "Real Energy scale factor")), // TOT_V_AH_EXP(new ScaledValuePoint("S201_TOT_V_AH_EXP", "Total VA-hours Exported", // "Total Apparent Energy Exported", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_HOURS, "TotVAh_SF")), // + ACC32, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_HOURS, "TotVAh_SF")), // TOT_V_AH_EXP_PH_A(new ScaledValuePoint("S201_TOT_V_AH_EXP_PH_A", "Total VA-hours Exported phase A", "", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_HOURS, "TotVAh_SF")), // + ACC32, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_HOURS, "TotVAh_SF")), // TOT_V_AH_EXP_PH_B(new ScaledValuePoint("S201_TOT_V_AH_EXP_PH_B", "Total VA-hours Exported phase B", "", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_HOURS, "TotVAh_SF")), // + ACC32, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_HOURS, "TotVAh_SF")), // TOT_V_AH_EXP_PH_C(new ScaledValuePoint("S201_TOT_V_AH_EXP_PH_C", "Total VA-hours Exported phase C", "", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_HOURS, "TotVAh_SF")), // + ACC32, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_HOURS, "TotVAh_SF")), // TOT_V_AH_IMP(new ScaledValuePoint("S201_TOT_V_AH_IMP", "Total VA-hours Imported", // "Total Apparent Energy Imported", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_HOURS, "TotVAh_SF")), // + ACC32, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_HOURS, "TotVAh_SF")), // TOT_V_AH_IMP_PH_A(new ScaledValuePoint("S201_TOT_V_AH_IMP_PH_A", "Total VA-hours Imported phase A", "", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_HOURS, "TotVAh_SF")), // + ACC32, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_HOURS, "TotVAh_SF")), // TOT_V_AH_IMP_PH_B(new ScaledValuePoint("S201_TOT_V_AH_IMP_PH_B", "Total VA-hours Imported phase B", "", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_HOURS, "TotVAh_SF")), // + ACC32, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_HOURS, "TotVAh_SF")), // TOT_V_AH_IMP_PH_C(new ScaledValuePoint("S201_TOT_V_AH_IMP_PH_C", "Total VA-hours Imported phase C", "", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_HOURS, "TotVAh_SF")), // + ACC32, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_HOURS, "TotVAh_SF")), // TOT_V_AH_S_F(new ScaleFactorPoint("S201_TOT_V_AH_S_F", "", // "Apparent Energy scale factor")), // TOT_V_ARH_IMP_Q1(new ScaledValuePoint("S201_TOT_V_ARH_IMP_Q1", "Total VAR-hours Imported Q1", // "Total Reactive Energy Imported Quadrant 1", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // - TOT_V_ARH_IMP_Q1_PH_A(new ScaledValuePoint("S201_TOT_V_ARH_IMP_Q1_PH_A", "Total VAr-hours Imported Q1 phase A", "", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // - TOT_V_ARH_IMP_Q1_PH_B(new ScaledValuePoint("S201_TOT_V_ARH_IMP_Q1_PH_B", "Total VAr-hours Imported Q1 phase B", "", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // - TOT_V_ARH_IMP_Q1_PH_C(new ScaledValuePoint("S201_TOT_V_ARH_IMP_Q1_PH_C", "Total VAr-hours Imported Q1 phase C", "", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // + ACC32, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // + TOT_V_ARH_IMP_Q1_PH_A( + new ScaledValuePoint("S201_TOT_V_ARH_IMP_Q1_PH_A", "Total VAr-hours Imported Q1 phase A", "", // + ACC32, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // + TOT_V_ARH_IMP_Q1_PH_B( + new ScaledValuePoint("S201_TOT_V_ARH_IMP_Q1_PH_B", "Total VAr-hours Imported Q1 phase B", "", // + ACC32, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // + TOT_V_ARH_IMP_Q1_PH_C( + new ScaledValuePoint("S201_TOT_V_ARH_IMP_Q1_PH_C", "Total VAr-hours Imported Q1 phase C", "", // + ACC32, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // TOT_V_ARH_IMP_Q2(new ScaledValuePoint("S201_TOT_V_ARH_IMP_Q2", "Total VAr-hours Imported Q2", // "Total Reactive Power Imported Quadrant 2", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // - TOT_V_ARH_IMP_Q2_PH_A(new ScaledValuePoint("S201_TOT_V_ARH_IMP_Q2_PH_A", "Total VAr-hours Imported Q2 phase A", "", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // - TOT_V_ARH_IMP_Q2_PH_B(new ScaledValuePoint("S201_TOT_V_ARH_IMP_Q2_PH_B", "Total VAr-hours Imported Q2 phase B", "", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // - TOT_V_ARH_IMP_Q2_PH_C(new ScaledValuePoint("S201_TOT_V_ARH_IMP_Q2_PH_C", "Total VAr-hours Imported Q2 phase C", "", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // + ACC32, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // + TOT_V_ARH_IMP_Q2_PH_A( + new ScaledValuePoint("S201_TOT_V_ARH_IMP_Q2_PH_A", "Total VAr-hours Imported Q2 phase A", "", // + ACC32, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // + TOT_V_ARH_IMP_Q2_PH_B( + new ScaledValuePoint("S201_TOT_V_ARH_IMP_Q2_PH_B", "Total VAr-hours Imported Q2 phase B", "", // + ACC32, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // + TOT_V_ARH_IMP_Q2_PH_C( + new ScaledValuePoint("S201_TOT_V_ARH_IMP_Q2_PH_C", "Total VAr-hours Imported Q2 phase C", "", // + ACC32, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // TOT_V_ARH_EXP_Q3(new ScaledValuePoint("S201_TOT_V_ARH_EXP_Q3", "Total VAr-hours Exported Q3", // "Total Reactive Power Exported Quadrant 3", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // - TOT_V_ARH_EXP_Q3_PH_A(new ScaledValuePoint("S201_TOT_V_ARH_EXP_Q3_PH_A", "Total VAr-hours Exported Q3 phase A", "", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // - TOT_V_ARH_EXP_Q3_PH_B(new ScaledValuePoint("S201_TOT_V_ARH_EXP_Q3_PH_B", "Total VAr-hours Exported Q3 phase B", "", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // - TOT_V_ARH_EXP_Q3_PH_C(new ScaledValuePoint("S201_TOT_V_ARH_EXP_Q3_PH_C", "Total VAr-hours Exported Q3 phase C", "", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // + ACC32, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // + TOT_V_ARH_EXP_Q3_PH_A( + new ScaledValuePoint("S201_TOT_V_ARH_EXP_Q3_PH_A", "Total VAr-hours Exported Q3 phase A", "", // + ACC32, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // + TOT_V_ARH_EXP_Q3_PH_B( + new ScaledValuePoint("S201_TOT_V_ARH_EXP_Q3_PH_B", "Total VAr-hours Exported Q3 phase B", "", // + ACC32, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // + TOT_V_ARH_EXP_Q3_PH_C( + new ScaledValuePoint("S201_TOT_V_ARH_EXP_Q3_PH_C", "Total VAr-hours Exported Q3 phase C", "", // + ACC32, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // TOT_V_ARH_EXP_Q4(new ScaledValuePoint("S201_TOT_V_ARH_EXP_Q4", "Total VAr-hours Exported Q4", // "Total Reactive Power Exported Quadrant 4", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // - TOT_V_ARH_EXP_Q4_PH_A(new ScaledValuePoint("S201_TOT_V_ARH_EXP_Q4_PH_A", "Total VAr-hours Exported Q4 Imported phase A", "", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // - TOT_V_ARH_EXP_Q4_PH_B(new ScaledValuePoint("S201_TOT_V_ARH_EXP_Q4_PH_B", "Total VAr-hours Exported Q4 Imported phase B", "", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // - TOT_V_ARH_EXP_Q4_PH_C(new ScaledValuePoint("S201_TOT_V_ARH_EXP_Q4_PH_C", "Total VAr-hours Exported Q4 Imported phase C", "", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // + ACC32, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // + TOT_V_ARH_EXP_Q4_PH_A( + new ScaledValuePoint("S201_TOT_V_ARH_EXP_Q4_PH_A", "Total VAr-hours Exported Q4 Imported phase A", "", // + ACC32, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // + TOT_V_ARH_EXP_Q4_PH_B( + new ScaledValuePoint("S201_TOT_V_ARH_EXP_Q4_PH_B", "Total VAr-hours Exported Q4 Imported phase B", "", // + ACC32, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // + TOT_V_ARH_EXP_Q4_PH_C( + new ScaledValuePoint("S201_TOT_V_ARH_EXP_Q4_PH_C", "Total VAr-hours Exported Q4 Imported phase C", "", // + ACC32, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // TOT_V_ARH_S_F(new ScaleFactorPoint("S201_TOT_V_ARH_S_F", "", // "Reactive Energy scale factor")), // EVT(new BitFieldPoint("S201_EVT", "Events", // "Meter Event Flags", // - BitFieldPoint.Type.BITFIELD32, true /* mandatory? */, AccessMode.READ_ONLY, S201_Evt.values())); + BITFIELD32, true /* mandatory? */, READ_ONLY, S201_Evt.values())); private final Point point; @@ -2871,174 +2905,186 @@ public BitPoint get() { public static enum S202 implements SunSpecPoint { A(new ScaledValuePoint("S202_A", "Amps", // "Total AC Current", // - ValuePoint.Type.INT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.AMPERE, "A_SF")), // + INT16, true /* mandatory? */, READ_ONLY, Unit.AMPERE, "A_SF")), // APH_A(new ScaledValuePoint("S202_APH_A", "Amps PhaseA", // "Phase A Current", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.AMPERE, "A_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.AMPERE, "A_SF")), // APH_B(new ScaledValuePoint("S202_APH_B", "Amps PhaseB", // "Phase B Current", // - ValuePoint.Type.INT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.AMPERE, "A_SF")), // + INT16, true /* mandatory? */, READ_ONLY, Unit.AMPERE, "A_SF")), // APH_C(new ScaledValuePoint("S202_APH_C", "Amps PhaseC", // "Phase C Current", // - ValuePoint.Type.INT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.AMPERE, "A_SF")), // + INT16, true /* mandatory? */, READ_ONLY, Unit.AMPERE, "A_SF")), // A_SF(new ScaleFactorPoint("S202_A_SF", "", // "Current scale factor")), // PH_V(new ScaledValuePoint("S202_PH_V", "Voltage LN", // "Line to Neutral AC Voltage (average of active phases)", // - ValuePoint.Type.INT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT, "V_SF")), // + INT16, true /* mandatory? */, READ_ONLY, Unit.VOLT, "V_SF")), // PH_VPH_A(new ScaledValuePoint("S202_PH_VPH_A", "Phase Voltage AN", // "Phase Voltage AN", // - ValuePoint.Type.INT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT, "V_SF")), // + INT16, true /* mandatory? */, READ_ONLY, Unit.VOLT, "V_SF")), // PH_VPH_B(new ScaledValuePoint("S202_PH_VPH_B", "Phase Voltage BN", // "Phase Voltage BN", // - ValuePoint.Type.INT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT, "V_SF")), // + INT16, true /* mandatory? */, READ_ONLY, Unit.VOLT, "V_SF")), // PH_VPH_C(new ScaledValuePoint("S202_PH_VPH_C", "Phase Voltage CN", // "Phase Voltage CN", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT, "V_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.VOLT, "V_SF")), // PPV(new ScaledValuePoint("S202_PPV", "Voltage LL", // "Line to Line AC Voltage (average of active phases)", // - ValuePoint.Type.INT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT, "V_SF")), // + INT16, true /* mandatory? */, READ_ONLY, Unit.VOLT, "V_SF")), // PH_VPH_A_B(new ScaledValuePoint("S202_PH_VPH_A_B", "Phase Voltage AB", // "Phase Voltage AB", // - ValuePoint.Type.INT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT, "V_SF")), // + INT16, true /* mandatory? */, READ_ONLY, Unit.VOLT, "V_SF")), // PH_VPH_B_C(new ScaledValuePoint("S202_PH_VPH_B_C", "Phase Voltage BC", // "Phase Voltage BC", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT, "V_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.VOLT, "V_SF")), // PH_VPH_C_A(new ScaledValuePoint("S202_PH_VPH_C_A", "Phase Voltage CA", // "Phase Voltage CA", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT, "V_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.VOLT, "V_SF")), // V_SF(new ScaleFactorPoint("S202_V_SF", "", // "Voltage scale factor")), // HZ(new ScaledValuePoint("S202_HZ", "Hz", // "Frequency", // - ValuePoint.Type.INT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.HERTZ, "Hz_SF")), // + INT16, true /* mandatory? */, READ_ONLY, Unit.HERTZ, "Hz_SF")), // HZ_S_F(new ScaleFactorPoint("S202_HZ_S_F", "", // "Frequency scale factor")), // W(new ScaledValuePoint("S202_W", "Watts", // "Total Real Power", // - ValuePoint.Type.INT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.WATT, "W_SF")), // + INT16, true /* mandatory? */, READ_ONLY, Unit.WATT, "W_SF")), // WPH_A(new ScaledValuePoint("S202_WPH_A", "Watts phase A", "", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.WATT, "W_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.WATT, "W_SF")), // WPH_B(new ScaledValuePoint("S202_WPH_B", "Watts phase B", "", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.WATT, "W_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.WATT, "W_SF")), // WPH_C(new ScaledValuePoint("S202_WPH_C", "Watts phase C", "", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.WATT, "W_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.WATT, "W_SF")), // W_SF(new ScaleFactorPoint("S202_W_SF", "", // "Real Power scale factor")), // VA(new ScaledValuePoint("S202_VA", "VA", // "AC Apparent Power", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE, "VA_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE, "VA_SF")), // V_APH_A(new ScaledValuePoint("S202_V_APH_A", "VA phase A", "", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE, "VA_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE, "VA_SF")), // V_APH_B(new ScaledValuePoint("S202_V_APH_B", "VA phase B", "", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE, "VA_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE, "VA_SF")), // V_APH_C(new ScaledValuePoint("S202_V_APH_C", "VA phase C", "", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE, "VA_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE, "VA_SF")), // VA_SF(new ScaleFactorPoint("S202_VA_SF", "", // "Apparent Power scale factor")), // VAR(new ScaledValuePoint("S202_VAR", "VAR", // "Reactive Power", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE, "VAR_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE, "VAR_SF")), // V_A_RPH_A(new ScaledValuePoint("S202_V_A_RPH_A", "VAR phase A", "", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE, "VAR_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE, "VAR_SF")), // V_A_RPH_B(new ScaledValuePoint("S202_V_A_RPH_B", "VAR phase B", "", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE, "VAR_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE, "VAR_SF")), // V_A_RPH_C(new ScaledValuePoint("S202_V_A_RPH_C", "VAR phase C", "", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE, "VAR_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE, "VAR_SF")), // VAR_SF(new ScaleFactorPoint("S202_VAR_SF", "", // "Reactive Power scale factor")), // PF(new ScaledValuePoint("S202_PF", "PF", // "Power Factor", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE, "PF_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.NONE, "PF_SF")), // P_FPH_A(new ScaledValuePoint("S202_P_FPH_A", "PF phase A", "", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE, "PF_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.NONE, "PF_SF")), // P_FPH_B(new ScaledValuePoint("S202_P_FPH_B", "PF phase B", "", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE, "PF_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.NONE, "PF_SF")), // P_FPH_C(new ScaledValuePoint("S202_P_FPH_C", "PF phase C", "", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE, "PF_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.NONE, "PF_SF")), // PF_SF(new ScaleFactorPoint("S202_PF_SF", "", // "Power Factor scale factor")), // TOT_WH_EXP(new ScaledValuePoint("S202_TOT_WH_EXP", "Total Watt-hours Exported", // "Total Real Energy Exported", // - ValuePoint.Type.ACC32, true /* mandatory? */, AccessMode.READ_ONLY, Unit.CUMULATED_WATT_HOURS, "TotWh_SF")), // + ACC32, true /* mandatory? */, READ_ONLY, Unit.CUMULATED_WATT_HOURS, "TotWh_SF")), // TOT_WH_EXP_PH_A(new ScaledValuePoint("S202_TOT_WH_EXP_PH_A", "Total Watt-hours Exported phase A", "", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.CUMULATED_WATT_HOURS, "TotWh_SF")), // + ACC32, false /* mandatory? */, READ_ONLY, Unit.CUMULATED_WATT_HOURS, "TotWh_SF")), // TOT_WH_EXP_PH_B(new ScaledValuePoint("S202_TOT_WH_EXP_PH_B", "Total Watt-hours Exported phase B", "", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.CUMULATED_WATT_HOURS, "TotWh_SF")), // + ACC32, false /* mandatory? */, READ_ONLY, Unit.CUMULATED_WATT_HOURS, "TotWh_SF")), // TOT_WH_EXP_PH_C(new ScaledValuePoint("S202_TOT_WH_EXP_PH_C", "Total Watt-hours Exported phase C", "", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.CUMULATED_WATT_HOURS, "TotWh_SF")), // + ACC32, false /* mandatory? */, READ_ONLY, Unit.CUMULATED_WATT_HOURS, "TotWh_SF")), // TOT_WH_IMP(new ScaledValuePoint("S202_TOT_WH_IMP", "Total Watt-hours Imported", // "Total Real Energy Imported", // - ValuePoint.Type.ACC32, true /* mandatory? */, AccessMode.READ_ONLY, Unit.CUMULATED_WATT_HOURS, "TotWh_SF")), // + ACC32, true /* mandatory? */, READ_ONLY, Unit.CUMULATED_WATT_HOURS, "TotWh_SF")), // TOT_WH_IMP_PH_A(new ScaledValuePoint("S202_TOT_WH_IMP_PH_A", "Total Watt-hours Imported phase A", "", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.CUMULATED_WATT_HOURS, "TotWh_SF")), // + ACC32, false /* mandatory? */, READ_ONLY, Unit.CUMULATED_WATT_HOURS, "TotWh_SF")), // TOT_WH_IMP_PH_B(new ScaledValuePoint("S202_TOT_WH_IMP_PH_B", "Total Watt-hours Imported phase B", "", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.CUMULATED_WATT_HOURS, "TotWh_SF")), // + ACC32, false /* mandatory? */, READ_ONLY, Unit.CUMULATED_WATT_HOURS, "TotWh_SF")), // TOT_WH_IMP_PH_C(new ScaledValuePoint("S202_TOT_WH_IMP_PH_C", "Total Watt-hours Imported phase C", "", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.CUMULATED_WATT_HOURS, "TotWh_SF")), // + ACC32, false /* mandatory? */, READ_ONLY, Unit.CUMULATED_WATT_HOURS, "TotWh_SF")), // TOT_WH_S_F(new ScaleFactorPoint("S202_TOT_WH_S_F", "", // "Real Energy scale factor")), // TOT_V_AH_EXP(new ScaledValuePoint("S202_TOT_V_AH_EXP", "Total VA-hours Exported", // "Total Apparent Energy Exported", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_HOURS, "TotVAh_SF")), // + ACC32, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_HOURS, "TotVAh_SF")), // TOT_V_AH_EXP_PH_A(new ScaledValuePoint("S202_TOT_V_AH_EXP_PH_A", "Total VA-hours Exported phase A", "", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_HOURS, "TotVAh_SF")), // + ACC32, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_HOURS, "TotVAh_SF")), // TOT_V_AH_EXP_PH_B(new ScaledValuePoint("S202_TOT_V_AH_EXP_PH_B", "Total VA-hours Exported phase B", "", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_HOURS, "TotVAh_SF")), // + ACC32, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_HOURS, "TotVAh_SF")), // TOT_V_AH_EXP_PH_C(new ScaledValuePoint("S202_TOT_V_AH_EXP_PH_C", "Total VA-hours Exported phase C", "", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_HOURS, "TotVAh_SF")), // + ACC32, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_HOURS, "TotVAh_SF")), // TOT_V_AH_IMP(new ScaledValuePoint("S202_TOT_V_AH_IMP", "Total VA-hours Imported", // "Total Apparent Energy Imported", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_HOURS, "TotVAh_SF")), // + ACC32, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_HOURS, "TotVAh_SF")), // TOT_V_AH_IMP_PH_A(new ScaledValuePoint("S202_TOT_V_AH_IMP_PH_A", "Total VA-hours Imported phase A", "", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_HOURS, "TotVAh_SF")), // + ACC32, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_HOURS, "TotVAh_SF")), // TOT_V_AH_IMP_PH_B(new ScaledValuePoint("S202_TOT_V_AH_IMP_PH_B", "Total VA-hours Imported phase B", "", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_HOURS, "TotVAh_SF")), // + ACC32, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_HOURS, "TotVAh_SF")), // TOT_V_AH_IMP_PH_C(new ScaledValuePoint("S202_TOT_V_AH_IMP_PH_C", "Total VA-hours Imported phase C", "", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_HOURS, "TotVAh_SF")), // + ACC32, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_HOURS, "TotVAh_SF")), // TOT_V_AH_S_F(new ScaleFactorPoint("S202_TOT_V_AH_S_F", "", // "Apparent Energy scale factor")), // TOT_V_ARH_IMP_Q1(new ScaledValuePoint("S202_TOT_V_ARH_IMP_Q1", "Total VAR-hours Imported Q1", // "Total Reactive Energy Imported Quadrant 1", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // - TOT_V_ARH_IMP_Q1_PH_A(new ScaledValuePoint("S202_TOT_V_ARH_IMP_Q1_PH_A", "Total VAr-hours Imported Q1 phase A", "", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // - TOT_V_ARH_IMP_Q1_PH_B(new ScaledValuePoint("S202_TOT_V_ARH_IMP_Q1_PH_B", "Total VAr-hours Imported Q1 phase B", "", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // - TOT_V_ARH_IMP_Q1_PH_C(new ScaledValuePoint("S202_TOT_V_ARH_IMP_Q1_PH_C", "Total VAr-hours Imported Q1 phase C", "", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // + ACC32, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // + TOT_V_ARH_IMP_Q1_PH_A( + new ScaledValuePoint("S202_TOT_V_ARH_IMP_Q1_PH_A", "Total VAr-hours Imported Q1 phase A", "", // + ACC32, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // + TOT_V_ARH_IMP_Q1_PH_B( + new ScaledValuePoint("S202_TOT_V_ARH_IMP_Q1_PH_B", "Total VAr-hours Imported Q1 phase B", "", // + ACC32, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // + TOT_V_ARH_IMP_Q1_PH_C( + new ScaledValuePoint("S202_TOT_V_ARH_IMP_Q1_PH_C", "Total VAr-hours Imported Q1 phase C", "", // + ACC32, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // TOT_V_ARH_IMP_Q2(new ScaledValuePoint("S202_TOT_V_ARH_IMP_Q2", "Total VAr-hours Imported Q2", // "Total Reactive Power Imported Quadrant 2", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // - TOT_V_ARH_IMP_Q2_PH_A(new ScaledValuePoint("S202_TOT_V_ARH_IMP_Q2_PH_A", "Total VAr-hours Imported Q2 phase A", "", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // - TOT_V_ARH_IMP_Q2_PH_B(new ScaledValuePoint("S202_TOT_V_ARH_IMP_Q2_PH_B", "Total VAr-hours Imported Q2 phase B", "", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // - TOT_V_ARH_IMP_Q2_PH_C(new ScaledValuePoint("S202_TOT_V_ARH_IMP_Q2_PH_C", "Total VAr-hours Imported Q2 phase C", "", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // + ACC32, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // + TOT_V_ARH_IMP_Q2_PH_A( + new ScaledValuePoint("S202_TOT_V_ARH_IMP_Q2_PH_A", "Total VAr-hours Imported Q2 phase A", "", // + ACC32, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // + TOT_V_ARH_IMP_Q2_PH_B( + new ScaledValuePoint("S202_TOT_V_ARH_IMP_Q2_PH_B", "Total VAr-hours Imported Q2 phase B", "", // + ACC32, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // + TOT_V_ARH_IMP_Q2_PH_C( + new ScaledValuePoint("S202_TOT_V_ARH_IMP_Q2_PH_C", "Total VAr-hours Imported Q2 phase C", "", // + ACC32, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // TOT_V_ARH_EXP_Q3(new ScaledValuePoint("S202_TOT_V_ARH_EXP_Q3", "Total VAr-hours Exported Q3", // "Total Reactive Power Exported Quadrant 3", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // - TOT_V_ARH_EXP_Q3_PH_A(new ScaledValuePoint("S202_TOT_V_ARH_EXP_Q3_PH_A", "Total VAr-hours Exported Q3 phase A", "", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // - TOT_V_ARH_EXP_Q3_PH_B(new ScaledValuePoint("S202_TOT_V_ARH_EXP_Q3_PH_B", "Total VAr-hours Exported Q3 phase B", "", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // - TOT_V_ARH_EXP_Q3_PH_C(new ScaledValuePoint("S202_TOT_V_ARH_EXP_Q3_PH_C", "Total VAr-hours Exported Q3 phase C", "", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // + ACC32, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // + TOT_V_ARH_EXP_Q3_PH_A( + new ScaledValuePoint("S202_TOT_V_ARH_EXP_Q3_PH_A", "Total VAr-hours Exported Q3 phase A", "", // + ACC32, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // + TOT_V_ARH_EXP_Q3_PH_B( + new ScaledValuePoint("S202_TOT_V_ARH_EXP_Q3_PH_B", "Total VAr-hours Exported Q3 phase B", "", // + ACC32, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // + TOT_V_ARH_EXP_Q3_PH_C( + new ScaledValuePoint("S202_TOT_V_ARH_EXP_Q3_PH_C", "Total VAr-hours Exported Q3 phase C", "", // + ACC32, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // TOT_V_ARH_EXP_Q4(new ScaledValuePoint("S202_TOT_V_ARH_EXP_Q4", "Total VAr-hours Exported Q4", // "Total Reactive Power Exported Quadrant 4", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // - TOT_V_ARH_EXP_Q4_PH_A(new ScaledValuePoint("S202_TOT_V_ARH_EXP_Q4_PH_A", "Total VAr-hours Exported Q4 Imported phase A", "", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // - TOT_V_ARH_EXP_Q4_PH_B(new ScaledValuePoint("S202_TOT_V_ARH_EXP_Q4_PH_B", "Total VAr-hours Exported Q4 Imported phase B", "", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // - TOT_V_ARH_EXP_Q4_PH_C(new ScaledValuePoint("S202_TOT_V_ARH_EXP_Q4_PH_C", "Total VAr-hours Exported Q4 Imported phase C", "", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // + ACC32, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // + TOT_V_ARH_EXP_Q4_PH_A( + new ScaledValuePoint("S202_TOT_V_ARH_EXP_Q4_PH_A", "Total VAr-hours Exported Q4 Imported phase A", "", // + ACC32, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // + TOT_V_ARH_EXP_Q4_PH_B( + new ScaledValuePoint("S202_TOT_V_ARH_EXP_Q4_PH_B", "Total VAr-hours Exported Q4 Imported phase B", "", // + ACC32, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // + TOT_V_ARH_EXP_Q4_PH_C( + new ScaledValuePoint("S202_TOT_V_ARH_EXP_Q4_PH_C", "Total VAr-hours Exported Q4 Imported phase C", "", // + ACC32, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // TOT_V_ARH_S_F(new ScaleFactorPoint("S202_TOT_V_ARH_S_F", "", // "Reactive Energy scale factor")), // EVT(new BitFieldPoint("S202_EVT", "Events", // "Meter Event Flags", // - BitFieldPoint.Type.BITFIELD32, true /* mandatory? */, AccessMode.READ_ONLY, S202_Evt.values())); + BITFIELD32, true /* mandatory? */, READ_ONLY, S202_Evt.values())); private final Point point; @@ -3098,174 +3144,186 @@ public BitPoint get() { public static enum S203 implements SunSpecPoint { A(new ScaledValuePoint("S203_A", "Amps", // "Total AC Current", // - ValuePoint.Type.INT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.AMPERE, "A_SF")), // + INT16, true /* mandatory? */, READ_ONLY, Unit.AMPERE, "A_SF")), // APH_A(new ScaledValuePoint("S203_APH_A", "Amps PhaseA", // "Phase A Current", // - ValuePoint.Type.INT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.AMPERE, "A_SF")), // + INT16, true /* mandatory? */, READ_ONLY, Unit.AMPERE, "A_SF")), // APH_B(new ScaledValuePoint("S203_APH_B", "Amps PhaseB", // "Phase B Current", // - ValuePoint.Type.INT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.AMPERE, "A_SF")), // + INT16, true /* mandatory? */, READ_ONLY, Unit.AMPERE, "A_SF")), // APH_C(new ScaledValuePoint("S203_APH_C", "Amps PhaseC", // "Phase C Current", // - ValuePoint.Type.INT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.AMPERE, "A_SF")), // + INT16, true /* mandatory? */, READ_ONLY, Unit.AMPERE, "A_SF")), // A_SF(new ScaleFactorPoint("S203_A_SF", "", // "Current scale factor")), // PH_V(new ScaledValuePoint("S203_PH_V", "Voltage LN", // "Line to Neutral AC Voltage (average of active phases)", // - ValuePoint.Type.INT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT, "V_SF")), // + INT16, true /* mandatory? */, READ_ONLY, Unit.VOLT, "V_SF")), // PH_VPH_A(new ScaledValuePoint("S203_PH_VPH_A", "Phase Voltage AN", // "Phase Voltage AN", // - ValuePoint.Type.INT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT, "V_SF")), // + INT16, true /* mandatory? */, READ_ONLY, Unit.VOLT, "V_SF")), // PH_VPH_B(new ScaledValuePoint("S203_PH_VPH_B", "Phase Voltage BN", // "Phase Voltage BN", // - ValuePoint.Type.INT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT, "V_SF")), // + INT16, true /* mandatory? */, READ_ONLY, Unit.VOLT, "V_SF")), // PH_VPH_C(new ScaledValuePoint("S203_PH_VPH_C", "Phase Voltage CN", // "Phase Voltage CN", // - ValuePoint.Type.INT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT, "V_SF")), // + INT16, true /* mandatory? */, READ_ONLY, Unit.VOLT, "V_SF")), // PPV(new ScaledValuePoint("S203_PPV", "Voltage LL", // "Line to Line AC Voltage (average of active phases)", // - ValuePoint.Type.INT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT, "V_SF")), // + INT16, true /* mandatory? */, READ_ONLY, Unit.VOLT, "V_SF")), // PH_VPH_A_B(new ScaledValuePoint("S203_PH_VPH_A_B", "Phase Voltage AB", // "Phase Voltage AB", // - ValuePoint.Type.INT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT, "V_SF")), // + INT16, true /* mandatory? */, READ_ONLY, Unit.VOLT, "V_SF")), // PH_VPH_B_C(new ScaledValuePoint("S203_PH_VPH_B_C", "Phase Voltage BC", // "Phase Voltage BC", // - ValuePoint.Type.INT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT, "V_SF")), // + INT16, true /* mandatory? */, READ_ONLY, Unit.VOLT, "V_SF")), // PH_VPH_C_A(new ScaledValuePoint("S203_PH_VPH_C_A", "Phase Voltage CA", // "Phase Voltage CA", // - ValuePoint.Type.INT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT, "V_SF")), // + INT16, true /* mandatory? */, READ_ONLY, Unit.VOLT, "V_SF")), // V_SF(new ScaleFactorPoint("S203_V_SF", "", // "Voltage scale factor")), // HZ(new ScaledValuePoint("S203_HZ", "Hz", // "Frequency", // - ValuePoint.Type.INT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.HERTZ, "Hz_SF")), // + INT16, true /* mandatory? */, READ_ONLY, Unit.HERTZ, "Hz_SF")), // HZ_S_F(new ScaleFactorPoint("S203_HZ_S_F", "", // "Frequency scale factor")), // W(new ScaledValuePoint("S203_W", "Watts", // "Total Real Power", // - ValuePoint.Type.INT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.WATT, "W_SF")), // + INT16, true /* mandatory? */, READ_ONLY, Unit.WATT, "W_SF")), // WPH_A(new ScaledValuePoint("S203_WPH_A", "Watts phase A", "", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.WATT, "W_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.WATT, "W_SF")), // WPH_B(new ScaledValuePoint("S203_WPH_B", "Watts phase B", "", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.WATT, "W_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.WATT, "W_SF")), // WPH_C(new ScaledValuePoint("S203_WPH_C", "Watts phase C", "", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.WATT, "W_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.WATT, "W_SF")), // W_SF(new ScaleFactorPoint("S203_W_SF", "", // "Real Power scale factor")), // VA(new ScaledValuePoint("S203_VA", "VA", // "AC Apparent Power", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE, "VA_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE, "VA_SF")), // V_APH_A(new ScaledValuePoint("S203_V_APH_A", "VA phase A", "", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE, "VA_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE, "VA_SF")), // V_APH_B(new ScaledValuePoint("S203_V_APH_B", "VA phase B", "", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE, "VA_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE, "VA_SF")), // V_APH_C(new ScaledValuePoint("S203_V_APH_C", "VA phase C", "", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE, "VA_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE, "VA_SF")), // VA_SF(new ScaleFactorPoint("S203_VA_SF", "", // "Apparent Power scale factor")), // VAR(new ScaledValuePoint("S203_VAR", "VAR", // "Reactive Power", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE, "VAR_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE, "VAR_SF")), // V_A_RPH_A(new ScaledValuePoint("S203_V_A_RPH_A", "VAR phase A", "", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE, "VAR_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE, "VAR_SF")), // V_A_RPH_B(new ScaledValuePoint("S203_V_A_RPH_B", "VAR phase B", "", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE, "VAR_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE, "VAR_SF")), // V_A_RPH_C(new ScaledValuePoint("S203_V_A_RPH_C", "VAR phase C", "", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE, "VAR_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE, "VAR_SF")), // VAR_SF(new ScaleFactorPoint("S203_VAR_SF", "", // "Reactive Power scale factor")), // PF(new ScaledValuePoint("S203_PF", "PF", // "Power Factor", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE, "PF_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.NONE, "PF_SF")), // P_FPH_A(new ScaledValuePoint("S203_P_FPH_A", "PF phase A", "", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE, "PF_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.NONE, "PF_SF")), // P_FPH_B(new ScaledValuePoint("S203_P_FPH_B", "PF phase B", "", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE, "PF_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.NONE, "PF_SF")), // P_FPH_C(new ScaledValuePoint("S203_P_FPH_C", "PF phase C", "", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE, "PF_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.NONE, "PF_SF")), // PF_SF(new ScaleFactorPoint("S203_PF_SF", "", // "Power Factor scale factor")), // TOT_WH_EXP(new ScaledValuePoint("S203_TOT_WH_EXP", "Total Watt-hours Exported", // "Total Real Energy Exported", // - ValuePoint.Type.ACC32, true /* mandatory? */, AccessMode.READ_ONLY, Unit.CUMULATED_WATT_HOURS, "TotWh_SF")), // + ACC32, true /* mandatory? */, READ_ONLY, Unit.CUMULATED_WATT_HOURS, "TotWh_SF")), // TOT_WH_EXP_PH_A(new ScaledValuePoint("S203_TOT_WH_EXP_PH_A", "Total Watt-hours Exported phase A", "", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.CUMULATED_WATT_HOURS, "TotWh_SF")), // + ACC32, false /* mandatory? */, READ_ONLY, Unit.CUMULATED_WATT_HOURS, "TotWh_SF")), // TOT_WH_EXP_PH_B(new ScaledValuePoint("S203_TOT_WH_EXP_PH_B", "Total Watt-hours Exported phase B", "", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.CUMULATED_WATT_HOURS, "TotWh_SF")), // + ACC32, false /* mandatory? */, READ_ONLY, Unit.CUMULATED_WATT_HOURS, "TotWh_SF")), // TOT_WH_EXP_PH_C(new ScaledValuePoint("S203_TOT_WH_EXP_PH_C", "Total Watt-hours Exported phase C", "", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.CUMULATED_WATT_HOURS, "TotWh_SF")), // + ACC32, false /* mandatory? */, READ_ONLY, Unit.CUMULATED_WATT_HOURS, "TotWh_SF")), // TOT_WH_IMP(new ScaledValuePoint("S203_TOT_WH_IMP", "Total Watt-hours Imported", // "Total Real Energy Imported", // - ValuePoint.Type.ACC32, true /* mandatory? */, AccessMode.READ_ONLY, Unit.CUMULATED_WATT_HOURS, "TotWh_SF")), // + ACC32, true /* mandatory? */, READ_ONLY, Unit.CUMULATED_WATT_HOURS, "TotWh_SF")), // TOT_WH_IMP_PH_A(new ScaledValuePoint("S203_TOT_WH_IMP_PH_A", "Total Watt-hours Imported phase A", "", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.CUMULATED_WATT_HOURS, "TotWh_SF")), // + ACC32, false /* mandatory? */, READ_ONLY, Unit.CUMULATED_WATT_HOURS, "TotWh_SF")), // TOT_WH_IMP_PH_B(new ScaledValuePoint("S203_TOT_WH_IMP_PH_B", "Total Watt-hours Imported phase B", "", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.CUMULATED_WATT_HOURS, "TotWh_SF")), // + ACC32, false /* mandatory? */, READ_ONLY, Unit.CUMULATED_WATT_HOURS, "TotWh_SF")), // TOT_WH_IMP_PH_C(new ScaledValuePoint("S203_TOT_WH_IMP_PH_C", "Total Watt-hours Imported phase C", "", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.CUMULATED_WATT_HOURS, "TotWh_SF")), // + ACC32, false /* mandatory? */, READ_ONLY, Unit.CUMULATED_WATT_HOURS, "TotWh_SF")), // TOT_WH_S_F(new ScaleFactorPoint("S203_TOT_WH_S_F", "", // "Real Energy scale factor")), // TOT_V_AH_EXP(new ScaledValuePoint("S203_TOT_V_AH_EXP", "Total VA-hours Exported", // "Total Apparent Energy Exported", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_HOURS, "TotVAh_SF")), // + ACC32, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_HOURS, "TotVAh_SF")), // TOT_V_AH_EXP_PH_A(new ScaledValuePoint("S203_TOT_V_AH_EXP_PH_A", "Total VA-hours Exported phase A", "", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_HOURS, "TotVAh_SF")), // + ACC32, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_HOURS, "TotVAh_SF")), // TOT_V_AH_EXP_PH_B(new ScaledValuePoint("S203_TOT_V_AH_EXP_PH_B", "Total VA-hours Exported phase B", "", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_HOURS, "TotVAh_SF")), // + ACC32, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_HOURS, "TotVAh_SF")), // TOT_V_AH_EXP_PH_C(new ScaledValuePoint("S203_TOT_V_AH_EXP_PH_C", "Total VA-hours Exported phase C", "", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_HOURS, "TotVAh_SF")), // + ACC32, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_HOURS, "TotVAh_SF")), // TOT_V_AH_IMP(new ScaledValuePoint("S203_TOT_V_AH_IMP", "Total VA-hours Imported", // "Total Apparent Energy Imported", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_HOURS, "TotVAh_SF")), // + ACC32, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_HOURS, "TotVAh_SF")), // TOT_V_AH_IMP_PH_A(new ScaledValuePoint("S203_TOT_V_AH_IMP_PH_A", "Total VA-hours Imported phase A", "", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_HOURS, "TotVAh_SF")), // + ACC32, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_HOURS, "TotVAh_SF")), // TOT_V_AH_IMP_PH_B(new ScaledValuePoint("S203_TOT_V_AH_IMP_PH_B", "Total VA-hours Imported phase B", "", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_HOURS, "TotVAh_SF")), // + ACC32, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_HOURS, "TotVAh_SF")), // TOT_V_AH_IMP_PH_C(new ScaledValuePoint("S203_TOT_V_AH_IMP_PH_C", "Total VA-hours Imported phase C", "", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_HOURS, "TotVAh_SF")), // + ACC32, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_HOURS, "TotVAh_SF")), // TOT_V_AH_S_F(new ScaleFactorPoint("S203_TOT_V_AH_S_F", "", // "Apparent Energy scale factor")), // TOT_V_ARH_IMP_Q1(new ScaledValuePoint("S203_TOT_V_ARH_IMP_Q1", "Total VAR-hours Imported Q1", // "Total Reactive Energy Imported Quadrant 1", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // - TOT_V_ARH_IMP_Q1_PH_A(new ScaledValuePoint("S203_TOT_V_ARH_IMP_Q1_PH_A", "Total VAr-hours Imported Q1 phase A", "", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // - TOT_V_ARH_IMP_Q1_PH_B(new ScaledValuePoint("S203_TOT_V_ARH_IMP_Q1_PH_B", "Total VAr-hours Imported Q1 phase B", "", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // - TOT_V_ARH_IMP_Q1_PH_C(new ScaledValuePoint("S203_TOT_V_ARH_IMP_Q1_PH_C", "Total VAr-hours Imported Q1 phase C", "", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // + ACC32, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // + TOT_V_ARH_IMP_Q1_PH_A( + new ScaledValuePoint("S203_TOT_V_ARH_IMP_Q1_PH_A", "Total VAr-hours Imported Q1 phase A", "", // + ACC32, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // + TOT_V_ARH_IMP_Q1_PH_B( + new ScaledValuePoint("S203_TOT_V_ARH_IMP_Q1_PH_B", "Total VAr-hours Imported Q1 phase B", "", // + ACC32, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // + TOT_V_ARH_IMP_Q1_PH_C( + new ScaledValuePoint("S203_TOT_V_ARH_IMP_Q1_PH_C", "Total VAr-hours Imported Q1 phase C", "", // + ACC32, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // TOT_V_ARH_IMP_Q2(new ScaledValuePoint("S203_TOT_V_ARH_IMP_Q2", "Total VAr-hours Imported Q2", // "Total Reactive Power Imported Quadrant 2", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // - TOT_V_ARH_IMP_Q2_PH_A(new ScaledValuePoint("S203_TOT_V_ARH_IMP_Q2_PH_A", "Total VAr-hours Imported Q2 phase A", "", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // - TOT_V_ARH_IMP_Q2_PH_B(new ScaledValuePoint("S203_TOT_V_ARH_IMP_Q2_PH_B", "Total VAr-hours Imported Q2 phase B", "", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // - TOT_V_ARH_IMP_Q2_PH_C(new ScaledValuePoint("S203_TOT_V_ARH_IMP_Q2_PH_C", "Total VAr-hours Imported Q2 phase C", "", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // + ACC32, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // + TOT_V_ARH_IMP_Q2_PH_A( + new ScaledValuePoint("S203_TOT_V_ARH_IMP_Q2_PH_A", "Total VAr-hours Imported Q2 phase A", "", // + ACC32, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // + TOT_V_ARH_IMP_Q2_PH_B( + new ScaledValuePoint("S203_TOT_V_ARH_IMP_Q2_PH_B", "Total VAr-hours Imported Q2 phase B", "", // + ACC32, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // + TOT_V_ARH_IMP_Q2_PH_C( + new ScaledValuePoint("S203_TOT_V_ARH_IMP_Q2_PH_C", "Total VAr-hours Imported Q2 phase C", "", // + ACC32, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // TOT_V_ARH_EXP_Q3(new ScaledValuePoint("S203_TOT_V_ARH_EXP_Q3", "Total VAr-hours Exported Q3", // "Total Reactive Power Exported Quadrant 3", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // - TOT_V_ARH_EXP_Q3_PH_A(new ScaledValuePoint("S203_TOT_V_ARH_EXP_Q3_PH_A", "Total VAr-hours Exported Q3 phase A", "", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // - TOT_V_ARH_EXP_Q3_PH_B(new ScaledValuePoint("S203_TOT_V_ARH_EXP_Q3_PH_B", "Total VAr-hours Exported Q3 phase B", "", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // - TOT_V_ARH_EXP_Q3_PH_C(new ScaledValuePoint("S203_TOT_V_ARH_EXP_Q3_PH_C", "Total VAr-hours Exported Q3 phase C", "", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // + ACC32, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // + TOT_V_ARH_EXP_Q3_PH_A( + new ScaledValuePoint("S203_TOT_V_ARH_EXP_Q3_PH_A", "Total VAr-hours Exported Q3 phase A", "", // + ACC32, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // + TOT_V_ARH_EXP_Q3_PH_B( + new ScaledValuePoint("S203_TOT_V_ARH_EXP_Q3_PH_B", "Total VAr-hours Exported Q3 phase B", "", // + ACC32, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // + TOT_V_ARH_EXP_Q3_PH_C( + new ScaledValuePoint("S203_TOT_V_ARH_EXP_Q3_PH_C", "Total VAr-hours Exported Q3 phase C", "", // + ACC32, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // TOT_V_ARH_EXP_Q4(new ScaledValuePoint("S203_TOT_V_ARH_EXP_Q4", "Total VAr-hours Exported Q4", // "Total Reactive Power Exported Quadrant 4", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // - TOT_V_ARH_EXP_Q4_PH_A(new ScaledValuePoint("S203_TOT_V_ARH_EXP_Q4_PH_A", "Total VAr-hours Exported Q4 Imported phase A", "", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // - TOT_V_ARH_EXP_Q4_PH_B(new ScaledValuePoint("S203_TOT_V_ARH_EXP_Q4_PH_B", "Total VAr-hours Exported Q4 Imported phase B", "", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // - TOT_V_ARH_EXP_Q4_PH_C(new ScaledValuePoint("S203_TOT_V_ARH_EXP_Q4_PH_C", "Total VAr-hours Exported Q4 Imported phase C", "", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // + ACC32, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // + TOT_V_ARH_EXP_Q4_PH_A( + new ScaledValuePoint("S203_TOT_V_ARH_EXP_Q4_PH_A", "Total VAr-hours Exported Q4 Imported phase A", "", // + ACC32, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // + TOT_V_ARH_EXP_Q4_PH_B( + new ScaledValuePoint("S203_TOT_V_ARH_EXP_Q4_PH_B", "Total VAr-hours Exported Q4 Imported phase B", "", // + ACC32, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // + TOT_V_ARH_EXP_Q4_PH_C( + new ScaledValuePoint("S203_TOT_V_ARH_EXP_Q4_PH_C", "Total VAr-hours Exported Q4 Imported phase C", "", // + ACC32, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // TOT_V_ARH_S_F(new ScaleFactorPoint("S203_TOT_V_ARH_S_F", "", // "Reactive Energy scale factor")), // EVT(new BitFieldPoint("S203_EVT", "Events", // "Meter Event Flags", // - BitFieldPoint.Type.BITFIELD32, true /* mandatory? */, AccessMode.READ_ONLY, S203_Evt.values())); + BITFIELD32, true /* mandatory? */, READ_ONLY, S203_Evt.values())); private final Point point; @@ -3325,174 +3383,186 @@ public BitPoint get() { public static enum S204 implements SunSpecPoint { A(new ScaledValuePoint("S204_A", "Amps", // "Total AC Current", // - ValuePoint.Type.INT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.AMPERE, "A_SF")), // + INT16, true /* mandatory? */, READ_ONLY, Unit.AMPERE, "A_SF")), // APH_A(new ScaledValuePoint("S204_APH_A", "Amps PhaseA", // "Phase A Current", // - ValuePoint.Type.INT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.AMPERE, "A_SF")), // + INT16, true /* mandatory? */, READ_ONLY, Unit.AMPERE, "A_SF")), // APH_B(new ScaledValuePoint("S204_APH_B", "Amps PhaseB", // "Phase B Current", // - ValuePoint.Type.INT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.AMPERE, "A_SF")), // + INT16, true /* mandatory? */, READ_ONLY, Unit.AMPERE, "A_SF")), // APH_C(new ScaledValuePoint("S204_APH_C", "Amps PhaseC", // "Phase C Current", // - ValuePoint.Type.INT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.AMPERE, "A_SF")), // + INT16, true /* mandatory? */, READ_ONLY, Unit.AMPERE, "A_SF")), // A_SF(new ScaleFactorPoint("S204_A_SF", "", // "Current scale factor")), // PH_V(new ScaledValuePoint("S204_PH_V", "Voltage LN", // "Line to Neutral AC Voltage (average of active phases)", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT, "V_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.VOLT, "V_SF")), // PH_VPH_A(new ScaledValuePoint("S204_PH_VPH_A", "Phase Voltage AN", // "Phase Voltage AN", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT, "V_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.VOLT, "V_SF")), // PH_VPH_B(new ScaledValuePoint("S204_PH_VPH_B", "Phase Voltage BN", // "Phase Voltage BN", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT, "V_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.VOLT, "V_SF")), // PH_VPH_C(new ScaledValuePoint("S204_PH_VPH_C", "Phase Voltage CN", // "Phase Voltage CN", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT, "V_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.VOLT, "V_SF")), // PPV(new ScaledValuePoint("S204_PPV", "Voltage LL", // "Line to Line AC Voltage (average of active phases)", // - ValuePoint.Type.INT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT, "V_SF")), // + INT16, true /* mandatory? */, READ_ONLY, Unit.VOLT, "V_SF")), // PH_VPH_A_B(new ScaledValuePoint("S204_PH_VPH_A_B", "Phase Voltage AB", // "Phase Voltage AB", // - ValuePoint.Type.INT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT, "V_SF")), // + INT16, true /* mandatory? */, READ_ONLY, Unit.VOLT, "V_SF")), // PH_VPH_B_C(new ScaledValuePoint("S204_PH_VPH_B_C", "Phase Voltage BC", // "Phase Voltage BC", // - ValuePoint.Type.INT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT, "V_SF")), // + INT16, true /* mandatory? */, READ_ONLY, Unit.VOLT, "V_SF")), // PH_VPH_C_A(new ScaledValuePoint("S204_PH_VPH_C_A", "Phase Voltage CA", // "Phase Voltage CA", // - ValuePoint.Type.INT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT, "V_SF")), // + INT16, true /* mandatory? */, READ_ONLY, Unit.VOLT, "V_SF")), // V_SF(new ScaleFactorPoint("S204_V_SF", "", // "Voltage scale factor")), // HZ(new ScaledValuePoint("S204_HZ", "Hz", // "Frequency", // - ValuePoint.Type.INT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.HERTZ, "Hz_SF")), // + INT16, true /* mandatory? */, READ_ONLY, Unit.HERTZ, "Hz_SF")), // HZ_S_F(new ScaleFactorPoint("S204_HZ_S_F", "", // "Frequency scale factor")), // W(new ScaledValuePoint("S204_W", "Watts", // "Total Real Power", // - ValuePoint.Type.INT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.WATT, "W_SF")), // + INT16, true /* mandatory? */, READ_ONLY, Unit.WATT, "W_SF")), // WPH_A(new ScaledValuePoint("S204_WPH_A", "Watts phase A", "", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.WATT, "W_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.WATT, "W_SF")), // WPH_B(new ScaledValuePoint("S204_WPH_B", "Watts phase B", "", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.WATT, "W_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.WATT, "W_SF")), // WPH_C(new ScaledValuePoint("S204_WPH_C", "Watts phase C", "", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.WATT, "W_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.WATT, "W_SF")), // W_SF(new ScaleFactorPoint("S204_W_SF", "", // "Real Power scale factor")), // VA(new ScaledValuePoint("S204_VA", "VA", // "AC Apparent Power", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE, "VA_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE, "VA_SF")), // V_APH_A(new ScaledValuePoint("S204_V_APH_A", "VA phase A", "", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE, "VA_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE, "VA_SF")), // V_APH_B(new ScaledValuePoint("S204_V_APH_B", "VA phase B", "", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE, "VA_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE, "VA_SF")), // V_APH_C(new ScaledValuePoint("S204_V_APH_C", "VA phase C", "", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE, "VA_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE, "VA_SF")), // VA_SF(new ScaleFactorPoint("S204_VA_SF", "", // "Apparent Power scale factor")), // VAR(new ScaledValuePoint("S204_VAR", "VAR", // "Reactive Power", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE, "VAR_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE, "VAR_SF")), // V_A_RPH_A(new ScaledValuePoint("S204_V_A_RPH_A", "VAR phase A", "", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE, "VAR_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE, "VAR_SF")), // V_A_RPH_B(new ScaledValuePoint("S204_V_A_RPH_B", "VAR phase B", "", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE, "VAR_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE, "VAR_SF")), // V_A_RPH_C(new ScaledValuePoint("S204_V_A_RPH_C", "VAR phase C", "", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE, "VAR_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE, "VAR_SF")), // VAR_SF(new ScaleFactorPoint("S204_VAR_SF", "", // "Reactive Power scale factor")), // PF(new ScaledValuePoint("S204_PF", "PF", // "Power Factor", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE, "PF_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.NONE, "PF_SF")), // P_FPH_A(new ScaledValuePoint("S204_P_FPH_A", "PF phase A", "", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE, "PF_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.NONE, "PF_SF")), // P_FPH_B(new ScaledValuePoint("S204_P_FPH_B", "PF phase B", "", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE, "PF_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.NONE, "PF_SF")), // P_FPH_C(new ScaledValuePoint("S204_P_FPH_C", "PF phase C", "", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE, "PF_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.NONE, "PF_SF")), // PF_SF(new ScaleFactorPoint("S204_PF_SF", "", // "Power Factor scale factor")), // TOT_WH_EXP(new ScaledValuePoint("S204_TOT_WH_EXP", "Total Watt-hours Exported", // "Total Real Energy Exported", // - ValuePoint.Type.ACC32, true /* mandatory? */, AccessMode.READ_ONLY, Unit.CUMULATED_WATT_HOURS, "TotWh_SF")), // + ACC32, true /* mandatory? */, READ_ONLY, Unit.CUMULATED_WATT_HOURS, "TotWh_SF")), // TOT_WH_EXP_PH_A(new ScaledValuePoint("S204_TOT_WH_EXP_PH_A", "Total Watt-hours Exported phase A", "", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.CUMULATED_WATT_HOURS, "TotWh_SF")), // + ACC32, false /* mandatory? */, READ_ONLY, Unit.CUMULATED_WATT_HOURS, "TotWh_SF")), // TOT_WH_EXP_PH_B(new ScaledValuePoint("S204_TOT_WH_EXP_PH_B", "Total Watt-hours Exported phase B", "", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.CUMULATED_WATT_HOURS, "TotWh_SF")), // + ACC32, false /* mandatory? */, READ_ONLY, Unit.CUMULATED_WATT_HOURS, "TotWh_SF")), // TOT_WH_EXP_PH_C(new ScaledValuePoint("S204_TOT_WH_EXP_PH_C", "Total Watt-hours Exported phase C", "", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.CUMULATED_WATT_HOURS, "TotWh_SF")), // + ACC32, false /* mandatory? */, READ_ONLY, Unit.CUMULATED_WATT_HOURS, "TotWh_SF")), // TOT_WH_IMP(new ScaledValuePoint("S204_TOT_WH_IMP", "Total Watt-hours Imported", // "Total Real Energy Imported", // - ValuePoint.Type.ACC32, true /* mandatory? */, AccessMode.READ_ONLY, Unit.CUMULATED_WATT_HOURS, "TotWh_SF")), // + ACC32, true /* mandatory? */, READ_ONLY, Unit.CUMULATED_WATT_HOURS, "TotWh_SF")), // TOT_WH_IMP_PH_A(new ScaledValuePoint("S204_TOT_WH_IMP_PH_A", "Total Watt-hours Imported phase A", "", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.CUMULATED_WATT_HOURS, "TotWh_SF")), // + ACC32, false /* mandatory? */, READ_ONLY, Unit.CUMULATED_WATT_HOURS, "TotWh_SF")), // TOT_WH_IMP_PH_B(new ScaledValuePoint("S204_TOT_WH_IMP_PH_B", "Total Watt-hours Imported phase B", "", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.CUMULATED_WATT_HOURS, "TotWh_SF")), // + ACC32, false /* mandatory? */, READ_ONLY, Unit.CUMULATED_WATT_HOURS, "TotWh_SF")), // TOT_WH_IMP_PH_C(new ScaledValuePoint("S204_TOT_WH_IMP_PH_C", "Total Watt-hours Imported phase C", "", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.CUMULATED_WATT_HOURS, "TotWh_SF")), // + ACC32, false /* mandatory? */, READ_ONLY, Unit.CUMULATED_WATT_HOURS, "TotWh_SF")), // TOT_WH_S_F(new ScaleFactorPoint("S204_TOT_WH_S_F", "", // "Real Energy scale factor")), // TOT_V_AH_EXP(new ScaledValuePoint("S204_TOT_V_AH_EXP", "Total VA-hours Exported", // "Total Apparent Energy Exported", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_HOURS, "TotVAh_SF")), // + ACC32, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_HOURS, "TotVAh_SF")), // TOT_V_AH_EXP_PH_A(new ScaledValuePoint("S204_TOT_V_AH_EXP_PH_A", "Total VA-hours Exported phase A", "", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_HOURS, "TotVAh_SF")), // + ACC32, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_HOURS, "TotVAh_SF")), // TOT_V_AH_EXP_PH_B(new ScaledValuePoint("S204_TOT_V_AH_EXP_PH_B", "Total VA-hours Exported phase B", "", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_HOURS, "TotVAh_SF")), // + ACC32, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_HOURS, "TotVAh_SF")), // TOT_V_AH_EXP_PH_C(new ScaledValuePoint("S204_TOT_V_AH_EXP_PH_C", "Total VA-hours Exported phase C", "", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_HOURS, "TotVAh_SF")), // + ACC32, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_HOURS, "TotVAh_SF")), // TOT_V_AH_IMP(new ScaledValuePoint("S204_TOT_V_AH_IMP", "Total VA-hours Imported", // "Total Apparent Energy Imported", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_HOURS, "TotVAh_SF")), // + ACC32, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_HOURS, "TotVAh_SF")), // TOT_V_AH_IMP_PH_A(new ScaledValuePoint("S204_TOT_V_AH_IMP_PH_A", "Total VA-hours Imported phase A", "", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_HOURS, "TotVAh_SF")), // + ACC32, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_HOURS, "TotVAh_SF")), // TOT_V_AH_IMP_PH_B(new ScaledValuePoint("S204_TOT_V_AH_IMP_PH_B", "Total VA-hours Imported phase B", "", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_HOURS, "TotVAh_SF")), // + ACC32, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_HOURS, "TotVAh_SF")), // TOT_V_AH_IMP_PH_C(new ScaledValuePoint("S204_TOT_V_AH_IMP_PH_C", "Total VA-hours Imported phase C", "", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_HOURS, "TotVAh_SF")), // + ACC32, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_HOURS, "TotVAh_SF")), // TOT_V_AH_S_F(new ScaleFactorPoint("S204_TOT_V_AH_S_F", "", // "Apparent Energy scale factor")), // TOT_V_ARH_IMP_Q1(new ScaledValuePoint("S204_TOT_V_ARH_IMP_Q1", "Total VAR-hours Imported Q1", // "Total Reactive Energy Imported Quadrant 1", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // - TOT_V_ARH_IMP_Q1_PH_A(new ScaledValuePoint("S204_TOT_V_ARH_IMP_Q1_PH_A", "Total VAr-hours Imported Q1 phase A", "", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // - TOT_V_ARH_IMP_Q1_PH_B(new ScaledValuePoint("S204_TOT_V_ARH_IMP_Q1_PH_B", "Total VAr-hours Imported Q1 phase B", "", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // - TOT_V_ARH_IMP_Q1_PH_C(new ScaledValuePoint("S204_TOT_V_ARH_IMP_Q1_PH_C", "Total VAr-hours Imported Q1 phase C", "", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // + ACC32, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // + TOT_V_ARH_IMP_Q1_PH_A( + new ScaledValuePoint("S204_TOT_V_ARH_IMP_Q1_PH_A", "Total VAr-hours Imported Q1 phase A", "", // + ACC32, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // + TOT_V_ARH_IMP_Q1_PH_B( + new ScaledValuePoint("S204_TOT_V_ARH_IMP_Q1_PH_B", "Total VAr-hours Imported Q1 phase B", "", // + ACC32, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // + TOT_V_ARH_IMP_Q1_PH_C( + new ScaledValuePoint("S204_TOT_V_ARH_IMP_Q1_PH_C", "Total VAr-hours Imported Q1 phase C", "", // + ACC32, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // TOT_V_ARH_IMP_Q2(new ScaledValuePoint("S204_TOT_V_ARH_IMP_Q2", "Total VAr-hours Imported Q2", // "Total Reactive Power Imported Quadrant 2", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // - TOT_V_ARH_IMP_Q2_PH_A(new ScaledValuePoint("S204_TOT_V_ARH_IMP_Q2_PH_A", "Total VAr-hours Imported Q2 phase A", "", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // - TOT_V_ARH_IMP_Q2_PH_B(new ScaledValuePoint("S204_TOT_V_ARH_IMP_Q2_PH_B", "Total VAr-hours Imported Q2 phase B", "", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // - TOT_V_ARH_IMP_Q2_PH_C(new ScaledValuePoint("S204_TOT_V_ARH_IMP_Q2_PH_C", "Total VAr-hours Imported Q2 phase C", "", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // + ACC32, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // + TOT_V_ARH_IMP_Q2_PH_A( + new ScaledValuePoint("S204_TOT_V_ARH_IMP_Q2_PH_A", "Total VAr-hours Imported Q2 phase A", "", // + ACC32, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // + TOT_V_ARH_IMP_Q2_PH_B( + new ScaledValuePoint("S204_TOT_V_ARH_IMP_Q2_PH_B", "Total VAr-hours Imported Q2 phase B", "", // + ACC32, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // + TOT_V_ARH_IMP_Q2_PH_C( + new ScaledValuePoint("S204_TOT_V_ARH_IMP_Q2_PH_C", "Total VAr-hours Imported Q2 phase C", "", // + ACC32, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // TOT_V_ARH_EXP_Q3(new ScaledValuePoint("S204_TOT_V_ARH_EXP_Q3", "Total VAr-hours Exported Q3", // "Total Reactive Power Exported Quadrant 3", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // - TOT_V_ARH_EXP_Q3_PH_A(new ScaledValuePoint("S204_TOT_V_ARH_EXP_Q3_PH_A", "Total VAr-hours Exported Q3 phase A", "", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // - TOT_V_ARH_EXP_Q3_PH_B(new ScaledValuePoint("S204_TOT_V_ARH_EXP_Q3_PH_B", "Total VAr-hours Exported Q3 phase B", "", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // - TOT_V_ARH_EXP_Q3_PH_C(new ScaledValuePoint("S204_TOT_V_ARH_EXP_Q3_PH_C", "Total VAr-hours Exported Q3 phase C", "", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // + ACC32, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // + TOT_V_ARH_EXP_Q3_PH_A( + new ScaledValuePoint("S204_TOT_V_ARH_EXP_Q3_PH_A", "Total VAr-hours Exported Q3 phase A", "", // + ACC32, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // + TOT_V_ARH_EXP_Q3_PH_B( + new ScaledValuePoint("S204_TOT_V_ARH_EXP_Q3_PH_B", "Total VAr-hours Exported Q3 phase B", "", // + ACC32, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // + TOT_V_ARH_EXP_Q3_PH_C( + new ScaledValuePoint("S204_TOT_V_ARH_EXP_Q3_PH_C", "Total VAr-hours Exported Q3 phase C", "", // + ACC32, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // TOT_V_ARH_EXP_Q4(new ScaledValuePoint("S204_TOT_V_ARH_EXP_Q4", "Total VAr-hours Exported Q4", // "Total Reactive Power Exported Quadrant 4", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // - TOT_V_ARH_EXP_Q4_PH_A(new ScaledValuePoint("S204_TOT_V_ARH_EXP_Q4_PH_A", "Total VAr-hours Exported Q4 Imported phase A", "", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // - TOT_V_ARH_EXP_Q4_PH_B(new ScaledValuePoint("S204_TOT_V_ARH_EXP_Q4_PH_B", "Total VAr-hours Exported Q4 Imported phase B", "", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // - TOT_V_ARH_EXP_Q4_PH_C(new ScaledValuePoint("S204_TOT_V_ARH_EXP_Q4_PH_C", "Total VAr-hours Exported Q4 Imported phase C", "", // - ValuePoint.Type.ACC32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // + ACC32, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // + TOT_V_ARH_EXP_Q4_PH_A( + new ScaledValuePoint("S204_TOT_V_ARH_EXP_Q4_PH_A", "Total VAr-hours Exported Q4 Imported phase A", "", // + ACC32, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // + TOT_V_ARH_EXP_Q4_PH_B( + new ScaledValuePoint("S204_TOT_V_ARH_EXP_Q4_PH_B", "Total VAr-hours Exported Q4 Imported phase B", "", // + ACC32, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // + TOT_V_ARH_EXP_Q4_PH_C( + new ScaledValuePoint("S204_TOT_V_ARH_EXP_Q4_PH_C", "Total VAr-hours Exported Q4 Imported phase C", "", // + ACC32, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVArh_SF")), // TOT_V_ARH_S_F(new ScaleFactorPoint("S204_TOT_V_ARH_S_F", "", // "Reactive Energy scale factor")), // EVT(new BitFieldPoint("S204_EVT", "Events", // "Meter Event Flags", // - BitFieldPoint.Type.BITFIELD32, true /* mandatory? */, AccessMode.READ_ONLY, S204_Evt.values())); + BITFIELD32, true /* mandatory? */, READ_ONLY, S204_Evt.values())); private final Point point; @@ -3552,22 +3622,22 @@ public BitPoint get() { public static enum S305 implements SunSpecPoint { TM(new ValuePoint("S305_TM", "Tm", // "UTC 24 hour time stamp to millisecond hhmmss.sssZ format", // - ValuePoint.Type.STRING6, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // + STRING6, false /* mandatory? */, READ_ONLY, Unit.NONE)), // DATE(new ValuePoint("S305_DATE", "Date", // "UTC Date string YYYYMMDD format", // - ValuePoint.Type.STRING4, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // + STRING4, false /* mandatory? */, READ_ONLY, Unit.NONE)), // LOC(new ValuePoint("S305_LOC", "Location", // "Location string (40 chars max)", // - ValuePoint.Type.STRING20, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // + STRING20, false /* mandatory? */, READ_ONLY, Unit.NONE)), // LAT(new ScaledValuePoint("S305_LAT", "Lat", // "Latitude with seven degrees of precision", // - ValuePoint.Type.INT32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE, "-7")), // + INT32, false /* mandatory? */, READ_ONLY, Unit.NONE, "-7")), // LONG(new ScaledValuePoint("S305_LONG", "Long", // "Longitude with seven degrees of precision", // - ValuePoint.Type.INT32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE, "-7")), // + INT32, false /* mandatory? */, READ_ONLY, Unit.NONE, "-7")), // ALT(new ValuePoint("S305_ALT", "Altitude", // "Altitude measurement in meters", // - ValuePoint.Type.INT32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)); + INT32, false /* mandatory? */, READ_ONLY, Unit.NONE)); private final Point point; @@ -3584,16 +3654,16 @@ public Point get() { public static enum S306 implements SunSpecPoint { GHI(new ValuePoint("S306_GHI", "GHI", // "Global Horizontal Irradiance", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // + UINT16, false /* mandatory? */, READ_ONLY, Unit.NONE)), // A(new ValuePoint("S306_A", "Amps", // "Current measurement at reference point", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // + UINT16, false /* mandatory? */, READ_ONLY, Unit.NONE)), // V(new ValuePoint("S306_V", "Voltage", // "Voltage measurement at reference point", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // + UINT16, false /* mandatory? */, READ_ONLY, Unit.NONE)), // TMP(new ValuePoint("S306_TMP", "Temperature", // "Temperature measurement at reference point", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)); + UINT16, false /* mandatory? */, READ_ONLY, Unit.NONE)); private final Point point; @@ -3609,28 +3679,28 @@ public Point get() { public static enum S307 implements SunSpecPoint { TMP_AMB(new ScaledValuePoint("S307_TMP_AMB", "Ambient Temperature", "", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.DEGREE_CELSIUS, "-1")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.DEGREE_CELSIUS, "-1")), // RH(new ValuePoint("S307_RH", "Relative Humidity", "", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // + INT16, false /* mandatory? */, READ_ONLY, Unit.NONE)), // PRES(new ValuePoint("S307_PRES", "Barometric Pressure", "", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // + INT16, false /* mandatory? */, READ_ONLY, Unit.NONE)), // WND_SPD(new ValuePoint("S307_WND_SPD", "Wind Speed", "", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // + INT16, false /* mandatory? */, READ_ONLY, Unit.NONE)), // WND_DIR(new ValuePoint("S307_WND_DIR", "Wind Direction", "", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // + INT16, false /* mandatory? */, READ_ONLY, Unit.NONE)), // RAIN(new ValuePoint("S307_RAIN", "Rainfall", "", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // + INT16, false /* mandatory? */, READ_ONLY, Unit.NONE)), // SNW(new ValuePoint("S307_SNW", "Snow Depth", "", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // + INT16, false /* mandatory? */, READ_ONLY, Unit.NONE)), // PPT(new ValuePoint("S307_PPT", "Precipitation Type", // "Precipitation Type (WMO 4680 SYNOP code reference)", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // + INT16, false /* mandatory? */, READ_ONLY, Unit.NONE)), // ELEC_FLD(new ValuePoint("S307_ELEC_FLD", "Electric Field", "", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // + INT16, false /* mandatory? */, READ_ONLY, Unit.NONE)), // SUR_WET(new ValuePoint("S307_SUR_WET", "Surface Wetness", "", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // + INT16, false /* mandatory? */, READ_ONLY, Unit.NONE)), // SOIL_WET(new ValuePoint("S307_SOIL_WET", "Soil Wetness", "", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)); + INT16, false /* mandatory? */, READ_ONLY, Unit.NONE)); private final Point point; @@ -3647,14 +3717,14 @@ public Point get() { public static enum S308 implements SunSpecPoint { GHI(new ValuePoint("S308_GHI", "GHI", // "Global Horizontal Irradiance", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // + UINT16, false /* mandatory? */, READ_ONLY, Unit.NONE)), // TMP_B_O_M(new ScaledValuePoint("S308_TMP_B_O_M", "Temp", // "Back of module temperature measurement", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.DEGREE_CELSIUS, "-1")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.DEGREE_CELSIUS, "-1")), // TMP_AMB(new ScaledValuePoint("S308_TMP_AMB", "Ambient Temperature", "", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.DEGREE_CELSIUS, "-1")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.DEGREE_CELSIUS, "-1")), // WND_SPD(new ValuePoint("S308_WND_SPD", "Wind Speed", "", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)); + UINT16, false /* mandatory? */, READ_ONLY, Unit.NONE)); private final Point point; @@ -3671,181 +3741,181 @@ public Point get() { public static enum S701 implements SunSpecPoint { A_C_TYPE(new EnumPoint("S701_A_C_TYPE", "AC Wiring Type", // "AC wiring type.", // - EnumPoint.Type.ENUM16, true /* mandatory? */, AccessMode.READ_ONLY, S701_ACType.values())), // + ENUM16, true /* mandatory? */, READ_ONLY, S701_ACType.values())), // ST(new EnumPoint("S701_ST", "Operating State", // "Operating state of the DER.", // - EnumPoint.Type.ENUM16, false /* mandatory? */, AccessMode.READ_ONLY, S701_St.values())), // + ENUM16, false /* mandatory? */, READ_ONLY, S701_St.values())), // INV_ST(new EnumPoint("S701_INV_ST", "Inverter State", // "Enumerated value. Inverter state.", // - EnumPoint.Type.ENUM16, false /* mandatory? */, AccessMode.READ_ONLY, S701_InvSt.values())), // + ENUM16, false /* mandatory? */, READ_ONLY, S701_InvSt.values())), // CONN_ST(new EnumPoint("S701_CONN_ST", "Grid Connection State", // "Grid connection state of the DER.", // - EnumPoint.Type.ENUM16, false /* mandatory? */, AccessMode.READ_ONLY, S701_ConnSt.values())), // + ENUM16, false /* mandatory? */, READ_ONLY, S701_ConnSt.values())), // ALRM(new BitFieldPoint("S701_ALRM", "Alarm Bitfield", // "Active alarms for the DER.", // - BitFieldPoint.Type.BITFIELD32, false /* mandatory? */, AccessMode.READ_ONLY, S701_Alrm.values())), // + BITFIELD32, false /* mandatory? */, READ_ONLY, S701_Alrm.values())), // D_E_R_MODE(new BitFieldPoint("S701_D_E_R_MODE", "DER Operational Characteristics", // "Current operational characteristics of the DER.", // - BitFieldPoint.Type.BITFIELD32, false /* mandatory? */, AccessMode.READ_ONLY, S701_DERMode.values())), // + BITFIELD32, false /* mandatory? */, READ_ONLY, S701_DERMode.values())), // W(new ScaledValuePoint("S701_W", "Active Power", // "Total active power. Active power is positive for DER generation and negative for absorption.", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.WATT, "W_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.WATT, "W_SF")), // VA(new ScaledValuePoint("S701_VA", "Apparent Power", // "Total apparent power.", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE, "VA_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE, "VA_SF")), // VAR(new ScaledValuePoint("S701_VAR", "Reactive Power", // "Total reactive power.", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE, "Var_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE, "Var_SF")), // PF(new ScaledValuePoint("S701_PF", "Power Factor", // "Power factor. The sign of power factor should be the sign of active power.", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE, "PF_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.NONE, "PF_SF")), // A(new ScaledValuePoint("S701_A", "Total AC Current", // "Total AC current.", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.AMPERE, "A_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.AMPERE, "A_SF")), // LLV(new ScaledValuePoint("S701_LLV", "Voltage LL", // "Line to line AC voltage as an average of active phases.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT, "V_SF")), // + UINT16, false /* mandatory? */, READ_ONLY, Unit.VOLT, "V_SF")), // LNV(new ScaledValuePoint("S701_LNV", "Voltage LN", // "Line to neutral AC voltage as an average of active phases.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT, "V_SF")), // + UINT16, false /* mandatory? */, READ_ONLY, Unit.VOLT, "V_SF")), // HZ(new ScaledValuePoint("S701_HZ", "Frequency", // "AC frequency.", // - ValuePoint.Type.UINT32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.HERTZ, "Hz_SF")), // + UINT32, false /* mandatory? */, READ_ONLY, Unit.HERTZ, "Hz_SF")), // TOT_WH_INJ(new ScaledValuePoint("S701_TOT_WH_INJ", "Total Energy Injected", // "Total active energy injected (Quadrants 1 & 4).", // - ValuePoint.Type.UINT64, false /* mandatory? */, AccessMode.READ_ONLY, Unit.CUMULATED_WATT_HOURS, "TotWh_SF")), // + UINT64, false /* mandatory? */, READ_ONLY, Unit.CUMULATED_WATT_HOURS, "TotWh_SF")), // TOT_WH_ABS(new ScaledValuePoint("S701_TOT_WH_ABS", "Total Energy Absorbed", // "Total active energy absorbed (Quadrants 2 & 3).", // - ValuePoint.Type.UINT64, false /* mandatory? */, AccessMode.READ_ONLY, Unit.CUMULATED_WATT_HOURS, "TotWh_SF")), // + UINT64, false /* mandatory? */, READ_ONLY, Unit.CUMULATED_WATT_HOURS, "TotWh_SF")), // TOT_VARH_INJ(new ScaledValuePoint("S701_TOT_VARH_INJ", "Total Reactive Energy Inj", // "Total reactive energy injected (Quadrants 1 & 2).", // - ValuePoint.Type.UINT64, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVarh_SF")), // + UINT64, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVarh_SF")), // TOT_VARH_ABS(new ScaledValuePoint("S701_TOT_VARH_ABS", "Total Reactive Energy Abs", // "Total reactive energy absorbed (Quadrants 3 & 4).", // - ValuePoint.Type.UINT64, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVarh_SF")), // + UINT64, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVarh_SF")), // TMP_AMB(new ScaledValuePoint("S701_TMP_AMB", "Ambient Temperature", // "Ambient temperature.", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.DEGREE_CELSIUS, "Tmp_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.DEGREE_CELSIUS, "Tmp_SF")), // TMP_CAB(new ScaledValuePoint("S701_TMP_CAB", "Cabinet Temperature", // "Cabinet temperature.", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.DEGREE_CELSIUS, "Tmp_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.DEGREE_CELSIUS, "Tmp_SF")), // TMP_SNK(new ScaledValuePoint("S701_TMP_SNK", "Heat Sink Temperature", // "Heat sink temperature.", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.DEGREE_CELSIUS, "Tmp_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.DEGREE_CELSIUS, "Tmp_SF")), // TMP_TRNS(new ScaledValuePoint("S701_TMP_TRNS", "Transformer Temperature", // "Transformer temperature.", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.DEGREE_CELSIUS, "Tmp_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.DEGREE_CELSIUS, "Tmp_SF")), // TMP_SW(new ScaledValuePoint("S701_TMP_SW", "IGBT/MOSFET Temperature", // "IGBT/MOSFET temperature.", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.DEGREE_CELSIUS, "Tmp_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.DEGREE_CELSIUS, "Tmp_SF")), // TMP_OT(new ScaledValuePoint("S701_TMP_OT", "Other Temperature", // "Other temperature.", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.DEGREE_CELSIUS, "Tmp_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.DEGREE_CELSIUS, "Tmp_SF")), // WL1(new ScaledValuePoint("S701_WL1", "Watts L1", // "Active power L1.", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.WATT, "W_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.WATT, "W_SF")), // VAL1(new ScaledValuePoint("S701_VAL1", "VA L1", // "Apparent power L1.", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE, "VA_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE, "VA_SF")), // VAR_L1(new ScaledValuePoint("S701_VAR_L1", "Var L1", // "Reactive power L1.", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE, "Var_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE, "Var_SF")), // PFL1(new ScaledValuePoint("S701_PFL1", "PF L1", // "Power factor phase L1.", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE, "PF_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.NONE, "PF_SF")), // AL1(new ScaledValuePoint("S701_AL1", "Amps L1", // "Current phase L1.", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.AMPERE, "A_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.AMPERE, "A_SF")), // VL1L2(new ScaledValuePoint("S701_VL1L2", "Phase Voltage L1-L2", // "Phase voltage L1-L2.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT, "V_SF")), // + UINT16, false /* mandatory? */, READ_ONLY, Unit.VOLT, "V_SF")), // VL1(new ScaledValuePoint("S701_VL1", "Phase Voltage L1-N", // "Phase voltage L1-N.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT, "V_SF")), // + UINT16, false /* mandatory? */, READ_ONLY, Unit.VOLT, "V_SF")), // TOT_WH_INJ_L1(new ScaledValuePoint("S701_TOT_WH_INJ_L1", "Total Watt-Hours Inj L1", // "Total active energy injected L1.", // - ValuePoint.Type.UINT64, false /* mandatory? */, AccessMode.READ_ONLY, Unit.CUMULATED_WATT_HOURS, "TotWh_SF")), // + UINT64, false /* mandatory? */, READ_ONLY, Unit.CUMULATED_WATT_HOURS, "TotWh_SF")), // TOT_WH_ABS_L1(new ScaledValuePoint("S701_TOT_WH_ABS_L1", "Total Watt-Hours Abs L1", // "Total active energy absorbed L1.", // - ValuePoint.Type.UINT64, false /* mandatory? */, AccessMode.READ_ONLY, Unit.CUMULATED_WATT_HOURS, "TotWh_SF")), // + UINT64, false /* mandatory? */, READ_ONLY, Unit.CUMULATED_WATT_HOURS, "TotWh_SF")), // TOT_VARH_INJ_L1(new ScaledValuePoint("S701_TOT_VARH_INJ_L1", "Total Var-Hours Inj L1", // "Total reactive energy injected L1.", // - ValuePoint.Type.UINT64, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVarh_SF")), // + UINT64, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVarh_SF")), // TOT_VARH_ABS_L1(new ScaledValuePoint("S701_TOT_VARH_ABS_L1", "Total Var-Hours Abs L1", // "Total reactive energy absorbed L1.", // - ValuePoint.Type.UINT64, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVarh_SF")), // + UINT64, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVarh_SF")), // WL2(new ScaledValuePoint("S701_WL2", "Watts L2", // "Active power L2.", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.WATT, "W_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.WATT, "W_SF")), // VAL2(new ScaledValuePoint("S701_VAL2", "VA L2", // "Apparent power L2.", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE, "VA_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE, "VA_SF")), // VAR_L2(new ScaledValuePoint("S701_VAR_L2", "Var L2", // "Reactive power L2.", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE, "Var_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE, "Var_SF")), // PFL2(new ScaledValuePoint("S701_PFL2", "PF L2", // "Power factor L2.", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE, "PF_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.NONE, "PF_SF")), // AL2(new ScaledValuePoint("S701_AL2", "Amps L2", // "Current L2.", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.AMPERE, "A_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.AMPERE, "A_SF")), // VL2L3(new ScaledValuePoint("S701_VL2L3", "Phase Voltage L2-L3", // "Phase voltage L2-L3.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT, "V_SF")), // + UINT16, false /* mandatory? */, READ_ONLY, Unit.VOLT, "V_SF")), // VL2(new ScaledValuePoint("S701_VL2", "Phase Voltage L2-N", // "Phase voltage L2-N.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT, "V_SF")), // + UINT16, false /* mandatory? */, READ_ONLY, Unit.VOLT, "V_SF")), // TOT_WH_INJ_L2(new ScaledValuePoint("S701_TOT_WH_INJ_L2", "Total Watt-Hours Inj L2", // "Total active energy injected L2.", // - ValuePoint.Type.UINT64, false /* mandatory? */, AccessMode.READ_ONLY, Unit.CUMULATED_WATT_HOURS, "TotWh_SF")), // + UINT64, false /* mandatory? */, READ_ONLY, Unit.CUMULATED_WATT_HOURS, "TotWh_SF")), // TOT_WH_ABS_L2(new ScaledValuePoint("S701_TOT_WH_ABS_L2", "Total Watt-Hours Abs L2", // "Total active energy absorbed L2.", // - ValuePoint.Type.UINT64, false /* mandatory? */, AccessMode.READ_ONLY, Unit.CUMULATED_WATT_HOURS, "TotWh_SF")), // + UINT64, false /* mandatory? */, READ_ONLY, Unit.CUMULATED_WATT_HOURS, "TotWh_SF")), // TOT_VARH_INJ_L2(new ScaledValuePoint("S701_TOT_VARH_INJ_L2", "Total Var-Hours Inj L2", // "Total reactive energy injected L2.", // - ValuePoint.Type.UINT64, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVarh_SF")), // + UINT64, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVarh_SF")), // TOT_VARH_ABS_L2(new ScaledValuePoint("S701_TOT_VARH_ABS_L2", "Total Var-Hours Abs L2", // "Total reactive energy absorbed L2.", // - ValuePoint.Type.UINT64, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVarh_SF")), // + UINT64, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVarh_SF")), // WL3(new ScaledValuePoint("S701_WL3", "Watts L3", // "Active power L3.", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.WATT, "W_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.WATT, "W_SF")), // VAL3(new ScaledValuePoint("S701_VAL3", "VA L3", // "Apparent power L3.", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE, "VA_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE, "VA_SF")), // VAR_L3(new ScaledValuePoint("S701_VAR_L3", "Var L3", // "Reactive power L3.", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE, "Var_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE, "Var_SF")), // PFL3(new ScaledValuePoint("S701_PFL3", "PF L3", // "Power factor L3.", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE, "PF_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.NONE, "PF_SF")), // AL3(new ScaledValuePoint("S701_AL3", "Amps L3", // "Current L3.", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.AMPERE, "A_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.AMPERE, "A_SF")), // VL3L1(new ScaledValuePoint("S701_VL3L1", "Phase Voltage L3-L1", // "Phase voltage L3-L1.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT, "V_SF")), // + UINT16, false /* mandatory? */, READ_ONLY, Unit.VOLT, "V_SF")), // VL3(new ScaledValuePoint("S701_VL3", "Phase Voltage L3-N", // "Phase voltage L3-N.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT, "V_SF")), // + UINT16, false /* mandatory? */, READ_ONLY, Unit.VOLT, "V_SF")), // TOT_WH_INJ_L3(new ScaledValuePoint("S701_TOT_WH_INJ_L3", "Total Watt-Hours Inj L3", // "Total active energy injected L3.", // - ValuePoint.Type.UINT64, false /* mandatory? */, AccessMode.READ_ONLY, Unit.CUMULATED_WATT_HOURS, "TotWh_SF")), // + UINT64, false /* mandatory? */, READ_ONLY, Unit.CUMULATED_WATT_HOURS, "TotWh_SF")), // TOT_WH_ABS_L3(new ScaledValuePoint("S701_TOT_WH_ABS_L3", "Total Watt-Hours Abs L3", // "Total active energy absorbed L3.", // - ValuePoint.Type.UINT64, false /* mandatory? */, AccessMode.READ_ONLY, Unit.CUMULATED_WATT_HOURS, "TotWh_SF")), // + UINT64, false /* mandatory? */, READ_ONLY, Unit.CUMULATED_WATT_HOURS, "TotWh_SF")), // TOT_VARH_INJ_L3(new ScaledValuePoint("S701_TOT_VARH_INJ_L3", "Total Var-Hours Inj L3", // "Total reactive energy injected L3.", // - ValuePoint.Type.UINT64, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVarh_SF")), // + UINT64, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVarh_SF")), // TOT_VARH_ABS_L3(new ScaledValuePoint("S701_TOT_VARH_ABS_L3", "Total Var-Hours Abs L3", // "Total reactive energy absorbed L3.", // - ValuePoint.Type.UINT64, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVarh_SF")), // + UINT64, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE_HOURS, "TotVarh_SF")), // THROT_PCT(new ValuePoint("S701_THROT_PCT", "Throttling In Pct", // "Throttling in pct of maximum active power.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // + UINT16, false /* mandatory? */, READ_ONLY, Unit.NONE)), // THROT_SRC(new BitFieldPoint("S701_THROT_SRC", "Throttle Source Information", // "Active throttling source.", // - BitFieldPoint.Type.BITFIELD32, false /* mandatory? */, AccessMode.READ_ONLY, S701_ThrotSrc.values())), // + BITFIELD32, false /* mandatory? */, READ_ONLY, S701_ThrotSrc.values())), // A_SF(new ScaleFactorPoint("S701_A_SF", "Current Scale Factor", // "Current scale factor.")), // V_SF(new ScaleFactorPoint("S701_V_SF", "Voltage Scale Factor", // @@ -3868,7 +3938,7 @@ public static enum S701 implements SunSpecPoint { "Temperature scale factor.")), // MN_ALRM_INFO(new ValuePoint("S701_MN_ALRM_INFO", "Manufacturer Alarm Info", // "Manufacturer alarm information. Valid if MANUFACTURER_ALRM indication is active.", // - ValuePoint.Type.STRING32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)); + STRING32, false /* mandatory? */, READ_ONLY, Unit.NONE)); private final Point point; @@ -4085,130 +4155,130 @@ public BitPoint get() { public static enum S702 implements SunSpecPoint { W_MAX_RTG(new ScaledValuePoint("S702_W_MAX_RTG", "Active Power Max Rating", // "Maximum active power rating at unity power factor in watts.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.WATT, "W_SF")), // + UINT16, false /* mandatory? */, READ_ONLY, Unit.WATT, "W_SF")), // W_OVR_EXT_RTG(new ScaledValuePoint("S702_W_OVR_EXT_RTG", "Active Power (Over-Excited) Rating", // "Active power rating at specified over-excited power factor in watts.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.WATT, "W_SF")), // + UINT16, false /* mandatory? */, READ_ONLY, Unit.WATT, "W_SF")), // W_OVR_EXT_RTG_P_F(new ScaledValuePoint("S702_W_OVR_EXT_RTG_P_F", "Specified Over-Excited PF", // "Specified over-excited power factor.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE, "PF_SF")), // + UINT16, false /* mandatory? */, READ_ONLY, Unit.NONE, "PF_SF")), // W_UND_EXT_RTG(new ScaledValuePoint("S702_W_UND_EXT_RTG", "Active Power (Under-Excited) Rating", // "Active power rating at specified under-excited power factor in watts.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.WATT, "W_SF")), // + UINT16, false /* mandatory? */, READ_ONLY, Unit.WATT, "W_SF")), // W_UND_EXT_RTG_P_F(new ScaledValuePoint("S702_W_UND_EXT_RTG_P_F", "Specified Under-Excited PF", // "Specified under-excited power factor.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE, "PF_SF")), // + UINT16, false /* mandatory? */, READ_ONLY, Unit.NONE, "PF_SF")), // V_A_MAX_RTG(new ScaledValuePoint("S702_V_A_MAX_RTG", "Apparent Power Max Rating", // "Maximum apparent power rating in voltamperes.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE, "VA_SF")), // + UINT16, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE, "VA_SF")), // VAR_MAX_INJ_RTG(new ScaledValuePoint("S702_VAR_MAX_INJ_RTG", "Reactive Power Injected Rating", // "Maximum injected reactive power rating in vars.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE, "Var_SF")), // + UINT16, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE, "Var_SF")), // VAR_MAX_ABS_RTG(new ScaledValuePoint("S702_VAR_MAX_ABS_RTG", "Reactive Power Absorbed Rating", // "Maximum absorbed reactive power rating in vars.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE_REACTIVE, "Var_SF")), // + UINT16, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE_REACTIVE, "Var_SF")), // W_CHA_RTE_MAX_RTG(new ScaledValuePoint("S702_W_CHA_RTE_MAX_RTG", "Charge Rate Max Rating", // "Maximum active power charge rate in watts.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.WATT, "W_SF")), // + UINT16, false /* mandatory? */, READ_ONLY, Unit.WATT, "W_SF")), // W_DIS_CHA_RTE_MAX_RTG(new ScaledValuePoint("S702_W_DIS_CHA_RTE_MAX_RTG", "Discharge Rate Max Rating", // "Maximum active power discharge rate in watts.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.WATT, "W_SF")), // + UINT16, false /* mandatory? */, READ_ONLY, Unit.WATT, "W_SF")), // V_A_CHA_RTE_MAX_RTG(new ScaledValuePoint("S702_V_A_CHA_RTE_MAX_RTG", "Charge Rate Max VA Rating", // "Maximum apparent power charge rate in voltamperes.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE, "VA_SF")), // + UINT16, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE, "VA_SF")), // V_A_DIS_CHA_RTE_MAX_RTG(new ScaledValuePoint("S702_V_A_DIS_CHA_RTE_MAX_RTG", "Discharge Rate Max VA Rating", // "Maximum apparent power discharge rate in voltamperes.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT_AMPERE, "VA_SF")), // + UINT16, false /* mandatory? */, READ_ONLY, Unit.VOLT_AMPERE, "VA_SF")), // V_NOM_RTG(new ScaledValuePoint("S702_V_NOM_RTG", "AC Voltage Nominal Rating", // "AC voltage nominal rating.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT, "V_SF")), // + UINT16, false /* mandatory? */, READ_ONLY, Unit.VOLT, "V_SF")), // V_MAX_RTG(new ScaledValuePoint("S702_V_MAX_RTG", "AC Voltage Max Rating", // "AC voltage maximum rating.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT, "V_SF")), // + UINT16, false /* mandatory? */, READ_ONLY, Unit.VOLT, "V_SF")), // V_MIN_RTG(new ScaledValuePoint("S702_V_MIN_RTG", "AC Voltage Min Rating", // "AC voltage minimum rating.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT, "V_SF")), // + UINT16, false /* mandatory? */, READ_ONLY, Unit.VOLT, "V_SF")), // A_MAX_RTG(new ScaledValuePoint("S702_A_MAX_RTG", "AC Current Max Rating", // "AC current maximum rating in amps.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.AMPERE, "A_SF")), // + UINT16, false /* mandatory? */, READ_ONLY, Unit.AMPERE, "A_SF")), // P_F_OVR_EXT_RTG(new ScaledValuePoint("S702_P_F_OVR_EXT_RTG", "PF Over-Excited Rating", // "Power factor over-excited rating.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE, "PF_SF")), // + UINT16, false /* mandatory? */, READ_ONLY, Unit.NONE, "PF_SF")), // P_F_UND_EXT_RTG(new ScaledValuePoint("S702_P_F_UND_EXT_RTG", "PF Under-Excited Rating", // "Power factor under-excited rating.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE, "PF_SF")), // + UINT16, false /* mandatory? */, READ_ONLY, Unit.NONE, "PF_SF")), // REACT_SUSCEPT_RTG(new ScaledValuePoint("S702_REACT_SUSCEPT_RTG", "Reactive Susceptance", // "Reactive susceptance that remains connected to the Area EPS in the cease to energize and trip state.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE, "S_SF")), // + UINT16, false /* mandatory? */, READ_ONLY, Unit.NONE, "S_SF")), // NOR_OP_CAT_RTG(new EnumPoint("S702_NOR_OP_CAT_RTG", "Normal Operating Category", // "Normal operating performance category as specified in IEEE 1547-2018.", // - EnumPoint.Type.ENUM16, false /* mandatory? */, AccessMode.READ_ONLY, S702_NorOpCatRtg.values())), // + ENUM16, false /* mandatory? */, READ_ONLY, S702_NorOpCatRtg.values())), // ABN_OP_CAT_RTG(new EnumPoint("S702_ABN_OP_CAT_RTG", "Abnormal Operating Category", // "Abnormal operating performance category as specified in IEEE 1547-2018.", // - EnumPoint.Type.ENUM16, false /* mandatory? */, AccessMode.READ_ONLY, S702_AbnOpCatRtg.values())), // + ENUM16, false /* mandatory? */, READ_ONLY, S702_AbnOpCatRtg.values())), // CTRL_MODES(new BitFieldPoint("S702_CTRL_MODES", "Supported Control Modes", // "Supported control mode functions.", // - BitFieldPoint.Type.BITFIELD32, false /* mandatory? */, AccessMode.READ_ONLY, S702_CtrlModes.values())), // + BITFIELD32, false /* mandatory? */, READ_ONLY, S702_CtrlModes.values())), // INT_ISLAND_CAT_RTG(new BitFieldPoint("S702_INT_ISLAND_CAT_RTG", "Intentional Island Categories", // "Intentional island categories.", // - BitFieldPoint.Type.BITFIELD16, false /* mandatory? */, AccessMode.READ_ONLY, S702_IntIslandCatRtg.values())), // + BITFIELD16, false /* mandatory? */, READ_ONLY, S702_IntIslandCatRtg.values())), // W_MAX(new ScaledValuePoint("S702_W_MAX", "Active Power Max Setting", // "Maximum active power setting used to adjust maximum active power setting.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_WRITE, Unit.WATT, "W_SF")), // + UINT16, false /* mandatory? */, READ_WRITE, Unit.WATT, "W_SF")), // W_MAX_OVR_EXT(new ScaledValuePoint("S702_W_MAX_OVR_EXT", "Active Power (Over-Excited) Setting", // "Active power setting at specified over-excited power factor in watts.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_WRITE, Unit.WATT, "W_SF")), // + UINT16, false /* mandatory? */, READ_WRITE, Unit.WATT, "W_SF")), // W_OVR_EXT_P_F(new ScaledValuePoint("S702_W_OVR_EXT_P_F", "Specified Over-Excited PF", // "Specified over-excited power factor.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_WRITE, Unit.NONE, "PF_SF")), // + UINT16, false /* mandatory? */, READ_WRITE, Unit.NONE, "PF_SF")), // W_MAX_UND_EXT(new ScaledValuePoint("S702_W_MAX_UND_EXT", "Active Power (Under-Excited) Setting", // "Active power setting at specified under-excited power factor in watts.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_WRITE, Unit.WATT, "W_SF")), // + UINT16, false /* mandatory? */, READ_WRITE, Unit.WATT, "W_SF")), // W_UND_EXT_P_F(new ScaledValuePoint("S702_W_UND_EXT_P_F", "Specified Under-Excited PF", // "Specified under-excited power factor.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_WRITE, Unit.NONE, "PF_SF")), // + UINT16, false /* mandatory? */, READ_WRITE, Unit.NONE, "PF_SF")), // V_A_MAX(new ScaledValuePoint("S702_V_A_MAX", "Apparent Power Max Setting", // "Maximum apparent power setting used to adjust maximum apparent power rating.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_WRITE, Unit.VOLT_AMPERE, "VA_SF")), // + UINT16, false /* mandatory? */, READ_WRITE, Unit.VOLT_AMPERE, "VA_SF")), // VAR_MAX_INJ(new ScaledValuePoint("S702_VAR_MAX_INJ", "Reactive Power Injected Setting", // "Maximum injected reactive power setting used to adjust maximum injected reactive power rating.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_WRITE, Unit.VOLT_AMPERE_REACTIVE, "Var_SF")), // + UINT16, false /* mandatory? */, READ_WRITE, Unit.VOLT_AMPERE_REACTIVE, "Var_SF")), // VAR_MAX_ABS(new ScaledValuePoint("S702_VAR_MAX_ABS", "Reactive Power Absorbed Setting", // "Maximum absorbed reactive power setting used to adjust maximum absorbed reactive power rating.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_WRITE, Unit.VOLT_AMPERE_REACTIVE, "Var_SF")), // + UINT16, false /* mandatory? */, READ_WRITE, Unit.VOLT_AMPERE_REACTIVE, "Var_SF")), // W_CHA_RTE_MAX(new ScaledValuePoint("S702_W_CHA_RTE_MAX", "Charge Rate Max Setting", // "Maximum active power charge rate setting used to adjust maximum active power charge rate rating.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_WRITE, Unit.WATT, "W_SF")), // + UINT16, false /* mandatory? */, READ_WRITE, Unit.WATT, "W_SF")), // W_DIS_CHA_RTE_MAX(new ScaledValuePoint("S702_W_DIS_CHA_RTE_MAX", "Discharge Rate Max Setting", // "Maximum active power discharge rate setting used to adjust maximum active power discharge rate rating.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_WRITE, Unit.WATT, "W_SF")), // + UINT16, false /* mandatory? */, READ_WRITE, Unit.WATT, "W_SF")), // V_A_CHA_RTE_MAX(new ScaledValuePoint("S702_V_A_CHA_RTE_MAX", "Charge Rate Max VA Setting", // "Maximum apparent power charge rate setting used to adjust maximum apparent power charge rate rating.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_WRITE, Unit.VOLT_AMPERE, "VA_SF")), // + UINT16, false /* mandatory? */, READ_WRITE, Unit.VOLT_AMPERE, "VA_SF")), // V_A_DIS_CHA_RTE_MAX(new ScaledValuePoint("S702_V_A_DIS_CHA_RTE_MAX", "Discharge Rate Max VA Setting", // "Maximum apparent power discharge rate setting used to adjust maximum apparent power discharge rate rating.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_WRITE, Unit.VOLT_AMPERE, "VA_SF")), // + UINT16, false /* mandatory? */, READ_WRITE, Unit.VOLT_AMPERE, "VA_SF")), // V_NOM(new ScaledValuePoint("S702_V_NOM", "Nominal AC Voltage Setting", // "Nominal AC voltage setting.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_WRITE, Unit.VOLT, "V_SF")), // + UINT16, false /* mandatory? */, READ_WRITE, Unit.VOLT, "V_SF")), // V_MAX(new ScaledValuePoint("S702_V_MAX", "AC Voltage Max Setting", // "AC voltage maximum setting used to adjust AC voltage maximum rating.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_WRITE, Unit.VOLT, "V_SF")), // + UINT16, false /* mandatory? */, READ_WRITE, Unit.VOLT, "V_SF")), // V_MIN(new ScaledValuePoint("S702_V_MIN", "AC Voltage Min Setting", // "AC voltage minimum setting used to adjust AC voltage minimum rating.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_WRITE, Unit.VOLT, "V_SF")), // + UINT16, false /* mandatory? */, READ_WRITE, Unit.VOLT, "V_SF")), // A_MAX(new ScaledValuePoint("S702_A_MAX", "AC Current Max Setting", // "Maximum AC current setting used to adjust maximum AC current rating.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_WRITE, Unit.AMPERE, "A_SF")), // + UINT16, false /* mandatory? */, READ_WRITE, Unit.AMPERE, "A_SF")), // P_F_OVR_EXT(new ScaledValuePoint("S702_P_F_OVR_EXT", "PF Over-Excited Setting", // "Power factor over-excited setting.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_WRITE, Unit.NONE, "PF_SF")), // + UINT16, false /* mandatory? */, READ_WRITE, Unit.NONE, "PF_SF")), // P_F_UND_EXT(new ScaledValuePoint("S702_P_F_UND_EXT", "PF Under-Excited Setting", // "Power factor under-excited setting.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_WRITE, Unit.NONE, "PF_SF")), // + UINT16, false /* mandatory? */, READ_WRITE, Unit.NONE, "PF_SF")), // INT_ISLAND_CAT(new BitFieldPoint("S702_INT_ISLAND_CAT", "Intentional Island Categories", // "Intentional island categories.", // - BitFieldPoint.Type.BITFIELD16, false /* mandatory? */, AccessMode.READ_WRITE, S702_IntIslandCat.values())), // + BITFIELD16, false /* mandatory? */, READ_WRITE, S702_IntIslandCat.values())), // W_SF(new ScaleFactorPoint("S702_W_SF", "Active Power Scale Factor", // "Active power scale factor.")), // PF_SF(new ScaleFactorPoint("S702_PF_SF", "Power Factor Scale Factor", // @@ -4362,31 +4432,31 @@ public BitPoint get() { public static enum S703 implements SunSpecPoint { ES(new EnumPoint("S703_ES", "Permit Enter Service", // "Permit enter service.", // - EnumPoint.Type.ENUM16, false /* mandatory? */, AccessMode.READ_WRITE, S703_ES.values())), // + ENUM16, false /* mandatory? */, READ_WRITE, S703_ES.values())), // E_S_V_HI(new ScaledValuePoint("S703_E_S_V_HI", "Enter Service Voltage High", // "Enter service voltage high threshold as percent of normal voltage.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_WRITE, Unit.NONE, "V_SF")), // + UINT16, false /* mandatory? */, READ_WRITE, Unit.NONE, "V_SF")), // E_S_V_LO(new ScaledValuePoint("S703_E_S_V_LO", "Enter Service Voltage Low", // "Enter service voltage low threshold as percent of normal voltage.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_WRITE, Unit.NONE, "V_SF")), // + UINT16, false /* mandatory? */, READ_WRITE, Unit.NONE, "V_SF")), // E_S_HZ_HI(new ScaledValuePoint("S703_E_S_HZ_HI", "Enter Service Frequency High", // "Enter service frequency high threshold.", // - ValuePoint.Type.UINT32, false /* mandatory? */, AccessMode.READ_WRITE, Unit.HERTZ, "Hz_SF")), // + UINT32, false /* mandatory? */, READ_WRITE, Unit.HERTZ, "Hz_SF")), // E_S_HZ_LO(new ScaledValuePoint("S703_E_S_HZ_LO", "Enter Service Frequency Low", // "Enter service frequency low threshold.", // - ValuePoint.Type.UINT32, false /* mandatory? */, AccessMode.READ_WRITE, Unit.HERTZ, "Hz_SF")), // + UINT32, false /* mandatory? */, READ_WRITE, Unit.HERTZ, "Hz_SF")), // E_S_DLY_TMS(new ValuePoint("S703_E_S_DLY_TMS", "Enter Service Delay Time", // "Enter service delay time in seconds.", // - ValuePoint.Type.UINT32, false /* mandatory? */, AccessMode.READ_WRITE, Unit.SECONDS)), // + UINT32, false /* mandatory? */, READ_WRITE, Unit.SECONDS)), // E_S_RND_TMS(new ValuePoint("S703_E_S_RND_TMS", "Enter Service Random Delay", // "Enter service random delay in seconds.", // - ValuePoint.Type.UINT32, false /* mandatory? */, AccessMode.READ_WRITE, Unit.SECONDS)), // + UINT32, false /* mandatory? */, READ_WRITE, Unit.SECONDS)), // E_S_RMP_TMS(new ValuePoint("S703_E_S_RMP_TMS", "Enter Service Ramp Time", // "Enter service ramp time in seconds.", // - ValuePoint.Type.UINT32, false /* mandatory? */, AccessMode.READ_WRITE, Unit.SECONDS)), // + UINT32, false /* mandatory? */, READ_WRITE, Unit.SECONDS)), // E_S_DLY_REM_TMS(new ValuePoint("S703_E_S_DLY_REM_TMS", "Enter Service Delay Remaining", // "Enter service delay time remaining in seconds.", // - ValuePoint.Type.UINT32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.SECONDS)), // + UINT32, false /* mandatory? */, READ_ONLY, Unit.SECONDS)), // V_SF(new ScaleFactorPoint("S703_V_SF", "Voltage Scale Factor", // "Voltage percentage scale factor.")), // HZ_S_F(new ScaleFactorPoint("S703_HZ_S_F", "Frequency Scale Factor", // @@ -4436,115 +4506,115 @@ public OptionsEnum getUndefined() { public static enum S704 implements SunSpecPoint { P_F_W_INJ_ENA(new EnumPoint("S704_P_F_W_INJ_ENA", "Power Factor Enable (W Inj) Enable", // "Power factor enable when injecting active power.", // - EnumPoint.Type.ENUM16, false /* mandatory? */, AccessMode.READ_WRITE, S704_PFWInjEna.values())), // + ENUM16, false /* mandatory? */, READ_WRITE, S704_PFWInjEna.values())), // P_F_W_INJ_ENA_RVRT(new EnumPoint("S704_P_F_W_INJ_ENA_RVRT", "Power Factor Reversion Enable (W Inj)", // "Power factor reversion timer when injecting active power enable.", // - EnumPoint.Type.ENUM16, false /* mandatory? */, AccessMode.READ_WRITE, S704_PFWInjEnaRvrt.values())), // + ENUM16, false /* mandatory? */, READ_WRITE, S704_PFWInjEnaRvrt.values())), // P_F_W_INJ_RVRT_TMS(new ValuePoint("S704_P_F_W_INJ_RVRT_TMS", "PF Reversion Time (W Inj)", // "Power factor reversion timer when injecting active power.", // - ValuePoint.Type.UINT32, false /* mandatory? */, AccessMode.READ_WRITE, Unit.SECONDS)), // + UINT32, false /* mandatory? */, READ_WRITE, Unit.SECONDS)), // P_F_W_INJ_RVRT_REM(new ValuePoint("S704_P_F_W_INJ_RVRT_REM", "PF Reversion Time Rem (W Inj)", // "Power factor reversion time remaining when injecting active power.", // - ValuePoint.Type.UINT32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.SECONDS)), // + UINT32, false /* mandatory? */, READ_ONLY, Unit.SECONDS)), // P_F_W_ABS_ENA(new EnumPoint("S704_P_F_W_ABS_ENA", "Power Factor Enable (W Abs) Enable", // "Power factor enable when absorbing active power.", // - EnumPoint.Type.ENUM16, false /* mandatory? */, AccessMode.READ_WRITE, S704_PFWAbsEna.values())), // + ENUM16, false /* mandatory? */, READ_WRITE, S704_PFWAbsEna.values())), // P_F_W_ABS_ENA_RVRT(new EnumPoint("S704_P_F_W_ABS_ENA_RVRT", "Power Factor Reversion Enable (W Abs)", // "Power factor reversion timer when absorbing active power enable.", // - EnumPoint.Type.ENUM16, false /* mandatory? */, AccessMode.READ_WRITE, S704_PFWAbsEnaRvrt.values())), // + ENUM16, false /* mandatory? */, READ_WRITE, S704_PFWAbsEnaRvrt.values())), // P_F_W_ABS_RVRT_TMS(new ValuePoint("S704_P_F_W_ABS_RVRT_TMS", "PF Reversion Time (W Abs)", // "Power factor reversion timer when absorbing active power.", // - ValuePoint.Type.UINT32, false /* mandatory? */, AccessMode.READ_WRITE, Unit.SECONDS)), // + UINT32, false /* mandatory? */, READ_WRITE, Unit.SECONDS)), // P_F_W_ABS_RVRT_REM(new ValuePoint("S704_P_F_W_ABS_RVRT_REM", "PF Reversion Time Rem (W Abs)", // "Power factor reversion time remaining when absorbing active power.", // - ValuePoint.Type.UINT32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.SECONDS)), // + UINT32, false /* mandatory? */, READ_ONLY, Unit.SECONDS)), // W_MAX_LIM_PCT_ENA(new EnumPoint("S704_W_MAX_LIM_PCT_ENA", "Limit Max Power Pct Enable", // "Limit maximum active power percent enable.", // - EnumPoint.Type.ENUM16, false /* mandatory? */, AccessMode.READ_WRITE, S704_WMaxLimPctEna.values())), // + ENUM16, false /* mandatory? */, READ_WRITE, S704_WMaxLimPctEna.values())), // W_MAX_LIM_PCT(new ScaledValuePoint("S704_W_MAX_LIM_PCT", "Limit Max Power Pct Setpoint", // "Limit maximum active power percent value.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_WRITE, Unit.NONE, "WMaxLimPct_SF")), // + UINT16, false /* mandatory? */, READ_WRITE, Unit.NONE, "WMaxLimPct_SF")), // W_MAX_LIM_PCT_RVRT(new ScaledValuePoint("S704_W_MAX_LIM_PCT_RVRT", "Reversion Limit Max Power Pct", // "Reversion limit maximum active power percent value.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_WRITE, Unit.NONE, "WMaxLimPct_SF")), // + UINT16, false /* mandatory? */, READ_WRITE, Unit.NONE, "WMaxLimPct_SF")), // W_MAX_LIM_PCT_ENA_RVRT(new EnumPoint("S704_W_MAX_LIM_PCT_ENA_RVRT", "Reversion Limit Max Power Pct Enable", // "Reversion limit maximum active power percent value enable.", // - EnumPoint.Type.ENUM16, false /* mandatory? */, AccessMode.READ_WRITE, S704_WMaxLimPctEnaRvrt.values())), // + ENUM16, false /* mandatory? */, READ_WRITE, S704_WMaxLimPctEnaRvrt.values())), // W_MAX_LIM_PCT_RVRT_TMS(new ValuePoint("S704_W_MAX_LIM_PCT_RVRT_TMS", "Limit Max Power Pct Reversion Time", // "Limit maximum active power percent reversion time.", // - ValuePoint.Type.UINT32, false /* mandatory? */, AccessMode.READ_WRITE, Unit.SECONDS)), // + UINT32, false /* mandatory? */, READ_WRITE, Unit.SECONDS)), // W_MAX_LIM_PCT_RVRT_REM(new ValuePoint("S704_W_MAX_LIM_PCT_RVRT_REM", "Limit Max Power Pct Rev Time Rem", // "Limit maximum active power percent reversion time remaining.", // - ValuePoint.Type.UINT32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.SECONDS)), // + UINT32, false /* mandatory? */, READ_ONLY, Unit.SECONDS)), // W_SET_ENA(new EnumPoint("S704_W_SET_ENA", "Set Active Power Enable", // "Set active power enable.", // - EnumPoint.Type.ENUM16, false /* mandatory? */, AccessMode.READ_WRITE, S704_WSetEna.values())), // + ENUM16, false /* mandatory? */, READ_WRITE, S704_WSetEna.values())), // W_SET_MOD(new EnumPoint("S704_W_SET_MOD", "Set Active Power Mode", // "Set active power mode.", // - EnumPoint.Type.ENUM16, false /* mandatory? */, AccessMode.READ_WRITE, S704_WSetMod.values())), // + ENUM16, false /* mandatory? */, READ_WRITE, S704_WSetMod.values())), // W_SET(new ScaledValuePoint("S704_W_SET", "Active Power Setpoint (W)", // "Active power setting value in watts.", // - ValuePoint.Type.INT32, false /* mandatory? */, AccessMode.READ_WRITE, Unit.WATT, "WSet_SF")), // + INT32, false /* mandatory? */, READ_WRITE, Unit.WATT, "WSet_SF")), // W_SET_RVRT(new ScaledValuePoint("S704_W_SET_RVRT", "Reversion Active Power (W)", // "Reversion active power setting value in watts.", // - ValuePoint.Type.INT32, false /* mandatory? */, AccessMode.READ_WRITE, Unit.WATT, "WSet_SF")), // + INT32, false /* mandatory? */, READ_WRITE, Unit.WATT, "WSet_SF")), // W_SET_PCT(new ScaledValuePoint("S704_W_SET_PCT", "Active Power Setpoint (Pct)", // "Active power setting value as percent.", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_WRITE, Unit.NONE, "WSetPct_SF")), // + INT16, false /* mandatory? */, READ_WRITE, Unit.NONE, "WSetPct_SF")), // W_SET_PCT_RVRT(new ScaledValuePoint("S704_W_SET_PCT_RVRT", "Reversion Active Power (Pct)", // "Reversion active power setting value as percent.", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_WRITE, Unit.NONE, "WSetPct_SF")), // + INT16, false /* mandatory? */, READ_WRITE, Unit.NONE, "WSetPct_SF")), // W_SET_ENA_RVRT(new EnumPoint("S704_W_SET_ENA_RVRT", "Reversion Active Power Enable", // "Reversion active power function enable.", // - EnumPoint.Type.ENUM16, false /* mandatory? */, AccessMode.READ_WRITE, S704_WSetEnaRvrt.values())), // + ENUM16, false /* mandatory? */, READ_WRITE, S704_WSetEnaRvrt.values())), // W_SET_RVRT_TMS(new ValuePoint("S704_W_SET_RVRT_TMS", "Active Power Reversion Time", // "Set active power reversion time.", // - ValuePoint.Type.UINT32, false /* mandatory? */, AccessMode.READ_WRITE, Unit.SECONDS)), // + UINT32, false /* mandatory? */, READ_WRITE, Unit.SECONDS)), // W_SET_RVRT_REM(new ValuePoint("S704_W_SET_RVRT_REM", "Active Power Rev Time Rem", // "Set active power reversion time remaining.", // - ValuePoint.Type.UINT32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.SECONDS)), // + UINT32, false /* mandatory? */, READ_ONLY, Unit.SECONDS)), // VAR_SET_ENA(new EnumPoint("S704_VAR_SET_ENA", "Set Reactive Power Enable", // "Set reactive power enable.", // - EnumPoint.Type.ENUM16, false /* mandatory? */, AccessMode.READ_WRITE, S704_VarSetEna.values())), // + ENUM16, false /* mandatory? */, READ_WRITE, S704_VarSetEna.values())), // VAR_SET_MOD(new EnumPoint("S704_VAR_SET_MOD", "Set Reactive Power Mode", // "Set reactive power mode.", // - EnumPoint.Type.ENUM16, false /* mandatory? */, AccessMode.READ_WRITE, S704_VarSetMod.values())), // + ENUM16, false /* mandatory? */, READ_WRITE, S704_VarSetMod.values())), // VAR_SET_PRI(new EnumPoint("S704_VAR_SET_PRI", "Reactive Power Priority", // "Reactive power priority.", // - EnumPoint.Type.ENUM16, false /* mandatory? */, AccessMode.READ_WRITE, S704_VarSetPri.values())), // + ENUM16, false /* mandatory? */, READ_WRITE, S704_VarSetPri.values())), // VAR_SET(new ScaledValuePoint("S704_VAR_SET", "Reactive Power Setpoint (Vars)", // "Reactive power setting value in vars.", // - ValuePoint.Type.INT32, false /* mandatory? */, AccessMode.READ_WRITE, Unit.VOLT_AMPERE_REACTIVE, "VarSet_SF")), // + INT32, false /* mandatory? */, READ_WRITE, Unit.VOLT_AMPERE_REACTIVE, "VarSet_SF")), // VAR_SET_RVRT(new ScaledValuePoint("S704_VAR_SET_RVRT", "Reversion Reactive Power (Vars)", // "Reversion reactive power setting value in vars.", // - ValuePoint.Type.INT32, false /* mandatory? */, AccessMode.READ_WRITE, Unit.VOLT_AMPERE_REACTIVE, "VarSet_SF")), // + INT32, false /* mandatory? */, READ_WRITE, Unit.VOLT_AMPERE_REACTIVE, "VarSet_SF")), // VAR_SET_PCT(new ScaledValuePoint("S704_VAR_SET_PCT", "Reactive Power Setpoint (Pct)", // "Reactive power setting value as percent.", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_WRITE, Unit.NONE, "VarSetPct_SF")), // + INT16, false /* mandatory? */, READ_WRITE, Unit.NONE, "VarSetPct_SF")), // VAR_SET_PCT_RVRT(new ScaledValuePoint("S704_VAR_SET_PCT_RVRT", "Reversion Reactive Power (Pct)", // "Reversion reactive power setting value as percent.", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_WRITE, Unit.NONE, "VarSetPct_SF")), // + INT16, false /* mandatory? */, READ_WRITE, Unit.NONE, "VarSetPct_SF")), // VAR_SET_ENA_RVRT(new EnumPoint("S704_VAR_SET_ENA_RVRT", "Reversion Reactive Power Enable", // "Reversion reactive power function enable.", // - EnumPoint.Type.ENUM16, false /* mandatory? */, AccessMode.READ_WRITE, S704_VarSetEnaRvrt.values())), // + ENUM16, false /* mandatory? */, READ_WRITE, S704_VarSetEnaRvrt.values())), // VAR_SET_RVRT_TMS(new ValuePoint("S704_VAR_SET_RVRT_TMS", "Reactive Power Reversion Time", // "Set reactive power reversion time.", // - ValuePoint.Type.UINT32, false /* mandatory? */, AccessMode.READ_WRITE, Unit.SECONDS)), // + UINT32, false /* mandatory? */, READ_WRITE, Unit.SECONDS)), // VAR_SET_RVRT_REM(new ValuePoint("S704_VAR_SET_RVRT_REM", "Reactive Power Rev Time Rem", // "Set reactive power reversion time remaining.", // - ValuePoint.Type.UINT32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.SECONDS)), // + UINT32, false /* mandatory? */, READ_ONLY, Unit.SECONDS)), // W_RMP(new ValuePoint("S704_W_RMP", "Normal Ramp Rate", // "Ramp rate for increases in active power during normal generation.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_WRITE, Unit.NONE)), // + UINT16, false /* mandatory? */, READ_WRITE, Unit.NONE)), // W_RMP_REF(new EnumPoint("S704_W_RMP_REF", "Normal Ramp Rate Reference", // "Ramp rate reference unit for increases in active power or current during normal generation.", // - EnumPoint.Type.ENUM16, false /* mandatory? */, AccessMode.READ_WRITE, S704_WRmpRef.values())), // + ENUM16, false /* mandatory? */, READ_WRITE, S704_WRmpRef.values())), // VAR_RMP(new ValuePoint("S704_VAR_RMP", "Reactive Power Ramp Rate", // "Ramp rate based on max reactive power per second.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_WRITE, Unit.NONE)), // + UINT16, false /* mandatory? */, READ_WRITE, Unit.NONE)), // ANTI_ISL_ENA(new EnumPoint("S704_ANTI_ISL_ENA", "Anti-Islanding Enable", // "Anti-islanding enable.", // - EnumPoint.Type.ENUM16, false /* mandatory? */, AccessMode.READ_WRITE, S704_AntiIslEna.values())), // + ENUM16, false /* mandatory? */, READ_WRITE, S704_AntiIslEna.values())), // PF_SF(new ScaleFactorPoint("S704_PF_SF", "Power Factor Scale Factor", // "Power factor scale factor.")), // W_MAX_LIM_PCT_S_F(new ScaleFactorPoint("S704_W_MAX_LIM_PCT_S_F", "Limit Max Power Scale Factor", // @@ -5012,28 +5082,28 @@ public OptionsEnum getUndefined() { public static enum S705 implements SunSpecPoint { ENA(new EnumPoint("S705_ENA", "DER Volt-Var Module Enable", // "Volt-Var control enable.", // - EnumPoint.Type.ENUM16, true /* mandatory? */, AccessMode.READ_WRITE, S705_Ena.values())), // + ENUM16, true /* mandatory? */, READ_WRITE, S705_Ena.values())), // ADPT_CRV_REQ(new ValuePoint("S705_ADPT_CRV_REQ", "Adopt Curve Request", // "Index of curve points to adopt. First curve index is 1.", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_WRITE, Unit.NONE)), // + UINT16, true /* mandatory? */, READ_WRITE, Unit.NONE)), // ADPT_CRV_RSLT(new EnumPoint("S705_ADPT_CRV_RSLT", "Adopt Curve Result", // "Result of last adopt curve operation.", // - EnumPoint.Type.ENUM16, true /* mandatory? */, AccessMode.READ_ONLY, S705_AdptCrvRslt.values())), // + ENUM16, true /* mandatory? */, READ_ONLY, S705_AdptCrvRslt.values())), // N_PT(new ValuePoint("S705_N_PT", "Number Of Points", // "Number of curve points supported.", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // + UINT16, true /* mandatory? */, READ_ONLY, Unit.NONE)), // N_CRV(new ValuePoint("S705_N_CRV", "Stored Curve Count", // "Number of stored curves supported.", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // + UINT16, true /* mandatory? */, READ_ONLY, Unit.NONE)), // RVRT_TMS(new ValuePoint("S705_RVRT_TMS", "Reversion Timeout", // "Reversion time in seconds. 0 = No reversion time.", // - ValuePoint.Type.UINT32, false /* mandatory? */, AccessMode.READ_WRITE, Unit.SECONDS)), // + UINT32, false /* mandatory? */, READ_WRITE, Unit.SECONDS)), // RVRT_REM(new ValuePoint("S705_RVRT_REM", "Reversion Time Remaining", // "Reversion time remaining in seconds.", // - ValuePoint.Type.UINT32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.SECONDS)), // + UINT32, false /* mandatory? */, READ_ONLY, Unit.SECONDS)), // RVRT_CRV(new ValuePoint("S705_RVRT_CRV", "Reversion Curve", // "Default curve after reversion timeout.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_WRITE, Unit.NONE)), // + UINT16, false /* mandatory? */, READ_WRITE, Unit.NONE)), // V_SF(new ScaleFactorPoint("S705_V_SF", "Voltage Scale Factor", // "Scale factor for curve voltage points.")), // DEPT_REF_S_F(new ScaleFactorPoint("S705_DEPT_REF_S_F", "Var Scale Factor", // @@ -5115,28 +5185,28 @@ public OptionsEnum getUndefined() { public static enum S706 implements SunSpecPoint { ENA(new EnumPoint("S706_ENA", "DER Volt-Watt Module Enable", // "Volt-Watt control enable.", // - EnumPoint.Type.ENUM16, true /* mandatory? */, AccessMode.READ_WRITE, S706_Ena.values())), // + ENUM16, true /* mandatory? */, READ_WRITE, S706_Ena.values())), // ADPT_CRV_REQ(new ValuePoint("S706_ADPT_CRV_REQ", "Adopt Curve Request", // "Index of curve points to adopt. First curve index is 1.", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_WRITE, Unit.NONE)), // + UINT16, true /* mandatory? */, READ_WRITE, Unit.NONE)), // ADPT_CRV_RSLT(new EnumPoint("S706_ADPT_CRV_RSLT", "Adopt Curve Result", // "Result of last adopt curve operation.", // - EnumPoint.Type.ENUM16, true /* mandatory? */, AccessMode.READ_ONLY, S706_AdptCrvRslt.values())), // + ENUM16, true /* mandatory? */, READ_ONLY, S706_AdptCrvRslt.values())), // N_PT(new ValuePoint("S706_N_PT", "Number Of Points", // "Number of curve points supported.", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // + UINT16, true /* mandatory? */, READ_ONLY, Unit.NONE)), // N_CRV(new ValuePoint("S706_N_CRV", "Stored Curve Count", // "Number of stored curves supported.", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // + UINT16, true /* mandatory? */, READ_ONLY, Unit.NONE)), // RVRT_TMS(new ValuePoint("S706_RVRT_TMS", "Reversion Timeout", // "Reversion time in seconds. 0 = No reversion time.", // - ValuePoint.Type.UINT32, false /* mandatory? */, AccessMode.READ_WRITE, Unit.SECONDS)), // + UINT32, false /* mandatory? */, READ_WRITE, Unit.SECONDS)), // RVRT_REM(new ValuePoint("S706_RVRT_REM", "Reversion Time Remaining", // "Reversion time remaining in seconds.", // - ValuePoint.Type.UINT32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.SECONDS)), // + UINT32, false /* mandatory? */, READ_ONLY, Unit.SECONDS)), // RVRT_CRV(new ValuePoint("S706_RVRT_CRV", "Reversion Curve", // "Default curve after reversion timeout.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_WRITE, Unit.NONE)), // + UINT16, false /* mandatory? */, READ_WRITE, Unit.NONE)), // V_SF(new ScaleFactorPoint("S706_V_SF", "Voltage Scale Factor", // "Scale factor for curve voltage points.")), // DEPT_REF_S_F(new ScaleFactorPoint("S706_DEPT_REF_S_F", "Watt Scale Factor", // @@ -5218,19 +5288,19 @@ public OptionsEnum getUndefined() { public static enum S707 implements SunSpecPoint { ENA(new EnumPoint("S707_ENA", "DER Trip LV Module Enable", // "DER low voltage trip control enable.", // - EnumPoint.Type.ENUM16, true /* mandatory? */, AccessMode.READ_WRITE, S707_Ena.values())), // + ENUM16, true /* mandatory? */, READ_WRITE, S707_Ena.values())), // ADPT_CRV_REQ(new ValuePoint("S707_ADPT_CRV_REQ", "Adopt Curve Request", // "Index of curve points to adopt. First curve index is 1.", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_WRITE, Unit.NONE)), // + UINT16, true /* mandatory? */, READ_WRITE, Unit.NONE)), // ADPT_CRV_RSLT(new EnumPoint("S707_ADPT_CRV_RSLT", "Adopt Curve Result", // "Result of last adopt curve operation.", // - EnumPoint.Type.ENUM16, true /* mandatory? */, AccessMode.READ_ONLY, S707_AdptCrvRslt.values())), // + ENUM16, true /* mandatory? */, READ_ONLY, S707_AdptCrvRslt.values())), // N_PT(new ValuePoint("S707_N_PT", "Number Of Points", // "Number of curve points supported.", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // + UINT16, true /* mandatory? */, READ_ONLY, Unit.NONE)), // N_CRV_SET(new ValuePoint("S707_N_CRV_SET", "Stored Curve Count", // "Number of stored curves supported.", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // + UINT16, true /* mandatory? */, READ_ONLY, Unit.NONE)), // V_SF(new ScaleFactorPoint("S707_V_SF", "Voltage Scale Factor", // "Scale factor for curve voltage points.")), // TMS_S_F(new ScaleFactorPoint("S707_TMS_S_F", "Time Point Scale Factor", // @@ -5310,19 +5380,19 @@ public OptionsEnum getUndefined() { public static enum S708 implements SunSpecPoint { ENA(new EnumPoint("S708_ENA", "DER Trip HV Module Enable", // "DER high voltage trip control enable.", // - EnumPoint.Type.ENUM16, true /* mandatory? */, AccessMode.READ_WRITE, S708_Ena.values())), // + ENUM16, true /* mandatory? */, READ_WRITE, S708_Ena.values())), // ADPT_CRV_REQ(new ValuePoint("S708_ADPT_CRV_REQ", "Adopt Curve Request", // "Index of curve points to adopt. First curve index is 1.", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_WRITE, Unit.NONE)), // + UINT16, true /* mandatory? */, READ_WRITE, Unit.NONE)), // ADPT_CRV_RSLT(new EnumPoint("S708_ADPT_CRV_RSLT", "Adopt Curve Result", // "Result of last adopt curve operation.", // - EnumPoint.Type.ENUM16, true /* mandatory? */, AccessMode.READ_ONLY, S708_AdptCrvRslt.values())), // + ENUM16, true /* mandatory? */, READ_ONLY, S708_AdptCrvRslt.values())), // N_PT(new ValuePoint("S708_N_PT", "Number Of Points", // "Number of curve points supported.", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // + UINT16, true /* mandatory? */, READ_ONLY, Unit.NONE)), // N_CRV_SET(new ValuePoint("S708_N_CRV_SET", "Stored Curve Count", // "Number of stored curves supported.", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // + UINT16, true /* mandatory? */, READ_ONLY, Unit.NONE)), // V_SF(new ScaleFactorPoint("S708_V_SF", "Voltage Scale Factor", // "Scale factor for curve voltage points.")), // TMS_S_F(new ScaleFactorPoint("S708_TMS_S_F", "Time Point Scale Factor", // @@ -5402,19 +5472,19 @@ public OptionsEnum getUndefined() { public static enum S709 implements SunSpecPoint { ENA(new EnumPoint("S709_ENA", "DER Trip LF Module Enable", // "DER low frequency trip control enable.", // - EnumPoint.Type.ENUM16, true /* mandatory? */, AccessMode.READ_WRITE, S709_Ena.values())), // + ENUM16, true /* mandatory? */, READ_WRITE, S709_Ena.values())), // ADPT_CRV_REQ(new ValuePoint("S709_ADPT_CRV_REQ", "Adopt Curve Request", // "Index of curve points to adopt. First curve index is 1.", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_WRITE, Unit.NONE)), // + UINT16, true /* mandatory? */, READ_WRITE, Unit.NONE)), // ADPT_CRV_RSLT(new EnumPoint("S709_ADPT_CRV_RSLT", "Adopt Curve Result", // "Result of last adopt curve operation.", // - EnumPoint.Type.ENUM16, true /* mandatory? */, AccessMode.READ_ONLY, S709_AdptCrvRslt.values())), // + ENUM16, true /* mandatory? */, READ_ONLY, S709_AdptCrvRslt.values())), // N_PT(new ValuePoint("S709_N_PT", "Number Of Points", // "Number of curve points supported.", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // + UINT16, true /* mandatory? */, READ_ONLY, Unit.NONE)), // N_CRV_SET(new ValuePoint("S709_N_CRV_SET", "Stored Curve Count", // "Number of stored curves supported.", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // + UINT16, true /* mandatory? */, READ_ONLY, Unit.NONE)), // HZ_S_F(new ScaleFactorPoint("S709_HZ_S_F", "Frequency Scale Factor", // "Scale factor for curve frequency points.")), // TMS_S_F(new ScaleFactorPoint("S709_TMS_S_F", "Time Point Scale Factor", // @@ -5494,19 +5564,19 @@ public OptionsEnum getUndefined() { public static enum S710 implements SunSpecPoint { ENA(new EnumPoint("S710_ENA", "DER Trip HF Module Enable", // "DER high frequency trip control enable.", // - EnumPoint.Type.ENUM16, true /* mandatory? */, AccessMode.READ_WRITE, S710_Ena.values())), // + ENUM16, true /* mandatory? */, READ_WRITE, S710_Ena.values())), // ADPT_CRV_REQ(new ValuePoint("S710_ADPT_CRV_REQ", "Adopt Curve Request", // "Index of curve points to adopt. First curve index is 1.", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_WRITE, Unit.NONE)), // + UINT16, true /* mandatory? */, READ_WRITE, Unit.NONE)), // ADPT_CRV_RSLT(new EnumPoint("S710_ADPT_CRV_RSLT", "Adopt Curve Result", // "Result of last adopt curve operation.", // - EnumPoint.Type.ENUM16, true /* mandatory? */, AccessMode.READ_ONLY, S710_AdptCrvRslt.values())), // + ENUM16, true /* mandatory? */, READ_ONLY, S710_AdptCrvRslt.values())), // N_PT(new ValuePoint("S710_N_PT", "Number Of Points", // "Number of curve points supported.", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // + UINT16, true /* mandatory? */, READ_ONLY, Unit.NONE)), // N_CRV_SET(new ValuePoint("S710_N_CRV_SET", "Stored Curve Count", // "Number of stored curves supported.", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // + UINT16, true /* mandatory? */, READ_ONLY, Unit.NONE)), // HZ_S_F(new ScaleFactorPoint("S710_HZ_S_F", "Frequency Scale Factor", // "Scale factor for curve frequency points.")), // TMS_S_F(new ScaleFactorPoint("S710_TMS_S_F", "Time Point Scale Factor", // @@ -5586,25 +5656,25 @@ public OptionsEnum getUndefined() { public static enum S711 implements SunSpecPoint { ENA(new EnumPoint("S711_ENA", "DER Frequency Droop Module Enable", // "DER Frequency-Watt (Frequency-Droop) control enable.", // - EnumPoint.Type.ENUM16, true /* mandatory? */, AccessMode.READ_WRITE, S711_Ena.values())), // + ENUM16, true /* mandatory? */, READ_WRITE, S711_Ena.values())), // ADPT_CTL_REQ(new ValuePoint("S711_ADPT_CTL_REQ", "Set Active Control Request", // "Set active control. 0 = No active control.", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_WRITE, Unit.NONE)), // + UINT16, true /* mandatory? */, READ_WRITE, Unit.NONE)), // ADPT_CTL_RSLT(new EnumPoint("S711_ADPT_CTL_RSLT", "Set Active Control Result", // "Result of last set active control operation.", // - EnumPoint.Type.ENUM16, true /* mandatory? */, AccessMode.READ_ONLY, S711_AdptCtlRslt.values())), // + ENUM16, true /* mandatory? */, READ_ONLY, S711_AdptCtlRslt.values())), // N_CTL(new ValuePoint("S711_N_CTL", "Stored Control Count", // "Number of stored controls supported.", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // + UINT16, true /* mandatory? */, READ_ONLY, Unit.NONE)), // RVRT_TMS(new ValuePoint("S711_RVRT_TMS", "Reversion Timeout", // "Reversion time in seconds. 0 = No reversion time.", // - ValuePoint.Type.UINT32, false /* mandatory? */, AccessMode.READ_WRITE, Unit.SECONDS)), // + UINT32, false /* mandatory? */, READ_WRITE, Unit.SECONDS)), // RVRT_REM(new ValuePoint("S711_RVRT_REM", "Reversion Time Left", // "Reversion time remaining in seconds.", // - ValuePoint.Type.UINT32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.SECONDS)), // + UINT32, false /* mandatory? */, READ_ONLY, Unit.SECONDS)), // RVRT_CTL(new ValuePoint("S711_RVRT_CTL", "Reversion Control", // "Default control after reversion timeout.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_WRITE, Unit.NONE)), // + UINT16, false /* mandatory? */, READ_WRITE, Unit.NONE)), // DB_S_F(new ScaleFactorPoint("S711_DB_S_F", "Deadband Scale Factor", // "Deadband scale factor.")), // K_SF(new ScaleFactorPoint("S711_K_SF", "Frequency Change Scale Factor", // @@ -5686,28 +5756,28 @@ public OptionsEnum getUndefined() { public static enum S712 implements SunSpecPoint { ENA(new EnumPoint("S712_ENA", "DER Watt-Var Module Enable", // "DER Watt-Var control enable.", // - EnumPoint.Type.ENUM16, true /* mandatory? */, AccessMode.READ_WRITE, S712_Ena.values())), // + ENUM16, true /* mandatory? */, READ_WRITE, S712_Ena.values())), // ADPT_CRV_REQ(new ValuePoint("S712_ADPT_CRV_REQ", "Set Active Curve Request", // "Set active curve. 0 = No active curve.", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_WRITE, Unit.NONE)), // + UINT16, true /* mandatory? */, READ_WRITE, Unit.NONE)), // ADPT_CRV_RSLT(new EnumPoint("S712_ADPT_CRV_RSLT", "Set Active Curve Result", // "Result of last set active curve operation.", // - EnumPoint.Type.ENUM16, true /* mandatory? */, AccessMode.READ_ONLY, S712_AdptCrvRslt.values())), // + ENUM16, true /* mandatory? */, READ_ONLY, S712_AdptCrvRslt.values())), // N_PT(new ValuePoint("S712_N_PT", "Number Of Points", // "Number of curve points supported.", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // + UINT16, true /* mandatory? */, READ_ONLY, Unit.NONE)), // N_CRV(new ValuePoint("S712_N_CRV", "Stored Curve Count", // "Number of stored curves supported.", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // + UINT16, true /* mandatory? */, READ_ONLY, Unit.NONE)), // RVRT_TMS(new ValuePoint("S712_RVRT_TMS", "Reversion Timeout", // "Reversion time in seconds. 0 = No reversion time.", // - ValuePoint.Type.UINT32, false /* mandatory? */, AccessMode.READ_WRITE, Unit.SECONDS)), // + UINT32, false /* mandatory? */, READ_WRITE, Unit.SECONDS)), // RVRT_REM(new ValuePoint("S712_RVRT_REM", "Reversion Time Left", // "Reversion time remaining in seconds.", // - ValuePoint.Type.UINT32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.SECONDS)), // + UINT32, false /* mandatory? */, READ_ONLY, Unit.SECONDS)), // RVRT_CRV(new ValuePoint("S712_RVRT_CRV", "Reversion Curve", // "Default curve after reversion timeout.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_WRITE, Unit.NONE)), // + UINT16, false /* mandatory? */, READ_WRITE, Unit.NONE)), // W_SF(new ScaleFactorPoint("S712_W_SF", "Active Power Scale Factor", // "Scale factor for curve active power points.")), // DEPT_REF_S_F(new ScaleFactorPoint("S712_DEPT_REF_S_F", "Var Scale Factor", // @@ -5787,19 +5857,19 @@ public OptionsEnum getUndefined() { public static enum S713 implements SunSpecPoint { W_H_RTG(new ScaledValuePoint("S713_W_H_RTG", "Energy Rating", // "Energy rating of the DER storage.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.CUMULATED_WATT_HOURS, "WH_SF")), // + UINT16, false /* mandatory? */, READ_ONLY, Unit.CUMULATED_WATT_HOURS, "WH_SF")), // W_H_AVAIL(new ScaledValuePoint("S713_W_H_AVAIL", "Energy Available", // "Energy available of the DER storage (WHAvail = WHRtg * SoC * SoH)", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.CUMULATED_WATT_HOURS, "WH_SF")), // + UINT16, false /* mandatory? */, READ_ONLY, Unit.CUMULATED_WATT_HOURS, "WH_SF")), // SO_C(new ScaledValuePoint("S713_SO_C", "State of Charge", // "State of charge of the DER storage.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE, "Pct_SF")), // + UINT16, false /* mandatory? */, READ_ONLY, Unit.NONE, "Pct_SF")), // SO_H(new ScaledValuePoint("S713_SO_H", "State of Health", // "State of health of the DER storage.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE, "Pct_SF")), // + UINT16, false /* mandatory? */, READ_ONLY, Unit.NONE, "Pct_SF")), // STA(new EnumPoint("S713_STA", "Status", // "Storage status.", // - EnumPoint.Type.ENUM16, false /* mandatory? */, AccessMode.READ_ONLY, S713_Sta.values())), // + ENUM16, false /* mandatory? */, READ_ONLY, S713_Sta.values())), // WH_SF(new ScaleFactorPoint("S713_WH_SF", "Energy Scale Factor", // "Scale factor for energy capacity.")), // PCT_S_F(new ScaleFactorPoint("S713_PCT_S_F", "Percent Scale Factor", // @@ -5850,22 +5920,22 @@ public OptionsEnum getUndefined() { public static enum S714 implements SunSpecPoint { PRT_ALRMS(new BitFieldPoint("S714_PRT_ALRMS", "Port Alarms", // "Bitfield of ports with active alarms. Bit is 1 if port has an active alarm. Bit 0 is first port.", // - BitFieldPoint.Type.BITFIELD32, false /* mandatory? */, AccessMode.READ_ONLY, new SunSpecBitPoint[0])), // + BITFIELD32, false /* mandatory? */, READ_ONLY, new SunSpecBitPoint[0])), // N_PRT(new ValuePoint("S714_N_PRT", "Number Of Ports", // "Number of DC ports.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // + UINT16, false /* mandatory? */, READ_ONLY, Unit.NONE)), // DCA(new ScaledValuePoint("S714_DCA", "DC Current", // "Total DC current for all ports.", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.AMPERE, "DCA_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.AMPERE, "DCA_SF")), // DCW(new ScaledValuePoint("S714_DCW", "DC Power", // "Total DC power for all ports.", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.WATT, "DCW_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.WATT, "DCW_SF")), // D_C_WH_INJ(new ScaledValuePoint("S714_D_C_WH_INJ", "DC Energy Injected", // "Total cumulative DC energy injected for all ports.", // - ValuePoint.Type.UINT64, false /* mandatory? */, AccessMode.READ_ONLY, Unit.CUMULATED_WATT_HOURS, "DCWH_SF")), // + UINT64, false /* mandatory? */, READ_ONLY, Unit.CUMULATED_WATT_HOURS, "DCWH_SF")), // D_C_WH_ABS(new ScaledValuePoint("S714_D_C_WH_ABS", "DC Energy Absorbed", // "Total cumulative DC energy absorbed for all ports.", // - ValuePoint.Type.UINT64, false /* mandatory? */, AccessMode.READ_ONLY, Unit.CUMULATED_WATT_HOURS, "DCWH_SF")), // + UINT64, false /* mandatory? */, READ_ONLY, Unit.CUMULATED_WATT_HOURS, "DCWH_SF")), // DCA_SF(new ScaleFactorPoint("S714_DCA_SF", "DC Current Scale Factor", // "DC current scale factor.")), // DCV_SF(new ScaleFactorPoint("S714_DCV_SF", "DC Voltage Scale Factor", // @@ -5892,19 +5962,19 @@ public Point get() { public static enum S715 implements SunSpecPoint { LOC_REM_CTL(new EnumPoint("S715_LOC_REM_CTL", "Control Mode", // "DER control mode. Enumeration.", // - EnumPoint.Type.ENUM16, false /* mandatory? */, AccessMode.READ_ONLY, S715_LocRemCtl.values())), // + ENUM16, false /* mandatory? */, READ_ONLY, S715_LocRemCtl.values())), // D_E_R_HB(new ValuePoint("S715_D_E_R_HB", "DER Heartbeat", // "Value is incremented every second by the DER with periodic resets to zero.", // - ValuePoint.Type.UINT32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // + UINT32, false /* mandatory? */, READ_ONLY, Unit.NONE)), // CONTROLLER_HB(new ValuePoint("S715_CONTROLLER_HB", "Controller Heartbeat", // "Value is incremented every second by the controller with periodic resets to zero.", // - ValuePoint.Type.UINT32, false /* mandatory? */, AccessMode.READ_WRITE, Unit.NONE)), // + UINT32, false /* mandatory? */, READ_WRITE, Unit.NONE)), // ALARM_RESET(new ValuePoint("S715_ALARM_RESET", "Alarm Reset", // "Used to reset any latched alarms. 1 = Reset.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_WRITE, Unit.NONE)), // + UINT16, false /* mandatory? */, READ_WRITE, Unit.NONE)), // OP_CTL(new EnumPoint("S715_OP_CTL", "Set Operation", // "Commands to PCS. Enumerated value.", // - EnumPoint.Type.ENUM16, false /* mandatory? */, AccessMode.READ_WRITE, S715_OpCtl.values())); + ENUM16, false /* mandatory? */, READ_WRITE, S715_OpCtl.values())); private final Point point; @@ -5981,7 +6051,7 @@ public OptionsEnum getUndefined() { public static enum S801 implements SunSpecPoint { DEPRECATED(new EnumPoint("S801_DEPRECATED", "Deprecated Model", // "This model has been deprecated.", // - EnumPoint.Type.ENUM16, true /* mandatory? */, AccessMode.READ_ONLY, new OptionsEnum[0])); + ENUM16, true /* mandatory? */, READ_ONLY, new OptionsEnum[0])); private final Point point; @@ -5998,136 +6068,136 @@ public Point get() { public static enum S802 implements SunSpecPoint { A_H_RTG(new ScaledValuePoint("S802_A_H_RTG", "Nameplate Charge Capacity", // "Nameplate charge capacity in amp-hours.", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.AMPERE_HOURS, "AHRtg_SF")), // + UINT16, true /* mandatory? */, READ_ONLY, Unit.AMPERE_HOURS, "AHRtg_SF")), // W_H_RTG(new ScaledValuePoint("S802_W_H_RTG", "Nameplate Energy Capacity", // "Nameplate energy capacity in DC watt-hours.", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.CUMULATED_WATT_HOURS, "WHRtg_SF")), // + UINT16, true /* mandatory? */, READ_ONLY, Unit.CUMULATED_WATT_HOURS, "WHRtg_SF")), // W_CHA_RTE_MAX(new ScaledValuePoint("S802_W_CHA_RTE_MAX", "Nameplate Max Charge Rate", // "Maximum rate of energy transfer into the storage device in DC watts.", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.WATT, "WChaDisChaMax_SF")), // + UINT16, true /* mandatory? */, READ_ONLY, Unit.WATT, "WChaDisChaMax_SF")), // W_DIS_CHA_RTE_MAX(new ScaledValuePoint("S802_W_DIS_CHA_RTE_MAX", "Nameplate Max Discharge Rate", // "Maximum rate of energy transfer out of the storage device in DC watts.", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.WATT, "WChaDisChaMax_SF")), // + UINT16, true /* mandatory? */, READ_ONLY, Unit.WATT, "WChaDisChaMax_SF")), // DIS_CHA_RTE(new ScaledValuePoint("S802_DIS_CHA_RTE", "Self Discharge Rate", // "Self discharge rate. Percentage of capacity (WHRtg) discharged per day.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.PERCENT, "DisChaRte_SF")), // + UINT16, false /* mandatory? */, READ_ONLY, Unit.PERCENT, "DisChaRte_SF")), // SO_C_MAX(new ScaledValuePoint("S802_SO_C_MAX", "Nameplate Max SoC", // "Manufacturer maximum state of charge, expressed as a percentage.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.PERCENT, "SoC_SF")), // + UINT16, false /* mandatory? */, READ_ONLY, Unit.PERCENT, "SoC_SF")), // SO_C_MIN(new ScaledValuePoint("S802_SO_C_MIN", "Nameplate Min SoC", // "Manufacturer minimum state of charge, expressed as a percentage.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.PERCENT, "SoC_SF")), // + UINT16, false /* mandatory? */, READ_ONLY, Unit.PERCENT, "SoC_SF")), // SOC_RSV_MAX(new ScaledValuePoint("S802_SOC_RSV_MAX", "Max Reserve Percent", // "Setpoint for maximum reserve for storage as a percentage of the nominal maximum storage.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_WRITE, Unit.PERCENT, "SoC_SF")), // + UINT16, false /* mandatory? */, READ_WRITE, Unit.PERCENT, "SoC_SF")), // SO_C_RSV_MIN(new ScaledValuePoint("S802_SO_C_RSV_MIN", "Min Reserve Percent", // "Setpoint for minimum reserve for storage as a percentage of the nominal maximum storage.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_WRITE, Unit.PERCENT, "SoC_SF")), // + UINT16, false /* mandatory? */, READ_WRITE, Unit.PERCENT, "SoC_SF")), // SO_C(new ScaledValuePoint("S802_SO_C", "State of Charge", // "State of charge, expressed as a percentage.", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.PERCENT, "SoC_SF")), // + UINT16, true /* mandatory? */, READ_ONLY, Unit.PERCENT, "SoC_SF")), // DO_D(new ScaledValuePoint("S802_DO_D", "Depth of Discharge", // "Depth of discharge, expressed as a percentage.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.PERCENT, "DoD_SF")), // + UINT16, false /* mandatory? */, READ_ONLY, Unit.PERCENT, "DoD_SF")), // SO_H(new ScaledValuePoint("S802_SO_H", "State of Health", // "Percentage of battery life remaining.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.PERCENT, "SoH_SF")), // + UINT16, false /* mandatory? */, READ_ONLY, Unit.PERCENT, "SoH_SF")), // N_CYC(new ValuePoint("S802_N_CYC", "Cycle Count", // "Number of cycles executed in the battery.", // - ValuePoint.Type.UINT32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // + UINT32, false /* mandatory? */, READ_ONLY, Unit.NONE)), // CHA_ST(new EnumPoint("S802_CHA_ST", "Charge Status", // "Charge status of storage device. Enumeration.", // - EnumPoint.Type.ENUM16, false /* mandatory? */, AccessMode.READ_ONLY, S802_ChaSt.values())), // + ENUM16, false /* mandatory? */, READ_ONLY, S802_ChaSt.values())), // LOC_REM_CTL(new EnumPoint("S802_LOC_REM_CTL", "Control Mode", // "Battery control mode. Enumeration.", // - EnumPoint.Type.ENUM16, true /* mandatory? */, AccessMode.READ_ONLY, S802_LocRemCtl.values())), // + ENUM16, true /* mandatory? */, READ_ONLY, S802_LocRemCtl.values())), // HB(new ValuePoint("S802_HB", "Battery Heartbeat", // "Value is incremented every second with periodic resets to zero.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // + UINT16, false /* mandatory? */, READ_ONLY, Unit.NONE)), // CTRL_HB(new ValuePoint("S802_CTRL_HB", "Controller Heartbeat", // "Value is incremented every second with periodic resets to zero.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_WRITE, Unit.NONE)), // + UINT16, false /* mandatory? */, READ_WRITE, Unit.NONE)), // ALM_RST(new ValuePoint("S802_ALM_RST", "Alarm Reset", // "Used to reset any latched alarms. 1 = Reset.", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_WRITE, Unit.NONE)), // + UINT16, true /* mandatory? */, READ_WRITE, Unit.NONE)), // TYP(new EnumPoint("S802_TYP", "Battery Type", // "Type of battery. Enumeration.", // - EnumPoint.Type.ENUM16, true /* mandatory? */, AccessMode.READ_ONLY, S802_Typ.values())), // + ENUM16, true /* mandatory? */, READ_ONLY, S802_Typ.values())), // STATE(new EnumPoint("S802_STATE", "State of the Battery Bank", // "State of the battery bank. Enumeration.", // - EnumPoint.Type.ENUM16, true /* mandatory? */, AccessMode.READ_ONLY, S802_State.values())), // + ENUM16, true /* mandatory? */, READ_ONLY, S802_State.values())), // STATE_VND(new EnumPoint("S802_STATE_VND", "Vendor Battery Bank State", // "Vendor specific battery bank state. Enumeration.", // - EnumPoint.Type.ENUM16, false /* mandatory? */, AccessMode.READ_ONLY, new OptionsEnum[0])), // + ENUM16, false /* mandatory? */, READ_ONLY, new OptionsEnum[0])), // WARR_DT(new ValuePoint("S802_WARR_DT", "Warranty Date", // "Date the device warranty expires.", // - ValuePoint.Type.UINT32, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // + UINT32, false /* mandatory? */, READ_ONLY, Unit.NONE)), // EVT1(new BitFieldPoint("S802_EVT1", "Battery Event 1 Bitfield", // "Alarms and warnings. Bit flags.", // - BitFieldPoint.Type.BITFIELD32, true /* mandatory? */, AccessMode.READ_ONLY, S802_Evt1.values())), // + BITFIELD32, true /* mandatory? */, READ_ONLY, S802_Evt1.values())), // EVT2(new BitFieldPoint("S802_EVT2", "Battery Event 2 Bitfield", // "Alarms and warnings. Bit flags.", // - BitFieldPoint.Type.BITFIELD32, true /* mandatory? */, AccessMode.READ_ONLY, new SunSpecBitPoint[0])), // + BITFIELD32, true /* mandatory? */, READ_ONLY, new SunSpecBitPoint[0])), // EVT_VND1(new BitFieldPoint("S802_EVT_VND1", "Vendor Event Bitfield 1", // "Vendor defined events.", // - BitFieldPoint.Type.BITFIELD32, true /* mandatory? */, AccessMode.READ_ONLY, new SunSpecBitPoint[0])), // + BITFIELD32, true /* mandatory? */, READ_ONLY, new SunSpecBitPoint[0])), // EVT_VND2(new BitFieldPoint("S802_EVT_VND2", "Vendor Event Bitfield 2", // "Vendor defined events.", // - BitFieldPoint.Type.BITFIELD32, true /* mandatory? */, AccessMode.READ_ONLY, new SunSpecBitPoint[0])), // + BITFIELD32, true /* mandatory? */, READ_ONLY, new SunSpecBitPoint[0])), // V(new ScaledValuePoint("S802_V", "External Battery Voltage", // "DC Bus Voltage.", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT, "V_SF")), // + UINT16, true /* mandatory? */, READ_ONLY, Unit.VOLT, "V_SF")), // V_MAX(new ScaledValuePoint("S802_V_MAX", "Max Battery Voltage", // "Instantaneous maximum battery voltage.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT, "V_SF")), // + UINT16, false /* mandatory? */, READ_ONLY, Unit.VOLT, "V_SF")), // V_MIN(new ScaledValuePoint("S802_V_MIN", "Min Battery Voltage", // "Instantaneous minimum battery voltage.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT, "V_SF")), // + UINT16, false /* mandatory? */, READ_ONLY, Unit.VOLT, "V_SF")), // CELL_V_MAX(new ScaledValuePoint("S802_CELL_V_MAX", "Max Cell Voltage", // "Maximum voltage for all cells in the bank.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT, "CellV_SF")), // + UINT16, false /* mandatory? */, READ_ONLY, Unit.VOLT, "CellV_SF")), // CELL_V_MAX_STR(new ValuePoint("S802_CELL_V_MAX_STR", "Max Cell Voltage String", // "String containing the cell with maximum voltage.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // + UINT16, false /* mandatory? */, READ_ONLY, Unit.NONE)), // CELL_V_MAX_MOD(new ValuePoint("S802_CELL_V_MAX_MOD", "Max Cell Voltage Module", // "Module containing the cell with maximum voltage.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // + UINT16, false /* mandatory? */, READ_ONLY, Unit.NONE)), // CELL_V_MIN(new ScaledValuePoint("S802_CELL_V_MIN", "Min Cell Voltage", // "Minimum voltage for all cells in the bank.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT, "CellV_SF")), // + UINT16, false /* mandatory? */, READ_ONLY, Unit.VOLT, "CellV_SF")), // CELL_V_MIN_STR(new ValuePoint("S802_CELL_V_MIN_STR", "Min Cell Voltage String", // "String containing the cell with minimum voltage.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // + UINT16, false /* mandatory? */, READ_ONLY, Unit.NONE)), // CELL_V_MIN_MOD(new ValuePoint("S802_CELL_V_MIN_MOD", "Min Cell Voltage Module", // "Module containing the cell with minimum voltage.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // + UINT16, false /* mandatory? */, READ_ONLY, Unit.NONE)), // CELL_V_AVG(new ScaledValuePoint("S802_CELL_V_AVG", "Average Cell Voltage", // "Average cell voltage for all cells in the bank.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT, "CellV_SF")), // + UINT16, false /* mandatory? */, READ_ONLY, Unit.VOLT, "CellV_SF")), // A(new ScaledValuePoint("S802_A", "Total DC Current", // "Total DC current flowing to/from the battery bank.", // - ValuePoint.Type.INT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.AMPERE, "A_SF")), // + INT16, true /* mandatory? */, READ_ONLY, Unit.AMPERE, "A_SF")), // A_CHA_MAX(new ScaledValuePoint("S802_A_CHA_MAX", "Max Charge Current", // "Instantaneous maximum DC charge current.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.AMPERE, "AMax_SF")), // + UINT16, false /* mandatory? */, READ_ONLY, Unit.AMPERE, "AMax_SF")), // A_DIS_CHA_MAX(new ScaledValuePoint("S802_A_DIS_CHA_MAX", "Max Discharge Current", // "Instantaneous maximum DC discharge current.", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.AMPERE, "AMax_SF")), // + UINT16, false /* mandatory? */, READ_ONLY, Unit.AMPERE, "AMax_SF")), // W(new ScaledValuePoint("S802_W", "Total Power", // "Total power flowing to/from the battery bank.", // - ValuePoint.Type.INT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.WATT, "W_SF")), // + INT16, true /* mandatory? */, READ_ONLY, Unit.WATT, "W_SF")), // REQ_INV_STATE(new EnumPoint("S802_REQ_INV_STATE", "Inverter State Request", // "Request from battery to start or stop the inverter. Enumeration.", // - EnumPoint.Type.ENUM16, false /* mandatory? */, AccessMode.READ_ONLY, S802_ReqInvState.values())), // + ENUM16, false /* mandatory? */, READ_ONLY, S802_ReqInvState.values())), // REQ_W(new ScaledValuePoint("S802_REQ_W", "Battery Power Request", // "AC Power requested by battery.", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.WATT, "W_SF")), // + INT16, false /* mandatory? */, READ_ONLY, Unit.WATT, "W_SF")), // SET_OP(new EnumPoint("S802_SET_OP", "Set Operation", // "Instruct the battery bank to perform an operation such as connecting. Enumeration.", // - EnumPoint.Type.ENUM16, true /* mandatory? */, AccessMode.READ_WRITE, S802_SetOp.values())), // + ENUM16, true /* mandatory? */, READ_WRITE, S802_SetOp.values())), // SET_INV_STATE(new EnumPoint("S802_SET_INV_STATE", "Set Inverter State", // "Set the current state of the inverter.", // - EnumPoint.Type.ENUM16, true /* mandatory? */, AccessMode.READ_WRITE, S802_SetInvState.values())), // + ENUM16, true /* mandatory? */, READ_WRITE, S802_SetInvState.values())), // A_H_RTG_S_F(new ScaleFactorPoint("S802_A_H_RTG_S_F", "", // "Scale factor for charge capacity.")), // W_H_RTG_S_F(new ScaleFactorPoint("S802_W_H_RTG_S_F", "", // @@ -6308,9 +6378,12 @@ public static enum S802_Evt1 implements SunSpecBitPoint { UNDER_TEMP_ALARM(new BitPoint(3, "S802_EVT1_UNDER_TEMP_ALARM", "Under Temp Alarm")), // UNDER_TEMP_WARNING(new BitPoint(4, "S802_EVT1_UNDER_TEMP_WARNING", "Under Temp Warning")), // OVER_CHARGE_CURRENT_ALARM(new BitPoint(5, "S802_EVT1_OVER_CHARGE_CURRENT_ALARM", "Over Charge Current Alarm")), // - OVER_CHARGE_CURRENT_WARNING(new BitPoint(6, "S802_EVT1_OVER_CHARGE_CURRENT_WARNING", "Over Charge Current Warning")), // - OVER_DISCHARGE_CURRENT_ALARM(new BitPoint(7, "S802_EVT1_OVER_DISCHARGE_CURRENT_ALARM", "Over Discharge Current Alarm")), // - OVER_DISCHARGE_CURRENT_WARNING(new BitPoint(8, "S802_EVT1_OVER_DISCHARGE_CURRENT_WARNING", "Over Discharge Current Warning")), // + OVER_CHARGE_CURRENT_WARNING( + new BitPoint(6, "S802_EVT1_OVER_CHARGE_CURRENT_WARNING", "Over Charge Current Warning")), // + OVER_DISCHARGE_CURRENT_ALARM( + new BitPoint(7, "S802_EVT1_OVER_DISCHARGE_CURRENT_ALARM", "Over Discharge Current Alarm")), // + OVER_DISCHARGE_CURRENT_WARNING( + new BitPoint(8, "S802_EVT1_OVER_DISCHARGE_CURRENT_WARNING", "Over Discharge Current Warning")), // OVER_VOLT_ALARM(new BitPoint(9, "S802_EVT1_OVER_VOLT_ALARM", "Over Volt Alarm")), // OVER_VOLT_WARNING(new BitPoint(10, "S802_EVT1_OVER_VOLT_WARNING", "Over Volt Warning")), // UNDER_VOLT_ALARM(new BitPoint(11, "S802_EVT1_UNDER_VOLT_ALARM", "Under Volt Alarm")), // @@ -6320,8 +6393,10 @@ public static enum S802_Evt1 implements SunSpecBitPoint { OVER_SOC_MAX_ALARM(new BitPoint(15, "S802_EVT1_OVER_SOC_MAX_ALARM", "Over Soc Max Alarm")), // OVER_SOC_MAX_WARNING(new BitPoint(16, "S802_EVT1_OVER_SOC_MAX_WARNING", "Over Soc Max Warning")), // VOLTAGE_IMBALANCE_WARNING(new BitPoint(17, "S802_EVT1_VOLTAGE_IMBALANCE_WARNING", "Voltage Imbalance Warning")), // - TEMPERATURE_IMBALANCE_ALARM(new BitPoint(18, "S802_EVT1_TEMPERATURE_IMBALANCE_ALARM", "Temperature Imbalance Alarm")), // - TEMPERATURE_IMBALANCE_WARNING(new BitPoint(19, "S802_EVT1_TEMPERATURE_IMBALANCE_WARNING", "Temperature Imbalance Warning")), // + TEMPERATURE_IMBALANCE_ALARM( + new BitPoint(18, "S802_EVT1_TEMPERATURE_IMBALANCE_ALARM", "Temperature Imbalance Alarm")), // + TEMPERATURE_IMBALANCE_WARNING( + new BitPoint(19, "S802_EVT1_TEMPERATURE_IMBALANCE_WARNING", "Temperature Imbalance Warning")), // CONTACTOR_ERROR(new BitPoint(20, "S802_EVT1_CONTACTOR_ERROR", "Contactor Error")), // FAN_ERROR(new BitPoint(21, "S802_EVT1_FAN_ERROR", "Fan Error")), // GROUND_FAULT(new BitPoint(22, "S802_EVT1_GROUND_FAULT", "Ground Fault")), // @@ -6436,75 +6511,75 @@ public OptionsEnum getUndefined() { public static enum S64001 implements SunSpecPoint { CMD(new EnumPoint("S64001_CMD", "Command Code", "", // - EnumPoint.Type.ENUM16, false /* mandatory? */, AccessMode.READ_WRITE, new OptionsEnum[0])), // + ENUM16, false /* mandatory? */, READ_WRITE, new OptionsEnum[0])), // H_W_REV(new ValuePoint("S64001_H_W_REV", "Hardware Revision", "", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // + UINT16, false /* mandatory? */, READ_ONLY, Unit.NONE)), // R_S_F_W_REV(new ValuePoint("S64001_R_S_F_W_REV", "RS FW Revision", "", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // + UINT16, false /* mandatory? */, READ_ONLY, Unit.NONE)), // O_S_F_W_REV(new ValuePoint("S64001_O_S_F_W_REV", "OS FW Revision", "", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // + UINT16, false /* mandatory? */, READ_ONLY, Unit.NONE)), // PROD_REV(new ValuePoint("S64001_PROD_REV", "Product Revision", "", // - ValuePoint.Type.STRING2, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // + STRING2, false /* mandatory? */, READ_ONLY, Unit.NONE)), // BOOTS(new ValuePoint("S64001_BOOTS", "Boot Count", "", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // + UINT16, false /* mandatory? */, READ_ONLY, Unit.NONE)), // SWITCH(new BitFieldPoint("S64001_SWITCH", "DIP Switches", "", // - BitFieldPoint.Type.BITFIELD16, false /* mandatory? */, AccessMode.READ_ONLY, new SunSpecBitPoint[0])), // + BITFIELD16, false /* mandatory? */, READ_ONLY, new SunSpecBitPoint[0])), // SENSORS(new ValuePoint("S64001_SENSORS", "Num Detected Sensors", "", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // + UINT16, false /* mandatory? */, READ_ONLY, Unit.NONE)), // TALKING(new ValuePoint("S64001_TALKING", "Num Communicating Sensors", "", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // + UINT16, false /* mandatory? */, READ_ONLY, Unit.NONE)), // STATUS(new BitFieldPoint("S64001_STATUS", "System Status", "", // - BitFieldPoint.Type.BITFIELD16, false /* mandatory? */, AccessMode.READ_ONLY, new SunSpecBitPoint[0])), // + BITFIELD16, false /* mandatory? */, READ_ONLY, new SunSpecBitPoint[0])), // CONFIG(new BitFieldPoint("S64001_CONFIG", "System Configuration", "", // - BitFieldPoint.Type.BITFIELD16, false /* mandatory? */, AccessMode.READ_ONLY, new SunSpecBitPoint[0])), // + BITFIELD16, false /* mandatory? */, READ_ONLY, new SunSpecBitPoint[0])), // L_E_DBLINK(new ValuePoint("S64001_L_E_DBLINK", "LED Blink Threshold", "", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // + UINT16, false /* mandatory? */, READ_ONLY, Unit.NONE)), // L_E_DON(new ValuePoint("S64001_L_E_DON", "LED On Threshold", "", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // + UINT16, false /* mandatory? */, READ_ONLY, Unit.NONE)), // RESERVED(new ValuePoint("S64001_RESERVED", "", "", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // + UINT16, false /* mandatory? */, READ_ONLY, Unit.NONE)), // LOC(new ValuePoint("S64001_LOC", "Location String", "", // - ValuePoint.Type.STRING16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // + STRING16, false /* mandatory? */, READ_ONLY, Unit.NONE)), // S1ID(new EnumPoint("S64001_S1ID", "Sensor 1 Unit ID", "", // - EnumPoint.Type.ENUM16, false /* mandatory? */, AccessMode.READ_ONLY, new OptionsEnum[0])), // + ENUM16, false /* mandatory? */, READ_ONLY, new OptionsEnum[0])), // S1_ADDR(new ValuePoint("S64001_S1_ADDR", "Sensor 1 Address", "", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // + UINT16, false /* mandatory? */, READ_ONLY, Unit.NONE)), // S1_O_S_VER(new ValuePoint("S64001_S1_O_S_VER", "Sensor 1 OS Version", "", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // + UINT16, false /* mandatory? */, READ_ONLY, Unit.NONE)), // S1_VER(new ValuePoint("S64001_S1_VER", "Sensor 1 Product Version", "", // - ValuePoint.Type.STRING2, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // + STRING2, false /* mandatory? */, READ_ONLY, Unit.NONE)), // S1_SERIAL(new ValuePoint("S64001_S1_SERIAL", "Sensor 1 Serial Num", "", // - ValuePoint.Type.STRING5, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // + STRING5, false /* mandatory? */, READ_ONLY, Unit.NONE)), // S2ID(new EnumPoint("S64001_S2ID", "Sensor 2 Unit ID", "", // - EnumPoint.Type.ENUM16, false /* mandatory? */, AccessMode.READ_ONLY, new OptionsEnum[0])), // + ENUM16, false /* mandatory? */, READ_ONLY, new OptionsEnum[0])), // S2_ADDR(new ValuePoint("S64001_S2_ADDR", "Sensor 2 Address", "", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // + UINT16, false /* mandatory? */, READ_ONLY, Unit.NONE)), // S2_O_S_VER(new ValuePoint("S64001_S2_O_S_VER", "Sensor 2 OS Version", "", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // + UINT16, false /* mandatory? */, READ_ONLY, Unit.NONE)), // S2_VER(new ValuePoint("S64001_S2_VER", "Sensor 2 Product Version", "", // - ValuePoint.Type.STRING2, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // + STRING2, false /* mandatory? */, READ_ONLY, Unit.NONE)), // S2_SERIAL(new ValuePoint("S64001_S2_SERIAL", "Sensor 2 Serial Num", "", // - ValuePoint.Type.STRING5, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // + STRING5, false /* mandatory? */, READ_ONLY, Unit.NONE)), // S3ID(new EnumPoint("S64001_S3ID", "Sensor 3 Unit ID", "", // - EnumPoint.Type.ENUM16, false /* mandatory? */, AccessMode.READ_ONLY, new OptionsEnum[0])), // + ENUM16, false /* mandatory? */, READ_ONLY, new OptionsEnum[0])), // S3_ADDR(new ValuePoint("S64001_S3_ADDR", "Sensor 3 Address", "", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // + UINT16, false /* mandatory? */, READ_ONLY, Unit.NONE)), // S3_O_S_VER(new ValuePoint("S64001_S3_O_S_VER", "Sensor 3 OS Version", "", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // + UINT16, false /* mandatory? */, READ_ONLY, Unit.NONE)), // S3_VER(new ValuePoint("S64001_S3_VER", "Sensor 3 Product Version", "", // - ValuePoint.Type.STRING2, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // + STRING2, false /* mandatory? */, READ_ONLY, Unit.NONE)), // S3_SERIAL(new ValuePoint("S64001_S3_SERIAL", "Sensor 3 Serial Num", "", // - ValuePoint.Type.STRING5, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // + STRING5, false /* mandatory? */, READ_ONLY, Unit.NONE)), // S4ID(new EnumPoint("S64001_S4ID", "Sensor 4 Unit ID", "", // - EnumPoint.Type.ENUM16, false /* mandatory? */, AccessMode.READ_ONLY, new OptionsEnum[0])), // + ENUM16, false /* mandatory? */, READ_ONLY, new OptionsEnum[0])), // S4_ADDR(new ValuePoint("S64001_S4_ADDR", "Sensor 4 Address", "", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // + UINT16, false /* mandatory? */, READ_ONLY, Unit.NONE)), // S4_O_S_VER(new ValuePoint("S64001_S4_O_S_VER", "Sensor 4 OS Version", "", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // + UINT16, false /* mandatory? */, READ_ONLY, Unit.NONE)), // S4_VER(new ValuePoint("S64001_S4_VER", "Sensor 4 Product Version", "", // - ValuePoint.Type.STRING2, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // + STRING2, false /* mandatory? */, READ_ONLY, Unit.NONE)), // S4_SERIAL(new ValuePoint("S64001_S4_SERIAL", "Sensor 4 Serial Num", "", // - ValuePoint.Type.STRING5, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)); + STRING5, false /* mandatory? */, READ_ONLY, Unit.NONE)); private final Point point; @@ -6520,19 +6595,19 @@ public Point get() { public static enum S64101 implements SunSpecPoint { ELTEK_COUNTRY_CODE(new ValuePoint("S64101_ELTEK_COUNTRY_CODE", "", "", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // + UINT16, false /* mandatory? */, READ_ONLY, Unit.NONE)), // ELTEK_FEEDING_PHASE(new ValuePoint("S64101_ELTEK_FEEDING_PHASE", "", "", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // + UINT16, false /* mandatory? */, READ_ONLY, Unit.NONE)), // ELTEK_A_P_D_METHOD(new ValuePoint("S64101_ELTEK_A_P_D_METHOD", "", "", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // + UINT16, false /* mandatory? */, READ_ONLY, Unit.NONE)), // ELTEK_A_P_D_POWER_REF(new ValuePoint("S64101_ELTEK_A_P_D_POWER_REF", "", "", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // + UINT16, false /* mandatory? */, READ_ONLY, Unit.NONE)), // ELTEK_R_P_S_METHOD(new ValuePoint("S64101_ELTEK_R_P_S_METHOD", "", "", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // + UINT16, false /* mandatory? */, READ_ONLY, Unit.NONE)), // ELTEK_R_P_S_Q_REF(new ValuePoint("S64101_ELTEK_R_P_S_Q_REF", "", "", // - ValuePoint.Type.UINT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // + UINT16, false /* mandatory? */, READ_ONLY, Unit.NONE)), // ELTEK_R_P_S_COS_PHI_REF(new ValuePoint("S64101_ELTEK_R_P_S_COS_PHI_REF", "", "", // - ValuePoint.Type.INT16, false /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)); + INT16, false /* mandatory? */, READ_ONLY, Unit.NONE)); private final Point point; @@ -6548,46 +6623,46 @@ public Point get() { public static enum S64111 implements SunSpecPoint { PORT(new ValuePoint("S64111_PORT", "Port Number", "", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // + UINT16, true /* mandatory? */, READ_ONLY, Unit.NONE)), // V_SF(new ScaleFactorPoint("S64111_V_SF", "", "")), // A_SF(new ScaleFactorPoint("S64111_A_SF", "", "")), // P_SF(new ScaleFactorPoint("S64111_P_SF", "", "")), // AH_SF(new ScaleFactorPoint("S64111_AH_SF", "", "")), // KWH_SF(new ScaleFactorPoint("S64111_KWH_SF", "", "")), // BATT_V(new ScaledValuePoint("S64111_BATT_V", "Battery Voltage", "", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT, "V_SF")), // + UINT16, true /* mandatory? */, READ_ONLY, Unit.VOLT, "V_SF")), // ARRAY_V(new ScaledValuePoint("S64111_ARRAY_V", "Array Voltage", "", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT, "V_SF")), // + UINT16, true /* mandatory? */, READ_ONLY, Unit.VOLT, "V_SF")), // OUTPUT_A(new ScaledValuePoint("S64111_OUTPUT_A", "Output Current", "", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.AMPERE, "A_SF")), // + UINT16, true /* mandatory? */, READ_ONLY, Unit.AMPERE, "A_SF")), // INPUT_A(new ScaledValuePoint("S64111_INPUT_A", "Array Current", "", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.AMPERE, "P_SF")), // + UINT16, true /* mandatory? */, READ_ONLY, Unit.AMPERE, "P_SF")), // CHARGER_ST(new EnumPoint("S64111_CHARGER_ST", "Operating State", "", // - EnumPoint.Type.ENUM16, true /* mandatory? */, AccessMode.READ_ONLY, S64111_ChargerSt.values())), // + ENUM16, true /* mandatory? */, READ_ONLY, S64111_ChargerSt.values())), // OUTPUT_W(new ScaledValuePoint("S64111_OUTPUT_W", "Output Wattage", "", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.WATT, "P_SF")), // + UINT16, true /* mandatory? */, READ_ONLY, Unit.WATT, "P_SF")), // TODAY_MIN_BAT_V(new ScaledValuePoint("S64111_TODAY_MIN_BAT_V", "Today's Minimum Battery Voltage", "", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT, "V_SF")), // + UINT16, true /* mandatory? */, READ_ONLY, Unit.VOLT, "V_SF")), // TODAY_MAX_BAT_V(new ScaledValuePoint("S64111_TODAY_MAX_BAT_V", "Today's Maximum Battery Voltage", "", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT, "V_SF")), // + UINT16, true /* mandatory? */, READ_ONLY, Unit.VOLT, "V_SF")), // VOCV(new ScaledValuePoint("S64111_VOCV", "VOC", "", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT, "V_SF")), // + UINT16, true /* mandatory? */, READ_ONLY, Unit.VOLT, "V_SF")), // TODAY_MAX_V_O_C(new ScaledValuePoint("S64111_TODAY_MAX_V_O_C", "Today's Maximum VOC", "", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT, "V_SF")), // + UINT16, true /* mandatory? */, READ_ONLY, Unit.VOLT, "V_SF")), // TODAYK_WH_OUTPUT(new ScaledValuePoint("S64111_TODAYK_WH_OUTPUT", "Today's kWh", "", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.KILOWATT_HOURS, "KWH_SF")), // + UINT16, true /* mandatory? */, READ_ONLY, Unit.KILOWATT_HOURS, "KWH_SF")), // TODAY_A_H_OUTPUT(new ScaledValuePoint("S64111_TODAY_A_H_OUTPUT", "Today's AH", "", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.AMPERE_HOURS, "AH_SF")), // + UINT16, true /* mandatory? */, READ_ONLY, Unit.AMPERE_HOURS, "AH_SF")), // LIFE_TIME_K_W_H_OUT(new ScaledValuePoint("S64111_LIFE_TIME_K_W_H_OUT", "Lifetime kWh", "", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.KILOWATT_HOURS, "P_SF")), // + UINT16, true /* mandatory? */, READ_ONLY, Unit.KILOWATT_HOURS, "P_SF")), // LIFE_TIME_A_H_OUT(new ScaledValuePoint("S64111_LIFE_TIME_A_H_OUT", "Lifetime kAH", "", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.KILOAMPERE_HOURS, "KWH_SF")), // + UINT16, true /* mandatory? */, READ_ONLY, Unit.KILOAMPERE_HOURS, "KWH_SF")), // LIFE_TIME_MAX_OUT(new ScaledValuePoint("S64111_LIFE_TIME_MAX_OUT", "Lifetime Maximum Output Wattage", "", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.WATT, "P_SF")), // + UINT16, true /* mandatory? */, READ_ONLY, Unit.WATT, "P_SF")), // LIFE_TIME_MAX_BATT(new ScaledValuePoint("S64111_LIFE_TIME_MAX_BATT", "Lifetime Maximum Battery Voltage", "", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT, "V_SF")), // + UINT16, true /* mandatory? */, READ_ONLY, Unit.VOLT, "V_SF")), // LIFE_TIME_MAX_V_O_C(new ScaledValuePoint("S64111_LIFE_TIME_MAX_V_O_C", "Lifetime Maximum VOC Voltage", "", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT, "V_SF")); + UINT16, true /* mandatory? */, READ_ONLY, Unit.VOLT, "V_SF")); private final Point point; @@ -6635,7 +6710,7 @@ public OptionsEnum getUndefined() { public static enum S64112 implements SunSpecPoint { PORT(new ValuePoint("S64112_PORT", "Port Number", "", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // + UINT16, true /* mandatory? */, READ_ONLY, Unit.NONE)), // V_SF(new ScaleFactorPoint("S64112_V_SF", "", "")), // C_SF(new ScaleFactorPoint("S64112_C_SF", "", "")), // H_SF(new ScaleFactorPoint("S64112_H_SF", "", "")), // @@ -6643,119 +6718,147 @@ public static enum S64112 implements SunSpecPoint { AH_SF(new ScaleFactorPoint("S64112_AH_SF", "", "")), // KWH_SF(new ScaleFactorPoint("S64112_KWH_SF", "", "")), // C_C_CONFIG_FAULT(new BitFieldPoint("S64112_C_C_CONFIG_FAULT", "Faults", "", // - BitFieldPoint.Type.BITFIELD16, true /* mandatory? */, AccessMode.READ_ONLY, new SunSpecBitPoint[0])), // + BITFIELD16, true /* mandatory? */, READ_ONLY, new SunSpecBitPoint[0])), // C_C_CONFIG_ABSORB_V(new ScaledValuePoint("S64112_C_C_CONFIG_ABSORB_V", "Absorb", "", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT, "V_SF")), // + UINT16, true /* mandatory? */, READ_ONLY, Unit.VOLT, "V_SF")), // C_C_CONFIG_ABSORB_HR(new ScaledValuePoint("S64112_C_C_CONFIG_ABSORB_HR", "Absorb Time", "", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE, "H_SF")), // + UINT16, true /* mandatory? */, READ_ONLY, Unit.NONE, "H_SF")), // C_C_CONFIG_ABSORB_END_A(new ScaledValuePoint("S64112_C_C_CONFIG_ABSORB_END_A", "Absorb End", "", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.AMPERE, "V_SF")), // + UINT16, true /* mandatory? */, READ_ONLY, Unit.AMPERE, "V_SF")), // C_C_CONFIG_REBULK_V(new ScaledValuePoint("S64112_C_C_CONFIG_REBULK_V", "Rebulk", "", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT, "V_SF")), // + UINT16, true /* mandatory? */, READ_ONLY, Unit.VOLT, "V_SF")), // C_C_CONFIG_FLOAT_V(new ScaledValuePoint("S64112_C_C_CONFIG_FLOAT_V", "Float", "", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT, "V_SF")), // + UINT16, true /* mandatory? */, READ_ONLY, Unit.VOLT, "V_SF")), // C_C_CONFIG_MAX_CHG_A(new ScaledValuePoint("S64112_C_C_CONFIG_MAX_CHG_A", "Maximum Charge", "", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.AMPERE, "V_SF")), // + UINT16, true /* mandatory? */, READ_ONLY, Unit.AMPERE, "V_SF")), // C_C_CONFIG_EQUALIZE_V(new ScaledValuePoint("S64112_C_C_CONFIG_EQUALIZE_V", "Equalize", "", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT, "V_SF")), // + UINT16, true /* mandatory? */, READ_ONLY, Unit.VOLT, "V_SF")), // C_C_CONFIG_EQUALIZE_HR(new ValuePoint("S64112_C_C_CONFIG_EQUALIZE_HR", "Equalize Time", "", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // + UINT16, true /* mandatory? */, READ_ONLY, Unit.NONE)), // C_C_CONFIG_AUTO_EQUALIZE(new ValuePoint("S64112_C_C_CONFIG_AUTO_EQUALIZE", "Auto Equalize Interval", "", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // + UINT16, true /* mandatory? */, READ_ONLY, Unit.NONE)), // C_C_CONFIG_M_P_P_T_MODE(new EnumPoint("S64112_C_C_CONFIG_M_P_P_T_MODE", "MPPT mode", "", // - EnumPoint.Type.ENUM16, true /* mandatory? */, AccessMode.READ_ONLY, S64112_CC_Config_MPPT_mode.values())), // + ENUM16, true /* mandatory? */, READ_ONLY, S64112_CC_Config_MPPT_mode.values())), // C_C_CONFIG_SWEEP_WIDTH(new EnumPoint("S64112_C_C_CONFIG_SWEEP_WIDTH", "Sweep Width", "", // - EnumPoint.Type.ENUM16, true /* mandatory? */, AccessMode.READ_ONLY, S64112_CC_Config_sweep_width.values())), // + ENUM16, true /* mandatory? */, READ_ONLY, S64112_CC_Config_sweep_width.values())), // C_C_CONFIG_SWEEP_MAX(new EnumPoint("S64112_C_C_CONFIG_SWEEP_MAX", "Sweep Maximum", "", // - EnumPoint.Type.ENUM16, true /* mandatory? */, AccessMode.READ_ONLY, S64112_CC_Config_sweep_max.values())), // - C_C_CONFIG_U_PICK_DUTY_CYC(new ScaledValuePoint("S64112_C_C_CONFIG_U_PICK_DUTY_CYC", "U-Pick PWM Duty Cycle", "", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE, "V_SF")), // + ENUM16, true /* mandatory? */, READ_ONLY, S64112_CC_Config_sweep_max.values())), // + C_C_CONFIG_U_PICK_DUTY_CYC( + new ScaledValuePoint("S64112_C_C_CONFIG_U_PICK_DUTY_CYC", "U-Pick PWM Duty Cycle", "", // + UINT16, true /* mandatory? */, READ_ONLY, Unit.NONE, "V_SF")), // C_C_CONFIG_GRID_TIE(new EnumPoint("S64112_C_C_CONFIG_GRID_TIE", "Grid Tie Mode", "", // - EnumPoint.Type.ENUM16, true /* mandatory? */, AccessMode.READ_ONLY, S64112_CC_Config_grid_tie.values())), // + ENUM16, true /* mandatory? */, READ_ONLY, S64112_CC_Config_grid_tie.values())), // C_C_CONFIG_TEMP_COMP(new EnumPoint("S64112_C_C_CONFIG_TEMP_COMP", "Temp Comp Mode", "", // - EnumPoint.Type.ENUM16, true /* mandatory? */, AccessMode.READ_ONLY, S64112_CC_Config_temp_comp.values())), // - C_C_CONFIG_TEMP_COMP_LLIMT(new ScaledValuePoint("S64112_C_C_CONFIG_TEMP_COMP_LLIMT", "Temp Comp Lower Limit", "", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT, "V_SF")), // - C_C_CONFIG_TEMP_COMP_HLIMT(new ScaledValuePoint("S64112_C_C_CONFIG_TEMP_COMP_HLIMT", "Temp Comp Upper Limit", "", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT, "V_SF")), // + ENUM16, true /* mandatory? */, READ_ONLY, S64112_CC_Config_temp_comp.values())), // + C_C_CONFIG_TEMP_COMP_LLIMT( + new ScaledValuePoint("S64112_C_C_CONFIG_TEMP_COMP_LLIMT", "Temp Comp Lower Limit", "", // + UINT16, true /* mandatory? */, READ_ONLY, Unit.VOLT, "V_SF")), // + C_C_CONFIG_TEMP_COMP_HLIMT( + new ScaledValuePoint("S64112_C_C_CONFIG_TEMP_COMP_HLIMT", "Temp Comp Upper Limit", "", // + UINT16, true /* mandatory? */, READ_ONLY, Unit.VOLT, "V_SF")), // C_C_CONFIG_AUTO_RESTART(new EnumPoint("S64112_C_C_CONFIG_AUTO_RESTART", "Auto Restart Mode", "", // - EnumPoint.Type.ENUM16, true /* mandatory? */, AccessMode.READ_ONLY, S64112_CC_Config_auto_restart.values())), // + ENUM16, true /* mandatory? */, READ_ONLY, S64112_CC_Config_auto_restart.values())), // C_C_CONFIG_WAKEUP_V_O_C(new ScaledValuePoint("S64112_C_C_CONFIG_WAKEUP_V_O_C", "Wakeup VOC Change", "", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT, "V_SF")), // + UINT16, true /* mandatory? */, READ_ONLY, Unit.VOLT, "V_SF")), // C_C_CONFIG_SNOOZE_MODE_A(new ScaledValuePoint("S64112_C_C_CONFIG_SNOOZE_MODE_A", "Snooze Mode", "", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.AMPERE, "V_SF")), // + UINT16, true /* mandatory? */, READ_ONLY, Unit.AMPERE, "V_SF")), // C_C_CONFIG_WAKEUP_INTERVAL(new ValuePoint("S64112_C_C_CONFIG_WAKEUP_INTERVAL", "Wakeup Interval", "", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // + UINT16, true /* mandatory? */, READ_ONLY, Unit.NONE)), // C_C_CONFIG_A_U_X_MODE(new EnumPoint("S64112_C_C_CONFIG_A_U_X_MODE", "AUX Output Mode", "", // - EnumPoint.Type.ENUM16, true /* mandatory? */, AccessMode.READ_ONLY, S64112_CC_Config_AUX_mode.values())), // + ENUM16, true /* mandatory? */, READ_ONLY, S64112_CC_Config_AUX_mode.values())), // C_C_CONFIG_A_U_X_CONTROL(new EnumPoint("S64112_C_C_CONFIG_A_U_X_CONTROL", "AUX Output Control", "", // - EnumPoint.Type.ENUM16, true /* mandatory? */, AccessMode.READ_ONLY, S64112_CC_Config_AUX_control.values())), // + ENUM16, true /* mandatory? */, READ_ONLY, S64112_CC_Config_AUX_control.values())), // C_C_CONFIG_A_U_X_STATE(new EnumPoint("S64112_C_C_CONFIG_A_U_X_STATE", "AUX Output State", "", // - EnumPoint.Type.ENUM16, true /* mandatory? */, AccessMode.READ_ONLY, S64112_CC_Config_AUX_state.values())), // + ENUM16, true /* mandatory? */, READ_ONLY, S64112_CC_Config_AUX_state.values())), // C_C_CONFIG_A_U_X_POLARITY(new EnumPoint("S64112_C_C_CONFIG_A_U_X_POLARITY", "AUX Output Polarity", "", // - EnumPoint.Type.ENUM16, true /* mandatory? */, AccessMode.READ_ONLY, S64112_CC_Config_AUX_polarity.values())), // - C_C_CONFIG_A_U_X_L_BATT_DISC(new ScaledValuePoint("S64112_C_C_CONFIG_A_U_X_L_BATT_DISC", "AUX Low Battery Disconnect", "", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT, "V_SF")), // - C_C_CONFIG_A_U_X_L_BATT_RCON(new ScaledValuePoint("S64112_C_C_CONFIG_A_U_X_L_BATT_RCON", "AUX Low Battery Reconnect", "", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT, "V_SF")), // - C_C_CONFIG_A_U_X_L_BATT_DLY(new ValuePoint("S64112_C_C_CONFIG_A_U_X_L_BATT_DLY", "AUX Low Battery Disconnect Delay", "", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // + ENUM16, true /* mandatory? */, READ_ONLY, S64112_CC_Config_AUX_polarity.values())), // + C_C_CONFIG_A_U_X_L_BATT_DISC( + new ScaledValuePoint("S64112_C_C_CONFIG_A_U_X_L_BATT_DISC", "AUX Low Battery Disconnect", "", // + UINT16, true /* mandatory? */, READ_ONLY, Unit.VOLT, "V_SF")), // + C_C_CONFIG_A_U_X_L_BATT_RCON( + new ScaledValuePoint("S64112_C_C_CONFIG_A_U_X_L_BATT_RCON", "AUX Low Battery Reconnect", "", // + UINT16, true /* mandatory? */, READ_ONLY, Unit.VOLT, "V_SF")), // + C_C_CONFIG_A_U_X_L_BATT_DLY( + new ValuePoint("S64112_C_C_CONFIG_A_U_X_L_BATT_DLY", "AUX Low Battery Disconnect Delay", "", // + UINT16, true /* mandatory? */, READ_ONLY, Unit.NONE)), // C_C_CONFIG_A_U_X_VENT_FAN_V(new ScaledValuePoint("S64112_C_C_CONFIG_A_U_X_VENT_FAN_V", "AUX Vent Fan", "", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT, "V_SF")), // - C_C_CONFIG_A_U_X_P_V_TRIGGER_V(new ScaledValuePoint("S64112_C_C_CONFIG_A_U_X_P_V_TRIGGER_V", "AUX PV Trigger", "", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT, "V_SF")), // - C_C_CONFIG_A_U_X_P_V_TRG_H_TM(new ValuePoint("S64112_C_C_CONFIG_A_U_X_P_V_TRG_H_TM", "AUX PV Trigger Hold Time", "", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // - C_C_CONFIG_A_U_X_NLITE_THRS_V(new ScaledValuePoint("S64112_C_C_CONFIG_A_U_X_NLITE_THRS_V", "AUX Night Light Threshold", "", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT, "V_SF")), // - C_C_CONFIG_A_U_X_NLITE_ON_TM(new ScaledValuePoint("S64112_C_C_CONFIG_A_U_X_NLITE_ON_TM", "AUX Night Light On Time", "", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE, "H_SF")), // - C_C_CONFIG_A_U_X_NLITE_ON_HIST(new ValuePoint("S64112_C_C_CONFIG_A_U_X_NLITE_ON_HIST", "AUX Night Light On Hysteresis", "", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // - C_C_CONFIG_A_U_X_NLITE_OFF_HIST(new ValuePoint("S64112_C_C_CONFIG_A_U_X_NLITE_OFF_HIST", "AUX Night Light Off Hysteresis", "", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // - C_C_CONFIG_A_U_X_ERROR_BATT_V(new ScaledValuePoint("S64112_C_C_CONFIG_A_U_X_ERROR_BATT_V", "AUX Error Output Low Battery", "", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT, "V_SF")), // - C_C_CONFIG_A_U_X_DIVERT_H_TIME(new ScaledValuePoint("S64112_C_C_CONFIG_A_U_X_DIVERT_H_TIME", "AUX Divert Hold Time", "", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE, "V_SF")), // - C_C_CONFIG_A_U_X_DIVERT_DLY_TIME(new ValuePoint("S64112_C_C_CONFIG_A_U_X_DIVERT_DLY_TIME", "AUX Divert Delay Time", "", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // - C_C_CONFIG_A_U_X_DIVERT_REL_V(new ScaledValuePoint("S64112_C_C_CONFIG_A_U_X_DIVERT_REL_V", "AUX Divert Relative", "", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT, "V_SF")), // - C_C_CONFIG_A_U_X_DIVERT_HYST_V(new ScaledValuePoint("S64112_C_C_CONFIG_A_U_X_DIVERT_HYST_V", "AUX Divert Hysteresis", "", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT, "V_SF")), // + UINT16, true /* mandatory? */, READ_ONLY, Unit.VOLT, "V_SF")), // + C_C_CONFIG_A_U_X_P_V_TRIGGER_V( + new ScaledValuePoint("S64112_C_C_CONFIG_A_U_X_P_V_TRIGGER_V", "AUX PV Trigger", "", // + UINT16, true /* mandatory? */, READ_ONLY, Unit.VOLT, "V_SF")), // + C_C_CONFIG_A_U_X_P_V_TRG_H_TM( + new ValuePoint("S64112_C_C_CONFIG_A_U_X_P_V_TRG_H_TM", "AUX PV Trigger Hold Time", "", // + UINT16, true /* mandatory? */, READ_ONLY, Unit.NONE)), // + C_C_CONFIG_A_U_X_NLITE_THRS_V( + new ScaledValuePoint("S64112_C_C_CONFIG_A_U_X_NLITE_THRS_V", "AUX Night Light Threshold", "", // + UINT16, true /* mandatory? */, READ_ONLY, Unit.VOLT, "V_SF")), // + C_C_CONFIG_A_U_X_NLITE_ON_TM( + new ScaledValuePoint("S64112_C_C_CONFIG_A_U_X_NLITE_ON_TM", "AUX Night Light On Time", "", // + UINT16, true /* mandatory? */, READ_ONLY, Unit.NONE, "H_SF")), // + C_C_CONFIG_A_U_X_NLITE_ON_HIST( + new ValuePoint("S64112_C_C_CONFIG_A_U_X_NLITE_ON_HIST", "AUX Night Light On Hysteresis", "", // + UINT16, true /* mandatory? */, READ_ONLY, Unit.NONE)), // + C_C_CONFIG_A_U_X_NLITE_OFF_HIST( + new ValuePoint("S64112_C_C_CONFIG_A_U_X_NLITE_OFF_HIST", "AUX Night Light Off Hysteresis", "", // + UINT16, true /* mandatory? */, READ_ONLY, Unit.NONE)), // + C_C_CONFIG_A_U_X_ERROR_BATT_V( + new ScaledValuePoint("S64112_C_C_CONFIG_A_U_X_ERROR_BATT_V", "AUX Error Output Low Battery", "", // + UINT16, true /* mandatory? */, READ_ONLY, Unit.VOLT, "V_SF")), // + C_C_CONFIG_A_U_X_DIVERT_H_TIME( + new ScaledValuePoint("S64112_C_C_CONFIG_A_U_X_DIVERT_H_TIME", "AUX Divert Hold Time", "", // + UINT16, true /* mandatory? */, READ_ONLY, Unit.NONE, "V_SF")), // + C_C_CONFIG_A_U_X_DIVERT_DLY_TIME( + new ValuePoint("S64112_C_C_CONFIG_A_U_X_DIVERT_DLY_TIME", "AUX Divert Delay Time", "", // + UINT16, true /* mandatory? */, READ_ONLY, Unit.NONE)), // + C_C_CONFIG_A_U_X_DIVERT_REL_V( + new ScaledValuePoint("S64112_C_C_CONFIG_A_U_X_DIVERT_REL_V", "AUX Divert Relative", "", // + UINT16, true /* mandatory? */, READ_ONLY, Unit.VOLT, "V_SF")), // + C_C_CONFIG_A_U_X_DIVERT_HYST_V( + new ScaledValuePoint("S64112_C_C_CONFIG_A_U_X_DIVERT_HYST_V", "AUX Divert Hysteresis", "", // + UINT16, true /* mandatory? */, READ_ONLY, Unit.VOLT, "V_SF")), // C_C_CONFIG_MAJOR_F_W_REV(new ValuePoint("S64112_C_C_CONFIG_MAJOR_F_W_REV", "FM CC Major Firmware Number", "", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // + UINT16, true /* mandatory? */, READ_ONLY, Unit.NONE)), // C_C_CONFIG_MID_F_W_REV(new ValuePoint("S64112_C_C_CONFIG_MID_F_W_REV", "FM CC Mid Firmware Number", "", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // + UINT16, true /* mandatory? */, READ_ONLY, Unit.NONE)), // C_C_CONFIG_MINOR_F_W_REV(new ValuePoint("S64112_C_C_CONFIG_MINOR_F_W_REV", "FM CC Minor Firmware Number", "", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // - C_C_CONFIG_DATA_LOG_DAY_OFFSET(new ValuePoint("S64112_C_C_CONFIG_DATA_LOG_DAY_OFFSET", "Set Data Log Day Offset", "", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // - C_C_CONFIG_DATA_LOG_CUR_DAY_OFF(new ValuePoint("S64112_C_C_CONFIG_DATA_LOG_CUR_DAY_OFF", "Current Data Log Day Offset", "", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // + UINT16, true /* mandatory? */, READ_ONLY, Unit.NONE)), // + C_C_CONFIG_DATA_LOG_DAY_OFFSET( + new ValuePoint("S64112_C_C_CONFIG_DATA_LOG_DAY_OFFSET", "Set Data Log Day Offset", "", // + UINT16, true /* mandatory? */, READ_ONLY, Unit.NONE)), // + C_C_CONFIG_DATA_LOG_CUR_DAY_OFF( + new ValuePoint("S64112_C_C_CONFIG_DATA_LOG_CUR_DAY_OFF", "Current Data Log Day Offset", "", // + UINT16, true /* mandatory? */, READ_ONLY, Unit.NONE)), // C_C_CONFIG_DATA_LOG_DAILY_A_H(new ValuePoint("S64112_C_C_CONFIG_DATA_LOG_DAILY_A_H", "Data Log Daily (Ah)", "", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.AMPERE_HOURS)), // - C_C_CONFIG_DATA_LOG_DAILY_K_W_H(new ScaledValuePoint("S64112_C_C_CONFIG_DATA_LOG_DAILY_K_W_H", "Data Log Daily (kWh)", "", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.KILOWATT_HOURS, "KWH_SF")), // - C_C_CONFIG_DATA_LOG_MAX_OUT_A(new ScaledValuePoint("S64112_C_C_CONFIG_DATA_LOG_MAX_OUT_A", "Data Log Daily Maximum Output (A)", "", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.AMPERE, "V_SF")), // - C_C_CONFIG_DATA_LOG_MAX_OUT_W(new ScaledValuePoint("S64112_C_C_CONFIG_DATA_LOG_MAX_OUT_W", "Data Log Daily Maximum Output (W)", "", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.WATT, "V_SF")), // - C_C_CONFIG_DATA_LOG_ABSORB_T(new ValuePoint("S64112_C_C_CONFIG_DATA_LOG_ABSORB_T", "Data Log Daily Absorb Time", "", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // - C_C_CONFIG_DATA_LOG_FLOAT_T(new ValuePoint("S64112_C_C_CONFIG_DATA_LOG_FLOAT_T", "Data Log Daily Float Time", "", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // - C_C_CONFIG_DATA_LOG_MIN_BATT_V(new ScaledValuePoint("S64112_C_C_CONFIG_DATA_LOG_MIN_BATT_V", "Data Log Daily Minimum Battery", "", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT, "V_SF")), // - C_C_CONFIG_DATA_LOG_MAX_BATT_V(new ScaledValuePoint("S64112_C_C_CONFIG_DATA_LOG_MAX_BATT_V", "Data Log Daily Maximum Battery", "", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT, "V_SF")), // - C_C_CONFIG_DATA_LOG_MAX_INPUT_V(new ScaledValuePoint("S64112_C_C_CONFIG_DATA_LOG_MAX_INPUT_V", "Data Log Daily Maximum Input", "", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.VOLT, "V_SF")), // + UINT16, true /* mandatory? */, READ_ONLY, Unit.AMPERE_HOURS)), // + C_C_CONFIG_DATA_LOG_DAILY_K_W_H( + new ScaledValuePoint("S64112_C_C_CONFIG_DATA_LOG_DAILY_K_W_H", "Data Log Daily (kWh)", "", // + UINT16, true /* mandatory? */, READ_ONLY, Unit.KILOWATT_HOURS, "KWH_SF")), // + C_C_CONFIG_DATA_LOG_MAX_OUT_A( + new ScaledValuePoint("S64112_C_C_CONFIG_DATA_LOG_MAX_OUT_A", "Data Log Daily Maximum Output (A)", "", // + UINT16, true /* mandatory? */, READ_ONLY, Unit.AMPERE, "V_SF")), // + C_C_CONFIG_DATA_LOG_MAX_OUT_W( + new ScaledValuePoint("S64112_C_C_CONFIG_DATA_LOG_MAX_OUT_W", "Data Log Daily Maximum Output (W)", "", // + UINT16, true /* mandatory? */, READ_ONLY, Unit.WATT, "V_SF")), // + C_C_CONFIG_DATA_LOG_ABSORB_T( + new ValuePoint("S64112_C_C_CONFIG_DATA_LOG_ABSORB_T", "Data Log Daily Absorb Time", "", // + UINT16, true /* mandatory? */, READ_ONLY, Unit.NONE)), // + C_C_CONFIG_DATA_LOG_FLOAT_T( + new ValuePoint("S64112_C_C_CONFIG_DATA_LOG_FLOAT_T", "Data Log Daily Float Time", "", // + UINT16, true /* mandatory? */, READ_ONLY, Unit.NONE)), // + C_C_CONFIG_DATA_LOG_MIN_BATT_V( + new ScaledValuePoint("S64112_C_C_CONFIG_DATA_LOG_MIN_BATT_V", "Data Log Daily Minimum Battery", "", // + UINT16, true /* mandatory? */, READ_ONLY, Unit.VOLT, "V_SF")), // + C_C_CONFIG_DATA_LOG_MAX_BATT_V( + new ScaledValuePoint("S64112_C_C_CONFIG_DATA_LOG_MAX_BATT_V", "Data Log Daily Maximum Battery", "", // + UINT16, true /* mandatory? */, READ_ONLY, Unit.VOLT, "V_SF")), // + C_C_CONFIG_DATA_LOG_MAX_INPUT_V( + new ScaledValuePoint("S64112_C_C_CONFIG_DATA_LOG_MAX_INPUT_V", "Data Log Daily Maximum Input", "", // + UINT16, true /* mandatory? */, READ_ONLY, Unit.VOLT, "V_SF")), // C_C_CONFIG_DATA_LOG_CLEAR(new ValuePoint("S64112_C_C_CONFIG_DATA_LOG_CLEAR", "Data Log Clear", "", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)), // - C_C_CONFIG_DATA_LOG_CLR_COMP(new ValuePoint("S64112_C_C_CONFIG_DATA_LOG_CLR_COMP", "Data Log Clear Complement", "", // - ValuePoint.Type.UINT16, true /* mandatory? */, AccessMode.READ_ONLY, Unit.NONE)); + UINT16, true /* mandatory? */, READ_ONLY, Unit.NONE)), // + C_C_CONFIG_DATA_LOG_CLR_COMP( + new ValuePoint("S64112_C_C_CONFIG_DATA_LOG_CLR_COMP", "Data Log Clear Complement", "", // + UINT16, true /* mandatory? */, READ_ONLY, Unit.NONE)); private final Point point; diff --git a/io.openems.edge.bridge.modbus/src/io/openems/edge/bridge/modbus/sunspec/Point.java b/io.openems.edge.bridge.modbus/src/io/openems/edge/bridge/modbus/sunspec/Point.java index 9f43d5aadcb..3de0bddcc5e 100644 --- a/io.openems.edge.bridge.modbus/src/io/openems/edge/bridge/modbus/sunspec/Point.java +++ b/io.openems.edge.bridge.modbus/src/io/openems/edge/bridge/modbus/sunspec/Point.java @@ -172,12 +172,14 @@ public ValuePoint(String name, String label, String description, ValuePoint.Type this(name, label, description, type, mandatory, accessMode, unit, // Doc.of(// switch (type) { - case UINT16, ACC16, INT16, COUNT, INT32, PAD, // ignore - EUI48, FLOAT32 // avoid floating point numbers; FLOAT32 might not fit in INTEGER + case UINT16, ACC16, INT16, COUNT, INT32, PAD, EUI48 // -> OpenemsType.INTEGER; - case ACC32, IPADDR, UINT32, UINT64, ACC64, INT64, IPV6ADDR, // - FLOAT64 // avoid floating point numbers + case ACC32, IPADDR, UINT32, UINT64, ACC64, INT64, IPV6ADDR // -> OpenemsType.LONG; + case FLOAT32 // + -> OpenemsType.FLOAT; + case FLOAT64 // + -> OpenemsType.DOUBLE; case STRING2, STRING4, STRING5, STRING6, STRING7, STRING8, STRING12, STRING16, STRING20, STRING25, STRING32 // -> OpenemsType.STRING; diff --git a/io.openems.edge.bridge.modbus/test/io/openems/edge/bridge/modbus/BridgeModbusTcpImplTest.java b/io.openems.edge.bridge.modbus/test/io/openems/edge/bridge/modbus/BridgeModbusTcpImplTest.java index 33c3496c644..cfcf6d532c0 100644 --- a/io.openems.edge.bridge.modbus/test/io/openems/edge/bridge/modbus/BridgeModbusTcpImplTest.java +++ b/io.openems.edge.bridge.modbus/test/io/openems/edge/bridge/modbus/BridgeModbusTcpImplTest.java @@ -1,5 +1,6 @@ package io.openems.edge.bridge.modbus; +import static io.openems.common.test.TestUtils.findRandomOpenPortOnAllLocalInterfaces; import static io.openems.edge.bridge.modbus.api.ModbusComponent.ChannelId.MODBUS_COMMUNICATION_FAILED; import org.junit.Test; @@ -22,7 +23,6 @@ import io.openems.edge.common.taskmanager.Priority; import io.openems.edge.common.test.AbstractComponentTest.TestCase; import io.openems.edge.common.test.ComponentTest; -import io.openems.edge.common.test.TestUtils; public class BridgeModbusTcpImplTest { @@ -33,7 +33,7 @@ public class BridgeModbusTcpImplTest { public void test() throws Exception { final ThrowingRunnable sleep = () -> Thread.sleep(CYCLE_TIME); - var port = TestUtils.findRandomOpenPortOnAllLocalInterfaces(); + var port = findRandomOpenPortOnAllLocalInterfaces(); ModbusSlave slave = null; try { /* diff --git a/io.openems.edge.bridge.modbus/test/io/openems/edge/bridge/modbus/api/worker/internal/DefectiveComponentsTest.java b/io.openems.edge.bridge.modbus/test/io/openems/edge/bridge/modbus/api/worker/internal/DefectiveComponentsTest.java index ce0b9f97068..fe8246dfb2f 100644 --- a/io.openems.edge.bridge.modbus/test/io/openems/edge/bridge/modbus/api/worker/internal/DefectiveComponentsTest.java +++ b/io.openems.edge.bridge.modbus/test/io/openems/edge/bridge/modbus/api/worker/internal/DefectiveComponentsTest.java @@ -1,7 +1,7 @@ package io.openems.edge.bridge.modbus.api.worker.internal; +import static io.openems.common.test.TestUtils.createDummyClock; import static io.openems.edge.bridge.modbus.api.worker.internal.CycleTasksManagerTest.LOG_HANDLER; -import static io.openems.edge.common.test.TestUtils.createDummyClock; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; diff --git a/io.openems.edge.bridge.modbus/test/io/openems/edge/bridge/modbus/api/worker/internal/TasksSupplierImplTest.java b/io.openems.edge.bridge.modbus/test/io/openems/edge/bridge/modbus/api/worker/internal/TasksSupplierImplTest.java index 77e3d8b8f3f..46b13094b91 100644 --- a/io.openems.edge.bridge.modbus/test/io/openems/edge/bridge/modbus/api/worker/internal/TasksSupplierImplTest.java +++ b/io.openems.edge.bridge.modbus/test/io/openems/edge/bridge/modbus/api/worker/internal/TasksSupplierImplTest.java @@ -1,7 +1,7 @@ package io.openems.edge.bridge.modbus.api.worker.internal; +import static io.openems.common.test.TestUtils.createDummyClock; import static io.openems.edge.bridge.modbus.api.worker.internal.CycleTasksManagerTest.LOG_HANDLER; -import static io.openems.edge.common.test.TestUtils.createDummyClock; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; diff --git a/io.openems.edge.bridge.modbus/test/io/openems/edge/bridge/modbus/sunspec/AbstractOpenemsSunSpecComponentTest.java b/io.openems.edge.bridge.modbus/test/io/openems/edge/bridge/modbus/sunspec/AbstractOpenemsSunSpecComponentTest.java index 2e877e2cb42..d55f8c1b395 100644 --- a/io.openems.edge.bridge.modbus/test/io/openems/edge/bridge/modbus/sunspec/AbstractOpenemsSunSpecComponentTest.java +++ b/io.openems.edge.bridge.modbus/test/io/openems/edge/bridge/modbus/sunspec/AbstractOpenemsSunSpecComponentTest.java @@ -1,5 +1,6 @@ package io.openems.edge.bridge.modbus.sunspec; +import static io.openems.common.test.TestUtils.findRandomOpenPortOnAllLocalInterfaces; import static io.openems.edge.bridge.modbus.sunspec.AbstractOpenemsSunSpecComponent.preprocessModbusElements; import static java.util.stream.IntStream.range; import static org.junit.Assert.assertEquals; @@ -37,7 +38,6 @@ import io.openems.edge.common.test.AbstractComponentTest.TestCase; import io.openems.edge.common.test.ComponentTest; import io.openems.edge.common.test.DummyConfigurationAdmin; -import io.openems.edge.common.test.TestUtils; public class AbstractOpenemsSunSpecComponentTest { @@ -163,7 +163,7 @@ private static ImmutableSortedMap.Builder generateSunSpec() { @Ignore @Test public void test() throws Exception { - var port = TestUtils.findRandomOpenPortOnAllLocalInterfaces(); + var port = findRandomOpenPortOnAllLocalInterfaces(); ModbusSlave slave = null; try { /* diff --git a/io.openems.edge.bridge.modbus/test/io/openems/edge/bridge/modbus/sunspec/PointTest.java b/io.openems.edge.bridge.modbus/test/io/openems/edge/bridge/modbus/sunspec/PointTest.java index 8e62fa932a5..21ee9b76f46 100644 --- a/io.openems.edge.bridge.modbus/test/io/openems/edge/bridge/modbus/sunspec/PointTest.java +++ b/io.openems.edge.bridge.modbus/test/io/openems/edge/bridge/modbus/sunspec/PointTest.java @@ -4,7 +4,7 @@ import static io.openems.common.channel.ChannelCategory.OPENEMS_TYPE; import static io.openems.common.channel.PersistencePriority.VERY_LOW; import static io.openems.common.channel.Unit.AMPERE; -import static io.openems.common.types.OpenemsType.INTEGER; +import static io.openems.common.types.OpenemsType.FLOAT; import static org.junit.Assert.assertEquals; import org.junit.Test; @@ -22,7 +22,7 @@ public void testChannelIdPoint() { assertEquals(OPENEMS_TYPE, doc.getChannelCategory()); assertEquals(VERY_LOW, doc.getPersistencePriority()); assertEquals("Amps. AC Current", doc.getText()); - assertEquals(INTEGER, doc.getType()); + assertEquals(FLOAT, doc.getType()); assertEquals(AMPERE, doc.getUnit()); } diff --git a/io.openems.edge.bridge.onewire/bnd.bnd b/io.openems.edge.bridge.onewire/bnd.bnd index e61cf21d959..017e4a82b22 100644 --- a/io.openems.edge.bridge.onewire/bnd.bnd +++ b/io.openems.edge.bridge.onewire/bnd.bnd @@ -12,8 +12,8 @@ Export-Package: \ com.dalsemi.onewire.application.tag,\ com.dalsemi.onewire.container,\ com.dalsemi.onewire.debug,\ - io.openems.edge.bridge.onewire,\ com.dalsemi.onewire.utils,\ + io.openems.edge.bridge.onewire,\ gnu.io Include-Resource: \ diff --git a/io.openems.edge.bridge.onewire/src/com/dalsemi/onewire/adapter/UAdapterState.java b/io.openems.edge.bridge.onewire/src/com/dalsemi/onewire/adapter/UAdapterState.java index ed93664f6c5..381ae0db30c 100644 --- a/io.openems.edge.bridge.onewire/src/com/dalsemi/onewire/adapter/UAdapterState.java +++ b/io.openems.edge.bridge.onewire/src/com/dalsemi/onewire/adapter/UAdapterState.java @@ -148,9 +148,9 @@ class UAdapterState { /** * This is the current 'real' speed that the OneWire is operating at. This is - * used to represent the actual mode that the DS2480 is operating in. For example - * the logical speed might be USPEED_REGULAR but for RF emission reasons we may - * put the actual DS2480 in SPEED_FLEX. + * used to represent the actual mode that the DS2480 is operating in. For + * example the logical speed might be USPEED_REGULAR but for RF emission reasons + * we may put the actual DS2480 in SPEED_FLEX. *

* The valid values for this are: *

    diff --git a/io.openems.edge.bridge.onewire/src/com/dalsemi/onewire/adapter/USerialAdapter.java b/io.openems.edge.bridge.onewire/src/com/dalsemi/onewire/adapter/USerialAdapter.java index fae5e1ee211..c6692349189 100644 --- a/io.openems.edge.bridge.onewire/src/com/dalsemi/onewire/adapter/USerialAdapter.java +++ b/io.openems.edge.bridge.onewire/src/com/dalsemi/onewire/adapter/USerialAdapter.java @@ -2154,24 +2154,13 @@ private void setStreamingSpeed(int operation) throws OneWireIOException { } // convert this baud to 'u' baud - char ubaud; - - switch (baud) { - - case 115200: - ubaud = UAdapterState.BAUD_115200; - break; - case 57600: - ubaud = UAdapterState.BAUD_57600; - break; - case 19200: - ubaud = UAdapterState.BAUD_19200; - break; - case 9600: - default: - ubaud = UAdapterState.BAUD_9600; - break; - } + var ubaud = switch (baud) { + case 115200 -> UAdapterState.BAUD_115200; + case 57600 -> UAdapterState.BAUD_57600; + case 19200 -> UAdapterState.BAUD_19200; + case 9600 -> UAdapterState.BAUD_9600; + default -> UAdapterState.BAUD_9600; + }; // see if this is a new baud if (ubaud == this.uState.ubaud) { diff --git a/io.openems.edge.bridge.onewire/src/com/dalsemi/onewire/application/monitor/NetworkDeviceMonitor.java b/io.openems.edge.bridge.onewire/src/com/dalsemi/onewire/application/monitor/NetworkDeviceMonitor.java index 4af1f56ad36..5d17d6ca8e9 100644 --- a/io.openems.edge.bridge.onewire/src/com/dalsemi/onewire/application/monitor/NetworkDeviceMonitor.java +++ b/io.openems.edge.bridge.onewire/src/com/dalsemi/onewire/application/monitor/NetworkDeviceMonitor.java @@ -207,8 +207,7 @@ public void search(Vector arrivals, Vector departures) throws OneWir var owc = getDeviceContainer(this.adapter, longAddress); // check to see if it's a switch and if we are supposed // to automatically search down branches - if (this.branchAutoSearching && owc instanceof SwitchContainer) { - var sc = (SwitchContainer) owc; + if (this.branchAutoSearching && owc instanceof SwitchContainer sc) { var state = sc.readDevice(); for (var j = 0; j < sc.getNumberChannels(state); j++) { var tmp = new OWPath(this.adapter, path); diff --git a/io.openems.edge.bridge.onewire/src/com/dalsemi/onewire/application/sha/SHADebit.java b/io.openems.edge.bridge.onewire/src/com/dalsemi/onewire/application/sha/SHADebit.java index e3b7a03f8a5..e48fd109f1b 100644 --- a/io.openems.edge.bridge.onewire/src/com/dalsemi/onewire/application/sha/SHADebit.java +++ b/io.openems.edge.bridge.onewire/src/com/dalsemi/onewire/application/sha/SHADebit.java @@ -705,16 +705,12 @@ private final boolean writeTransactionData(SHAiButtonUser user, int transID, int */ @Override public synchronized int getParameter(int type) { - switch (type) { - case DEBIT_AMOUNT: - return this.debitAmount; - case INITIAL_AMOUNT: - return this.initialAmount; - case USER_BALANCE: - return this.userBalance; - default: - throw new IllegalArgumentException("Invalid parameter type"); - } + return switch (type) { + case DEBIT_AMOUNT -> this.debitAmount; + case INITIAL_AMOUNT -> this.initialAmount; + case USER_BALANCE -> this.userBalance; + default -> throw new IllegalArgumentException("Invalid parameter type"); + }; } /** diff --git a/io.openems.edge.bridge.onewire/src/com/dalsemi/onewire/application/sha/SHADebitUnsigned.java b/io.openems.edge.bridge.onewire/src/com/dalsemi/onewire/application/sha/SHADebitUnsigned.java index b44cbe76c64..ea4b9caaf70 100644 --- a/io.openems.edge.bridge.onewire/src/com/dalsemi/onewire/application/sha/SHADebitUnsigned.java +++ b/io.openems.edge.bridge.onewire/src/com/dalsemi/onewire/application/sha/SHADebitUnsigned.java @@ -887,16 +887,12 @@ private final boolean writeTransactionData(SHAiButtonUser user, int transID, int */ @Override public synchronized int getParameter(int type) { - switch (type) { - case DEBIT_AMOUNT: - return this.debitAmount; - case INITIAL_AMOUNT: - return this.initialAmount; - case USER_BALANCE: - return this.userBalance; - default: - return -1; - } + return switch (type) { + case DEBIT_AMOUNT -> this.debitAmount; + case INITIAL_AMOUNT -> this.initialAmount; + case USER_BALANCE -> this.userBalance; + default -> -1; + }; } /** diff --git a/io.openems.edge.bridge.onewire/src/com/dalsemi/onewire/application/tag/TaggedDevice.java b/io.openems.edge.bridge.onewire/src/com/dalsemi/onewire/application/tag/TaggedDevice.java index 9f6e3edb440..b1a99065b69 100644 --- a/io.openems.edge.bridge.onewire/src/com/dalsemi/onewire/application/tag/TaggedDevice.java +++ b/io.openems.edge.bridge.onewire/src/com/dalsemi/onewire/application/tag/TaggedDevice.java @@ -266,8 +266,7 @@ public boolean equals(Object o) { return true; } - if (o instanceof TaggedDevice) { - var td = (TaggedDevice) o; + if (o instanceof TaggedDevice td) { return td.DeviceContainer.equals(this.DeviceContainer) && td.DeviceType.equals(this.DeviceType) && td.min.equals(this.min) && td.max.equals(this.max) && td.init.equals(this.init) && td.clusterName.equals(this.clusterName) && td.label.equals(this.label); diff --git a/io.openems.edge.bridge.onewire/src/com/dalsemi/onewire/container/OneWireContainer.java b/io.openems.edge.bridge.onewire/src/com/dalsemi/onewire/container/OneWireContainer.java index 863d4153458..dbac249cea2 100644 --- a/io.openems.edge.bridge.onewire/src/com/dalsemi/onewire/container/OneWireContainer.java +++ b/io.openems.edge.bridge.onewire/src/com/dalsemi/onewire/container/OneWireContainer.java @@ -559,8 +559,7 @@ public boolean equals(Object obj) { return true; } - if (obj instanceof OneWireContainer) { - var owc = (OneWireContainer) obj; + if (obj instanceof OneWireContainer owc) { // don't claim that all subclasses of a specific container are // equivalent to the parent container if (owc.getClass() == this.getClass()) { diff --git a/io.openems.edge.bridge.onewire/src/com/dalsemi/onewire/container/OneWireContainer12.java b/io.openems.edge.bridge.onewire/src/com/dalsemi/onewire/container/OneWireContainer12.java index 75572fe9fde..e281df1fc1a 100644 --- a/io.openems.edge.bridge.onewire/src/com/dalsemi/onewire/container/OneWireContainer12.java +++ b/io.openems.edge.bridge.onewire/src/com/dalsemi/onewire/container/OneWireContainer12.java @@ -1139,18 +1139,15 @@ public byte[] channelAccess(byte[] inbuffer, boolean toggleRW, boolean readIniti inlength = inlength << 1; // = inlength * 2 } - switch (CRCMode) { + inlength = switch (CRCMode) { default: case CRC_EVERY_BYTE: // we need to allow for 2 CRC bytes for every byte of the length - inlength = inlength * 3; // length + 2*length - break; + yield inlength * 3; // length + 2*length case CRC_EVERY_8_BYTES: // we need to allow for 2 CRC bytes for every 8 bytes of length - inlength = inlength + (inlength >> 3 << 1); // (length DIV 8) * 2 - break; + yield inlength + (inlength >> 3 << 1); // (length DIV 8) * 2 case CRC_EVERY_32_BYTES: // we need to allow for 2 CRC bytes for every 32 bytes of length - inlength = inlength + (inlength >> 5 << 1); // (length DIV 32) * 2 - break; - } + yield inlength + (inlength >> 5 << 1); // (length DIV 32) * 2 + }; var outputbuffer = new byte[inlength + 3 + 1]; // 3 control bytes + 1 information byte diff --git a/io.openems.edge.bridge.onewire/src/com/dalsemi/onewire/container/OneWireContainer21.java b/io.openems.edge.bridge.onewire/src/com/dalsemi/onewire/container/OneWireContainer21.java index 8f9406a0481..edffe87634e 100644 --- a/io.openems.edge.bridge.onewire/src/com/dalsemi/onewire/container/OneWireContainer21.java +++ b/io.openems.edge.bridge.onewire/src/com/dalsemi/onewire/container/OneWireContainer21.java @@ -2026,27 +2026,16 @@ public void setClockAlarm(int hours, int minutes, int seconds, int day, int alar state[0x0a] = (byte) day; - var number_0_msb = 0; // how many of the MS, MM, MH, MD bytes have - + // how many of the MS, MM, MH, MD bytes have // 0 as their ms bit??? - switch (alarmFrequency) { - case ONCE_PER_SECOND: - number_0_msb = 0; - break; - case ONCE_PER_MINUTE: - number_0_msb = 1; - break; - case ONCE_PER_HOUR: - number_0_msb = 2; - break; - case ONCE_PER_DAY: - number_0_msb = 3; - break; - default: - case ONCE_PER_WEEK: - number_0_msb = 4; - break; - } + var number_0_msb = switch (alarmFrequency) { + case ONCE_PER_SECOND -> 0; + case ONCE_PER_MINUTE -> 1; + case ONCE_PER_HOUR -> 2; + case ONCE_PER_DAY -> 3; + case ONCE_PER_WEEK -> 4; + default -> 4; + }; for (var i = 0x07; i < 0x0b; i++) { if (number_0_msb > 0) { diff --git a/io.openems.edge.bridge.onewire/src/com/dalsemi/onewire/container/OneWireContainer26.java b/io.openems.edge.bridge.onewire/src/com/dalsemi/onewire/container/OneWireContainer26.java index a12ed7d3923..9a5de5478ff 100644 --- a/io.openems.edge.bridge.onewire/src/com/dalsemi/onewire/container/OneWireContainer26.java +++ b/io.openems.edge.bridge.onewire/src/com/dalsemi/onewire/container/OneWireContainer26.java @@ -662,26 +662,15 @@ public void calibrateCurrentADC() throws OneWireIOException, OneWireException, I * @throws IllegalArgumentException Bad parameters passed */ public void setThreshold(byte thresholdValue) throws OneWireIOException, OneWireException { - byte thresholdReg; byte[] data; - switch (thresholdValue) { - - case 0: - thresholdReg = 0; - break; - case 2: - thresholdReg = 64; - break; - case 4: - thresholdReg = (byte) 128; - break; - case 8: - thresholdReg = (byte) 192; - break; - default: - throw new IllegalArgumentException("OneWireContainer26-Threshold value must be 0,2,4, or 8."); - } + var thresholdReg = switch (thresholdValue) { + case 0 -> (byte) 0; + case 2 -> (byte) 64; + case 4 -> (byte) 128; + case 8 -> (byte) 192; + default -> throw new IllegalArgumentException("OneWireContainer26-Threshold value must be 0,2,4, or 8."); + }; // first save their original IAD settings so we dont change anything var IADvalue = this.getFlag(IAD_FLAG); diff --git a/io.openems.edge.bridge.onewire/src/com/dalsemi/onewire/container/OneWireContainer28.java b/io.openems.edge.bridge.onewire/src/com/dalsemi/onewire/container/OneWireContainer28.java index 6b2ba98c326..15cb9c17954 100644 --- a/io.openems.edge.bridge.onewire/src/com/dalsemi/onewire/container/OneWireContainer28.java +++ b/io.openems.edge.bridge.onewire/src/com/dalsemi/onewire/container/OneWireContainer28.java @@ -361,8 +361,6 @@ public double getMinTemperature() { */ @Override public void doTemperatureConvert(byte[] state) throws OneWireIOException, OneWireException { - var msDelay = 750; // in milliseconds - // select the device if (!this.adapter.select(this.address)) { @@ -376,23 +374,13 @@ public void doTemperatureConvert(byte[] state) throws OneWireIOException, OneWir this.adapter.putByte(CONVERT_TEMPERATURE_COMMAND); // calculate duration of delay according to resolution desired - switch (state[4]) { - - case RESOLUTION_9_BIT: - msDelay = 94; - break; - case RESOLUTION_10_BIT: - msDelay = 188; - break; - case RESOLUTION_11_BIT: - msDelay = 375; - break; - case RESOLUTION_12_BIT: - msDelay = 750; - break; - default: - msDelay = 750; - } // switch + var msDelay = switch (state[4]) { + case RESOLUTION_9_BIT -> 94; + case RESOLUTION_10_BIT -> 188; + case RESOLUTION_11_BIT -> 375; + case RESOLUTION_12_BIT -> 750; + default -> 750; + }; // delay for specified amount of time try { @@ -502,28 +490,14 @@ public double getTemperatureAlarm(int alarmType, byte[] state) { */ @Override public double getTemperatureResolution(byte[] state) { - var tempres = 0.0; - // calculate temperature resolution according to configuration byte - switch (state[4]) { - - case RESOLUTION_9_BIT: - tempres = 0.5; - break; - case RESOLUTION_10_BIT: - tempres = 0.25; - break; - case RESOLUTION_11_BIT: - tempres = 0.125; - break; - case RESOLUTION_12_BIT: - tempres = 0.0625; - break; - default: - tempres = 0.0; - } // switch - - return tempres; + return switch (state[4]) { + case RESOLUTION_9_BIT -> 0.5; + case RESOLUTION_10_BIT -> 0.25; + case RESOLUTION_11_BIT -> 0.125; + case RESOLUTION_12_BIT -> 0.0625; + default -> 0.0; + }; } // -------- diff --git a/io.openems.edge.bridge.onewire/src/com/dalsemi/onewire/container/OneWireContainer2C.java b/io.openems.edge.bridge.onewire/src/com/dalsemi/onewire/container/OneWireContainer2C.java index 4ff3518aecf..a908b173c66 100644 --- a/io.openems.edge.bridge.onewire/src/com/dalsemi/onewire/container/OneWireContainer2C.java +++ b/io.openems.edge.bridge.onewire/src/com/dalsemi/onewire/container/OneWireContainer2C.java @@ -271,17 +271,12 @@ public int numberOfPotentiometers(byte[] state) { */ @Override public int numberOfWiperSettings(byte[] state) { - switch (state[0] & 0x30) { - - case 0x00: - return 32; - case 0x10: - return 64; - case 0x20: - return 128; - default: - return 256; - } + return switch (state[0] & 0x30) { + case 0x00 -> 32; + case 0x10 -> 64; + case 0x20 -> 128; + default -> 256; + }; } /** @@ -293,17 +288,12 @@ public int numberOfWiperSettings(byte[] state) { */ @Override public int potentiometerResistance(byte[] state) { - switch (state[0] & 0xc0) { - - case 0x00: - return 5; - case 0x40: - return 10; - case 0x80: - return 50; - default: - return 100; - } + return switch (state[0] & 0xc0) { + case 0x00 -> 5; + case 0x40 -> 10; + case 0x80 -> 50; + default -> 100; + }; } /** diff --git a/io.openems.edge.bridge.onewire/src/com/dalsemi/onewire/container/OneWireContainer42.java b/io.openems.edge.bridge.onewire/src/com/dalsemi/onewire/container/OneWireContainer42.java index 31f26a7390b..83c93eb277f 100644 --- a/io.openems.edge.bridge.onewire/src/com/dalsemi/onewire/container/OneWireContainer42.java +++ b/io.openems.edge.bridge.onewire/src/com/dalsemi/onewire/container/OneWireContainer42.java @@ -449,8 +449,6 @@ public double getMinTemperature() { */ @Override public void doTemperatureConvert(byte[] state) throws OneWireIOException, OneWireException { - var msDelay = 750; // in milliseconds - // select the device if (!this.adapter.select(this.address)) { @@ -464,23 +462,13 @@ public void doTemperatureConvert(byte[] state) throws OneWireIOException, OneWir this.adapter.putByte(CONVERT_TEMPERATURE_COMMAND); // calculate duration of delay according to resolution desired - switch (state[4]) { - - case RESOLUTION_9_BIT: - msDelay = 94; - break; - case RESOLUTION_10_BIT: - msDelay = 188; - break; - case RESOLUTION_11_BIT: - msDelay = 375; - break; - case RESOLUTION_12_BIT: - msDelay = 750; - break; - default: - msDelay = 750; - } // switch + var msDelay = switch (state[4]) { + case RESOLUTION_9_BIT -> 94; + case RESOLUTION_10_BIT -> 188; + case RESOLUTION_11_BIT -> 375; + case RESOLUTION_12_BIT -> 750; + default -> 750; + }; // delay for specified amount of time try { @@ -589,28 +577,14 @@ public double getTemperatureAlarm(int alarmType, byte[] state) { */ @Override public double getTemperatureResolution(byte[] state) { - var tempres = 0.0; - // calculate temperature resolution according to configuration byte - switch (state[4]) { - - case RESOLUTION_9_BIT: - tempres = 0.5; - break; - case RESOLUTION_10_BIT: - tempres = 0.25; - break; - case RESOLUTION_11_BIT: - tempres = 0.125; - break; - case RESOLUTION_12_BIT: - tempres = 0.0625; - break; - default: - tempres = 0.0; - } // switch - - return tempres; + return switch (state[4]) { + case RESOLUTION_9_BIT -> 0.5; + case RESOLUTION_10_BIT -> 0.25; + case RESOLUTION_11_BIT -> 0.125; + case RESOLUTION_12_BIT -> 0.0625; + default -> 0.0; + }; } // -------- diff --git a/io.openems.edge.bridge.onewire/src/io/openems/edge/bridge/onewire/impl/BridgeOnewireImpl.java b/io.openems.edge.bridge.onewire/src/io/openems/edge/bridge/onewire/impl/BridgeOnewireImpl.java index b03ef071bd0..d1f60ff3073 100644 --- a/io.openems.edge.bridge.onewire/src/io/openems/edge/bridge/onewire/impl/BridgeOnewireImpl.java +++ b/io.openems.edge.bridge.onewire/src/io/openems/edge/bridge/onewire/impl/BridgeOnewireImpl.java @@ -82,7 +82,8 @@ protected void logError(Logger log, String message) { @Override public void buildJsonApiRoutes(JsonApiBuilder builder) { - builder.handleRequest(GetDevicesRequest.METHOD, call -> this.taskWorker.handleGetDevicesRequest(call.getRequest())); + builder.handleRequest(GetDevicesRequest.METHOD, + call -> this.taskWorker.handleGetDevicesRequest(call.getRequest())); } } \ No newline at end of file diff --git a/io.openems.edge.bridge.onewire/src/io/openems/edge/bridge/onewire/jsonrpc/GetDeviceResponse.java b/io.openems.edge.bridge.onewire/src/io/openems/edge/bridge/onewire/jsonrpc/GetDeviceResponse.java index 04549846a09..b98337c68e7 100644 --- a/io.openems.edge.bridge.onewire/src/io/openems/edge/bridge/onewire/jsonrpc/GetDeviceResponse.java +++ b/io.openems.edge.bridge.onewire/src/io/openems/edge/bridge/onewire/jsonrpc/GetDeviceResponse.java @@ -50,10 +50,9 @@ public static class Device { public static Device from(OneWireContainer owc) { final var details = new JsonObject(); - if (owc instanceof TemperatureContainer) { + if (owc instanceof TemperatureContainer tc) { details.addProperty("type", "TemperatureContainer"); try { - var tc = (TemperatureContainer) owc; var state = tc.readDevice(); tc.doTemperatureConvert(state); state = tc.readDevice(); diff --git a/io.openems.edge.common/src/io/openems/edge/common/channel/BooleanDoc.java b/io.openems.edge.common/src/io/openems/edge/common/channel/BooleanDoc.java index 86b591e5263..f2187b13a16 100644 --- a/io.openems.edge.common/src/io/openems/edge/common/channel/BooleanDoc.java +++ b/io.openems.edge.common/src/io/openems/edge/common/channel/BooleanDoc.java @@ -19,15 +19,12 @@ protected BooleanDoc self() { @SuppressWarnings("unchecked") @Override public BooleanReadChannel createChannelInstance(OpenemsComponent component, ChannelId channelId) { - switch (this.getAccessMode()) { - case READ_ONLY: - return new BooleanReadChannel(component, channelId, this, this.debounce, this.debounceMode); - case READ_WRITE: - case WRITE_ONLY: - return new BooleanWriteChannel(component, channelId, this); - } - throw new IllegalArgumentException( - "AccessMode [" + this.getAccessMode() + "] is unhandled. This should never happen."); + return switch (this.getAccessMode()) { + case READ_ONLY // + -> new BooleanReadChannel(component, channelId, this, this.debounce, this.debounceMode); + case READ_WRITE, WRITE_ONLY // + -> new BooleanWriteChannel(component, channelId, this); + }; } /** diff --git a/io.openems.edge.common/src/io/openems/edge/common/channel/DoubleDoc.java b/io.openems.edge.common/src/io/openems/edge/common/channel/DoubleDoc.java index 22c0185cc29..3e45b9ed7d0 100644 --- a/io.openems.edge.common/src/io/openems/edge/common/channel/DoubleDoc.java +++ b/io.openems.edge.common/src/io/openems/edge/common/channel/DoubleDoc.java @@ -18,14 +18,11 @@ protected DoubleDoc self() { @SuppressWarnings("unchecked") @Override public DoubleReadChannel createChannelInstance(OpenemsComponent component, ChannelId channelId) { - switch (this.getAccessMode()) { - case READ_ONLY: - return new DoubleReadChannel(component, channelId, this); - case READ_WRITE: - case WRITE_ONLY: - return new DoubleWriteChannel(component, channelId, this); - } - throw new IllegalArgumentException( - "AccessMode [" + this.getAccessMode() + "] is unhandled. This should never happen."); + return switch (this.getAccessMode()) { + case READ_ONLY // + -> new DoubleReadChannel(component, channelId, this); + case READ_WRITE, WRITE_ONLY // + -> new DoubleWriteChannel(component, channelId, this); + }; } } diff --git a/io.openems.edge.common/src/io/openems/edge/common/channel/EnumDoc.java b/io.openems.edge.common/src/io/openems/edge/common/channel/EnumDoc.java index 92306580030..854a4de096e 100644 --- a/io.openems.edge.common/src/io/openems/edge/common/channel/EnumDoc.java +++ b/io.openems.edge.common/src/io/openems/edge/common/channel/EnumDoc.java @@ -60,15 +60,12 @@ public EnumDoc initialValue(OptionsEnum initialValue) { @Override public EnumReadChannel createChannelInstance(OpenemsComponent component, io.openems.edge.common.channel.ChannelId channelId) { - switch (this.getAccessMode()) { - case READ_ONLY: - return new EnumReadChannel(component, channelId, this, this.getUndefinedOption(), this.getDebounce()); - case READ_WRITE: - case WRITE_ONLY: - return new EnumWriteChannel(component, channelId, this, this.getUndefinedOption()); - } - throw new IllegalArgumentException( - "Unable to initialize Channel-ID [" + channelId.id() + "] from OptionsEnumDoc!"); + return switch (this.getAccessMode()) { + case READ_ONLY // + -> new EnumReadChannel(component, channelId, this, this.getUndefinedOption(), this.getDebounce()); + case READ_WRITE, WRITE_ONLY // + -> new EnumWriteChannel(component, channelId, this, this.getUndefinedOption()); + }; } /** diff --git a/io.openems.edge.common/src/io/openems/edge/common/channel/FloatDoc.java b/io.openems.edge.common/src/io/openems/edge/common/channel/FloatDoc.java index 3a1e89d4597..8ea3c035129 100644 --- a/io.openems.edge.common/src/io/openems/edge/common/channel/FloatDoc.java +++ b/io.openems.edge.common/src/io/openems/edge/common/channel/FloatDoc.java @@ -18,14 +18,11 @@ protected FloatDoc self() { @SuppressWarnings("unchecked") @Override public FloatReadChannel createChannelInstance(OpenemsComponent component, ChannelId channelId) { - switch (this.getAccessMode()) { - case READ_ONLY: - return new FloatReadChannel(component, channelId, this); - case READ_WRITE: - case WRITE_ONLY: - return new FloatWriteChannel(component, channelId, this); - } - throw new IllegalArgumentException( - "AccessMode [" + this.getAccessMode() + "] is unhandled. This should never happen."); + return switch (this.getAccessMode()) { + case READ_ONLY // + -> new FloatReadChannel(component, channelId, this); + case READ_WRITE, WRITE_ONLY // + -> new FloatWriteChannel(component, channelId, this); + }; } } diff --git a/io.openems.edge.common/src/io/openems/edge/common/channel/IntegerDoc.java b/io.openems.edge.common/src/io/openems/edge/common/channel/IntegerDoc.java index e1b92cf338d..e9de3ebdcd0 100644 --- a/io.openems.edge.common/src/io/openems/edge/common/channel/IntegerDoc.java +++ b/io.openems.edge.common/src/io/openems/edge/common/channel/IntegerDoc.java @@ -18,14 +18,11 @@ protected IntegerDoc self() { @SuppressWarnings("unchecked") @Override public IntegerReadChannel createChannelInstance(OpenemsComponent component, ChannelId channelId) { - switch (this.getAccessMode()) { - case READ_ONLY: - return new IntegerReadChannel(component, channelId, this); - case READ_WRITE: - case WRITE_ONLY: - return new IntegerWriteChannel(component, channelId, this); - } - throw new IllegalArgumentException( - "AccessMode [" + this.getAccessMode() + "] is unhandled. This should never happen."); + return switch (this.getAccessMode()) { + case READ_ONLY // + -> new IntegerReadChannel(component, channelId, this); + case READ_WRITE, WRITE_ONLY // + -> new IntegerWriteChannel(component, channelId, this); + }; } } diff --git a/io.openems.edge.common/src/io/openems/edge/common/channel/LongDoc.java b/io.openems.edge.common/src/io/openems/edge/common/channel/LongDoc.java index 2a54a98958e..398d4930386 100644 --- a/io.openems.edge.common/src/io/openems/edge/common/channel/LongDoc.java +++ b/io.openems.edge.common/src/io/openems/edge/common/channel/LongDoc.java @@ -18,14 +18,11 @@ protected LongDoc self() { @SuppressWarnings("unchecked") @Override public LongReadChannel createChannelInstance(OpenemsComponent component, ChannelId channelId) { - switch (this.getAccessMode()) { - case READ_ONLY: - return new LongReadChannel(component, channelId, this); - case READ_WRITE: - case WRITE_ONLY: - return new LongWriteChannel(component, channelId, this); - } - throw new IllegalArgumentException( - "AccessMode [" + this.getAccessMode() + "] is unhandled. This should never happen."); + return switch (this.getAccessMode()) { + case READ_ONLY // + -> new LongReadChannel(component, channelId, this); + case READ_WRITE, WRITE_ONLY // + -> new LongWriteChannel(component, channelId, this); + }; } } diff --git a/io.openems.edge.common/src/io/openems/edge/common/channel/ShortDoc.java b/io.openems.edge.common/src/io/openems/edge/common/channel/ShortDoc.java index b4486bf388a..dd4d9e877ba 100644 --- a/io.openems.edge.common/src/io/openems/edge/common/channel/ShortDoc.java +++ b/io.openems.edge.common/src/io/openems/edge/common/channel/ShortDoc.java @@ -18,14 +18,11 @@ protected ShortDoc self() { @SuppressWarnings("unchecked") @Override public ShortReadChannel createChannelInstance(OpenemsComponent component, ChannelId channelId) { - switch (this.getAccessMode()) { - case READ_ONLY: - return new ShortReadChannel(component, channelId, this); - case READ_WRITE: - case WRITE_ONLY: - return new ShortWriteChannel(component, channelId, this); - } - throw new IllegalArgumentException( - "AccessMode [" + this.getAccessMode() + "] is unhandled. This should never happen."); + return switch (this.getAccessMode()) { + case READ_ONLY // + -> new ShortReadChannel(component, channelId, this); + case READ_WRITE, WRITE_ONLY // + -> new ShortWriteChannel(component, channelId, this); + }; } } diff --git a/io.openems.edge.common/src/io/openems/edge/common/channel/StringDoc.java b/io.openems.edge.common/src/io/openems/edge/common/channel/StringDoc.java index b4d5f5b11c9..fe3db4ca6b1 100644 --- a/io.openems.edge.common/src/io/openems/edge/common/channel/StringDoc.java +++ b/io.openems.edge.common/src/io/openems/edge/common/channel/StringDoc.java @@ -18,14 +18,11 @@ protected StringDoc self() { @SuppressWarnings("unchecked") @Override public StringReadChannel createChannelInstance(OpenemsComponent component, ChannelId channelId) { - switch (this.getAccessMode()) { - case READ_ONLY: - return new StringReadChannel(component, channelId, this); - case READ_WRITE: - case WRITE_ONLY: - return new StringWriteChannel(component, channelId, this); - } - throw new IllegalArgumentException( - "AccessMode [" + this.getAccessMode() + "] is unhandled. This should never happen."); + return switch (this.getAccessMode()) { + case READ_ONLY // + -> new StringReadChannel(component, channelId, this); + case READ_WRITE, WRITE_ONLY // + -> new StringWriteChannel(component, channelId, this); + }; } } diff --git a/io.openems.edge.common/src/io/openems/edge/common/channel/internal/AbstractReadChannel.java b/io.openems.edge.common/src/io/openems/edge/common/channel/internal/AbstractReadChannel.java index 529dc6437e2..551af28eb6c 100644 --- a/io.openems.edge.common/src/io/openems/edge/common/channel/internal/AbstractReadChannel.java +++ b/io.openems.edge.common/src/io/openems/edge/common/channel/internal/AbstractReadChannel.java @@ -270,32 +270,20 @@ protected List> getOnSetNextWrites() * @return true if validation ok */ private boolean validateType(OpenemsType expected, OpenemsType actual) { - switch (expected) { - case BOOLEAN: - case FLOAT: - case SHORT: - case STRING: - return actual == expected; - case DOUBLE: - switch (actual) { - case DOUBLE: - case FLOAT: - return true; - default: - return false; - } - case INTEGER: - case LONG: - switch (actual) { - case SHORT: - case INTEGER: - case LONG: - return true; - default: - return false; - } - } - return false; + return switch (expected) { + case BOOLEAN, FLOAT, SHORT, STRING // + -> actual == expected; + case DOUBLE // + -> switch (actual) { + case DOUBLE, FLOAT -> true; + default -> false; + }; + case INTEGER, LONG // + -> switch (actual) { + case SHORT, INTEGER, LONG -> true; + default -> false; + }; + }; } /** diff --git a/io.openems.edge.common/src/io/openems/edge/common/channel/internal/OpenemsTypeDoc.java b/io.openems.edge.common/src/io/openems/edge/common/channel/internal/OpenemsTypeDoc.java index 7f9bdcd22be..fad703f8dbd 100644 --- a/io.openems.edge.common/src/io/openems/edge/common/channel/internal/OpenemsTypeDoc.java +++ b/io.openems.edge.common/src/io/openems/edge/common/channel/internal/OpenemsTypeDoc.java @@ -21,23 +21,15 @@ public abstract class OpenemsTypeDoc extends AbstractDoc { * @return the {@link OpenemsTypeDoc} */ public static OpenemsTypeDoc of(OpenemsType type) { - switch (type) { - case BOOLEAN: - return new BooleanDoc(); - case DOUBLE: - return new DoubleDoc(); - case FLOAT: - return new FloatDoc(); - case INTEGER: - return new IntegerDoc(); - case LONG: - return new LongDoc(); - case SHORT: - return new ShortDoc(); - case STRING: - return new StringDoc(); - } - throw new IllegalArgumentException("OpenemsType [" + type + "] is unhandled. This should never happen."); + return switch (type) { + case BOOLEAN -> new BooleanDoc(); + case DOUBLE -> new DoubleDoc(); + case FLOAT -> new FloatDoc(); + case INTEGER -> new IntegerDoc(); + case LONG -> new LongDoc(); + case SHORT -> new ShortDoc(); + case STRING -> new StringDoc(); + }; } protected OpenemsTypeDoc(OpenemsType type) { diff --git a/io.openems.edge.common/src/io/openems/edge/common/channel/value/Value.java b/io.openems.edge.common/src/io/openems/edge/common/channel/value/Value.java index ca3925b6e49..7e47e9d1b2c 100644 --- a/io.openems.edge.common/src/io/openems/edge/common/channel/value/Value.java +++ b/io.openems.edge.common/src/io/openems/edge/common/channel/value/Value.java @@ -215,10 +215,10 @@ public JsonElement asJson() { * enum */ private EnumDoc isEnumValue() { - if (this.parent.channelDoc() instanceof EnumDoc) { - return (EnumDoc) this.parent.channelDoc(); - } - return null; + return switch (this.parent.channelDoc()) { + case EnumDoc ed -> ed; + default -> null; + }; } /** diff --git a/io.openems.edge.common/src/io/openems/edge/common/component/ComponentManager.java b/io.openems.edge.common/src/io/openems/edge/common/component/ComponentManager.java index ea444764b63..9ea55060009 100644 --- a/io.openems.edge.common/src/io/openems/edge/common/component/ComponentManager.java +++ b/io.openems.edge.common/src/io/openems/edge/common/component/ComponentManager.java @@ -2,6 +2,7 @@ import java.time.Clock; import java.util.List; +import java.util.Map; import org.osgi.framework.BundleContext; @@ -173,6 +174,20 @@ public default void _setDefaultConfigurationFailed(boolean value) { @Override public Clock getClock(); + /** + * Gets the component properties by its component id. + * + * @param componentId the id of the component + * @return the properties or a empty map if none found + * @implNote this method is preferred to use when only the properties of an + * component are of interest. Because of OSGi delivering the component + * updates asynchronously and if a component update happens the config + * update may not reflect immediately to the config of the + * implementation of that component but this method uses the direct + * configuration in the service registration. + */ + public Map getComponentProperties(String componentId); + /** * Gets all enabled OpenEMS-Components. * diff --git a/io.openems.edge.common/src/io/openems/edge/common/converter/StaticConverters.java b/io.openems.edge.common/src/io/openems/edge/common/converter/StaticConverters.java index 08ecb837ce1..48c95d69fdd 100644 --- a/io.openems.edge.common/src/io/openems/edge/common/converter/StaticConverters.java +++ b/io.openems.edge.common/src/io/openems/edge/common/converter/StaticConverters.java @@ -2,112 +2,40 @@ import java.util.function.Function; -import io.openems.common.types.OpenemsType; - public class StaticConverters { /** * Converts only positive values from Element to Channel. */ public static final Function KEEP_POSITIVE = value -> { - if (value == null) { - return null; - } - for (OpenemsType openemsType : OpenemsType.values()) { - // this 'for' + 'switch' is only utilized to get an alert by Eclipse IDE if a - // new OpenemsType was added. ("The enum constant XX needs a corresponding case - // label in this enum switch on OpenemsType") - switch (openemsType) { - case BOOLEAN: - case SHORT: - case INTEGER: - case LONG: - case FLOAT: - case DOUBLE: - case STRING: - if (value instanceof Boolean || value instanceof String) { - return value; // impossible - } - if (value instanceof Short) { - short shortValue = (Short) value; - if (shortValue > 0) { - return shortValue; - } else { - return 0; - } - } else if (value instanceof Integer) { - int intValue = (Integer) value; - if (intValue > 0) { - return intValue; - } else { - return 0; - } - } else if (value instanceof Long) { - long longValue = (Long) value; - if (longValue > 0) { - return longValue; - } else { - return 0; - } - } else if (value instanceof Float) { - float floatValue = (Float) value; - if (floatValue > 0) { - return floatValue; - } else { - return 0; - } - } else if (value instanceof Double) { - double doubleValue = (Double) value; - if (doubleValue > 0) { - return doubleValue; - } else { - return 0; - } - } - } - break; - } - throw new IllegalArgumentException("Converter KEEP_POSITIVE does not accept the type of [" + value + "]"); + return switch (value) { + case null -> null; + case Boolean b -> b; + case String s -> s; + case Short s -> s > 0 ? s : 0; + case Integer i -> i > 0 ? i : 0; + case Long l -> l > 0 ? l : 0; + case Float f -> f > 0 ? f : 0; + case Double d -> d > 0 ? d : 0; + default -> + throw new IllegalArgumentException("Converter KEEP_POSITIVE does not accept the type of [" + value + "]"); + }; }; /** * Invert a value. */ public static final Function INVERT = value -> { - if (value == null) { - return null; - } - for (OpenemsType openemsType : OpenemsType.values()) { - // this 'for' + 'switch' is only utilized to get an alert by Eclipse IDE if a - // new OpenemsType was added. ("The enum constant XX needs a corresponding case - // label in this enum switch on OpenemsType") - switch (openemsType) { - case BOOLEAN: - case SHORT: - case INTEGER: - case LONG: - case FLOAT: - case DOUBLE: - case STRING: - if (value instanceof String) { - return value; // impossible - } - if (value instanceof Boolean) { - return Boolean.valueOf(!(boolean) value); - } else if (value instanceof Short) { - return Short.valueOf((short) ((short) value * -1)); - } else if (value instanceof Integer) { - return Integer.valueOf((int) value * -1); - } else if (value instanceof Long) { - return Long.valueOf((long) value * -1); - } else if (value instanceof Float) { - return Float.valueOf((float) value * -1); - } else if (value instanceof Double) { - return Double.valueOf((double) value * -1); - } - } - break; - } - throw new IllegalArgumentException("Converter INVERT does not accept the type of [" + value + "]"); + return switch (value) { + case null -> null; + case Boolean b -> !b; + case String s -> s; // impossible + case Short s -> s * -1; + case Integer i -> i * -1; + case Long l -> l * -1; + case Float f -> f * -1; + case Double d -> d * -1; + default -> throw new IllegalArgumentException("Converter INVERT does not accept the type of [" + value + "]"); + }; }; } diff --git a/io.openems.edge.common/src/io/openems/edge/common/currency/Currency.java b/io.openems.edge.common/src/io/openems/edge/common/currency/Currency.java index 52337d0c78f..d1750f819fe 100644 --- a/io.openems.edge.common/src/io/openems/edge/common/currency/Currency.java +++ b/io.openems.edge.common/src/io/openems/edge/common/currency/Currency.java @@ -44,5 +44,4 @@ public static Currency fromCurrencyConfig(CurrencyConfig config) { case CHF -> Currency.CHF; }; } - } diff --git a/io.openems.edge.common/src/io/openems/edge/common/host/Host.java b/io.openems.edge.common/src/io/openems/edge/common/host/Host.java index 3048111f0ad..304fc98d217 100644 --- a/io.openems.edge.common/src/io/openems/edge/common/host/Host.java +++ b/io.openems.edge.common/src/io/openems/edge/common/host/Host.java @@ -106,7 +106,7 @@ public default void _setHostname(String value) { * @throws OpenemsNamedException exception */ public List getSystemIPs() throws OpenemsNamedException; - + /** * Gets the Channel for {@link ChannelId#OS_VERSION}. * diff --git a/io.openems.edge.common/src/io/openems/edge/common/jsonapi/JsonApiBuilder.java b/io.openems.edge.common/src/io/openems/edge/common/jsonapi/JsonApiBuilder.java index e1c1cae8031..fef18e45bf0 100644 --- a/io.openems.edge.common/src/io/openems/edge/common/jsonapi/JsonApiBuilder.java +++ b/io.openems.edge.common/src/io/openems/edge/common/jsonapi/JsonApiBuilder.java @@ -531,11 +531,12 @@ private JsonrpcResponseError handleException(Call new JsonrpcResponseError(call.getRequest().getId(), ex); + default // + -> new JsonrpcResponseError(call.getRequest().getId(), t.getMessage()); + }; } private static final Key DEPTH = new Key("depth", Integer.class); diff --git a/io.openems.edge.common/src/io/openems/edge/common/jsonapi/MultipleJsonApiBinder.java b/io.openems.edge.common/src/io/openems/edge/common/jsonapi/MultipleJsonApiBinder.java index f051eaa18eb..369064bc85e 100644 --- a/io.openems.edge.common/src/io/openems/edge/common/jsonapi/MultipleJsonApiBinder.java +++ b/io.openems.edge.common/src/io/openems/edge/common/jsonapi/MultipleJsonApiBinder.java @@ -19,8 +19,8 @@ public class MultipleJsonApiBinder { * logs a warning. * *

    - * Commonly used like this with OSGi injection to bind all {@link JsonApi} - * which target the specific {@code ENTRY_POINT}:
    + * Commonly used like this with OSGi injection to bind all {@link JsonApi} which + * target the specific {@code ENTRY_POINT}:
    * *

     	 * {@code @Reference}(//
    diff --git a/io.openems.edge.common/src/io/openems/edge/common/jsonapi/SingleJsonApiBinder.java b/io.openems.edge.common/src/io/openems/edge/common/jsonapi/SingleJsonApiBinder.java
    index e13e2838e9e..941e9e6cec2 100644
    --- a/io.openems.edge.common/src/io/openems/edge/common/jsonapi/SingleJsonApiBinder.java
    +++ b/io.openems.edge.common/src/io/openems/edge/common/jsonapi/SingleJsonApiBinder.java
    @@ -1,5 +1,8 @@
     package io.openems.edge.common.jsonapi;
     
    +import static java.util.concurrent.CompletableFuture.completedFuture;
    +import static java.util.concurrent.CompletableFuture.failedFuture;
    +
     import java.util.concurrent.CompletableFuture;
     import java.util.function.Consumer;
     
    @@ -83,13 +86,14 @@ public CompletableFuture handleRequest(//
     			throw new OpenemsException("No response");
     		}
     
    -		if (response instanceof JsonrpcResponseSuccess success) {
    -			return CompletableFuture
    -					.completedFuture(new GenericJsonrpcResponseSuccess(request.getId(), success.getResult()));
    -		} else if (response instanceof JsonrpcResponseError error) {
    -			return CompletableFuture.failedFuture(error.getOpenemsError().exception(error.getParamsAsObjectArray()));
    -		}
    -		throw new OpenemsException("Unhandled response");
    +		return switch (response) {
    +		case JsonrpcResponseSuccess success //
    +			-> completedFuture(new GenericJsonrpcResponseSuccess(request.getId(), success.getResult()));
    +		case JsonrpcResponseError error //
    +			-> failedFuture(error.getOpenemsError().exception(error.getParamsAsObjectArray()));
    +		default //
    +			-> throw new OpenemsException("Unhandled response");
    +		};
     	}
     
     	public void setDebug(boolean debug) {
    diff --git a/io.openems.edge.common/src/io/openems/edge/common/modbusslave/ModbusRecordUint16.java b/io.openems.edge.common/src/io/openems/edge/common/modbusslave/ModbusRecordUint16.java
    index 3e2e751cde0..0c6801f6b84 100644
    --- a/io.openems.edge.common/src/io/openems/edge/common/modbusslave/ModbusRecordUint16.java
    +++ b/io.openems.edge.common/src/io/openems/edge/common/modbusslave/ModbusRecordUint16.java
    @@ -3,6 +3,7 @@
     import java.nio.ByteBuffer;
     
     import io.openems.common.types.OpenemsType;
    +import io.openems.common.types.OptionsEnum;
     import io.openems.edge.common.type.TypeUtils;
     
     public class ModbusRecordUint16 extends ModbusRecordConstant {
    @@ -40,8 +41,7 @@ public static byte[] toByteArray(short value) {
     	 * @return the byte array
     	 */
     	public static byte[] toByteArray(Object value) {
    -		if (value == null || value instanceof io.openems.common.types.OptionsEnum
    -				&& ((io.openems.common.types.OptionsEnum) value).isUndefined()) {
    +		if (value == null || (value instanceof OptionsEnum oe && oe.isUndefined())) {
     			return UNDEFINED_VALUE;
     		}
     		return toByteArray((short) TypeUtils.getAsType(OpenemsType.SHORT, value));
    diff --git a/io.openems.edge.common/src/io/openems/edge/common/modbusslave/ModbusRecordUint32.java b/io.openems.edge.common/src/io/openems/edge/common/modbusslave/ModbusRecordUint32.java
    index 23bae440c32..a7b7f19539f 100644
    --- a/io.openems.edge.common/src/io/openems/edge/common/modbusslave/ModbusRecordUint32.java
    +++ b/io.openems.edge.common/src/io/openems/edge/common/modbusslave/ModbusRecordUint32.java
    @@ -3,6 +3,7 @@
     import java.nio.ByteBuffer;
     
     import io.openems.common.types.OpenemsType;
    +import io.openems.common.types.OptionsEnum;
     import io.openems.edge.common.type.TypeUtils;
     
     public class ModbusRecordUint32 extends ModbusRecordConstant {
    @@ -40,8 +41,7 @@ public static byte[] toByteArray(int value) {
     	 * @return the byte array
     	 */
     	public static byte[] toByteArray(Object value) {
    -		if (value == null || value instanceof io.openems.common.types.OptionsEnum
    -				&& ((io.openems.common.types.OptionsEnum) value).isUndefined()) {
    +		if (value == null || (value instanceof OptionsEnum oe && oe.isUndefined())) {
     			return UNDEFINED_VALUE;
     		}
     		return toByteArray((int) TypeUtils.getAsType(OpenemsType.INTEGER, value));
    diff --git a/io.openems.edge.common/src/io/openems/edge/common/modbusslave/ModbusRecordUint64.java b/io.openems.edge.common/src/io/openems/edge/common/modbusslave/ModbusRecordUint64.java
    index 87ccc8e779d..c0f893e56f5 100644
    --- a/io.openems.edge.common/src/io/openems/edge/common/modbusslave/ModbusRecordUint64.java
    +++ b/io.openems.edge.common/src/io/openems/edge/common/modbusslave/ModbusRecordUint64.java
    @@ -3,6 +3,7 @@
     import java.nio.ByteBuffer;
     
     import io.openems.common.types.OpenemsType;
    +import io.openems.common.types.OptionsEnum;
     import io.openems.edge.common.type.TypeUtils;
     
     public class ModbusRecordUint64 extends ModbusRecordConstant {
    @@ -42,8 +43,7 @@ public static byte[] toByteArray(long value) {
     	 * @return the byte array
     	 */
     	public static byte[] toByteArray(Object value) {
    -		if (value == null || value instanceof io.openems.common.types.OptionsEnum
    -				&& ((io.openems.common.types.OptionsEnum) value).isUndefined()) {
    +		if (value == null || (value instanceof OptionsEnum oe && oe.isUndefined())) {
     			return UNDEFINED_VALUE;
     		}
     		return toByteArray((long) TypeUtils.getAsType(OpenemsType.LONG, value));
    diff --git a/io.openems.edge.common/src/io/openems/edge/common/sum/DummySum.java b/io.openems.edge.common/src/io/openems/edge/common/sum/DummySum.java
    index 2a2b9bd7568..64d093c8511 100644
    --- a/io.openems.edge.common/src/io/openems/edge/common/sum/DummySum.java
    +++ b/io.openems.edge.common/src/io/openems/edge/common/sum/DummySum.java
    @@ -93,4 +93,59 @@ public DummySum withEssMaxDischargePower(int value) {
     		return this.self();
     	}
     
    +	/**
    +	 * Set {@link Sum.ChannelId#GRID_BUY_ACTIVE_ENERGY}.
    +	 *
    +	 * @param value the value
    +	 * @return myself
    +	 */
    +	public DummySum withGridBuyActiveEnergy(long value) {
    +		withValue(this, Sum.ChannelId.GRID_BUY_ACTIVE_ENERGY, value);
    +		return this.self();
    +	}
    +
    +	/**
    +	 * Set {@link Sum.ChannelId#GRID_SELL_ACTIVE_ENERGY}.
    +	 *
    +	 * @param value the value
    +	 * @return myself
    +	 */
    +	public DummySum withGridSellActiveEnergy(long value) {
    +		withValue(this, Sum.ChannelId.GRID_SELL_ACTIVE_ENERGY, value);
    +		return this.self();
    +	}
    +
    +	/**
    +	 * Set {@link Sum.ChannelId#ESS_ACTIVE_CHARGE_ENERGY}.
    +	 *
    +	 * @param value the value
    +	 * @return myself
    +	 */
    +	public DummySum withEssActiveChargeEnergy(long value) {
    +		withValue(this, Sum.ChannelId.ESS_ACTIVE_CHARGE_ENERGY, value);
    +		return this.self();
    +	}
    +
    +	/**
    +	 * Set {@link Sum.ChannelId#ESS_ACTIVE_DISCHARGE_ENERGY}.
    +	 *
    +	 * @param value the value
    +	 * @return myself
    +	 */
    +	public DummySum withEssActiveDischargeEnergy(long value) {
    +		withValue(this, Sum.ChannelId.ESS_ACTIVE_DISCHARGE_ENERGY, value);
    +		return this.self();
    +	}
    +
    +	/**
    +	 * Set {@link Sum.ChannelId#CONSUMPTION_ACTIVE_ENERGY}.
    +	 *
    +	 * @param value the value
    +	 * @return myself
    +	 */
    +	public DummySum withConsumptionActiveEnergy(long value) {
    +		withValue(this, Sum.ChannelId.CONSUMPTION_ACTIVE_ENERGY, value);
    +		return this.self();
    +	}
    +
     }
    diff --git a/io.openems.edge.common/src/io/openems/edge/common/sum/Sum.java b/io.openems.edge.common/src/io/openems/edge/common/sum/Sum.java
    index b065cb50c18..c42c686cdc2 100644
    --- a/io.openems.edge.common/src/io/openems/edge/common/sum/Sum.java
    +++ b/io.openems.edge.common/src/io/openems/edge/common/sum/Sum.java
    @@ -398,7 +398,8 @@ public enum ChannelId implements io.openems.edge.common.channel.ChannelId {
     		 */
     		CONSUMPTION_ACTIVE_POWER(Doc.of(OpenemsType.INTEGER) //
     				.unit(Unit.WATT) //
    -				.persistencePriority(PersistencePriority.VERY_HIGH)), //
    +				.persistencePriority(PersistencePriority.VERY_HIGH) //
    +				.text("Active power of the electrical consumption")), //
     		/**
     		 * Consumption: Active Power L1.
     		 *
    @@ -413,7 +414,8 @@ public enum ChannelId implements io.openems.edge.common.channel.ChannelId {
     		 */
     		CONSUMPTION_ACTIVE_POWER_L1(Doc.of(OpenemsType.INTEGER) //
     				.unit(Unit.WATT) //
    -				.persistencePriority(PersistencePriority.VERY_HIGH)), //
    +				.persistencePriority(PersistencePriority.VERY_HIGH) //
    +				.text("Active power of the electrical consumption on phase L1")), //
     		/**
     		 * Consumption: Active Power L2.
     		 *
    @@ -428,7 +430,8 @@ public enum ChannelId implements io.openems.edge.common.channel.ChannelId {
     		 */
     		CONSUMPTION_ACTIVE_POWER_L2(Doc.of(OpenemsType.INTEGER) //
     				.unit(Unit.WATT) //
    -				.persistencePriority(PersistencePriority.VERY_HIGH)), //
    +				.persistencePriority(PersistencePriority.VERY_HIGH) //
    +				.text("Active power of the electrical consumption on phase L2")), //
     		/**
     		 * Consumption: Active Power L3.
     		 *
    @@ -443,7 +446,8 @@ public enum ChannelId implements io.openems.edge.common.channel.ChannelId {
     		 */
     		CONSUMPTION_ACTIVE_POWER_L3(Doc.of(OpenemsType.INTEGER) //
     				.unit(Unit.WATT) //
    -				.persistencePriority(PersistencePriority.VERY_HIGH)), //
    +				.persistencePriority(PersistencePriority.VERY_HIGH) //
    +				.text("Active power of the electrical consumption on phase L3")), //
     		/**
     		 * Consumption: Maximum Ever Active Power.
     		 *
    @@ -456,7 +460,8 @@ public enum ChannelId implements io.openems.edge.common.channel.ChannelId {
     		 */
     		CONSUMPTION_MAX_ACTIVE_POWER(Doc.of(OpenemsType.INTEGER) //
     				.unit(Unit.WATT) //
    -				.persistencePriority(PersistencePriority.VERY_HIGH)), //
    +				.persistencePriority(PersistencePriority.VERY_HIGH) //
    +				.text("Maximum measured active power of the electrical consumpton")), //
     		/**
     		 * Unmanaged Consumption: Active Power.
     		 *
    @@ -521,7 +526,8 @@ public enum ChannelId implements io.openems.edge.common.channel.ChannelId {
     		 */
     		ESS_ACTIVE_CHARGE_ENERGY(Doc.of(OpenemsType.LONG) //
     				.unit(Unit.CUMULATED_WATT_HOURS) //
    -				.persistencePriority(PersistencePriority.VERY_HIGH)), //
    +				.persistencePriority(PersistencePriority.VERY_HIGH) //
    +				.text("Accumulated electrical energy of the AC-side storage charging incl. excess PV generation at the hybrid inverter")), //
     		/**
     		 * Ess: Active Discharge Energy.
     		 *
    @@ -533,7 +539,8 @@ public enum ChannelId implements io.openems.edge.common.channel.ChannelId {
     		 */
     		ESS_ACTIVE_DISCHARGE_ENERGY(Doc.of(OpenemsType.LONG) //
     				.unit(Unit.CUMULATED_WATT_HOURS) //
    -				.persistencePriority(PersistencePriority.VERY_HIGH)), //
    +				.persistencePriority(PersistencePriority.VERY_HIGH) //
    +				.text("Accumulated electrical energy of the AC-side storage discharge incl. excess PV generation at the hybrid inverter")), //
     		/**
     		 * Ess: DC Discharge Energy.
     		 *
    @@ -545,7 +552,8 @@ public enum ChannelId implements io.openems.edge.common.channel.ChannelId {
     		 */
     		ESS_DC_DISCHARGE_ENERGY(Doc.of(OpenemsType.LONG) //
     				.unit(Unit.CUMULATED_WATT_HOURS) //
    -				.persistencePriority(PersistencePriority.VERY_HIGH)), //
    +				.persistencePriority(PersistencePriority.VERY_HIGH) //
    +				.text("Accumulated DC electrical energy of the storage discharging")), //
     		/**
     		 * Ess: DC Charge Energy.
     		 *
    @@ -557,7 +565,8 @@ public enum ChannelId implements io.openems.edge.common.channel.ChannelId {
     		 */
     		ESS_DC_CHARGE_ENERGY(Doc.of(OpenemsType.LONG) //
     				.unit(Unit.CUMULATED_WATT_HOURS) //
    -				.persistencePriority(PersistencePriority.VERY_HIGH)), //
    +				.persistencePriority(PersistencePriority.VERY_HIGH) //
    +				.text("Accumulated DC electrical energy of the storage charging")), //
     		/**
     		 * Grid: Buy-from-grid Energy ("Production").
     		 *
    @@ -569,7 +578,8 @@ public enum ChannelId implements io.openems.edge.common.channel.ChannelId {
     		 */
     		GRID_BUY_ACTIVE_ENERGY(Doc.of(OpenemsType.LONG) //
     				.unit(Unit.CUMULATED_WATT_HOURS) //
    -				.persistencePriority(PersistencePriority.VERY_HIGH)), //
    +				.persistencePriority(PersistencePriority.VERY_HIGH) //
    +				.text("Accumulated electrical energy of grid consumption")), //
     		/**
     		 * Grid: Sell-to-grid Energy ("Consumption").
     		 *
    @@ -581,7 +591,8 @@ public enum ChannelId implements io.openems.edge.common.channel.ChannelId {
     		 */
     		GRID_SELL_ACTIVE_ENERGY(Doc.of(OpenemsType.LONG) //
     				.unit(Unit.CUMULATED_WATT_HOURS) //
    -				.persistencePriority(PersistencePriority.VERY_HIGH)), //
    +				.persistencePriority(PersistencePriority.VERY_HIGH) //
    +				.text("Accumulated electrical energy of grid feed-in")), //
     		/**
     		 * Production: Energy.
     		 *
    @@ -592,7 +603,8 @@ public enum ChannelId implements io.openems.edge.common.channel.ChannelId {
     		 */
     		PRODUCTION_ACTIVE_ENERGY(Doc.of(OpenemsType.LONG) //
     				.unit(Unit.CUMULATED_WATT_HOURS) //
    -				.persistencePriority(PersistencePriority.VERY_HIGH)), //
    +				.persistencePriority(PersistencePriority.VERY_HIGH) //
    +				.text("Accumulated electrical energy of DC- and AC-side generators, e.g. photovoltaics")), //
     		/**
     		 * Production: AC Energy.
     		 *
    @@ -604,7 +616,8 @@ public enum ChannelId implements io.openems.edge.common.channel.ChannelId {
     		 */
     		PRODUCTION_AC_ACTIVE_ENERGY(Doc.of(OpenemsType.LONG) //
     				.unit(Unit.CUMULATED_WATT_HOURS) //
    -				.persistencePriority(PersistencePriority.VERY_HIGH)), //
    +				.persistencePriority(PersistencePriority.VERY_HIGH) //
    +				.text("Accumulated electrical energy of AC-side generators")), //
     		/**
     		 * Production: DC Energy.
     		 *
    @@ -616,7 +629,8 @@ public enum ChannelId implements io.openems.edge.common.channel.ChannelId {
     		 */
     		PRODUCTION_DC_ACTIVE_ENERGY(Doc.of(OpenemsType.LONG) //
     				.unit(Unit.CUMULATED_WATT_HOURS) //
    -				.persistencePriority(PersistencePriority.VERY_HIGH)), //
    +				.persistencePriority(PersistencePriority.VERY_HIGH) //
    +				.text("Accumulated electrical energy of DC-side generators")), //
     		/**
     		 * Consumption: Energy.
     		 *
    @@ -628,7 +642,8 @@ public enum ChannelId implements io.openems.edge.common.channel.ChannelId {
     		 */
     		CONSUMPTION_ACTIVE_ENERGY(Doc.of(OpenemsType.LONG) //
     				.unit(Unit.CUMULATED_WATT_HOURS) //
    -				.persistencePriority(PersistencePriority.VERY_HIGH)), //
    +				.persistencePriority(PersistencePriority.VERY_HIGH) //
    +				.text("Accumulated electrical energy consumption")), //
     
     		/**
     		 * Is there any Component Info/Warning/Fault that is getting ignored/hidden
    diff --git a/io.openems.edge.common/src/io/openems/edge/common/test/AbstractComponentTest.java b/io.openems.edge.common/src/io/openems/edge/common/test/AbstractComponentTest.java
    index 9096c7d91ef..07e2f9201d3 100644
    --- a/io.openems.edge.common/src/io/openems/edge/common/test/AbstractComponentTest.java
    +++ b/io.openems.edge.common/src/io/openems/edge/common/test/AbstractComponentTest.java
    @@ -1,8 +1,16 @@
     package io.openems.edge.common.test;
     
    +import static io.openems.common.utils.FunctionUtils.doNothing;
     import static io.openems.common.utils.ReflectionUtils.invokeMethodViaReflection;
     import static io.openems.common.utils.ReflectionUtils.invokeMethodWithoutArgumentsViaReflection;
     import static io.openems.common.utils.ReflectionUtils.setAttributeViaReflection;
    +import static io.openems.edge.common.event.EdgeEventConstants.TOPIC_CYCLE_AFTER_CONTROLLERS;
    +import static io.openems.edge.common.event.EdgeEventConstants.TOPIC_CYCLE_AFTER_PROCESS_IMAGE;
    +import static io.openems.edge.common.event.EdgeEventConstants.TOPIC_CYCLE_AFTER_WRITE;
    +import static io.openems.edge.common.event.EdgeEventConstants.TOPIC_CYCLE_BEFORE_CONTROLLERS;
    +import static io.openems.edge.common.event.EdgeEventConstants.TOPIC_CYCLE_BEFORE_PROCESS_IMAGE;
    +import static io.openems.edge.common.event.EdgeEventConstants.TOPIC_CYCLE_BEFORE_WRITE;
    +import static io.openems.edge.common.event.EdgeEventConstants.TOPIC_CYCLE_EXECUTE_WRITE;
     
     import java.io.IOException;
     import java.lang.reflect.InvocationTargetException;
    @@ -23,7 +31,6 @@
     
     import org.osgi.framework.BundleContext;
     import org.osgi.framework.InvalidSyntaxException;
    -import org.osgi.service.cm.Configuration;
     import org.osgi.service.cm.ConfigurationAdmin;
     import org.osgi.service.component.ComponentContext;
     import org.osgi.service.event.Event;
    @@ -542,8 +549,7 @@ protected void validateOutputs(AbstractComponentTest act) throws Exception
     					readWriteInfo = "ReadValue";
     				}
     				// Try to parse an Enum
    -				if (channel.channelDoc() instanceof EnumDoc) {
    -					var enumDoc = (EnumDoc) channel.channelDoc();
    +				if (channel.channelDoc() instanceof EnumDoc enumDoc) {
     					var intGot = TypeUtils.getAsType(OpenemsType.INTEGER, got);
     					got = enumDoc.getOption(intGot);
     				}
    @@ -569,25 +575,22 @@ private OpenemsComponent getComponent(Map components,
     
     		private Channel getChannel(AbstractComponentTest act, ChannelValue cv)
     				throws IllegalArgumentException {
    -			if (cv instanceof ChannelAddressValue cav) {
    +			return switch (cv) {
    +			case ChannelAddressValue cav -> {
     				var component = this.getComponent(act.components, cav.address.getComponentId());
    -				return component.channel(cav.address.getChannelId());
    +				yield component.channel(cav.address.getChannelId());
     			}
    -
    -			if (cv instanceof ChannelIdValue civ) {
    -				return act.sut.channel(civ.channelId);
    -			}
    -
    -			if (cv instanceof ChannelNameValue civ2) {
    -				return act.sut.channel(civ2.channelName);
    -			}
    -
    -			if (cv instanceof ComponentChannelIdValue cciv) {
    +			case ChannelIdValue civ //
    +				-> act.sut.channel(civ.channelId);
    +			case ChannelNameValue civ2 //
    +				-> act.sut.channel(civ2.channelName);
    +			case ComponentChannelIdValue cciv -> {
     				var component = this.getComponent(act.components, cciv.componentId());
    -				return component.channel(cciv.channelId());
    +				yield component.channel(cciv.channelId());
     			}
    -
    -			throw new IllegalArgumentException("Unhandled subtype of ChannelValue");
    +			default //
    +				-> throw new IllegalArgumentException("Unhandled subtype of ChannelValue");
    +			};
     		}
     	}
     
    @@ -688,23 +691,25 @@ public SELF addReference(String memberName, Object object) throws Exception {
     		// Store reference
     		this.references.add(object);
     
    -		// If this is a DummyComponentManager -> fill it with existing Components
    -		if (object instanceof DummyComponentManager) {
    -			for (OpenemsComponent component : this.components.values()) {
    -				((DummyComponentManager) object).addComponent(component);
    -			}
    -		}
    -		// If this is an OpenemsComponent -> store it for later
    -		if (object instanceof OpenemsComponent) {
    -			this.addComponent((OpenemsComponent) object);
    -		}
    -		if (object instanceof Collection) {
    -			for (Object o : (Collection) object) {
    -				if (o instanceof OpenemsComponent) {
    -					this.addComponent((OpenemsComponent) o);
    -				}
    -			}
    +		switch (object) {
    +		case DummyComponentManager dcm ->
    +			// If this is a DummyComponentManager -> fill it with existing Components
    +			this.components.values() //
    +					.forEach(dcm::addComponent);
    +
    +		case OpenemsComponent oc ->
    +			// If this is an OpenemsComponent -> store it for later
    +			this.addComponent(oc);
    +
    +		case Collection os -> //
    +			os.stream() //
    +					.filter(OpenemsComponent.class::isInstance) //
    +					.map(OpenemsComponent.class::cast) //
    +					.forEach(this::addComponent);
    +
    +		case null, default -> doNothing();
     		}
    +
     		return this.self();
     	}
     
    @@ -741,11 +746,11 @@ public SELF addComponent(OpenemsComponent component) {
     		this.components.put(component.id(), component);
     
     		// Is a DummyComponentManager present -> add this Component
    -		for (Object object : this.references) {
    -			if (object instanceof DummyComponentManager) {
    -				((DummyComponentManager) object).addComponent(component);
    -			}
    -		}
    +		this.references.stream() //
    +				.filter(DummyComponentManager.class::isInstance) //
    +				.map(DummyComponentManager.class::cast) //
    +				.forEach(dcm -> dcm.addComponent(component));
    +
     		return this.self();
     	}
     
    @@ -763,8 +768,7 @@ public SELF addComponent(OpenemsComponent component) {
     	public SELF activate(AbstractComponentConfig config) throws Exception {
     		// Add the configuration to ConfigurationAdmin
     		for (Object object : this.references) {
    -			if (object instanceof DummyConfigurationAdmin) {
    -				var cm = (DummyConfigurationAdmin) object;
    +			if (object instanceof DummyConfigurationAdmin cm) {
     				cm.addConfig(config);
     			}
     		}
    @@ -795,11 +799,9 @@ public SELF deactivate() throws Exception {
     
     	private int getConfigChangeCount() throws IOException, InvalidSyntaxException {
     		var result = 0;
    -		for (Object object : this.references) {
    -			if (object instanceof ConfigurationAdmin) {
    -				var cm = (ConfigurationAdmin) object;
    -				var configs = cm.listConfigurations(null);
    -				for (Configuration config : configs) {
    +		for (var object : this.references) {
    +			if (object instanceof ConfigurationAdmin cm) {
    +				for (var config : cm.listConfigurations(null)) {
     					result += config.getChangeCount();
     				}
     			}
    @@ -900,31 +902,30 @@ public SELF next(TestCase testCase) throws Exception {
     		testCase.applyTimeLeap();
     		this.onBeforeProcessImage();
     		executeCallbacks(testCase.onBeforeProcessImageCallbacks);
    -		this.handleEvent(EdgeEventConstants.TOPIC_CYCLE_BEFORE_PROCESS_IMAGE);
    -		for (Channel channel : this.getSut().channels()) {
    -			channel.nextProcessImage();
    -		}
    +		this.handleEvent(TOPIC_CYCLE_BEFORE_PROCESS_IMAGE);
    +		this.sut.channels() //
    +				.forEach(Channel::nextProcessImage);
     		testCase.applyInputs(this);
     		this.onAfterProcessImage();
     		executeCallbacks(testCase.onAfterProcessImageCallbacks);
    -		this.handleEvent(EdgeEventConstants.TOPIC_CYCLE_AFTER_PROCESS_IMAGE);
    +		this.handleEvent(TOPIC_CYCLE_AFTER_PROCESS_IMAGE);
     		this.onBeforeControllers();
     		executeCallbacks(testCase.onBeforeControllersCallbacks);
    -		this.handleEvent(EdgeEventConstants.TOPIC_CYCLE_BEFORE_CONTROLLERS);
    +		this.handleEvent(TOPIC_CYCLE_BEFORE_CONTROLLERS);
     		this.onExecuteControllers();
     		executeCallbacks(testCase.onExecuteControllersCallbacks);
     		this.onAfterControllers();
     		executeCallbacks(testCase.onAfterControllersCallbacks);
    -		this.handleEvent(EdgeEventConstants.TOPIC_CYCLE_AFTER_CONTROLLERS);
    +		this.handleEvent(TOPIC_CYCLE_AFTER_CONTROLLERS);
     		this.onBeforeWrite();
     		executeCallbacks(testCase.onBeforeWriteCallbacks);
    -		this.handleEvent(EdgeEventConstants.TOPIC_CYCLE_BEFORE_WRITE);
    +		this.handleEvent(TOPIC_CYCLE_BEFORE_WRITE);
     		this.onExecuteWrite();
     		executeCallbacks(testCase.onExecuteWriteCallbacks);
    -		this.handleEvent(EdgeEventConstants.TOPIC_CYCLE_EXECUTE_WRITE);
    +		this.handleEvent(TOPIC_CYCLE_EXECUTE_WRITE);
     		this.onAfterWrite();
     		executeCallbacks(testCase.onAfterWriteCallbacks);
    -		this.handleEvent(EdgeEventConstants.TOPIC_CYCLE_AFTER_WRITE);
    +		this.handleEvent(TOPIC_CYCLE_AFTER_WRITE);
     		testCase.validateOutputs(this);
     		return this.self();
     	}
    diff --git a/io.openems.edge.common/src/io/openems/edge/common/test/DummyComponentManager.java b/io.openems.edge.common/src/io/openems/edge/common/test/DummyComponentManager.java
    index db5ebb96825..63c3ba3d539 100644
    --- a/io.openems.edge.common/src/io/openems/edge/common/test/DummyComponentManager.java
    +++ b/io.openems.edge.common/src/io/openems/edge/common/test/DummyComponentManager.java
    @@ -1,6 +1,7 @@
     package io.openems.edge.common.test;
     
    -import static io.openems.edge.common.test.TestUtils.createDummyClock;
    +import static io.openems.common.test.TestUtils.createDummyClock;
    +import static java.util.Collections.unmodifiableList;
     
     import java.io.IOException;
     import java.time.Clock;
    @@ -9,6 +10,9 @@
     import java.util.Collections;
     import java.util.Hashtable;
     import java.util.List;
    +import java.util.Map;
    +import java.util.Map.Entry;
    +import java.util.stream.Collectors;
     
     import org.osgi.framework.InvalidSyntaxException;
     import org.osgi.service.cm.ConfigurationAdmin;
    @@ -25,10 +29,10 @@
     import io.openems.common.jsonrpc.request.DeleteComponentConfigRequest;
     import io.openems.common.jsonrpc.request.GetEdgeConfigRequest;
     import io.openems.common.jsonrpc.request.UpdateComponentConfigRequest;
    -import io.openems.common.jsonrpc.request.UpdateComponentConfigRequest.Property;
     import io.openems.common.jsonrpc.response.GetEdgeConfigResponse;
     import io.openems.common.types.EdgeConfig;
     import io.openems.common.utils.JsonUtils;
    +import io.openems.common.utils.StreamUtils;
     import io.openems.edge.common.channel.Channel;
     import io.openems.edge.common.component.ComponentManager;
     import io.openems.edge.common.component.OpenemsComponent;
    @@ -58,12 +62,12 @@ public DummyComponentManager(Clock clock) {
     
     	@Override
     	public List getEnabledComponents() {
    -		return Collections.unmodifiableList(this.components);
    +		return unmodifiableList(this.components);
     	}
     
     	@Override
     	public List getAllComponents() {
    -		return Collections.unmodifiableList(this.components);
    +		return unmodifiableList(this.components);
     	}
     
     	@Override
    @@ -199,9 +203,9 @@ public void handleCreateComponentConfigRequest(User user, CreateComponentConfigR
     			var config = this.configurationAdmin.createFactoryConfiguration(request.getFactoryPid(), null);
     
     			// set properties
    -			for (Property property : request.getProperties()) {
    +			for (var property : request.getProperties()) {
     				var value = JsonUtils.getAsBestType(property.getValue());
    -				if (value instanceof Object[] && ((Object[]) value).length == 0) {
    +				if (value instanceof Object[] os && os.length == 0) {
     					value = new String[0];
     				}
     				config.getProperties().put(property.getName(), value);
    @@ -271,4 +275,15 @@ public void setConfigurationAdmin(ConfigurationAdmin configurationAdmin) {
     		this.configurationAdmin = configurationAdmin;
     	}
     
    +	@Override
    +	public Map getComponentProperties(String componentId) {
    +		try {
    +			var component = this.getComponent(componentId);
    +			return StreamUtils.dictionaryToStream(component.getComponentContext().getProperties())//
    +					.collect(Collectors.toMap(Entry::getKey, Entry::getValue));
    +		} catch (OpenemsNamedException e) {
    +			return Collections.emptyMap();
    +		}
    +	}
    +
     }
    \ No newline at end of file
    diff --git a/io.openems.edge.common/src/io/openems/edge/common/test/Plot.java b/io.openems.edge.common/src/io/openems/edge/common/test/Plot.java
    index d6a73e22d47..e54440b033d 100644
    --- a/io.openems.edge.common/src/io/openems/edge/common/test/Plot.java
    +++ b/io.openems.edge.common/src/io/openems/edge/common/test/Plot.java
    @@ -1022,24 +1022,16 @@ else if (vAlign == VertAlign.CENTER)
     	}
     
     	public static String formatDouble(double d, AxisFormat format) {
    -		switch (format) {
    -		case TIME_HM:
    -			return String.format("%tR", new java.util.Date((long) d));
    -		case TIME_HMS:
    -			return String.format("%tT", new java.util.Date((long) d));
    -		case DATE:
    -			return String.format("%tF", new java.util.Date((long) d));
    -		case DATETIME_HM:
    -			return String.format("%tF %1$tR", new java.util.Date((long) d));
    -		case DATETIME_HMS:
    -			return String.format("%tF %1$tT", new java.util.Date((long) d));
    -		case NUMBER_KGM:
    -			return formatDoubleAsNumber(d, true);
    -		case NUMBER_INT:
    -			return Integer.toString((int) d);
    -		default:
    -			return formatDoubleAsNumber(d, false);
    -		}
    +		return switch (format) {
    +		case TIME_HM -> String.format("%tR", new java.util.Date((long) d));
    +		case TIME_HMS -> String.format("%tT", new java.util.Date((long) d));
    +		case DATE -> String.format("%tF", new java.util.Date((long) d));
    +		case DATETIME_HM -> String.format("%tF %1$tR", new java.util.Date((long) d));
    +		case DATETIME_HMS -> String.format("%tF %1$tT", new java.util.Date((long) d));
    +		case NUMBER_KGM -> formatDoubleAsNumber(d, true);
    +		case NUMBER_INT -> Integer.toString((int) d);
    +		default -> formatDoubleAsNumber(d, false);
    +		};
     	}
     
     	private static String formatDoubleAsNumber(double d, boolean useKGM) {
    diff --git a/io.openems.edge.common/src/io/openems/edge/common/test/TestUtils.java b/io.openems.edge.common/src/io/openems/edge/common/test/TestUtils.java
    index 4cb54a3f37e..5f99649086e 100644
    --- a/io.openems.edge.common/src/io/openems/edge/common/test/TestUtils.java
    +++ b/io.openems.edge.common/src/io/openems/edge/common/test/TestUtils.java
    @@ -1,12 +1,8 @@
     package io.openems.edge.common.test;
     
    -import java.io.IOException;
    -import java.net.ServerSocket;
    -import java.time.Instant;
     import java.util.function.BiFunction;
     import java.util.function.Function;
     
    -import io.openems.common.test.TimeLeapClock;
     import io.openems.edge.common.channel.Channel;
     import io.openems.edge.common.channel.ChannelId;
     import io.openems.edge.common.channel.value.Value;
    @@ -15,31 +11,6 @@
     public class TestUtils {
     
     	private TestUtils() {
    -
    -	}
    -
    -	/**
    -	 * Creates a {@link TimeLeapClock} for 1st January 2000 00:00.
    -	 * 
    -	 * @return the {@link TimeLeapClock}
    -	 */
    -	public static TimeLeapClock createDummyClock() {
    -		return new TimeLeapClock(Instant.ofEpochSecond(1577836800) /* starts at 1. January 2020 00:00:00 */);
    -	}
    -
    -	/**
    -	 * Finds and returns an open port.
    -	 *
    -	 * 

    - * Source https://stackoverflow.com/a/26644672 - * - * @return an open port - * @throws IOException on error - */ - public static int findRandomOpenPortOnAllLocalInterfaces() throws IOException { - try (var socket = new ServerSocket(0);) { - return socket.getLocalPort(); - } } /** diff --git a/io.openems.edge.common/src/io/openems/edge/common/type/TypeUtils.java b/io.openems.edge.common/src/io/openems/edge/common/type/TypeUtils.java index d43a8bc6716..a468d55e6a7 100644 --- a/io.openems.edge.common/src/io/openems/edge/common/type/TypeUtils.java +++ b/io.openems.edge.common/src/io/openems/edge/common/type/TypeUtils.java @@ -43,16 +43,16 @@ public static T getAsType(OpenemsType type, Object value) throws IllegalArgu } // Extract OptionsEnum if (value instanceof OptionsEnum oe) { - value = oe.getValue(); + return getAsType(type, oe.getValue()); } // Extract Enum (lower priority than OptionsEnum) if (value instanceof Enum e) { - value = e.ordinal(); + return getAsType(type, e.ordinal()); } // Extract value from Array if (type != OpenemsType.STRING && value != null && value.getClass().isArray()) { if (Array.getLength(value) == 1) { - return TypeUtils.getAsType(type, Array.get(value, 0)); + return getAsType(type, Array.get(value, 0)); } return null; } @@ -66,26 +66,15 @@ public static T getAsType(OpenemsType type, Object value) throws IllegalArgu } return (T) switch (type) { - case BOOLEAN -> { - if (value instanceof Boolean b) { - yield b; - - } else if (value instanceof Short s) { - yield s == 0 ? Boolean.FALSE : Boolean.TRUE; - - } else if (value instanceof Integer i) { - yield i == 0 ? Boolean.FALSE : Boolean.TRUE; - - } else if (value instanceof Long l) { - yield l == 0 ? Boolean.FALSE : Boolean.TRUE; - - } else if (value instanceof Float f) { - yield f == 0 ? Boolean.FALSE : Boolean.TRUE; - - } else if (value instanceof Double d) { - yield d == 0 ? Boolean.FALSE : Boolean.TRUE; - - } else if (value instanceof String s) { + case BOOLEAN // + -> switch (value) { + case Boolean b -> b; + case Short s -> s == 0 ? Boolean.FALSE : Boolean.TRUE; + case Integer i -> i == 0 ? Boolean.FALSE : Boolean.TRUE; + case Long l -> l == 0 ? Boolean.FALSE : Boolean.TRUE; + case Float f -> f == 0 ? Boolean.FALSE : Boolean.TRUE; + case Double d -> d == 0 ? Boolean.FALSE : Boolean.TRUE; + case String s -> { if (s.isEmpty()) { yield null; } else if (s.equalsIgnoreCase("false")) { @@ -96,17 +85,14 @@ public static T getAsType(OpenemsType type, Object value) throws IllegalArgu throw new IllegalArgumentException("Cannot convert String [" + s + "] to Boolean."); } } - throw converterIsNotImplemented(type, value); - } - - case SHORT -> { - if (value instanceof Boolean b) { - yield Short.valueOf(b ? (short) 1 : (short) 0); - - } else if (value instanceof Short s) { - yield s; - - } else if (value instanceof Integer i) { + default -> throw converterIsNotImplemented(type, value); + }; + + case SHORT // + -> switch (value) { + case Boolean b -> Short.valueOf(b ? (short) 1 : (short) 0); + case Short s -> s; + case Integer i -> { var intValue = i.intValue(); if (intValue >= Short.MIN_VALUE && intValue <= Short.MAX_VALUE) { yield Short.valueOf((short) intValue); @@ -114,8 +100,8 @@ public static T getAsType(OpenemsType type, Object value) throws IllegalArgu throw new IllegalArgumentException( "Cannot convert. Integer [" + value + "] is not fitting in Short range."); } - - } else if (value instanceof Long l) { + } + case Long l -> { var longValue = l.longValue(); if (longValue >= Short.MIN_VALUE && longValue <= Short.MAX_VALUE) { yield Short.valueOf((short) longValue); @@ -123,8 +109,8 @@ public static T getAsType(OpenemsType type, Object value) throws IllegalArgu throw new IllegalArgumentException( "Cannot convert. Long [" + value + "] is not fitting in Short range."); } - - } else if (value instanceof Float f) { + } + case Float f -> { var intValue = Math.round(f.floatValue()); if (intValue >= Short.MIN_VALUE && intValue <= Short.MAX_VALUE) { yield Short.valueOf((short) intValue); @@ -132,8 +118,8 @@ public static T getAsType(OpenemsType type, Object value) throws IllegalArgu throw new IllegalArgumentException( "Cannot convert. Float [" + value + "] is not fitting in Short range."); } - - } else if (value instanceof Double d) { + } + case Double d -> { var longValue = Math.round(d.doubleValue()); if (longValue >= Short.MIN_VALUE && longValue <= Short.MAX_VALUE) { yield Short.valueOf((short) longValue); @@ -141,8 +127,8 @@ public static T getAsType(OpenemsType type, Object value) throws IllegalArgu throw new IllegalArgumentException( "Cannot convert. Double [" + value + "] is not fitting in Short range."); } - - } else if (value instanceof String s) { + } + case String s -> { if (s.isEmpty()) { yield null; } @@ -152,20 +138,15 @@ public static T getAsType(OpenemsType type, Object value) throws IllegalArgu throw new IllegalArgumentException("Cannot convert String [" + s + "] to Short."); } } - throw converterIsNotImplemented(type, value); - } - - case INTEGER -> { - if (value instanceof Boolean b) { - yield Integer.valueOf(b ? 1 : 0); - - } else if (value instanceof Short s) { - yield Integer.valueOf(s); - - } else if (value instanceof Integer i) { - yield i; - - } else if (value instanceof Long l) { + default -> throw converterIsNotImplemented(type, value); + }; + + case INTEGER // + -> switch (value) { + case Boolean b -> Integer.valueOf(b ? 1 : 0); + case Short s -> Integer.valueOf(s); + case Integer i -> i; + case Long l -> { var longValue = l.longValue(); if (longValue >= Integer.MIN_VALUE && longValue <= Integer.MAX_VALUE) { yield Integer.valueOf((int) longValue); @@ -173,8 +154,8 @@ public static T getAsType(OpenemsType type, Object value) throws IllegalArgu throw new IllegalArgumentException( "Cannot convert. Long [" + value + "] is not fitting in Integer range."); } - - } else if (value instanceof Float f) { + } + case Float f -> { var floatValue = f.floatValue(); if (floatValue >= Integer.MIN_VALUE && floatValue <= Integer.MAX_VALUE) { yield Integer.valueOf((int) floatValue); @@ -182,8 +163,8 @@ public static T getAsType(OpenemsType type, Object value) throws IllegalArgu throw new IllegalArgumentException( "Cannot convert. Float [" + value + "] is not fitting in Integer range."); } - - } else if (value instanceof Double d) { + } + case Double d -> { var longValue = Math.round(d.doubleValue()); if (longValue >= Integer.MIN_VALUE && longValue <= Integer.MAX_VALUE) { yield Integer.valueOf((int) longValue); @@ -191,8 +172,8 @@ public static T getAsType(OpenemsType type, Object value) throws IllegalArgu throw new IllegalArgumentException( "Cannot convert. Double [" + value + "] is not fitting in Integer range."); } - - } else if (value instanceof String s) { + } + case String s -> { if (s.isEmpty()) { yield null; } @@ -202,23 +183,16 @@ public static T getAsType(OpenemsType type, Object value) throws IllegalArgu throw new IllegalArgumentException("Cannot convert String [" + s + "] to Integer."); } } - throw converterIsNotImplemented(type, value); - } - - case LONG -> { - if (value instanceof Boolean b) { - yield Long.valueOf(b ? 1L : 0L); - - } else if (value instanceof Short s) { - yield (Long) s.longValue(); - - } else if (value instanceof Integer i) { - yield (Long) i.longValue(); - - } else if (value instanceof Long l) { - yield l; - - } else if (value instanceof Float f) { + default -> throw converterIsNotImplemented(type, value); + }; + + case LONG // + -> switch (value) { + case Boolean b -> Long.valueOf(b ? 1L : 0L); + case Short s -> (Long) s.longValue(); + case Integer i -> (Long) i.longValue(); + case Long l -> l; + case Float f -> { var floatValue = f.floatValue(); if (floatValue >= Long.MIN_VALUE && floatValue <= Long.MAX_VALUE) { yield Long.valueOf((long) floatValue); @@ -226,8 +200,8 @@ public static T getAsType(OpenemsType type, Object value) throws IllegalArgu throw new IllegalArgumentException( "Cannot convert. Float [" + value + "] is not fitting in Long range."); } - - } else if (value instanceof Double d) { + } + case Double d -> { var doubleValue = d.doubleValue(); if (doubleValue >= Long.MIN_VALUE && doubleValue <= Long.MAX_VALUE) { yield (Long) Math.round(d.doubleValue()); @@ -235,8 +209,8 @@ public static T getAsType(OpenemsType type, Object value) throws IllegalArgu throw new IllegalArgumentException( "Cannot convert. Double [" + value + "] is not fitting in Long range."); } - - } else if (value instanceof String s) { + } + case String s -> { if (s.isEmpty()) { yield null; } @@ -246,31 +220,21 @@ public static T getAsType(OpenemsType type, Object value) throws IllegalArgu throw new IllegalArgumentException("Cannot convert String [" + s + "] to Long."); } } - throw converterIsNotImplemented(type, value); - } - - case FLOAT -> { - if (value instanceof Boolean b) { - yield Float.valueOf(b ? 1f : 0f); - - } else if (value instanceof Short s) { - yield (Float) s.floatValue(); - - } else if (value instanceof Integer i) { - yield (Float) i.floatValue(); - - } else if (value instanceof Long l) { - yield (Float) l.floatValue(); - - } else if (value instanceof Float f) { - yield f; - - } else if (value instanceof Double d) { + default -> throw converterIsNotImplemented(type, value); + }; + + case FLOAT // + -> switch (value) { + case Boolean b -> Float.valueOf(b ? 1f : 0f); + case Short s -> (Float) s.floatValue(); + case Integer i -> (Float) i.floatValue(); + case Long l -> (Float) l.floatValue(); + case Float f -> f; + case Double d -> // Returns the value of this Double as a float after a narrowing primitive // conversion. - yield Float.valueOf(d.floatValue()); - - } else if (value instanceof String s) { + Float.valueOf(d.floatValue()); + case String s -> { if (s.isEmpty()) { yield null; } @@ -280,29 +244,18 @@ public static T getAsType(OpenemsType type, Object value) throws IllegalArgu throw new IllegalArgumentException("Cannot convert String [" + s + "] to Float."); } } - throw converterIsNotImplemented(type, value); - } - - case DOUBLE -> { - if (value instanceof Boolean b) { - yield Double.valueOf(b ? 1L : 0L); - - } else if (value instanceof Short s) { - yield Double.valueOf(s); - - } else if (value instanceof Integer i) { - yield Double.valueOf(i); - - } else if (value instanceof Long l) { - yield Double.valueOf(l); - - } else if (value instanceof Float f) { - yield Double.valueOf(f); - - } else if (value instanceof Double d) { - yield d; - - } else if (value instanceof String s) { + default -> throw converterIsNotImplemented(type, value); + }; + + case DOUBLE // + -> switch (value) { + case Boolean b -> Double.valueOf(b ? 1L : 0L); + case Short s -> Double.valueOf(s); + case Integer i -> Double.valueOf(i); + case Long l -> Double.valueOf(l); + case Float f -> Double.valueOf(f); + case Double d -> d; + case String s -> { if (s.isEmpty()) { yield null; } @@ -312,33 +265,25 @@ public static T getAsType(OpenemsType type, Object value) throws IllegalArgu throw new IllegalArgumentException("Cannot convert String [" + s + "] to Double."); } } - throw converterIsNotImplemented(type, value); - } + default -> throw converterIsNotImplemented(type, value); + }; case STRING -> { - if (value instanceof Object[]) { - yield Arrays.deepToString((Object[]) value); + if (value instanceof Object[] os) { + yield Arrays.deepToString(os); } else if (value.getClass().isArray()) { - if (value instanceof boolean[]) { - yield Arrays.toString((boolean[]) value); - } else if (value instanceof byte[]) { - yield Arrays.toString((byte[]) value); - } else if (value instanceof char[]) { - yield Arrays.toString((char[]) value); - } else if (value instanceof double[]) { - yield Arrays.toString((double[]) value); - } else if (value instanceof float[]) { - yield Arrays.toString((float[]) value); - } else if (value instanceof int[]) { - yield Arrays.toString((int[]) value); - } else if (value instanceof long[]) { - yield Arrays.toString((long[]) value); - } else if (value instanceof short[]) { - yield Arrays.toString((short[]) value); - } else { - yield value.toString(); - } + yield switch (value) { + case boolean[] bs -> Arrays.toString(bs); + case byte[] bs -> Arrays.toString(bs); + case char[] cs -> Arrays.toString(cs); + case double[] ds -> Arrays.toString(ds); + case float[] fs -> Arrays.toString(fs); + case int[] is -> Arrays.toString(is); + case long[] ls -> Arrays.toString(ls); + case short[] ss -> Arrays.toString(ss); + default -> value.toString(); + }; } else { yield value.toString(); diff --git a/io.openems.edge.common/test/io/openems/edge/common/jsonapi/CallTest.java b/io.openems.edge.common/test/io/openems/edge/common/jsonapi/CallTest.java index 56a1820b518..3b3b4125502 100644 --- a/io.openems.edge.common/test/io/openems/edge/common/jsonapi/CallTest.java +++ b/io.openems.edge.common/test/io/openems/edge/common/jsonapi/CallTest.java @@ -43,7 +43,7 @@ public void testMapRequest() { class DummyRequestClass { } - + final var dummyRequest = new DummyRequestClass(); final var newCall = call.mapRequest(dummyRequest); @@ -58,7 +58,7 @@ public void testMapResponse() { class DummyResponseClass { } - + final var mappedCall = call.mapResponse(); final var originalResponse = new GenericJsonrpcResponseSuccess(call.getRequest().getId()); diff --git a/io.openems.edge.common/test/io/openems/edge/common/type/QuarterlyValuesTest.java b/io.openems.edge.common/test/io/openems/edge/common/type/QuarterlyValuesTest.java index b418b9bb1a9..56e5cf9032d 100644 --- a/io.openems.edge.common/test/io/openems/edge/common/type/QuarterlyValuesTest.java +++ b/io.openems.edge.common/test/io/openems/edge/common/type/QuarterlyValuesTest.java @@ -1,5 +1,6 @@ package io.openems.edge.common.type; +import static io.openems.common.test.TestUtils.createDummyClock; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNull; @@ -11,8 +12,6 @@ import com.google.common.collect.ImmutableSortedMap; -import io.openems.edge.common.test.TestUtils; - public class QuarterlyValuesTest { private static class MyQuarterlyValues extends QuarterlyValues { @@ -32,14 +31,14 @@ protected Double[] asArray() { @Test(expected = IllegalArgumentException.class) public void testExpectError() { - var time = ZonedDateTime.now(TestUtils.createDummyClock()); + var time = ZonedDateTime.now(createDummyClock()); new MyQuarterlyValues(ImmutableSortedMap.of(// time.plusMinutes(1), 0.1)); } @Test public void testEmpty() { - var time = ZonedDateTime.now(TestUtils.createDummyClock()); + var time = ZonedDateTime.now(createDummyClock()); var sut = new MyQuarterlyValues(time); assertTrue(sut.isEmpty()); assertNull(sut.getFirst()); @@ -53,7 +52,7 @@ public void testEmpty() { @Test public void test() { - var time = ZonedDateTime.now(TestUtils.createDummyClock()); + var time = ZonedDateTime.now(createDummyClock()); var sut = new MyQuarterlyValues(ImmutableSortedMap.of(// time, 0.1, // time.plusMinutes(15), 0.2, // @@ -71,7 +70,7 @@ public void test() { @Test public void test2() { - var time = ZonedDateTime.now(TestUtils.createDummyClock()); + var time = ZonedDateTime.now(createDummyClock()); var sut = new MyQuarterlyValues(time, 0.1, 0.2, null, 0.3); assertEquals(3, sut.asArray().length); assertEquals(4, sut.toMapWithAllQuarters().size()); diff --git a/io.openems.edge.controller.api.backend/src/io/openems/edge/controller/api/backend/SendChannelValuesWorker.java b/io.openems.edge.controller.api.backend/src/io/openems/edge/controller/api/backend/SendChannelValuesWorker.java index 94289206d45..95a01a9e335 100644 --- a/io.openems.edge.controller.api.backend/src/io/openems/edge/controller/api/backend/SendChannelValuesWorker.java +++ b/io.openems.edge.controller.api.backend/src/io/openems/edge/controller/api/backend/SendChannelValuesWorker.java @@ -172,7 +172,7 @@ private TreeBasedTable collectAggregatedData(ZonedDat List enabledComponents) { final var endTime = now.truncatedTo(DurationUnit.ofMinutes(AGGREGATION_MINUTES)); final var startTime = endTime.minusMinutes(AGGREGATION_MINUTES); - + final var timestamp = startTime.toInstant(); if (this.lastSendAggregatedDataTimestamp == null) { this.lastSendAggregatedDataTimestamp = timestamp; diff --git a/io.openems.edge.controller.api.backend/src/io/openems/edge/controller/api/backend/handler/AuthenticatedRequestHandler.java b/io.openems.edge.controller.api.backend/src/io/openems/edge/controller/api/backend/handler/AuthenticatedRequestHandler.java index e95c94ad568..6b2c0807ce2 100644 --- a/io.openems.edge.controller.api.backend/src/io/openems/edge/controller/api/backend/handler/AuthenticatedRequestHandler.java +++ b/io.openems.edge.controller.api.backend/src/io/openems/edge/controller/api/backend/handler/AuthenticatedRequestHandler.java @@ -49,12 +49,15 @@ public void buildJsonApiRoutes(JsonApiBuilder b) { final var authenticatedRpcRequest = AuthenticatedRpcRequest.from(t.getRequest(), User::from); t.put(EdgeKeys.USER_KEY, authenticatedRpcRequest.getUser()); return authenticatedRpcRequest.getPayload(); + }, c -> this.binder.getJsonApiBuilder(), response -> { // wrap response in a AuthenticatedRpcResponse if successful - if (response instanceof JsonrpcResponseSuccess success) { - return new AuthenticatedRpcResponse(response.getId(), success); - } - return response; + return switch (response) { + case JsonrpcResponseSuccess success // + -> new AuthenticatedRpcResponse(response.getId(), success); + default -> response; + }; + }, () -> { final var subrequest = new Subrequest(JsonUtils.buildJsonObject().build()); subrequest.addRpcBuilderFor(this.binder.getJsonApiBuilder(), "payload"); diff --git a/io.openems.edge.controller.api.common/src/io/openems/edge/controller/api/common/ApiWorker.java b/io.openems.edge.controller.api.common/src/io/openems/edge/controller/api/common/ApiWorker.java index 4e15cd6d476..492326b2e24 100644 --- a/io.openems.edge.controller.api.common/src/io/openems/edge/controller/api/common/ApiWorker.java +++ b/io.openems.edge.controller.api.common/src/io/openems/edge/controller/api/common/ApiWorker.java @@ -140,8 +140,7 @@ public CompletableFuture handleSetChannelValueRequest(Co value = null; } else { value = JsonUtils.getAsBestType(request.getValue()); - if (value instanceof String && ((String) value).isEmpty() - && channel.channelId().doc().getType() != OpenemsType.STRING) { + if (value instanceof String s && s.isEmpty() && channel.channelId().doc().getType() != OpenemsType.STRING) { // Allow non-string Channels to be set to 'UNDEFINED' using an empty string value = null; } diff --git a/io.openems.edge.controller.api.common/src/io/openems/edge/controller/api/common/Status.java b/io.openems.edge.controller.api.common/src/io/openems/edge/controller/api/common/Status.java index 14c18bde3e8..27edce1e31c 100644 --- a/io.openems.edge.controller.api.common/src/io/openems/edge/controller/api/common/Status.java +++ b/io.openems.edge.controller.api.common/src/io/openems/edge/controller/api/common/Status.java @@ -3,14 +3,10 @@ import io.openems.common.types.OptionsEnum; public enum Status implements OptionsEnum { - ACTIVE(0, "Active"), // - INACTIVE(1, "Inactive"), // - ERROR(2, "Error"); // - private final int value; private final String name; @@ -33,5 +29,4 @@ public String getName() { public OptionsEnum getUndefined() { return INACTIVE; } - } diff --git a/io.openems.edge.controller.api.common/src/io/openems/edge/controller/api/common/WriteObject.java b/io.openems.edge.controller.api.common/src/io/openems/edge/controller/api/common/WriteObject.java index 02c4533867d..1b5b4b9fcd3 100644 --- a/io.openems.edge.controller.api.common/src/io/openems/edge/controller/api/common/WriteObject.java +++ b/io.openems.edge.controller.api.common/src/io/openems/edge/controller/api/common/WriteObject.java @@ -118,7 +118,7 @@ public void notifyTimeout() { * @return the value as String */ public abstract String valueToString(); - + /** * Gets the value of the current object. * diff --git a/io.openems.edge.controller.api.common/src/io/openems/edge/controller/api/common/handler/QueryRequestHandler.java b/io.openems.edge.controller.api.common/src/io/openems/edge/controller/api/common/handler/QueryRequestHandler.java index 64496f773cc..a21ac88bb8b 100644 --- a/io.openems.edge.controller.api.common/src/io/openems/edge/controller/api/common/handler/QueryRequestHandler.java +++ b/io.openems.edge.controller.api.common/src/io/openems/edge/controller/api/common/handler/QueryRequestHandler.java @@ -1,7 +1,8 @@ package io.openems.edge.controller.api.common.handler; +import static java.time.temporal.ChronoUnit.MINUTES; + import java.io.IOException; -import java.time.temporal.ChronoUnit; import java.util.Collections; import java.util.TreeSet; @@ -86,8 +87,8 @@ private QueryHistoricTimeseriesExportXlsxResponse handleQueryHistoricTimeseriesE final var channelsByType = detailData.getChannelsBySaveType(); powerChannels.addAll(channelsByType.getOrDefault(HistoricTimedataSaveType.POWER, Collections.emptyList())); energyChannels.addAll(channelsByType.getOrDefault(HistoricTimedataSaveType.ENERGY, Collections.emptyList())); - var powerData = this.timedata.queryHistoricData(null, request.getFromDate(), request.getToDate(), - powerChannels, new Resolution(15, ChronoUnit.MINUTES)); + var powerData = this.timedata.queryHistoricData(null, request.getFromDate(), request.getToDate(), powerChannels, + new Resolution(15, MINUTES)); var energyData = this.timedata.queryHistoricEnergy(null, request.getFromDate(), request.getToDate(), energyChannels); diff --git a/io.openems.edge.controller.api.common/src/io/openems/edge/controller/api/common/handler/RoutesJsonApiHandler.java b/io.openems.edge.controller.api.common/src/io/openems/edge/controller/api/common/handler/RoutesJsonApiHandler.java index 4cceb550d83..13741e20121 100644 --- a/io.openems.edge.controller.api.common/src/io/openems/edge/controller/api/common/handler/RoutesJsonApiHandler.java +++ b/io.openems.edge.controller.api.common/src/io/openems/edge/controller/api/common/handler/RoutesJsonApiHandler.java @@ -86,11 +86,10 @@ private static final List getAllRequests(List parent .map(Tag.serializer()::serialize) // .collect(toJsonArray())) .add("guards", def.getGuards().stream() // - .map(t -> { - if (t instanceof JsonrpcRoleEndpointGuard a) { - return JsonrpcRoleEndpointGuard.serializer().serialize(a); - } - return null; + .map(t -> switch (t) { + case JsonrpcRoleEndpointGuard a // + -> JsonrpcRoleEndpointGuard.serializer().serialize(a); + default -> null; }) // .filter(Objects::nonNull) // .collect(toJsonArray())) diff --git a/io.openems.edge.controller.api.modbus/bnd.bnd b/io.openems.edge.controller.api.modbus/bnd.bnd index 87fd5d5a4a8..aaaa2848a5c 100644 --- a/io.openems.edge.controller.api.modbus/bnd.bnd +++ b/io.openems.edge.controller.api.modbus/bnd.bnd @@ -5,14 +5,15 @@ Bundle-Version: 1.0.0.${tstamp} -buildpath: \ ${buildpath},\ - com.ghgande.j2mod;version=2.5.5,\ + com.ghgande.j2mod,\ io.openems.common,\ + io.openems.edge.bridge.modbus,\ io.openems.edge.common,\ io.openems.edge.controller.api,\ io.openems.edge.controller.api.common,\ io.openems.edge.ess.api,\ io.openems.edge.timedata.api,\ - io.openems.wrapper.fastexcel + io.openems.wrapper.fastexcel,\ -testpath: \ ${testpath} diff --git a/io.openems.edge.controller.api.modbus/src/io/openems/edge/controller/api/modbus/AbstractModbusApi.java b/io.openems.edge.controller.api.modbus/src/io/openems/edge/controller/api/modbus/AbstractModbusApi.java new file mode 100644 index 00000000000..be3b15d2f4f --- /dev/null +++ b/io.openems.edge.controller.api.modbus/src/io/openems/edge/controller/api/modbus/AbstractModbusApi.java @@ -0,0 +1,481 @@ +package io.openems.edge.controller.api.modbus; + +import java.util.List; +import java.util.Map.Entry; +import java.util.TreeMap; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.function.Consumer; + +import org.osgi.service.cm.ConfigurationAdmin; +import org.osgi.service.component.ComponentContext; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.ghgande.j2mod.modbus.ModbusException; +import com.ghgande.j2mod.modbus.slave.ModbusSlaveFactory; + +import io.openems.common.channel.AccessMode; +import io.openems.common.exceptions.OpenemsError.OpenemsNamedException; +import io.openems.common.exceptions.OpenemsException; +import io.openems.common.utils.ConfigUtils; +import io.openems.common.utils.FunctionUtils; +import io.openems.common.worker.AbstractWorker; +import io.openems.edge.common.channel.WriteChannel; +import io.openems.edge.common.component.AbstractOpenemsComponent; +import io.openems.edge.common.component.OpenemsComponent; +import io.openems.edge.common.jsonapi.ComponentJsonApi; +import io.openems.edge.common.jsonapi.JsonApiBuilder; +import io.openems.edge.common.jsonapi.JsonrpcEndpointGuard; +import io.openems.edge.common.meta.Meta; +import io.openems.edge.common.modbusslave.ModbusRecord; +import io.openems.edge.common.modbusslave.ModbusRecordChannel; +import io.openems.edge.common.modbusslave.ModbusRecordCycleValue; +import io.openems.edge.common.modbusslave.ModbusRecordString16; +import io.openems.edge.common.modbusslave.ModbusRecordUint16BlockLength; +import io.openems.edge.common.modbusslave.ModbusRecordUint16Hash; +import io.openems.edge.common.modbusslave.ModbusSlave; +import io.openems.edge.common.modbusslave.ModbusSlaveNatureTable; +import io.openems.edge.controller.api.Controller; +import io.openems.edge.controller.api.common.ApiWorker; +import io.openems.edge.controller.api.common.ApiWorker.WriteHandler; +import io.openems.edge.controller.api.common.Status; +import io.openems.edge.controller.api.common.WriteObject; +import io.openems.edge.controller.api.common.WritePojo; +import io.openems.edge.controller.api.modbus.jsonrpc.GetModbusProtocolExportXlsxRequest; +import io.openems.edge.controller.api.modbus.jsonrpc.GetModbusProtocolExportXlsxResponse; +import io.openems.edge.controller.api.modbus.jsonrpc.GetModbusProtocolRequest; +import io.openems.edge.controller.api.modbus.jsonrpc.GetModbusProtocolResponse; + +public abstract class AbstractModbusApi extends AbstractOpenemsComponent + implements ModbusApi, ComponentJsonApi, Controller { + + public static final int UNIT_ID = 1; + public static final int DEFAULT_MAX_CONCURRENT_CONNECTIONS = 5; + + /** + * Holds the link between Modbus start address of a Component and the + * Component-ID. + */ + protected final TreeMap components = new TreeMap<>(); + protected final TreeMap records = new TreeMap<>(); + protected volatile List _components = new CopyOnWriteArrayList<>(); + protected List invalidComponents = new CopyOnWriteArrayList<>(); + protected final Logger log = LoggerFactory.getLogger(AbstractModbusApi.class); + protected final MyProcessImage processImage; + + /** + * Holds the link between Modbus address and ModbusRecord. + */ + protected final ApiWorker apiWorker = new ApiWorker(this, + new WriteHandler(this.handleWrites(), this::setOverrideStatus, this.handleTimeouts())); + + private AbstractModbusConfig config; + + protected AbstractModbusApi(io.openems.edge.common.channel.ChannelId[] firstInitialChannelIds, + io.openems.edge.common.channel.ChannelId[][] furtherInitialChannelIds) { + super(firstInitialChannelIds, furtherInitialChannelIds); + this.processImage = new MyProcessImage(this); + } + + protected void activate(ComponentContext context, ConfigurationAdmin cm, AbstractModbusConfig config) + throws OpenemsException { + this.config = config; + super.activate(context, config.id(), config.alias(), config.enabled()); + + final var filter = ConfigUtils.generateReferenceTargetFilter(this.servicePid(), false, config.componentIds()); + OpenemsComponent.updateReferenceFilterRaw(cm, this.servicePid(), "Component", filter); + + this.apiWorker.setTimeoutSeconds(config.apiTimeout()); + + if (!this.isEnabled()) { + return; + } + + this.startApiWorker.activate(config.id()); + + } + + protected void modified(ComponentContext context, ConfigurationAdmin cm, AbstractModbusConfig config) + throws OpenemsException { + super.modified(context, config.id(), config.alias(), config.enabled()); + + final var filter = ConfigUtils.generateReferenceTargetFilter(this.servicePid(), false, config.componentIds()); + OpenemsComponent.updateReferenceFilterRaw(cm, this.servicePid(), "Component", filter); + + if (this.config.equals(config)) { + return; + } + + this.config = config; + + this.apiWorker.setTimeoutSeconds(config.apiTimeout()); + + if (!this.isEnabled()) { + this.startApiWorker.deactivate(); + return; + } + + this.startApiWorker.modified(config.id()); + + } + + @Override + protected void deactivate() { + this.startApiWorker.deactivate(); + super.deactivate(); + + // wait until modbus slave was completely closed + try { + Thread.sleep(10000); + } catch (InterruptedException e) { + this.log.warn(e.getMessage()); + } + } + + protected void onStarted() { + AbstractModbusApi.this.logInfo(this.log, "ModbusApi started."); + } + + protected Consumer, WriteObject>> handleWrites() { + return FunctionUtils::doNothing; + } + + protected void setOverrideStatus(Status status) { + // do nothing + } + + protected Runnable handleTimeouts() { + return FunctionUtils::doNothing; + } + + protected abstract com.ghgande.j2mod.modbus.slave.ModbusSlave createSlave() throws ModbusException; + + private final AbstractWorker startApiWorker = new AbstractWorker() { + + private static final int DEFAULT_WAIT_TIME = 5000; // 5 seconds + + private final Logger log = LoggerFactory.getLogger(AbstractWorker.class); + + protected com.ghgande.j2mod.modbus.slave.ModbusSlave slave = null; + + protected AbstractModbusConfig currentConfig = null; + + @Override + protected void forever() throws ModbusException { + if (this.slave == null) { + try { + // start new server + this.currentConfig = AbstractModbusApi.this.config; + this.slave = AbstractModbusApi.this.createSlave(); + this.slave.addProcessImage(UNIT_ID, AbstractModbusApi.this.processImage); + this.slave.open(); + if (isEnabled()) { + AbstractModbusApi.this.onStarted(); + AbstractModbusApi.this._setUnableToStart(false); + } + } catch (ModbusException e) { + ModbusSlaveFactory.close(this.slave); + AbstractModbusApi.this.logError(this.log, "Unable to start Modbus-Api: " + e.getMessage()); + AbstractModbusApi.this._setUnableToStart(true); + } + + } else { + // regular check for errors + String error = this.slave.getError(); + if (error != null) { + AbstractModbusApi.this.logError(this.log, "Unable to start Modbus-Api: " + error); + AbstractModbusApi.this._setUnableToStart(true); + this.stopSlave(); + } else if (!this.currentConfig.equals(AbstractModbusApi.this.config)) { + this.stopSlave(); + } + } + } + + private void stopSlave() { + ModbusSlaveFactory.close(this.slave); + this.slave = null; + } + + @Override + protected int getCycleTime() { + return DEFAULT_WAIT_TIME; + } + + }; + + @Override + public void run() throws OpenemsNamedException { + if (!this.isEnabled()) { + return; + } + + this.updateCycleValues(); + this.apiWorker.run(); + } + + /** + * Called by addComponent/removeComponent. Initializes the ModbusRecords, once + * all Components are available. Fault-State otherwise. + */ + protected synchronized void updateComponents() { + var config = this.config; + + if (config == null) { + return; + } + if (config.componentIds().length > this._components.size()) { + if (this.getComponentNoModbusApiFaultChannel().getNextValue().get() != true) { + this._setComponentMissingFault(true); // Either this or that fault + } + return; + } + this._setComponentMissingFault(false); + + this.initializeModbusRecords(this.config.metaComponent(), this.config.componentIds()); + } + + protected synchronized void addComponent(OpenemsComponent component) { + if (!(component instanceof ModbusSlave ms)) { + this.logError(this.log, "Component [" + component.id() + "] does not implement ModbusSlave"); + this.invalidComponents.add(component); + this._setComponentNoModbusApiFault(true); + return; + } + this._components.add(ms); + this.updateComponents(); + } + + protected synchronized void removeComponent(OpenemsComponent component) { + this._components.remove(component); + if (this.invalidComponents.remove(component)) { + if (this.invalidComponents.isEmpty()) { + this._setComponentNoModbusApiFault(false); + } + return; + } + this.updateComponents(); + } + + /** + * Once every cycle: update the values for each registered + * {@link ModbusRecordCycleValue}. + */ + @SuppressWarnings("unchecked") + protected void updateCycleValues() { + this.records.values() // + .stream() // + .filter(ModbusRecordCycleValue.class::isInstance) // + .map(ModbusRecordCycleValue.class::cast) // + .forEach(r -> { + var component = this.getPossiblyDisabledComponent(r.getComponentId()); + if (component != null && component.isEnabled()) { + r.updateValue(component); + } else { + r.updateValue(null); + } + }); + } + + @Override + protected void logDebug(Logger log, String message) { + super.logDebug(log, message); + } + + @Override + protected void logInfo(Logger log, String message) { + super.logInfo(log, message); + } + + @Override + protected void logWarn(Logger log, String message) { + super.logWarn(log, message); + } + + /** + * Gets the AccessMode. + * + * @return the {@link AccessMode} + */ + protected abstract AccessMode getAccessMode(); + + /** + * Gets the Component. Be aware, that it might be 'disabled'. + * + * @param componentId the Component-ID + * + * @return the {@link ModbusSlave} Component; possibly null + */ + protected ModbusSlave getPossiblyDisabledComponent(String componentId) { + if (componentId == null) { + return null; + } + if (componentId == Meta.SINGLETON_COMPONENT_ID) { + return this.config.metaComponent(); + } + return this._components.stream() // + .filter(c -> componentId.equals(c.id())) // + .findFirst() // + .orElse(null); + } + + /** + * Adds a Record to the process image at the given address. + * + * @param address the address + * @param record the record + * @param component the OpenEMS Component + * @return the next address after this record + */ + private int addRecordToProcessImage(int address, ModbusRecord record, OpenemsComponent component) { + record.setComponentId(component.id()); + + // Handle writes to the Channel; limited to ModbusRecordChannels + if (record instanceof ModbusRecordChannel r) { + r.onWriteValue(value -> { + var readChannel = component.channel(r.getChannelId()); + if (!(readChannel instanceof WriteChannel wc)) { + this.logWarn(this.log, "Unable to write to Read-Only-Channel [" + readChannel.address() + "]"); + return; + } + this.apiWorker.addValue(wc, new WritePojo(value)); + }); + } + + this.records.put(address, record); + return address + record.getType().getWords(); + } + + /** + * Initialize Modbus-Records for all configured Component-IDs. + * + * @param metaComponent the {@link Meta} component + * @param componentIds the configured Component-IDs. + */ + private void initializeModbusRecords(Meta metaComponent, String[] componentIds) { + this.records.clear(); + // Add generic header + this.records.put(0, new ModbusRecordUint16Hash(0, "OpenEMS")); + var nextAddress = 1; + + // add Meta-Component + nextAddress = this.addMetaComponentToProcessImage(nextAddress, metaComponent); + + // add remaining components; sorted by configured componentIds + for (String id : componentIds) { + // find next component in order + var component = this.getPossiblyDisabledComponent(id); + if (component == null) { // This should never happen + this.logWarn(this.log, "Required Component [" + id + "] " // + + "is not available. Component may not implement ModbusSlave or is not active."); + continue; + } + + nextAddress = this.addComponentToProcessImage(nextAddress, component); + } + } + + /** + * Adds the Meta-Component to the Process Image. + * + * @param startAddress the start-address + * @param component the {@link Meta} component + * @return the next start-address + */ + private int addMetaComponentToProcessImage(int startAddress, Meta component) { + var table = component.getModbusSlaveTable(this.getAccessMode()); + + // add the Component-Model Length + var nextAddress = this.addRecordToProcessImage(startAddress, + new ModbusRecordUint16BlockLength(-1, component.id(), (short) table.getLength()), component); + + // add Records + for (ModbusSlaveNatureTable natureTable : table.getNatureTables()) { + for (ModbusRecord record : natureTable.getModbusRecords()) { + this.addRecordToProcessImage(nextAddress + record.getOffset(), record, component); + } + } + return startAddress + table.getLength(); + } + + /** + * Adds a Component to the Process Image. + * + * @param startAddress the start-address + * @param component the OpenEMS Component + * @return the next start-address + */ + private int addComponentToProcessImage(int startAddress, ModbusSlave component) { + this.components.put(startAddress, component.alias()); + var table = component.getModbusSlaveTable(this.getAccessMode()); + + // add the Component-ID and Component-Model Length + var nextAddress = this.addRecordToProcessImage(startAddress, + new ModbusRecordString16(-1, "Component-ID", component.id()), component); + this.addRecordToProcessImage(nextAddress, + new ModbusRecordUint16BlockLength(-1, component.id(), (short) table.getLength()), component); + nextAddress = startAddress + 20; + var nextNatureAddress = nextAddress; + + // add all Nature-Tables + for (ModbusSlaveNatureTable natureTable : table.getNatureTables()) { + // add the Interface Hash-Code and Length + nextAddress = this.addRecordToProcessImage(nextNatureAddress, + new ModbusRecordUint16Hash(-1, natureTable.getNatureName()), component); + nextAddress = this.addRecordToProcessImage(nextAddress, + new ModbusRecordUint16BlockLength(-1, natureTable.getNatureName(), (short) natureTable.getLength()), + component); + + // add Records + for (ModbusRecord record : natureTable.getModbusRecords()) { + this.addRecordToProcessImage(nextNatureAddress + 2 + record.getOffset(), record, component); + } + + nextNatureAddress = nextNatureAddress += natureTable.getLength(); + } + + // calculate next address after this component + return startAddress + table.getLength(); + } + + @Override + public void buildJsonApiRoutes(JsonApiBuilder builder) { + builder.handleRequest(GetModbusProtocolRequest.METHOD, def -> { + def.setGuards(this.componentMissingGuard(), this.componentNoModbusApiGuard()); + }, call -> { + return new GetModbusProtocolResponse(call.getRequest().getId(), this.records); + }); + builder.handleRequest(GetModbusProtocolExportXlsxRequest.METHOD, def -> { + def.setGuards(this.componentMissingGuard(), this.componentNoModbusApiGuard()); + }, call -> { + return new GetModbusProtocolExportXlsxResponse(call.getRequest().getId(), this.components, this.records); + }); + } + + private JsonrpcEndpointGuard componentMissingGuard() { + return call -> { + if (this.getComponentMissingFault().get() == true) { + throw new OpenemsException(this.getComponentMissingFaultChannel().channelDoc().getText()); + } + }; + } + + private JsonrpcEndpointGuard componentNoModbusApiGuard() { + return call -> { + if (this.getComponentNoModbusApiFault().get() == true) { + throw new OpenemsException(this.getComponentNoModbusApiFaultChannel().channelDoc().getText()); + } + }; + } + + /** + * Format a given channelAddress to a ChannelId. + * + * @param channel WriteChannel + * @return component_channelId as String + */ + public static String formatChannelName(WriteChannel channel) { + return channel.getComponent().id() + "_" + channel.channelId().name(); + } + +} diff --git a/io.openems.edge.controller.api.modbus/src/io/openems/edge/controller/api/modbus/AbstractModbusConfig.java b/io.openems.edge.controller.api.modbus/src/io/openems/edge/controller/api/modbus/AbstractModbusConfig.java new file mode 100644 index 00000000000..a9792bd4199 --- /dev/null +++ b/io.openems.edge.controller.api.modbus/src/io/openems/edge/controller/api/modbus/AbstractModbusConfig.java @@ -0,0 +1,108 @@ +package io.openems.edge.controller.api.modbus; + +import java.util.Arrays; + +import io.openems.edge.common.meta.Meta; + +public abstract class AbstractModbusConfig { + private final String id; + private final String alias; + private final boolean enabled; + private final Meta metaComponent; + private final String[] componentIds; + private final int apiTimeout; + private final int maxConcurrentConnections; + + public AbstractModbusConfig(String id, String alias, boolean enabled, Meta metaComponent, String[] componentIds, + int apiTimeout, int maxConcurrentConnections) { + this.id = id; + this.alias = alias; + this.enabled = enabled; + this.metaComponent = metaComponent; + this.componentIds = componentIds; + this.apiTimeout = apiTimeout; + this.maxConcurrentConnections = maxConcurrentConnections; + } + + /** + * Returns a unique ID for this OpenEMS component. + * + * @return the unique ID + */ + public String id() { + return this.id; + } + + /** + * Returns a unique ID for this OpenEMS component. + * + * @return the unique ID + */ + public String alias() { + return this.alias; + } + + /** + * Is this controller enabled?. + * + * @return boolean + */ + public boolean enabled() { + return this.enabled; + } + + /** + * Returns a metaComponent. + * + * @return the metaComponent + */ + public Meta metaComponent() { + return this.metaComponent; + } + + /** + * Returns an array of component ids. + * + * @return the componentIds + */ + public String[] componentIds() { + return this.componentIds; + } + + /** + * Returns the api timeout. + * + * @return the apiTimeout + */ + public int apiTimeout() { + return this.apiTimeout; + } + + /** + * Returns the max number of concurrent connections. + * + * @return the maxConcurrentConnections + */ + public int maxConcurrentConnections() { + return this.maxConcurrentConnections; + } + + @Override + public boolean equals(Object other) { + if (this == other) { + return true; + } + if (other == null || getClass() != other.getClass()) { + return false; + } + AbstractModbusConfig config = (AbstractModbusConfig) other; + return this.enabled == config.enabled // + && this.apiTimeout == config.apiTimeout // + && this.maxConcurrentConnections == config.maxConcurrentConnections + && this.id.equals(config.id) // + && this.alias.equals(config.alias) + && this.metaComponent.equals(config.metaComponent) // + && Arrays.equals(this.componentIds, config.componentIds); + } + +} diff --git a/io.openems.edge.controller.api.modbus/src/io/openems/edge/controller/api/modbus/AbstractModbusRtuApi.java b/io.openems.edge.controller.api.modbus/src/io/openems/edge/controller/api/modbus/AbstractModbusRtuApi.java new file mode 100644 index 00000000000..4781e65aa2d --- /dev/null +++ b/io.openems.edge.controller.api.modbus/src/io/openems/edge/controller/api/modbus/AbstractModbusRtuApi.java @@ -0,0 +1,99 @@ +package io.openems.edge.controller.api.modbus; + +import io.openems.edge.bridge.modbus.api.Parity; +import io.openems.edge.bridge.modbus.api.Stopbit; +import io.openems.edge.common.component.OpenemsComponent; +import io.openems.edge.common.jsonapi.ComponentJsonApi; +import io.openems.edge.common.meta.Meta; +import io.openems.edge.controller.api.Controller; + +public abstract class AbstractModbusRtuApi extends AbstractModbusApi + implements ModbusApi, Controller, OpenemsComponent, ComponentJsonApi { + + public AbstractModbusRtuApi(String implementationName, + io.openems.edge.common.channel.ChannelId[] firstInitialChannelIds, + io.openems.edge.common.channel.ChannelId[]... furtherInitialChannelIds) { + super(firstInitialChannelIds, furtherInitialChannelIds); + } + + public static class RtuConfig extends AbstractModbusConfig { + private final String portName; + private final int baudRate; + private final int databits; + private final Stopbit stopbits; + private final Parity parity; + + public RtuConfig(String id, String alias, boolean enabled, Meta metaComponent, String[] componentIds, + int apiTimeout, String portName, int baudRate, int databits, Stopbit stopbits, Parity parity, + int maxConcurrentConnections) { + super(id, alias, enabled, metaComponent, componentIds, apiTimeout, maxConcurrentConnections); + this.portName = portName; + this.baudRate = baudRate; + this.databits = databits; + this.stopbits = stopbits; + this.parity = parity; + } + + /** + * Returns the portName. + * + * @return the portName + */ + public String portName() { + return this.portName; + } + + /** + * Returns the baudRate. + * + * @return the baudRate + */ + public int baudRate() { + return this.baudRate; + } + + /** + * Returns the databits. + * + * @return databits + */ + public int databits() { + return this.databits; + } + + /** + * Returns the stopbits. + * + * @return the stopbits + */ + public Stopbit stopbits() { + return this.stopbits; + } + + /** + * Returns the parity. + * + * @return the parity + */ + public Parity parity() { + return this.parity; + } + + @Override + public boolean equals(Object other) { + if (!super.equals(other)) { + return false; + } + if (!(other instanceof RtuConfig config)) { + return false; + } + return this.baudRate == config.baudRate // + && this.databits == config.databits // + && this.stopbits == config.stopbits // + && this.parity == config.parity // + && this.portName.equals(config.portName); + } + + } + +} diff --git a/io.openems.edge.controller.api.modbus/src/io/openems/edge/controller/api/modbus/AbstractModbusTcpApi.java b/io.openems.edge.controller.api.modbus/src/io/openems/edge/controller/api/modbus/AbstractModbusTcpApi.java index 7aff8bc95ec..fa5cbb2d909 100644 --- a/io.openems.edge.controller.api.modbus/src/io/openems/edge/controller/api/modbus/AbstractModbusTcpApi.java +++ b/io.openems.edge.controller.api.modbus/src/io/openems/edge/controller/api/modbus/AbstractModbusTcpApi.java @@ -1,531 +1,43 @@ package io.openems.edge.controller.api.modbus; -import java.util.Arrays; -import java.util.List; -import java.util.Map.Entry; -import java.util.TreeMap; -import java.util.concurrent.CopyOnWriteArrayList; -import java.util.function.Consumer; - -import org.osgi.service.cm.ConfigurationAdmin; -import org.osgi.service.component.ComponentContext; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.ghgande.j2mod.modbus.ModbusException; -import com.ghgande.j2mod.modbus.slave.ModbusSlaveFactory; - -import io.openems.common.channel.AccessMode; -import io.openems.common.exceptions.OpenemsError.OpenemsNamedException; -import io.openems.common.exceptions.OpenemsException; -import io.openems.common.utils.ConfigUtils; -import io.openems.common.worker.AbstractWorker; -import io.openems.edge.common.channel.Channel; -import io.openems.edge.common.channel.WriteChannel; -import io.openems.edge.common.component.AbstractOpenemsComponent; import io.openems.edge.common.component.OpenemsComponent; -import io.openems.edge.common.jsonapi.ComponentJsonApi; -import io.openems.edge.common.jsonapi.JsonApiBuilder; -import io.openems.edge.common.jsonapi.JsonrpcEndpointGuard; import io.openems.edge.common.meta.Meta; -import io.openems.edge.common.modbusslave.ModbusRecord; -import io.openems.edge.common.modbusslave.ModbusRecordChannel; -import io.openems.edge.common.modbusslave.ModbusRecordCycleValue; -import io.openems.edge.common.modbusslave.ModbusRecordString16; -import io.openems.edge.common.modbusslave.ModbusRecordUint16BlockLength; -import io.openems.edge.common.modbusslave.ModbusRecordUint16Hash; -import io.openems.edge.common.modbusslave.ModbusSlave; -import io.openems.edge.common.modbusslave.ModbusSlaveNatureTable; import io.openems.edge.controller.api.Controller; -import io.openems.edge.controller.api.common.ApiWorker; -import io.openems.edge.controller.api.common.ApiWorker.WriteHandler; -import io.openems.edge.controller.api.common.Status; -import io.openems.edge.controller.api.common.WriteObject; -import io.openems.edge.controller.api.common.WritePojo; -import io.openems.edge.controller.api.modbus.jsonrpc.GetModbusProtocolExportXlsxRequest; -import io.openems.edge.controller.api.modbus.jsonrpc.GetModbusProtocolExportXlsxResponse; -import io.openems.edge.controller.api.modbus.jsonrpc.GetModbusProtocolRequest; -import io.openems.edge.controller.api.modbus.jsonrpc.GetModbusProtocolResponse; -public abstract class AbstractModbusTcpApi extends AbstractOpenemsComponent - implements ModbusTcpApi, Controller, OpenemsComponent, ComponentJsonApi { +public abstract class AbstractModbusTcpApi extends AbstractModbusApi + implements ModbusApi, Controller, OpenemsComponent { - public static final int UNIT_ID = 1; public static final int DEFAULT_PORT = 502; - public static final int DEFAULT_MAX_CONCURRENT_CONNECTIONS = 5; - - /** - * Holds the link between Modbus address and ModbusRecord. - */ - protected final TreeMap records = new TreeMap<>(); - protected final ApiWorker apiWorker = new ApiWorker(this, - new WriteHandler(this.handleWrites(), this::setOverrideStatus, this.handleTimeouts())); - private final Logger log = LoggerFactory.getLogger(AbstractModbusTcpApi.class); - private final MyProcessImage processImage; - private final String implementationName; - - /** - * Holds the link between Modbus start address of a Component and the - * Component-ID. - */ - private final TreeMap components = new TreeMap<>(); - - private ConfigRecord config; - private List invalidComponents = new CopyOnWriteArrayList<>(); - - protected synchronized void addComponent(OpenemsComponent component) { - if (!(component instanceof ModbusSlave)) { - this.logError(this.log, "Component [" + component.id() + "] does not implement ModbusSlave"); - this.invalidComponents.add(component); - this._setComponentNoModbusApiFault(true); - return; - } - this._components.add((ModbusSlave) component); - this.updateComponents(); - } - - protected abstract Consumer, WriteObject>> handleWrites(); - - protected abstract void setOverrideStatus(Status status); - - protected abstract Runnable handleTimeouts(); - - protected synchronized void removeComponent(OpenemsComponent component) { - this._components.remove(component); - if (this.invalidComponents.remove(component)) { - if (this.invalidComponents.isEmpty()) { - this._setComponentNoModbusApiFault(false); - } - return; - } - this.updateComponents(); - } - - private volatile List _components = new CopyOnWriteArrayList<>(); public AbstractModbusTcpApi(String implementationName, io.openems.edge.common.channel.ChannelId[] firstInitialChannelIds, io.openems.edge.common.channel.ChannelId[]... furtherInitialChannelIds) { super(firstInitialChannelIds, furtherInitialChannelIds); - this.implementationName = implementationName; - this.processImage = new MyProcessImage(this); - } - - protected void activate(ComponentContext context, ConfigurationAdmin cm, ConfigRecord config) - throws OpenemsException { - super.activate(context, config.id(), config.alias(), config.enabled()); - this.handleActivate(config, cm, config.id()); - } - - protected void modified(ComponentContext context, ConfigurationAdmin cm, ConfigRecord config) - throws OpenemsException { - super.modified(context, config.id(), config.alias(), config.enabled()); - - // update filter for 'Components'; allow disable components - final var filter = ConfigUtils.generateReferenceTargetFilter(this.servicePid(), false, config.componentIds); - OpenemsComponent.updateReferenceFilterRaw(cm, this.servicePid(), "Component", filter); - - // Config (relevant for API) was not modified - if (this.config.equals(config)) { - return; - } - - ModbusSlaveFactory.close(); - - // Activate with new config - this.handleModified(config, cm, config.id()); - } - - private void handleActivate(ConfigRecord config, ConfigurationAdmin cm, String id) { - // configuration settings - this.config = config; - - // update filter for 'Components'; allow disable components - final var filter = ConfigUtils.generateReferenceTargetFilter(this.servicePid(), false, config.componentIds); - OpenemsComponent.updateReferenceFilterRaw(cm, this.servicePid(), "Component", filter); - - this.apiWorker.setTimeoutSeconds(config.apiTimeout); - - if (!this.isEnabled()) { - // abort if disabled - return; - } - - // Start Modbus-Server - this.startApiWorker.activate(id); - - this.updateComponents(); - } - - private void handleModified(ConfigRecord config, ConfigurationAdmin cm, String id) { - // configuration settings - this.config = config; - - this.apiWorker.setTimeoutSeconds(config.apiTimeout); - - if (!this.isEnabled()) { - // abort if disabled - this.startApiWorker.deactivate(); - return; - } - - // Modify Modbus-Server - this.startApiWorker.modified(id); - - this.updateComponents(); - } - - /** - * Called by addComponent/removeComponent. Initializes the ModbusRecords, once - * all Components are available. Fault-State otherwise. - */ - private synchronized void updateComponents() { - // Check if all Components are available - var config = this.config; - if (config == null) { - return; - } - if (config.componentIds.length > this._components.size()) { - if (this.getComponentNoModbusApiFaultChannel().getNextValue().get() != Boolean.TRUE) { - this._setComponentMissingFault(true); // Either this or that fault - } - return; - } - this._setComponentMissingFault(false); - - // Initialize Modbus Records - this.initializeModbusRecords(this.config.metaComponent, this.config.componentIds); - } - - @Override - protected void deactivate() { - - this.startApiWorker.deactivate(); - ModbusSlaveFactory.close(); - super.deactivate(); - - // wait until modbus slave was completely closed - try { - Thread.sleep(10000); - } catch (InterruptedException e) { - this.log.warn(e.getMessage()); - } - } - - private final AbstractWorker startApiWorker = new AbstractWorker() { - - private static final int DEFAULT_WAIT_TIME = 5000; // 5 seconds - - private final Logger log = LoggerFactory.getLogger(AbstractWorker.class); - - private com.ghgande.j2mod.modbus.slave.ModbusSlave slave = null; - - @Override - protected void forever() { - var port = AbstractModbusTcpApi.this.config.port; - if (this.slave == null) { - try { - // start new server - this.slave = ModbusSlaveFactory.createTCPSlave(port, - AbstractModbusTcpApi.this.config.maxConcurrentConnections); - this.slave.addProcessImage(UNIT_ID, AbstractModbusTcpApi.this.processImage); - if (isEnabled()) { - this.slave.open(); - AbstractModbusTcpApi.this.logInfo(this.log, - AbstractModbusTcpApi.this.implementationName + " started " // - + "on port [" + port + "] with UnitId [" + AbstractModbusTcpApi.UNIT_ID + "]."); - } - } catch (ModbusException e) { - ModbusSlaveFactory.close(); - AbstractModbusTcpApi.this.logError(this.log, - "Unable to start " + AbstractModbusTcpApi.this.implementationName + " on port [" + port - + "]: " + e.getMessage()); - AbstractModbusTcpApi.this._setUnableToStart(true); - } - - } else { - // regular check for errors - var error = this.slave.getError(); - if (error == null) { - AbstractModbusTcpApi.this._setUnableToStart(false); - - } else { - AbstractModbusTcpApi.this.logError(this.log, - "Unable to start Modbus/TCP Api on port [" + port + "]: " + error); - AbstractModbusTcpApi.this._setUnableToStart(true); - this.slave = null; - // stop server - ModbusSlaveFactory.close(); - } - } - } - - @Override - protected int getCycleTime() { - return DEFAULT_WAIT_TIME; - } - - }; - - /** - * Initialize Modbus-Records for all configured Component-IDs. - * - * @param metaComponent the {@link Meta} component - * @param componentIds the configured Component-IDs. - */ - private void initializeModbusRecords(Meta metaComponent, String[] componentIds) { - // Add generic header - this.records.clear(); - this.records.put(0, new ModbusRecordUint16Hash(0, "OpenEMS")); - var nextAddress = 1; - - // add Meta-Component - nextAddress = this.addMetaComponentToProcessImage(nextAddress, metaComponent); - - // add remaining components; sorted by configured componentIds - for (String id : componentIds) { - // find next component in order - var component = this.getPossiblyDisabledComponent(id); - if (component == null) { // This should never happen - this.logWarn(this.log, "Required Component [" + id + "] " // - + "is not available. Component may not implement ModbusSlave or is not active."); - continue; - } - - // add component to process image - nextAddress = this.addComponentToProcessImage(nextAddress, component); - } - } - - /** - * Adds the Meta-Component to the Process Image. - * - * @param startAddress the start-address - * @param component the {@link Meta} component - * @return the next start-address - */ - private int addMetaComponentToProcessImage(int startAddress, Meta component) { - var table = component.getModbusSlaveTable(this.getAccessMode()); - - // add the Component-Model Length - var nextAddress = this.addRecordToProcessImage(startAddress, - new ModbusRecordUint16BlockLength(-1, component.id(), (short) table.getLength()), component); - - // add Records - for (ModbusSlaveNatureTable natureTable : table.getNatureTables()) { - for (ModbusRecord record : natureTable.getModbusRecords()) { - this.addRecordToProcessImage(nextAddress + record.getOffset(), record, component); - } - } - return startAddress + table.getLength(); } - /** - * Adds a Component to the Process Image. - * - * @param startAddress the start-address - * @param component the OpenEMS Component - * @return the next start-address - */ - private int addComponentToProcessImage(int startAddress, ModbusSlave component) { - this.components.put(startAddress, component.alias()); - var table = component.getModbusSlaveTable(this.getAccessMode()); - - // add the Component-ID and Component-Model Length - var nextAddress = this.addRecordToProcessImage(startAddress, - new ModbusRecordString16(-1, "Component-ID", component.id()), component); - this.addRecordToProcessImage(nextAddress, - new ModbusRecordUint16BlockLength(-1, component.id(), (short) table.getLength()), component); - nextAddress = startAddress + 20; - var nextNatureAddress = nextAddress; + public class TcpConfig extends AbstractModbusConfig { + private final int port; - // add all Nature-Tables - for (ModbusSlaveNatureTable natureTable : table.getNatureTables()) { - // add the Interface Hash-Code and Length - nextAddress = this.addRecordToProcessImage(nextNatureAddress, - new ModbusRecordUint16Hash(-1, natureTable.getNatureName()), component); - nextAddress = this.addRecordToProcessImage(nextAddress, - new ModbusRecordUint16BlockLength(-1, natureTable.getNatureName(), (short) natureTable.getLength()), - component); - - // add Records - for (ModbusRecord record : natureTable.getModbusRecords()) { - this.addRecordToProcessImage(nextNatureAddress + 2 + record.getOffset(), record, component); - } - - nextNatureAddress = nextNatureAddress += natureTable.getLength(); + public TcpConfig(String id, String alias, boolean enabled, Meta metaComponent, String[] componentIds, + int apiTimeout, int port, int maxConcurrentConnections) { + super(id, alias, enabled, metaComponent, componentIds, apiTimeout, maxConcurrentConnections); + this.port = port; } - // calculate next address after this component - return startAddress + table.getLength(); - } - - /** - * Adds a Record to the process image at the given address. - * - * @param address the address - * @param record the record - * @param component the OpenEMS Component - * @return the next address after this record - */ - private int addRecordToProcessImage(int address, ModbusRecord record, OpenemsComponent component) { - record.setComponentId(component.id()); - - // Handle writes to the Channel; limited to ModbusRecordChannels - if (record instanceof ModbusRecordChannel) { - var r = (ModbusRecordChannel) record; - r.onWriteValue(value -> { - Channel readChannel = component.channel(r.getChannelId()); - if (!(readChannel instanceof WriteChannel)) { - this.logWarn(this.log, "Unable to write to Read-Only-Channel [" + readChannel.address() + "]"); - return; - } - WriteChannel channel = (WriteChannel) readChannel; - this.apiWorker.addValue(channel, new WritePojo(value)); - }); + public int getPort() { + return this.port; } - this.records.put(address, record); - return address + record.getType().getWords(); - } - - @Override - public void run() throws OpenemsNamedException { - // Enabled? - if (!this.isEnabled()) { - return; - } - - this.updateCycleValues(); - this.apiWorker.run(); - } - - @SuppressWarnings("unchecked") - /** - * Once every cycle: update the values for each registered - * {@link ModbusRecordCycleValue}. - */ - private void updateCycleValues() { - this.records.values() // - .stream() // - .filter(r -> r instanceof ModbusRecordCycleValue) // - .map(r -> (ModbusRecordCycleValue) r) // - .forEach(r -> { - OpenemsComponent component = this.getPossiblyDisabledComponent(r.getComponentId()); - if (component != null && component.isEnabled()) { - r.updateValue(component); - } else { - r.updateValue(null); - } - }); - } - - @Override - protected void logDebug(Logger log, String message) { - super.logDebug(log, message); - } - - @Override - protected void logInfo(Logger log, String message) { - super.logInfo(log, message); - } - - @Override - protected void logWarn(Logger log, String message) { - super.logWarn(log, message); - } - - @Override - public void buildJsonApiRoutes(JsonApiBuilder builder) { - builder.handleRequest(GetModbusProtocolRequest.METHOD, def -> { - def.setGuards(this.componentMissingGuard(), this.componentNoModbusApiGuard()); - }, call -> { - return new GetModbusProtocolResponse(call.getRequest().getId(), this.records); - }); - builder.handleRequest(GetModbusProtocolExportXlsxRequest.METHOD, def -> { - def.setGuards(this.componentMissingGuard(), this.componentNoModbusApiGuard()); - }, call -> { - return new GetModbusProtocolExportXlsxResponse(call.getRequest().getId(), this.components, this.records); - }); - } - - private JsonrpcEndpointGuard componentMissingGuard() { - return call -> { - if (this.getComponentMissingFault().get() == Boolean.TRUE) { - throw new OpenemsException(this.getComponentMissingFaultChannel().channelDoc().getText()); - } - }; - } - - private JsonrpcEndpointGuard componentNoModbusApiGuard() { - return call -> { - if (this.getComponentNoModbusApiFault().get() == Boolean.TRUE) { - throw new OpenemsException(this.getComponentNoModbusApiFaultChannel().channelDoc().getText()); - } - }; - } - - /** - * Gets the AccessMode. - * - * @return the {@link AccessMode} - */ - protected abstract AccessMode getAccessMode(); - - /** - * Gets the Component. Be aware, that it might be 'disabled'. - * - * @param componentId the Component-ID - * - * @return the {@link ModbusSlave} Component; possibly null - */ - protected ModbusSlave getPossiblyDisabledComponent(String componentId) { - if (componentId == null) { - return null; - } - if (componentId == Meta.SINGLETON_COMPONENT_ID) { - return this.config.metaComponent; - } - return this._components.stream() // - .filter(c -> componentId.equals(c.id())) // - .findFirst() // - .orElse(null); - } - - public static record ConfigRecord(String id, String alias, boolean enabled, Meta metaComponent, - String[] componentIds, int apiTimeout, int port, int maxConcurrentConnections) { - @Override public boolean equals(Object other) { - if (this == other) { - return true; - } - if (other == null) { + if (!super.equals(other)) { return false; } - if (!(other instanceof ConfigRecord)) { + if (!(other instanceof TcpConfig config)) { return false; } - ConfigRecord config = (ConfigRecord) other; - - if (config.id.equals(this.id) && config.alias.equals(this.alias) // - && config.enabled == this.enabled && config.metaComponent.equals(this.metaComponent) // - && Arrays.equals(config.componentIds, this.componentIds) // - && config.apiTimeout == this.apiTimeout && config.port == this.port // - && config.maxConcurrentConnections == this.maxConcurrentConnections) { - return true; - } - return false; + return this.port == config.port; } - } - /** - * Format a given channelAddress to a ChannelId. - * - * @param channel WriteChannel - * @return component_channelId as String - */ - public static String formatChannelName(WriteChannel channel) { - return channel.getComponent().id() + "_" + channel.channelId().name(); } } diff --git a/io.openems.edge.controller.api.modbus/src/io/openems/edge/controller/api/modbus/ModbusTcpApi.java b/io.openems.edge.controller.api.modbus/src/io/openems/edge/controller/api/modbus/ModbusApi.java similarity index 97% rename from io.openems.edge.controller.api.modbus/src/io/openems/edge/controller/api/modbus/ModbusTcpApi.java rename to io.openems.edge.controller.api.modbus/src/io/openems/edge/controller/api/modbus/ModbusApi.java index da838a2d947..c7357b08c1d 100644 --- a/io.openems.edge.controller.api.modbus/src/io/openems/edge/controller/api/modbus/ModbusTcpApi.java +++ b/io.openems.edge.controller.api.modbus/src/io/openems/edge/controller/api/modbus/ModbusApi.java @@ -7,11 +7,11 @@ import io.openems.edge.common.channel.value.Value; import io.openems.edge.common.component.OpenemsComponent; -public interface ModbusTcpApi extends OpenemsComponent { +public interface ModbusApi extends OpenemsComponent { public enum ChannelId implements io.openems.edge.common.channel.ChannelId { UNABLE_TO_START(Doc.of(Level.FAULT) // - .text("Unable to start Modbus/TCP-Api Server")), // + .text("Unable to start ModbusTCP/RTU-Api Server")), // COMPONENT_NO_MODBUS_API_FAULT(Doc.of(Level.FAULT) // .text("A configured Component does not support Modbus-API")), // COMPONENT_MISSING_FAULT(Doc.of(Level.FAULT) // diff --git a/io.openems.edge.controller.api.modbus/src/io/openems/edge/controller/api/modbus/MyProcessImage.java b/io.openems.edge.controller.api.modbus/src/io/openems/edge/controller/api/modbus/MyProcessImage.java index cbc587a8c4f..e155ba3576f 100644 --- a/io.openems.edge.controller.api.modbus/src/io/openems/edge/controller/api/modbus/MyProcessImage.java +++ b/io.openems.edge.controller.api.modbus/src/io/openems/edge/controller/api/modbus/MyProcessImage.java @@ -19,15 +19,15 @@ import io.openems.edge.common.modbusslave.ModbusRecordUint16Reserved; /** - * This implementation answers Modbus-TCP Slave requests. + * This implementation answers Modbus-TCP/RTU Slave requests. */ public class MyProcessImage implements ProcessImage { private final Logger log = LoggerFactory.getLogger(MyProcessImage.class); - protected final AbstractModbusTcpApi parent; + protected final AbstractModbusApi parent; - protected MyProcessImage(AbstractModbusTcpApi parent) { + protected MyProcessImage(AbstractModbusApi parent) { this.parent = parent; } diff --git a/io.openems.edge.controller.api.modbus/src/io/openems/edge/controller/api/modbus/readonly/rtu/Config.java b/io.openems.edge.controller.api.modbus/src/io/openems/edge/controller/api/modbus/readonly/rtu/Config.java new file mode 100644 index 00000000000..d2ca0403017 --- /dev/null +++ b/io.openems.edge.controller.api.modbus/src/io/openems/edge/controller/api/modbus/readonly/rtu/Config.java @@ -0,0 +1,52 @@ +package io.openems.edge.controller.api.modbus.readonly.rtu; + +import org.osgi.service.metatype.annotations.AttributeDefinition; +import org.osgi.service.metatype.annotations.ObjectClassDefinition; + +import io.openems.edge.bridge.modbus.api.Parity; +import io.openems.edge.bridge.modbus.api.Stopbit; +import io.openems.edge.controller.api.modbus.AbstractModbusRtuApi; + +@ObjectClassDefinition(// + name = "Controller Api Modbus/RTU Read-Only", // + description = "This controller provides a read-only Modbus/RTU api.") +@interface Config { + + @AttributeDefinition(name = "Component-ID", description = "Unique ID of this Component") + String id() default "ctrlApiModbusRtu0"; + + @AttributeDefinition(name = "Alias", description = "Human-readable name of this Component; defaults to Component-ID") + String alias() default "ModbusRtu Read-Only"; + + @AttributeDefinition(name = "Is enabled?", description = "Is this Component enabled?") + boolean enabled() default true; + + @AttributeDefinition(name = "Port-Name", description = "The name of the serial port - e.g. '/dev/ttyUSB0' or 'COM3'") + String portName() default "/dev/ttyUSB0"; + + @AttributeDefinition(name = "Component-IDs", description = "Components that should be made available via Modbus.") + String[] component_ids() default { "_sum" }; + + @AttributeDefinition(name = "Api-Timeout", description = "Sets the timeout in seconds for updates on Channels set by this Api.") + int apiTimeout() default 60; + + @AttributeDefinition(name = "Max concurrent connections", description = "Sets the maximum number of concurrent connections via Modbus.") + int maxConcurrentConnections() default AbstractModbusRtuApi.DEFAULT_MAX_CONCURRENT_CONNECTIONS; + + @AttributeDefinition(name = "Components target filter", description = "This is auto-generated by 'Component-IDs'.") + String Component_target() default "(enabled=true)"; + + @AttributeDefinition(name = "Baudrate", description = "The baudrate - e.g. 9600, 19200, 38400, 57600 or 115200") + int baudRate() default 9600; + + @AttributeDefinition(name = "Databits", description = "The number of databits - e.g. 8") + int databits() default 8; + + @AttributeDefinition(name = "Stopbits", description = "The number of stopbits - '1', '1.5' or '2'") + Stopbit stopbits() default Stopbit.ONE; + + @AttributeDefinition(name = "Parity", description = "The parity - 'none', 'even', 'odd', 'mark' or 'space'") + Parity parity() default Parity.NONE; + + String webconsole_configurationFactory_nameHint() default "Controller Api Modbus/RTU Read-Write [{id}]"; +} \ No newline at end of file diff --git a/io.openems.edge.controller.api.modbus/src/io/openems/edge/controller/api/modbus/readonly/rtu/ControllerApiModbusRtuReadOnly.java b/io.openems.edge.controller.api.modbus/src/io/openems/edge/controller/api/modbus/readonly/rtu/ControllerApiModbusRtuReadOnly.java new file mode 100644 index 00000000000..3695fe79585 --- /dev/null +++ b/io.openems.edge.controller.api.modbus/src/io/openems/edge/controller/api/modbus/readonly/rtu/ControllerApiModbusRtuReadOnly.java @@ -0,0 +1,23 @@ +package io.openems.edge.controller.api.modbus.readonly.rtu; + +import io.openems.edge.common.channel.Doc; +import io.openems.edge.common.component.OpenemsComponent; + +public interface ControllerApiModbusRtuReadOnly extends OpenemsComponent { + + public enum ChannelId implements io.openems.edge.common.channel.ChannelId { + ; + + private final Doc doc; + + private ChannelId(Doc doc) { + this.doc = doc; + } + + @Override + public Doc doc() { + return this.doc; + } + } +} + diff --git a/io.openems.edge.controller.api.modbus/src/io/openems/edge/controller/api/modbus/readonly/rtu/ControllerApiModbusRtuReadOnlyImpl.java b/io.openems.edge.controller.api.modbus/src/io/openems/edge/controller/api/modbus/readonly/rtu/ControllerApiModbusRtuReadOnlyImpl.java new file mode 100644 index 00000000000..2a6d065a9b1 --- /dev/null +++ b/io.openems.edge.controller.api.modbus/src/io/openems/edge/controller/api/modbus/readonly/rtu/ControllerApiModbusRtuReadOnlyImpl.java @@ -0,0 +1,107 @@ +package io.openems.edge.controller.api.modbus.readonly.rtu; + +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.metatype.annotations.Designate; + +import com.ghgande.j2mod.modbus.Modbus; +import com.ghgande.j2mod.modbus.ModbusException; +import com.ghgande.j2mod.modbus.slave.ModbusSlave; +import com.ghgande.j2mod.modbus.slave.ModbusSlaveFactory; +import com.ghgande.j2mod.modbus.util.SerialParameters; + +import io.openems.common.channel.AccessMode; +import io.openems.common.exceptions.OpenemsException; +import io.openems.edge.common.component.OpenemsComponent; +import io.openems.edge.common.jsonapi.ComponentJsonApi; +import io.openems.edge.common.meta.Meta; +import io.openems.edge.controller.api.Controller; +import io.openems.edge.controller.api.modbus.AbstractModbusRtuApi; +import io.openems.edge.controller.api.modbus.ModbusApi; + +@Designate(ocd = Config.class, factory = true) +@Component(// + name = "Controller.Api.ModbusRtu.ReadOnly", // + immediate = true, // + configurationPolicy = ConfigurationPolicy.REQUIRE // +) +public class ControllerApiModbusRtuReadOnlyImpl extends AbstractModbusRtuApi + implements ControllerApiModbusRtuReadOnly, ModbusApi, Controller, OpenemsComponent, ComponentJsonApi { + + @Reference + private Meta metaComponent = null; + + @Reference + private ConfigurationAdmin cm; + + private RtuConfig config; + + public ControllerApiModbusRtuReadOnlyImpl() { + super("Modbus/RTU-Api Read-Only", // + OpenemsComponent.ChannelId.values(), // + Controller.ChannelId.values(), // + ModbusApi.ChannelId.values(), // + ControllerApiModbusRtuReadOnly.ChannelId.values() // + ); + } + + @Override + @Reference(policy = ReferencePolicy.DYNAMIC, policyOption = ReferencePolicyOption.GREEDY, cardinality = ReferenceCardinality.MULTIPLE) + protected void addComponent(OpenemsComponent component) { + super.addComponent(component); + } + + protected void removeComponent(OpenemsComponent component) { + super.removeComponent(component); + } + + @Activate + private void activate(ComponentContext context, Config config) throws OpenemsException { + this.config = new RtuConfig(config.id(), config.alias(), config.enabled(), this.metaComponent, + config.component_ids(), 0 /* no timeout */, config.portName(), config.baudRate(), config.databits(), + config.stopbits(), config.parity(), config.maxConcurrentConnections()); + super.activate(context, this.cm, this.config); + } + + @Modified + private void modified(ComponentContext context, Config config) throws OpenemsException { + this.config = new RtuConfig(config.id(), config.alias(), config.enabled(), this.metaComponent, + config.component_ids(), 0 /* no timeout */, config.portName(), config.baudRate(), config.databits(), + config.stopbits(), config.parity(), config.maxConcurrentConnections()); + super.modified(context, this.cm, this.config); + } + + @Override + @Deactivate + protected void deactivate() { + super.deactivate(); + } + + @Override + protected ModbusSlave createSlave() throws ModbusException { + SerialParameters params = new SerialParameters(); + params.setPortName(this.config.portName()); + params.setBaudRate(this.config.baudRate()); + params.setDatabits(this.config.databits()); + params.setStopbits(this.config.stopbits().getValue()); + params.setParity(this.config.parity().getValue()); + params.setEncoding(Modbus.SERIAL_ENCODING_RTU); + params.setEcho(false); + return ModbusSlaveFactory.createSerialSlave(params); + } + + @Override + protected AccessMode getAccessMode() { + return AccessMode.READ_ONLY; + } + +} \ No newline at end of file diff --git a/io.openems.edge.controller.api.modbus/src/io/openems/edge/controller/api/modbus/readonly/Config.java b/io.openems.edge.controller.api.modbus/src/io/openems/edge/controller/api/modbus/readonly/tcp/Config.java similarity index 93% rename from io.openems.edge.controller.api.modbus/src/io/openems/edge/controller/api/modbus/readonly/Config.java rename to io.openems.edge.controller.api.modbus/src/io/openems/edge/controller/api/modbus/readonly/tcp/Config.java index 56c67020d85..e8947eea421 100644 --- a/io.openems.edge.controller.api.modbus/src/io/openems/edge/controller/api/modbus/readonly/Config.java +++ b/io.openems.edge.controller.api.modbus/src/io/openems/edge/controller/api/modbus/readonly/tcp/Config.java @@ -1,4 +1,4 @@ -package io.openems.edge.controller.api.modbus.readonly; +package io.openems.edge.controller.api.modbus.readonly.tcp; import org.osgi.service.metatype.annotations.AttributeDefinition; import org.osgi.service.metatype.annotations.ObjectClassDefinition; @@ -14,7 +14,7 @@ String id() default "ctrlApiModbusTcp0"; @AttributeDefinition(name = "Alias", description = "Human-readable name of this Component; defaults to Component-ID") - String alias() default ""; + String alias() default "ModbusTcp Read-Only"; @AttributeDefinition(name = "Is enabled?", description = "Is this Component enabled?") boolean enabled() default true; diff --git a/io.openems.edge.controller.api.modbus/src/io/openems/edge/controller/api/modbus/readonly/ControllerApiModbusTcpReadOnly.java b/io.openems.edge.controller.api.modbus/src/io/openems/edge/controller/api/modbus/readonly/tcp/ControllerApiModbusTcpReadOnly.java similarity index 87% rename from io.openems.edge.controller.api.modbus/src/io/openems/edge/controller/api/modbus/readonly/ControllerApiModbusTcpReadOnly.java rename to io.openems.edge.controller.api.modbus/src/io/openems/edge/controller/api/modbus/readonly/tcp/ControllerApiModbusTcpReadOnly.java index 52bb94c3b2e..cb31ba9d8d4 100644 --- a/io.openems.edge.controller.api.modbus/src/io/openems/edge/controller/api/modbus/readonly/ControllerApiModbusTcpReadOnly.java +++ b/io.openems.edge.controller.api.modbus/src/io/openems/edge/controller/api/modbus/readonly/tcp/ControllerApiModbusTcpReadOnly.java @@ -1,4 +1,4 @@ -package io.openems.edge.controller.api.modbus.readonly; +package io.openems.edge.controller.api.modbus.readonly.tcp; import io.openems.edge.common.channel.Doc; import io.openems.edge.common.component.OpenemsComponent; diff --git a/io.openems.edge.controller.api.modbus/src/io/openems/edge/controller/api/modbus/readonly/ControllerApiModbusTcpReadOnlyImpl.java b/io.openems.edge.controller.api.modbus/src/io/openems/edge/controller/api/modbus/readonly/tcp/ControllerApiModbusTcpReadOnlyImpl.java similarity index 65% rename from io.openems.edge.controller.api.modbus/src/io/openems/edge/controller/api/modbus/readonly/ControllerApiModbusTcpReadOnlyImpl.java rename to io.openems.edge.controller.api.modbus/src/io/openems/edge/controller/api/modbus/readonly/tcp/ControllerApiModbusTcpReadOnlyImpl.java index 01c6e47638a..2f35e4bf4fe 100644 --- a/io.openems.edge.controller.api.modbus/src/io/openems/edge/controller/api/modbus/readonly/ControllerApiModbusTcpReadOnlyImpl.java +++ b/io.openems.edge.controller.api.modbus/src/io/openems/edge/controller/api/modbus/readonly/tcp/ControllerApiModbusTcpReadOnlyImpl.java @@ -1,4 +1,4 @@ -package io.openems.edge.controller.api.modbus.readonly; +package io.openems.edge.controller.api.modbus.readonly.tcp; import java.util.Map.Entry; import java.util.function.Consumer; @@ -9,6 +9,7 @@ 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; @@ -16,9 +17,13 @@ import org.osgi.service.metatype.annotations.Designate; import com.ghgande.j2mod.modbus.ModbusException; +import com.ghgande.j2mod.modbus.slave.ModbusSlave; +import com.ghgande.j2mod.modbus.slave.ModbusSlaveFactory; import io.openems.common.channel.AccessMode; +import io.openems.common.exceptions.OpenemsError.OpenemsNamedException; import io.openems.common.exceptions.OpenemsException; +import io.openems.common.utils.FunctionUtils; import io.openems.edge.common.channel.WriteChannel; import io.openems.edge.common.component.OpenemsComponent; import io.openems.edge.common.jsonapi.ComponentJsonApi; @@ -27,7 +32,7 @@ import io.openems.edge.controller.api.common.Status; import io.openems.edge.controller.api.common.WriteObject; import io.openems.edge.controller.api.modbus.AbstractModbusTcpApi; -import io.openems.edge.controller.api.modbus.ModbusTcpApi; +import io.openems.edge.controller.api.modbus.ModbusApi; @Designate(ocd = Config.class, factory = true) @Component(// @@ -36,14 +41,16 @@ configurationPolicy = ConfigurationPolicy.REQUIRE // ) public class ControllerApiModbusTcpReadOnlyImpl extends AbstractModbusTcpApi - implements ControllerApiModbusTcpReadOnly, ModbusTcpApi, Controller, OpenemsComponent, ComponentJsonApi { + implements ControllerApiModbusTcpReadOnly, ModbusApi, Controller, OpenemsComponent, ComponentJsonApi { - @Reference(policy = ReferencePolicy.STATIC, policyOption = ReferencePolicyOption.GREEDY, cardinality = ReferenceCardinality.MANDATORY) + @Reference private Meta metaComponent = null; @Reference private ConfigurationAdmin cm; + private TcpConfig config; + @Override @Reference(policy = ReferencePolicy.DYNAMIC, policyOption = ReferencePolicyOption.GREEDY, cardinality = ReferenceCardinality.MULTIPLE) protected void addComponent(OpenemsComponent component) { @@ -58,16 +65,23 @@ public ControllerApiModbusTcpReadOnlyImpl() { super("Modbus/TCP-Api Read-Only", // OpenemsComponent.ChannelId.values(), // Controller.ChannelId.values(), // - ModbusTcpApi.ChannelId.values(), // + ModbusApi.ChannelId.values(), // ControllerApiModbusTcpReadOnly.ChannelId.values() // ); } @Activate private void activate(ComponentContext context, Config config) throws ModbusException, OpenemsException { - super.activate(context, this.cm, - new ConfigRecord(config.id(), config.alias(), config.enabled(),this.metaComponent, config.component_ids(), 0 /* no timeout */, config.port(), - config.maxConcurrentConnections())); + this.config = new TcpConfig(config.id(), config.alias(), config.enabled(), this.metaComponent, + config.component_ids(), 0 /* no timeout */, config.port(), config.maxConcurrentConnections()); + super.activate(context, this.cm, this.config); + } + + @Modified + private void modified(ComponentContext context, Config config) throws OpenemsNamedException { + this.config = new TcpConfig(config.id(), config.alias(), config.enabled(), this.metaComponent, + config.component_ids(), 0 /* no timeout */, config.port(), config.maxConcurrentConnections()); + super.modified(context, this.cm, this.config); } @Override @@ -83,7 +97,7 @@ protected AccessMode getAccessMode() { @Override protected Consumer, WriteObject>> handleWrites() { - return entry -> { }; + return FunctionUtils::doNothing; } @Override @@ -92,6 +106,11 @@ protected void setOverrideStatus(Status status) { @Override protected Runnable handleTimeouts() { - return () -> { }; + return FunctionUtils::doNothing; + } + + @Override + protected ModbusSlave createSlave() throws ModbusException { + return ModbusSlaveFactory.createTCPSlave(this.config.getPort(), this.config.maxConcurrentConnections()); } } diff --git a/io.openems.edge.controller.api.modbus/src/io/openems/edge/controller/api/modbus/readwrite/rtu/Config.java b/io.openems.edge.controller.api.modbus/src/io/openems/edge/controller/api/modbus/readwrite/rtu/Config.java new file mode 100644 index 00000000000..380d24fb662 --- /dev/null +++ b/io.openems.edge.controller.api.modbus/src/io/openems/edge/controller/api/modbus/readwrite/rtu/Config.java @@ -0,0 +1,52 @@ +package io.openems.edge.controller.api.modbus.readwrite.rtu; + +import org.osgi.service.metatype.annotations.AttributeDefinition; +import org.osgi.service.metatype.annotations.ObjectClassDefinition; + +import io.openems.edge.bridge.modbus.api.Parity; +import io.openems.edge.bridge.modbus.api.Stopbit; +import io.openems.edge.controller.api.modbus.AbstractModbusRtuApi; + +@ObjectClassDefinition(// + name = "Controller Api Modbus/RTU Read-Write", // + description = "This controller provides a read-write Modbus/RTU api.") +@interface Config { + + @AttributeDefinition(name = "Component-ID", description = "Unique ID of this Component") + String id() default "ctrlApiModbusRtu0"; + + @AttributeDefinition(name = "Alias", description = "Human-readable name of this Component; defaults to Component-ID") + String alias() default "ModbusRtu Read-Write"; + + @AttributeDefinition(name = "Is enabled?", description = "Is this Component enabled?") + boolean enabled() default true; + + @AttributeDefinition(name = "Port-Name", description = "The name of the serial port - e.g. '/dev/ttyUSB0' or 'COM3'") + String portName() default "/dev/ttyUSB0"; + + @AttributeDefinition(name = "Component-IDs", description = "Components that should be made available via Modbus.") + String[] component_ids() default { "_sum" }; + + @AttributeDefinition(name = "Api-Timeout", description = "Sets the timeout in seconds for updates on Channels set by this Api.") + int apiTimeout() default 60; + + @AttributeDefinition(name = "Max concurrent connections", description = "Sets the maximum number of concurrent connections via Modbus.") + int maxConcurrentConnections() default AbstractModbusRtuApi.DEFAULT_MAX_CONCURRENT_CONNECTIONS; + + @AttributeDefinition(name = "Components target filter", description = "This is auto-generated by 'Component-IDs'.") + String Component_target() default "(enabled=true)"; + + @AttributeDefinition(name = "Baudrate", description = "The baudrate - e.g. 9600, 19200, 38400, 57600 or 115200") + int baudRate() default 9600; + + @AttributeDefinition(name = "Databits", description = "The number of databits - e.g. 8") + int databits() default 8; + + @AttributeDefinition(name = "Stopbits", description = "The number of stopbits - '1', '1.5' or '2'") + Stopbit stopbits() default Stopbit.ONE; + + @AttributeDefinition(name = "Parity", description = "The parity - 'none', 'even', 'odd', 'mark' or 'space'") + Parity parity() default Parity.NONE; + + String webconsole_configurationFactory_nameHint() default "Controller Api Modbus/RTU Read-Write [{id}]"; +} \ No newline at end of file diff --git a/io.openems.edge.controller.api.modbus/src/io/openems/edge/controller/api/modbus/readwrite/rtu/ControllerApiModbusRtuReadWrite.java b/io.openems.edge.controller.api.modbus/src/io/openems/edge/controller/api/modbus/readwrite/rtu/ControllerApiModbusRtuReadWrite.java new file mode 100644 index 00000000000..85280084c66 --- /dev/null +++ b/io.openems.edge.controller.api.modbus/src/io/openems/edge/controller/api/modbus/readwrite/rtu/ControllerApiModbusRtuReadWrite.java @@ -0,0 +1,50 @@ +package io.openems.edge.controller.api.modbus.readwrite.rtu; + +import io.openems.common.channel.Unit; +import io.openems.common.types.OpenemsType; +import io.openems.edge.common.channel.Doc; +import io.openems.edge.common.channel.StringReadChannel; +import io.openems.edge.common.component.OpenemsComponent; + +public interface ControllerApiModbusRtuReadWrite extends OpenemsComponent { + + public enum ChannelId implements io.openems.edge.common.channel.ChannelId { + API_WORKER_LOG(Doc.of(OpenemsType.STRING) // + .text("Logs Write-Commands via ApiWorker")), // + DEBUG_SET_ACTIVE_POWER_EQUALS(Doc.of(OpenemsType.INTEGER) // + .unit(Unit.WATT)), // + DEBUG_SET_ACTIVE_POWER_GREATER_OR_EQUALS(Doc.of(OpenemsType.INTEGER) // + .unit(Unit.WATT)), // + DEBUG_SET_ACTIVE_POWER_LESS_OR_EQUALS(Doc.of(OpenemsType.INTEGER) // + .unit(Unit.WATT)), // + DEBUG_SET_REACTIVE_POWER_EQUALS(Doc.of(OpenemsType.INTEGER) // + .unit(Unit.VOLT_AMPERE_REACTIVE)), // + DEBUG_SET_REACTIVE_POWER_GREATER_OR_EQUALS(Doc.of(OpenemsType.INTEGER) // + .unit(Unit.VOLT_AMPERE_REACTIVE)), // + DEBUG_SET_REACTIVE_POWER_LESS_OR_EQUALS(Doc.of(OpenemsType.INTEGER) // + .unit(Unit.VOLT_AMPERE_REACTIVE)), // + + ; + + private final Doc doc; + + private ChannelId(Doc doc) { + this.doc = doc; + } + + @Override + public Doc doc() { + return this.doc; + } + } + + /** + * Gets the Channel for {@link ChannelId#API_WORKER_LOG}. + * + * @return the Channel + */ + public default StringReadChannel getApiWorkerLogChannel() { + return this.channel(ChannelId.API_WORKER_LOG); + } + +} \ No newline at end of file diff --git a/io.openems.edge.controller.api.modbus/src/io/openems/edge/controller/api/modbus/readwrite/rtu/ControllerApiModbusRtuReadWriteImpl.java b/io.openems.edge.controller.api.modbus/src/io/openems/edge/controller/api/modbus/readwrite/rtu/ControllerApiModbusRtuReadWriteImpl.java new file mode 100644 index 00000000000..7cfd34c5840 --- /dev/null +++ b/io.openems.edge.controller.api.modbus/src/io/openems/edge/controller/api/modbus/readwrite/rtu/ControllerApiModbusRtuReadWriteImpl.java @@ -0,0 +1,141 @@ +package io.openems.edge.controller.api.modbus.readwrite.rtu; + +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.metatype.annotations.Designate; + +import com.ghgande.j2mod.modbus.Modbus; +import com.ghgande.j2mod.modbus.ModbusException; +import com.ghgande.j2mod.modbus.slave.ModbusSlave; +import com.ghgande.j2mod.modbus.slave.ModbusSlaveFactory; +import com.ghgande.j2mod.modbus.util.SerialParameters; + +import io.openems.common.channel.AccessMode; +import io.openems.common.exceptions.OpenemsException; +import io.openems.edge.common.component.ComponentManager; +import io.openems.edge.common.component.OpenemsComponent; +import io.openems.edge.common.jsonapi.ComponentJsonApi; +import io.openems.edge.common.meta.Meta; +import io.openems.edge.common.modbusslave.ModbusSlaveNatureTable; +import io.openems.edge.common.modbusslave.ModbusSlaveTable; +import io.openems.edge.common.modbusslave.ModbusType; +import io.openems.edge.controller.api.Controller; +import io.openems.edge.controller.api.modbus.AbstractModbusRtuApi; +import io.openems.edge.controller.api.modbus.ModbusApi; + +@Designate(ocd = Config.class, factory = true) +@Component(// + name = "Controller.Api.ModbusRtu.ReadWrite", // + immediate = true, // + configurationPolicy = ConfigurationPolicy.REQUIRE // +) +public class ControllerApiModbusRtuReadWriteImpl extends AbstractModbusRtuApi + implements ControllerApiModbusRtuReadWrite, ModbusApi, Controller, OpenemsComponent, ComponentJsonApi, + io.openems.edge.common.modbusslave.ModbusSlave { + + @Reference + private Meta metaComponent = null; + + @Reference + private ConfigurationAdmin cm; + + private RtuConfig config; + + @Reference + private ComponentManager componentManager; + + public ControllerApiModbusRtuReadWriteImpl() { + super("Modbus/RTU-Api Read-Write", // + OpenemsComponent.ChannelId.values(), // + Controller.ChannelId.values(), // + ModbusApi.ChannelId.values(), // + ControllerApiModbusRtuReadWrite.ChannelId.values() // + ); + this.apiWorker.setLogChannel(this.getApiWorkerLogChannel()); + } + + @Override + @Reference(policy = ReferencePolicy.DYNAMIC, policyOption = ReferencePolicyOption.GREEDY, cardinality = ReferenceCardinality.MULTIPLE) + protected void addComponent(OpenemsComponent component) { + super.addComponent(component); + } + + @Override + protected void removeComponent(OpenemsComponent component) { + super.removeComponent(component); + } + + @Activate + private void activate(ComponentContext context, Config config) throws OpenemsException { + this.config = new RtuConfig(config.id(), config.alias(), config.enabled(), this.metaComponent, + config.component_ids(), config.apiTimeout(), config.portName(), config.baudRate(), config.databits(), + config.stopbits(), config.parity(), config.maxConcurrentConnections()); + super.activate(context, this.cm, this.config); + } + + @Modified + private void modified(ComponentContext context, Config config) throws OpenemsException { + this.config = new RtuConfig(config.id(), config.alias(), config.enabled(), this.metaComponent, + config.component_ids(), config.apiTimeout(), config.portName(), config.baudRate(), config.databits(), + config.stopbits(), config.parity(), config.maxConcurrentConnections()); + super.modified(context, this.cm, this.config); + } + + @Override + @Deactivate + protected void deactivate() { + super.deactivate(); + } + + @Override + protected ModbusSlave createSlave() throws ModbusException { + SerialParameters params = new SerialParameters(); + params.setPortName(this.config.portName()); + params.setBaudRate(this.config.baudRate()); + params.setDatabits(this.config.databits()); + params.setStopbits(this.config.stopbits().getValue()); + params.setParity(this.config.parity().getValue()); + params.setEncoding(Modbus.SERIAL_ENCODING_RTU); + params.setEcho(false); + return ModbusSlaveFactory.createSerialSlave(params); + } + + @Override + protected AccessMode getAccessMode() { + return AccessMode.READ_WRITE; + } + + @Override + public ModbusSlaveTable getModbusSlaveTable(AccessMode accessMode) { + return new ModbusSlaveTable(// + OpenemsComponent.getModbusSlaveNatureTable(accessMode), // + ModbusSlaveNatureTable.of(ControllerApiModbusRtuReadWrite.class, accessMode, 100) // + .channel(0, ModbusApi.ChannelId.UNABLE_TO_START, ModbusType.UINT16) // + .channel(1, ModbusApi.ChannelId.COMPONENT_MISSING_FAULT, ModbusType.UINT16) // + .channel(2, ModbusApi.ChannelId.PROCESS_IMAGE_FAULT, ModbusType.UINT16) // + .channel(3, ModbusApi.ChannelId.COMPONENT_NO_MODBUS_API_FAULT, ModbusType.UINT16) // + .channel(4, ControllerApiModbusRtuReadWrite.ChannelId.DEBUG_SET_ACTIVE_POWER_EQUALS, + ModbusType.FLOAT32) // + .channel(6, ControllerApiModbusRtuReadWrite.ChannelId.DEBUG_SET_ACTIVE_POWER_GREATER_OR_EQUALS, + ModbusType.FLOAT32) // + .channel(8, ControllerApiModbusRtuReadWrite.ChannelId.DEBUG_SET_ACTIVE_POWER_LESS_OR_EQUALS, + ModbusType.FLOAT32) // + .channel(10, ControllerApiModbusRtuReadWrite.ChannelId.DEBUG_SET_REACTIVE_POWER_EQUALS, + ModbusType.FLOAT32) // + .channel(12, + ControllerApiModbusRtuReadWrite.ChannelId.DEBUG_SET_REACTIVE_POWER_GREATER_OR_EQUALS, + ModbusType.FLOAT32) // + .channel(14, ControllerApiModbusRtuReadWrite.ChannelId.DEBUG_SET_REACTIVE_POWER_LESS_OR_EQUALS, + ModbusType.FLOAT32) // + .build()); // + } +} \ No newline at end of file diff --git a/io.openems.edge.controller.api.modbus/src/io/openems/edge/controller/api/modbus/readwrite/Config.java b/io.openems.edge.controller.api.modbus/src/io/openems/edge/controller/api/modbus/readwrite/tcp/Config.java similarity index 93% rename from io.openems.edge.controller.api.modbus/src/io/openems/edge/controller/api/modbus/readwrite/Config.java rename to io.openems.edge.controller.api.modbus/src/io/openems/edge/controller/api/modbus/readwrite/tcp/Config.java index 0614487de2f..efd08feb754 100644 --- a/io.openems.edge.controller.api.modbus/src/io/openems/edge/controller/api/modbus/readwrite/Config.java +++ b/io.openems.edge.controller.api.modbus/src/io/openems/edge/controller/api/modbus/readwrite/tcp/Config.java @@ -1,4 +1,4 @@ -package io.openems.edge.controller.api.modbus.readwrite; +package io.openems.edge.controller.api.modbus.readwrite.tcp; import org.osgi.service.metatype.annotations.AttributeDefinition; import org.osgi.service.metatype.annotations.ObjectClassDefinition; @@ -14,7 +14,7 @@ String id() default "ctrlApiModbusTcp0"; @AttributeDefinition(name = "Alias", description = "Human-readable name of this Component; defaults to Component-ID") - String alias() default ""; + String alias() default "ModbusTcp Read-Write"; @AttributeDefinition(name = "Is enabled?", description = "Is this Component enabled?") boolean enabled() default true; @@ -27,7 +27,7 @@ // TODO: Currently unused @AttributeDefinition(name = "Read Channel-IDs", description = "Contains the channelnames of all read channels.") - String[] readChannels() default { }; + String[] readChannels() default {}; @AttributeDefinition(name = "Write Channel-IDs", description = "Contains the channelnames of all overridden channels.") String[] writeChannels(); diff --git a/io.openems.edge.controller.api.modbus/src/io/openems/edge/controller/api/modbus/readwrite/ControllerApiModbusTcpReadWrite.java b/io.openems.edge.controller.api.modbus/src/io/openems/edge/controller/api/modbus/readwrite/tcp/ControllerApiModbusTcpReadWrite.java similarity index 95% rename from io.openems.edge.controller.api.modbus/src/io/openems/edge/controller/api/modbus/readwrite/ControllerApiModbusTcpReadWrite.java rename to io.openems.edge.controller.api.modbus/src/io/openems/edge/controller/api/modbus/readwrite/tcp/ControllerApiModbusTcpReadWrite.java index 8a18a1aada2..47e04f0b476 100644 --- a/io.openems.edge.controller.api.modbus/src/io/openems/edge/controller/api/modbus/readwrite/ControllerApiModbusTcpReadWrite.java +++ b/io.openems.edge.controller.api.modbus/src/io/openems/edge/controller/api/modbus/readwrite/tcp/ControllerApiModbusTcpReadWrite.java @@ -1,4 +1,4 @@ -package io.openems.edge.controller.api.modbus.readwrite; +package io.openems.edge.controller.api.modbus.readwrite.tcp; import static io.openems.common.channel.PersistencePriority.HIGH; import static io.openems.common.channel.Unit.CUMULATED_SECONDS; @@ -16,18 +16,18 @@ public interface ControllerApiModbusTcpReadWrite extends OpenemsComponent { public enum ChannelId implements io.openems.edge.common.channel.ChannelId { - + OVERRIDE_STATUS(Doc.of(Status.values()) // .persistencePriority(PersistencePriority.HIGH)), // - + CUMULATED_ACTIVE_TIME(Doc.of(LONG)// .unit(CUMULATED_SECONDS) // .persistencePriority(HIGH)), // - + CUMULATED_INACTIVE_TIME(Doc.of(LONG)// .unit(CUMULATED_SECONDS) // .persistencePriority(HIGH)), // - + API_WORKER_LOG(Doc.of(OpenemsType.STRING) // .text("Logs Write-Commands via ApiWorker")); // @@ -71,7 +71,8 @@ public default Status getOverrideStatus() { } /** - * Internal method to set the 'nextValue' on {@link ChannelId#OVERRIDE_STATUS} Channel. + * Internal method to set the 'nextValue' on {@link ChannelId#OVERRIDE_STATUS} + * Channel. * * @param value the next value */ diff --git a/io.openems.edge.controller.api.modbus/src/io/openems/edge/controller/api/modbus/readwrite/ControllerApiModbusTcpReadWriteImpl.java b/io.openems.edge.controller.api.modbus/src/io/openems/edge/controller/api/modbus/readwrite/tcp/ControllerApiModbusTcpReadWriteImpl.java similarity index 86% rename from io.openems.edge.controller.api.modbus/src/io/openems/edge/controller/api/modbus/readwrite/ControllerApiModbusTcpReadWriteImpl.java rename to io.openems.edge.controller.api.modbus/src/io/openems/edge/controller/api/modbus/readwrite/tcp/ControllerApiModbusTcpReadWriteImpl.java index 6f1a47ad49c..6aff04589ce 100644 --- a/io.openems.edge.controller.api.modbus/src/io/openems/edge/controller/api/modbus/readwrite/ControllerApiModbusTcpReadWriteImpl.java +++ b/io.openems.edge.controller.api.modbus/src/io/openems/edge/controller/api/modbus/readwrite/tcp/ControllerApiModbusTcpReadWriteImpl.java @@ -1,4 +1,4 @@ -package io.openems.edge.controller.api.modbus.readwrite; +package io.openems.edge.controller.api.modbus.readwrite.tcp; import static io.openems.edge.common.channel.ChannelId.channelIdCamelToUpper; import static io.openems.edge.common.channel.ChannelId.channelIdUpperToCamel; @@ -27,6 +27,7 @@ import org.slf4j.LoggerFactory; import com.ghgande.j2mod.modbus.ModbusException; +import com.ghgande.j2mod.modbus.slave.ModbusSlaveFactory; import io.openems.common.channel.AccessMode; import io.openems.common.channel.PersistencePriority; @@ -48,7 +49,7 @@ import io.openems.edge.controller.api.common.Status; import io.openems.edge.controller.api.common.WriteObject; import io.openems.edge.controller.api.modbus.AbstractModbusTcpApi; -import io.openems.edge.controller.api.modbus.ModbusTcpApi; +import io.openems.edge.controller.api.modbus.ModbusApi; import io.openems.edge.ess.api.ManagedSymmetricEss; import io.openems.edge.timedata.api.Timedata; import io.openems.edge.timedata.api.TimedataProvider; @@ -61,7 +62,7 @@ configurationPolicy = ConfigurationPolicy.REQUIRE // ) public class ControllerApiModbusTcpReadWriteImpl extends AbstractModbusTcpApi - implements ControllerApiModbusTcpReadWrite, ModbusTcpApi, Controller, OpenemsComponent, ComponentJsonApi, + implements ControllerApiModbusTcpReadWrite, ModbusApi, Controller, OpenemsComponent, ComponentJsonApi, TimedataProvider, ModbusSlave { private final Logger log = LoggerFactory.getLogger(ControllerApiModbusTcpReadWriteImpl.class); @@ -76,12 +77,14 @@ public class ControllerApiModbusTcpReadWriteImpl extends AbstractModbusTcpApi private List components = new ArrayList<>(); + private TcpConfig config; + private boolean isActive = false; @Reference(policy = ReferencePolicy.DYNAMIC, policyOption = ReferencePolicyOption.GREEDY, cardinality = ReferenceCardinality.OPTIONAL) private volatile Timedata timedata = null; - @Reference(policy = ReferencePolicy.STATIC, policyOption = ReferencePolicyOption.GREEDY, cardinality = ReferenceCardinality.MANDATORY) + @Reference private Meta metaComponent = null; @Reference @@ -107,7 +110,7 @@ public ControllerApiModbusTcpReadWriteImpl() { super("Modbus/TCP-Api Read-Write", // OpenemsComponent.ChannelId.values(), // Controller.ChannelId.values(), // - ModbusTcpApi.ChannelId.values(), // + ModbusApi.ChannelId.values(), // ControllerApiModbusTcpReadWrite.ChannelId.values() // ); this.apiWorker.setLogChannel(this.getApiWorkerLogChannel()); @@ -115,17 +118,17 @@ public ControllerApiModbusTcpReadWriteImpl() { @Activate private void activate(ComponentContext context, Config config) throws ModbusException, OpenemsException { - super.activate(context, this.cm, - new ConfigRecord(config.id(), config.alias(), config.enabled(), this.metaComponent, - config.component_ids(), config.apiTimeout(), config.port(), config.maxConcurrentConnections())); + this.config = new TcpConfig(config.id(), config.alias(), config.enabled(), this.metaComponent, + config.component_ids(), config.apiTimeout(), config.port(), config.maxConcurrentConnections()); + super.activate(context, this.cm, this.config); this.applyConfig(config); } @Modified private void modified(ComponentContext context, Config config) throws OpenemsNamedException { - super.modified(context, this.cm, - new ConfigRecord(config.id(), config.alias(), config.enabled(), this.metaComponent, - config.component_ids(), config.apiTimeout(), config.port(), config.maxConcurrentConnections())); + this.config = new TcpConfig(config.id(), config.alias(), config.enabled(), this.metaComponent, + config.component_ids(), config.apiTimeout(), config.port(), config.maxConcurrentConnections()); + super.modified(context, this.cm, this.config); this.applyConfig(config); } @@ -245,14 +248,18 @@ protected Integer getChannelValue(String componentId, io.openems.edge.common.cha public ModbusSlaveTable getModbusSlaveTable(AccessMode accessMode) { return new ModbusSlaveTable(// OpenemsComponent.getModbusSlaveNatureTable(AccessMode.READ_ONLY), - ModbusSlaveNatureTable.of(ControllerApiModbusTcpReadWriteImpl.class, AccessMode.READ_ONLY, 300) - .cycleValue(0, this.id() + "/ Ess0ActivePowerLimit", Unit.WATT, "", ModbusType.FLOAT32, + ModbusSlaveNatureTable.of(ControllerApiModbusTcpReadWrite.class, AccessMode.READ_ONLY, 300) + .cycleValue(0, this.id() + "/Ess0ActivePowerLimit", Unit.WATT, "", ModbusType.FLOAT32, t -> this.getChannelValue("ess0", ManagedSymmetricEss.ChannelId.SET_ACTIVE_POWER_EQUALS)) - .cycleValue(2, this.id() + "/Ess0ReactivePowerLimit", Unit.WATT, "", ModbusType.FLOAT32, - t -> this.getChannelValue("ess0", + .cycleValue(2, this.id() + "/Ess0ReactivePowerLimit", Unit.VOLT_AMPERE_REACTIVE, "", + ModbusType.FLOAT32, t -> this.getChannelValue("ess0", ManagedSymmetricEss.ChannelId.SET_REACTIVE_POWER_EQUALS)) .build()); } + @Override + protected com.ghgande.j2mod.modbus.slave.ModbusSlave createSlave() throws ModbusException { + return ModbusSlaveFactory.createTCPSlave(this.config.getPort(), this.config.maxConcurrentConnections()); + } } diff --git a/io.openems.edge.controller.api.modbus/test/io/openems/edge/controller/api/modbus/readonly/rtu/ControllerApiModbusRtuReadOnlyImplTest.java b/io.openems.edge.controller.api.modbus/test/io/openems/edge/controller/api/modbus/readonly/rtu/ControllerApiModbusRtuReadOnlyImplTest.java new file mode 100644 index 00000000000..c183e8f9529 --- /dev/null +++ b/io.openems.edge.controller.api.modbus/test/io/openems/edge/controller/api/modbus/readonly/rtu/ControllerApiModbusRtuReadOnlyImplTest.java @@ -0,0 +1,32 @@ +package io.openems.edge.controller.api.modbus.readonly.rtu; + +import org.junit.Test; + +import io.openems.edge.bridge.modbus.api.Parity; +import io.openems.edge.bridge.modbus.api.Stopbit; +import io.openems.edge.common.test.AbstractComponentTest.TestCase; +import io.openems.edge.common.test.DummyConfigurationAdmin; +import io.openems.edge.controller.test.ControllerTest; + +public class ControllerApiModbusRtuReadOnlyImplTest { + + private static final String CTRL_ID = "ctrl0"; + + @Test + public void test() throws Exception { + new ControllerTest(new ControllerApiModbusRtuReadOnlyImpl()) // + .addReference("cm", new DummyConfigurationAdmin()) // + .activate(MyConfig.create() // + .setId(CTRL_ID) // + .setEnabled(false) // do not actually start server + .setParity(Parity.NONE) + .setStopbit(Stopbit.ONE) + .setBaudrate(9600) // + .setComponentIds() // + .setMaxConcurrentConnections(5) // + .setPortName("/dev/ttyUSB0") // + .build()) // + .next(new TestCase()) // + ; + } +} diff --git a/io.openems.edge.controller.api.modbus/test/io/openems/edge/controller/api/modbus/readonly/rtu/MyConfig.java b/io.openems.edge.controller.api.modbus/test/io/openems/edge/controller/api/modbus/readonly/rtu/MyConfig.java new file mode 100644 index 00000000000..4eef1319428 --- /dev/null +++ b/io.openems.edge.controller.api.modbus/test/io/openems/edge/controller/api/modbus/readonly/rtu/MyConfig.java @@ -0,0 +1,147 @@ +package io.openems.edge.controller.api.modbus.readonly.rtu; + +import io.openems.common.test.AbstractComponentConfig; +import io.openems.common.utils.ConfigUtils; +import io.openems.edge.bridge.modbus.api.Parity; +import io.openems.edge.bridge.modbus.api.Stopbit; + +@SuppressWarnings("all") +public class MyConfig extends AbstractComponentConfig implements Config { + + protected static class Builder { + private String id; + private boolean enabled; + private String portName; + private String[] componentIds; + private int baudrate; + private int databits; + private Stopbit stopbit; + private Parity parity; + private int apiTimeout; + private int maxConcurrentConnections; + + private Builder() { + } + + public Builder setId(String id) { + this.id = id; + return this; + } + + public Builder setEnabled(boolean enabled) { + this.enabled = enabled; + return this; + } + + public Builder setPortName(String portName) { + this.portName = portName; + return this; + } + + public Builder setComponentIds(String... componentIds) { + this.componentIds = componentIds; + return this; + } + + public Builder setMaxConcurrentConnections(int maxConcurrentConnections) { + this.maxConcurrentConnections = maxConcurrentConnections; + return this; + } + + public Builder setBaudrate(int baudrate) { + this.baudrate = baudrate; + return this; + } + + public Builder setDatabits(int databits) { + this.databits = databits; + return this; + } + + public Builder setStopbit(Stopbit stopbit) { + this.stopbit = stopbit; + return this; + } + + public Builder setParity(Parity parity) { + this.parity = parity; + return this; + } + + public Builder setApiTimeout(int apiTimeout) { + this.apiTimeout = apiTimeout; + 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 enabled() { + return this.builder.enabled; + } + + @Override + public String portName() { + return this.builder.portName; + } + + @Override + public int apiTimeout() { + return this.builder.apiTimeout; + } + + @Override + public int baudRate() { + return this.builder.baudrate; + } + + @Override + public int databits() { + return this.builder.baudrate; + } + + @Override + public Stopbit stopbits() { + return this.builder.stopbit; + } + + @Override + public Parity parity() { + return this.builder.parity; + } + + @Override + public String[] component_ids() { + return this.builder.componentIds; + } + + @Override + public int maxConcurrentConnections() { + return this.builder.maxConcurrentConnections; + } + + @Override + public String Component_target() { + return ConfigUtils.generateReferenceTargetFilter(this.id(), false, this.component_ids()); + } + +} \ No newline at end of file diff --git a/io.openems.edge.controller.api.modbus/test/io/openems/edge/controller/api/modbus/readonly/ControllerApiModbusTcpReadOnlyImplTest.java b/io.openems.edge.controller.api.modbus/test/io/openems/edge/controller/api/modbus/readonly/tcp/ControllerApiModbusTcpReadOnlyImplTest.java similarity index 93% rename from io.openems.edge.controller.api.modbus/test/io/openems/edge/controller/api/modbus/readonly/ControllerApiModbusTcpReadOnlyImplTest.java rename to io.openems.edge.controller.api.modbus/test/io/openems/edge/controller/api/modbus/readonly/tcp/ControllerApiModbusTcpReadOnlyImplTest.java index 6248a9b4e41..dc90cfccd44 100644 --- a/io.openems.edge.controller.api.modbus/test/io/openems/edge/controller/api/modbus/readonly/ControllerApiModbusTcpReadOnlyImplTest.java +++ b/io.openems.edge.controller.api.modbus/test/io/openems/edge/controller/api/modbus/readonly/tcp/ControllerApiModbusTcpReadOnlyImplTest.java @@ -1,4 +1,4 @@ -package io.openems.edge.controller.api.modbus.readonly; +package io.openems.edge.controller.api.modbus.readonly.tcp; import static io.openems.edge.controller.api.modbus.AbstractModbusTcpApi.DEFAULT_PORT; diff --git a/io.openems.edge.controller.api.modbus/test/io/openems/edge/controller/api/modbus/readonly/MyConfig.java b/io.openems.edge.controller.api.modbus/test/io/openems/edge/controller/api/modbus/readonly/tcp/MyConfig.java similarity index 96% rename from io.openems.edge.controller.api.modbus/test/io/openems/edge/controller/api/modbus/readonly/MyConfig.java rename to io.openems.edge.controller.api.modbus/test/io/openems/edge/controller/api/modbus/readonly/tcp/MyConfig.java index 0b9618e3806..428f8b1dd1e 100644 --- a/io.openems.edge.controller.api.modbus/test/io/openems/edge/controller/api/modbus/readonly/MyConfig.java +++ b/io.openems.edge.controller.api.modbus/test/io/openems/edge/controller/api/modbus/readonly/tcp/MyConfig.java @@ -1,4 +1,4 @@ -package io.openems.edge.controller.api.modbus.readonly; +package io.openems.edge.controller.api.modbus.readonly.tcp; import io.openems.common.test.AbstractComponentConfig; import io.openems.common.utils.ConfigUtils; diff --git a/io.openems.edge.controller.api.modbus/test/io/openems/edge/controller/api/modbus/readwrite/rtu/ControllerApiModbusRtuReadWriteImplTest.java b/io.openems.edge.controller.api.modbus/test/io/openems/edge/controller/api/modbus/readwrite/rtu/ControllerApiModbusRtuReadWriteImplTest.java new file mode 100644 index 00000000000..26dc37018c0 --- /dev/null +++ b/io.openems.edge.controller.api.modbus/test/io/openems/edge/controller/api/modbus/readwrite/rtu/ControllerApiModbusRtuReadWriteImplTest.java @@ -0,0 +1,30 @@ +package io.openems.edge.controller.api.modbus.readwrite.rtu; + +import org.junit.Test; + +import io.openems.edge.bridge.modbus.api.Parity; +import io.openems.edge.bridge.modbus.api.Stopbit; +import io.openems.edge.common.test.AbstractComponentTest.TestCase; +import io.openems.edge.common.test.DummyConfigurationAdmin; +import io.openems.edge.controller.test.ControllerTest; + +public class ControllerApiModbusRtuReadWriteImplTest { + + private static final String CTRL_ID = "ctrl0"; + + @Test + public void test() throws Exception { + new ControllerTest(new ControllerApiModbusRtuReadWriteImpl()) // + .addReference("cm", new DummyConfigurationAdmin()) // + .activate(MyConfig.create() // + .setId(CTRL_ID) // + .setEnabled(false) // do not actually start server + .setParity(Parity.NONE).setStopbit(Stopbit.ONE).setBaudrate(9600) // + .setComponentIds() // + .setMaxConcurrentConnections(5) // + .setPortName("/dev/ttyUSB0") // + .build()) // + .next(new TestCase()) // + ; + } +} diff --git a/io.openems.edge.controller.api.modbus/test/io/openems/edge/controller/api/modbus/readwrite/rtu/MyConfig.java b/io.openems.edge.controller.api.modbus/test/io/openems/edge/controller/api/modbus/readwrite/rtu/MyConfig.java new file mode 100644 index 00000000000..6f28ca0db52 --- /dev/null +++ b/io.openems.edge.controller.api.modbus/test/io/openems/edge/controller/api/modbus/readwrite/rtu/MyConfig.java @@ -0,0 +1,147 @@ +package io.openems.edge.controller.api.modbus.readwrite.rtu; + +import io.openems.common.test.AbstractComponentConfig; +import io.openems.common.utils.ConfigUtils; +import io.openems.edge.bridge.modbus.api.Parity; +import io.openems.edge.bridge.modbus.api.Stopbit; + +@SuppressWarnings("all") +public class MyConfig extends AbstractComponentConfig implements Config { + + protected static class Builder { + private String id; + private boolean enabled; + private String portName; + private String[] componentIds; + private int baudrate; + private int databits; + private Stopbit stopbit; + private Parity parity; + private int apiTimeout; + private int maxConcurrentConnections; + + private Builder() { + } + + public Builder setId(String id) { + this.id = id; + return this; + } + + public Builder setEnabled(boolean enabled) { + this.enabled = enabled; + return this; + } + + public Builder setPortName(String portName) { + this.portName = portName; + return this; + } + + public Builder setComponentIds(String... componentIds) { + this.componentIds = componentIds; + return this; + } + + public Builder setMaxConcurrentConnections(int maxConcurrentConnections) { + this.maxConcurrentConnections = maxConcurrentConnections; + return this; + } + + public Builder setBaudrate(int baudrate) { + this.baudrate = baudrate; + return this; + } + + public Builder setDatabits(int databits) { + this.databits = databits; + return this; + } + + public Builder setStopbit(Stopbit stopbit) { + this.stopbit = stopbit; + return this; + } + + public Builder setParity(Parity parity) { + this.parity = parity; + return this; + } + + public Builder setApiTimeout(int apiTimeout) { + this.apiTimeout = apiTimeout; + 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 enabled() { + return this.builder.enabled; + } + + @Override + public String portName() { + return this.builder.portName; + } + + @Override + public int apiTimeout() { + return this.builder.apiTimeout; + } + + @Override + public int baudRate() { + return this.builder.baudrate; + } + + @Override + public int databits() { + return this.builder.baudrate; + } + + @Override + public Stopbit stopbits() { + return this.builder.stopbit; + } + + @Override + public Parity parity() { + return this.builder.parity; + } + + @Override + public String[] component_ids() { + return this.builder.componentIds; + } + + @Override + public int maxConcurrentConnections() { + return this.builder.maxConcurrentConnections; + } + + @Override + public String Component_target() { + return ConfigUtils.generateReferenceTargetFilter(this.id(), false, this.component_ids()); + } + +} \ No newline at end of file diff --git a/io.openems.edge.controller.api.modbus/test/io/openems/edge/controller/api/modbus/readwrite/ControllerApiModbusTcpReadWriteImplTest.java b/io.openems.edge.controller.api.modbus/test/io/openems/edge/controller/api/modbus/readwrite/tcp/ControllerApiModbusTcpReadWriteImplTest.java similarity index 72% rename from io.openems.edge.controller.api.modbus/test/io/openems/edge/controller/api/modbus/readwrite/ControllerApiModbusTcpReadWriteImplTest.java rename to io.openems.edge.controller.api.modbus/test/io/openems/edge/controller/api/modbus/readwrite/tcp/ControllerApiModbusTcpReadWriteImplTest.java index f87124a5295..7ca3f80aaaa 100644 --- a/io.openems.edge.controller.api.modbus/test/io/openems/edge/controller/api/modbus/readwrite/ControllerApiModbusTcpReadWriteImplTest.java +++ b/io.openems.edge.controller.api.modbus/test/io/openems/edge/controller/api/modbus/readwrite/tcp/ControllerApiModbusTcpReadWriteImplTest.java @@ -1,8 +1,8 @@ -package io.openems.edge.controller.api.modbus.readwrite; +package io.openems.edge.controller.api.modbus.readwrite.tcp; import static io.openems.edge.controller.api.modbus.AbstractModbusTcpApi.DEFAULT_PORT; -import static io.openems.edge.controller.api.modbus.readwrite.ControllerApiModbusTcpReadWriteImpl.getChannelNameCamel; -import static io.openems.edge.controller.api.modbus.readwrite.ControllerApiModbusTcpReadWriteImpl.getChannelNameUpper; +import static io.openems.edge.controller.api.modbus.readwrite.tcp.ControllerApiModbusTcpReadWriteImpl.getChannelNameCamel; +import static io.openems.edge.controller.api.modbus.readwrite.tcp.ControllerApiModbusTcpReadWriteImpl.getChannelNameUpper; import static io.openems.edge.ess.api.ManagedSymmetricEss.ChannelId.SET_ACTIVE_POWER_EQUALS; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -53,13 +53,17 @@ public void testAddFalseComponents() throws Exception { @Test public void testGetChannelNameUpper() { - assertEquals("ESS0_SET_ACTIVE_POWER_EQUALS", getChannelNameUpper("ess0", SET_ACTIVE_POWER_EQUALS)); - assertEquals("ESS0_SET_ACTIVE_POWER_EQUALS", getChannelNameUpper("Ess0", SET_ACTIVE_POWER_EQUALS)); + assertEquals("ESS0_SET_ACTIVE_POWER_EQUALS", + getChannelNameUpper("ess0", SET_ACTIVE_POWER_EQUALS)); + assertEquals("ESS0_SET_ACTIVE_POWER_EQUALS", + getChannelNameUpper("Ess0", SET_ACTIVE_POWER_EQUALS)); } @Test public void testGetChannelNameCamel() { - assertEquals("Ess0SetActivePowerEquals", getChannelNameCamel("ess0", SET_ACTIVE_POWER_EQUALS)); - assertEquals("Ess0SetActivePowerEquals", getChannelNameCamel("Ess0", SET_ACTIVE_POWER_EQUALS)); + assertEquals("Ess0SetActivePowerEquals", + getChannelNameCamel("ess0", SET_ACTIVE_POWER_EQUALS)); + assertEquals("Ess0SetActivePowerEquals", + getChannelNameCamel("Ess0", SET_ACTIVE_POWER_EQUALS)); } } diff --git a/io.openems.edge.controller.api.modbus/test/io/openems/edge/controller/api/modbus/readwrite/MyConfig.java b/io.openems.edge.controller.api.modbus/test/io/openems/edge/controller/api/modbus/readwrite/tcp/MyConfig.java similarity index 97% rename from io.openems.edge.controller.api.modbus/test/io/openems/edge/controller/api/modbus/readwrite/MyConfig.java rename to io.openems.edge.controller.api.modbus/test/io/openems/edge/controller/api/modbus/readwrite/tcp/MyConfig.java index dfbd3ea52b8..6a6a40a630a 100644 --- a/io.openems.edge.controller.api.modbus/test/io/openems/edge/controller/api/modbus/readwrite/MyConfig.java +++ b/io.openems.edge.controller.api.modbus/test/io/openems/edge/controller/api/modbus/readwrite/tcp/MyConfig.java @@ -1,4 +1,4 @@ -package io.openems.edge.controller.api.modbus.readwrite; +package io.openems.edge.controller.api.modbus.readwrite.tcp; import io.openems.common.test.AbstractComponentConfig; import io.openems.common.utils.ConfigUtils; @@ -18,12 +18,12 @@ protected static class Builder { private Builder() { } - + public Builder setWriteChannels(String... writeChannels) { this.writeChannels = writeChannels; return this; } - + public Builder setReadChannels(String... readChannels) { this.readChannels = readChannels; return this; diff --git a/io.openems.edge.controller.api.mqtt/src/io/openems/edge/controller/api/mqtt/MqttUtils.java b/io.openems.edge.controller.api.mqtt/src/io/openems/edge/controller/api/mqtt/MqttUtils.java index f245063471a..b208a16b28e 100644 --- a/io.openems.edge.controller.api.mqtt/src/io/openems/edge/controller/api/mqtt/MqttUtils.java +++ b/io.openems.edge.controller.api.mqtt/src/io/openems/edge/controller/api/mqtt/MqttUtils.java @@ -115,22 +115,15 @@ private static X509Certificate loadCertificate(String cert) throws IOException, */ private static PrivateKey loadPrivateKey(String privateKey) throws IOException, NoSuchAlgorithmException, InvalidKeySpecException { - try (PEMParser pemParser = new PEMParser( - new InputStreamReader(new ByteArrayInputStream(privateKey.getBytes())))) { - Object obj = pemParser.readObject(); - if (obj instanceof PEMKeyPair) { - // Handle RSA private key - PEMKeyPair pemKeyPair = (PEMKeyPair) obj; - JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider("BC"); - return converter.getPrivateKey(pemKeyPair.getPrivateKeyInfo()); - } else if (obj instanceof PrivateKeyInfo) { - // Handle other private key formats - PrivateKeyInfo privateKeyInfo = (PrivateKeyInfo) obj; - JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider("BC"); - return converter.getPrivateKey(privateKeyInfo); - } else { - throw new InvalidKeySpecException("Invalid private key format"); - } + try (var pemParser = new PEMParser(new InputStreamReader(new ByteArrayInputStream(privateKey.getBytes())))) { + var converter = new JcaPEMKeyConverter().setProvider("BC"); + return switch (pemParser.readObject()) { + case PEMKeyPair pemKeyPair // Handle RSA private key + -> converter.getPrivateKey(pemKeyPair.getPrivateKeyInfo()); + case PrivateKeyInfo privateKeyInfo // Handle other private key formats + -> converter.getPrivateKey(privateKeyInfo); + default -> throw new InvalidKeySpecException("Invalid private key format"); + }; } } } \ No newline at end of file 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 1819afa7696..9fa0a35258b 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 @@ -148,13 +148,12 @@ private boolean handleRest(User user, List targets, Request baseRequest, var thisTarget = targets.get(0); var remainingTargets = targets.subList(1, targets.size()); - switch (thisTarget) { - case "channel": - return this.handleChannel(user, remainingTargets, baseRequest, request, response); - - default: - throw new OpenemsException("Unhandled REST target [" + thisTarget + "]"); - } + return switch (thisTarget) { + case "channel"// + -> this.handleChannel(user, remainingTargets, baseRequest, request, response); + default // + -> throw new OpenemsException("Unhandled REST target [" + thisTarget + "]"); + }; } private boolean handleChannel(User user, List targets, Request baseRequest, HttpServletRequest request, @@ -167,23 +166,21 @@ private boolean handleChannel(User user, List targets, Request baseReque var channelAddress = new ChannelAddress(targets.get(0), targets.get(1)); // call handler methods - switch (request.getMethod()) { - case "GET": - return this.handleGet(user, channelAddress, baseRequest, request, response); - - case "POST": - // Validate API Access-Mode - switch (this.parent.getAccessMode()) { - case READ_ONLY: - throw new OpenemsException("REST-Api is in Read-Only mode"); - case READ_WRITE: - case WRITE_ONLY: - return this.handlePost(user, channelAddress, baseRequest, request, response); - } - - default: - throw new OpenemsException("Unhandled REST Channel request method [" + request.getMethod() + "]"); - } + return switch (request.getMethod()) { + case "GET" // + -> this.handleGet(user, channelAddress, baseRequest, request, response); + + case "POST" // + -> switch (this.parent.getAccessMode()) { + case READ_ONLY // + -> throw new OpenemsException("REST-Api is in Read-Only mode"); + case READ_WRITE, WRITE_ONLY // + -> this.handlePost(user, channelAddress, baseRequest, request, response); + }; + + default // + -> throw new OpenemsException("Unhandled REST Channel request method [" + request.getMethod() + "]"); + }; } /** @@ -271,19 +268,20 @@ private void sendErrorResponse(Request baseRequest, HttpServletResponse response response.setContentType("application/json"); response.setStatus(HttpServletResponse.SC_BAD_REQUEST); baseRequest.setHandled(true); - JsonrpcResponseError message; - if (ex instanceof OpenemsNamedException) { + var message = switch (ex) { + case OpenemsNamedException one -> { // Check for authentication error and set more specific response code // accordingly - if (((OpenemsNamedException) ex).getError() == OpenemsError.COMMON_AUTHENTICATION_FAILED) { + if (one.getError() == OpenemsError.COMMON_AUTHENTICATION_FAILED) { response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); } // Get Named Exception error response - message = new JsonrpcResponseError(jsonrpcId, (OpenemsNamedException) ex); - } else { - // Get GENERIC error response - message = new JsonrpcResponseError(jsonrpcId, ex.getMessage()); + yield new JsonrpcResponseError(jsonrpcId, one); } + default -> + // Get GENERIC error response + new JsonrpcResponseError(jsonrpcId, ex.getMessage()); + }; response.getWriter().write(message.toString()); } catch (IOException e) { this.parent.logWarn(this.log, "Unable to send Error-Response: " + e.getMessage()); @@ -411,10 +409,9 @@ private void handleJsonRpc(User user, Request baseRequest, HttpServletRequest ht // parse JSON-RPC Request var message = JsonrpcMessage.from(json); - if (!(message instanceof JsonrpcRequest)) { + if (!(message instanceof JsonrpcRequest request)) { throw new OpenemsException("Only JSON-RPC Request is supported here."); } - var request = (JsonrpcRequest) message; requestId = request.getId(); // handle the request diff --git a/io.openems.edge.controller.api.rest/test/io/openems/edge/controller/api/rest/readonly/ControllerApiRestReadOnlyImplTest.java b/io.openems.edge.controller.api.rest/test/io/openems/edge/controller/api/rest/readonly/ControllerApiRestReadOnlyImplTest.java index 04c9d124dd6..6c93e76983e 100644 --- a/io.openems.edge.controller.api.rest/test/io/openems/edge/controller/api/rest/readonly/ControllerApiRestReadOnlyImplTest.java +++ b/io.openems.edge.controller.api.rest/test/io/openems/edge/controller/api/rest/readonly/ControllerApiRestReadOnlyImplTest.java @@ -1,11 +1,12 @@ package io.openems.edge.controller.api.rest.readonly; +import static io.openems.common.test.TestUtils.findRandomOpenPortOnAllLocalInterfaces; + import org.junit.Test; import io.openems.common.exceptions.OpenemsException; import io.openems.edge.common.test.DummyComponentManager; import io.openems.edge.common.test.DummyUserService; -import io.openems.edge.common.test.TestUtils; import io.openems.edge.controller.api.rest.DummyJsonRpcRestHandlerFactory; import io.openems.edge.controller.api.rest.JsonRpcRestHandler; import io.openems.edge.controller.test.ControllerTest; @@ -14,7 +15,7 @@ public class ControllerApiRestReadOnlyImplTest { @Test public void test() throws OpenemsException, Exception { - final var port = TestUtils.findRandomOpenPortOnAllLocalInterfaces(); + final var port = findRandomOpenPortOnAllLocalInterfaces(); new ControllerTest(new ControllerApiRestReadOnlyImpl()) // .addReference("componentManager", new DummyComponentManager()) // diff --git a/io.openems.edge.controller.api.rest/test/io/openems/edge/controller/api/rest/readwrite/ControllerApiRestReadWriteImplTest.java b/io.openems.edge.controller.api.rest/test/io/openems/edge/controller/api/rest/readwrite/ControllerApiRestReadWriteImplTest.java index eaaf3fae866..29c3f530886 100644 --- a/io.openems.edge.controller.api.rest/test/io/openems/edge/controller/api/rest/readwrite/ControllerApiRestReadWriteImplTest.java +++ b/io.openems.edge.controller.api.rest/test/io/openems/edge/controller/api/rest/readwrite/ControllerApiRestReadWriteImplTest.java @@ -1,5 +1,6 @@ package io.openems.edge.controller.api.rest.readwrite; +import static io.openems.common.test.TestUtils.findRandomOpenPortOnAllLocalInterfaces; import static io.openems.common.utils.JsonUtils.getAsJsonObject; import static io.openems.edge.common.test.DummyUser.DUMMY_ADMIN; import static io.openems.edge.common.test.DummyUser.DUMMY_GUEST; @@ -54,7 +55,7 @@ public class ControllerApiRestReadWriteImplTest { @Test public void test() throws OpenemsException, Exception { - final var port = TestUtils.findRandomOpenPortOnAllLocalInterfaces(); + final var port = findRandomOpenPortOnAllLocalInterfaces(); final var componentManager = new DummyComponentManager(); diff --git a/io.openems.edge.controller.api.websocket/src/io/openems/edge/controller/api/websocket/handler/EdgeRequestHandler.java b/io.openems.edge.controller.api.websocket/src/io/openems/edge/controller/api/websocket/handler/EdgeRequestHandler.java index 45234bfaa4f..d47cecfd29b 100644 --- a/io.openems.edge.controller.api.websocket/src/io/openems/edge/controller/api/websocket/handler/EdgeRequestHandler.java +++ b/io.openems.edge.controller.api.websocket/src/io/openems/edge/controller/api/websocket/handler/EdgeRequestHandler.java @@ -31,7 +31,8 @@ public void buildJsonApiRoutes(JsonApiBuilder builder) { return new GetEdgeResponse(call.getRequest().getId(), Utils.getEdgeMetadata(user.getGlobalRole())); }); - builder.handleRequest(SubscribeEdgesRequest.METHOD, call -> new GenericJsonrpcResponseSuccess(call.getRequest().getId())); + builder.handleRequest(SubscribeEdgesRequest.METHOD, + call -> new GenericJsonrpcResponseSuccess(call.getRequest().getId())); } } diff --git a/io.openems.edge.controller.api.websocket/src/io/openems/edge/controller/api/websocket/handler/EdgeRpcRequestHandler.java b/io.openems.edge.controller.api.websocket/src/io/openems/edge/controller/api/websocket/handler/EdgeRpcRequestHandler.java index 8aa5e780c95..aea61333a15 100644 --- a/io.openems.edge.controller.api.websocket/src/io/openems/edge/controller/api/websocket/handler/EdgeRpcRequestHandler.java +++ b/io.openems.edge.controller.api.websocket/src/io/openems/edge/controller/api/websocket/handler/EdgeRpcRequestHandler.java @@ -45,14 +45,18 @@ public void buildJsonApiRoutes(JsonApiBuilder builder) { }, call -> { return EdgeRpcRequest.from(call.getRequest()).getPayload(); + }, b -> { return this.binder.getJsonApiBuilder(); + }, response -> { // wrap response in a EdgeRpcResponse if successful - if (response instanceof JsonrpcResponseSuccess success) { - return new EdgeRpcResponse(response.getId(), success); - } - return response; + return switch (response) { + case JsonrpcResponseSuccess success // + -> new EdgeRpcResponse(response.getId(), success); + default -> response; + }; + }, () -> { final var subrequest = new Subrequest(JsonUtils.buildJsonObject() // .addProperty("edgeId", ControllerApiWebsocket.EDGE_ID) // diff --git a/io.openems.edge.controller.chp.soc/src/io/openems/edge/controller/chp/soc/ControllerChpSocImpl.java b/io.openems.edge.controller.chp.soc/src/io/openems/edge/controller/chp/soc/ControllerChpSocImpl.java index 8affca4f438..85016e592d4 100644 --- a/io.openems.edge.controller.chp.soc/src/io/openems/edge/controller/chp/soc/ControllerChpSocImpl.java +++ b/io.openems.edge.controller.chp.soc/src/io/openems/edge/controller/chp/soc/ControllerChpSocImpl.java @@ -90,21 +90,20 @@ protected void deactivate() { public void run() throws OpenemsNamedException { boolean modeChanged; do { - modeChanged = false; - switch (this.mode) { - case MANUAL_ON: + modeChanged = switch (this.mode) { + case MANUAL_ON -> { this.setOutput(true); - modeChanged = this.changeMode(Mode.MANUAL_ON); - break; - case MANUAL_OFF: + yield this.changeMode(Mode.MANUAL_ON); + } + case MANUAL_OFF -> { this.setOutput(false); - modeChanged = this.changeMode(Mode.MANUAL_OFF); - break; - case AUTOMATIC: + yield this.changeMode(Mode.MANUAL_OFF); + } + case AUTOMATIC -> { this.automaticMode(); - modeChanged = this.changeMode(Mode.AUTOMATIC); - break; + yield this.changeMode(Mode.AUTOMATIC); } + }; } while (modeChanged); this.channel(ControllerChpSoc.ChannelId.MODE).setNextValue(this.mode); diff --git a/io.openems.edge.controller.debug.detailedlog/src/io/openems/edge/controller/debug/detailedlog/ControllerDebugDetailedLogImpl.java b/io.openems.edge.controller.debug.detailedlog/src/io/openems/edge/controller/debug/detailedlog/ControllerDebugDetailedLogImpl.java index 629a04e491b..44f3a79261d 100644 --- a/io.openems.edge.controller.debug.detailedlog/src/io/openems/edge/controller/debug/detailedlog/ControllerDebugDetailedLogImpl.java +++ b/io.openems.edge.controller.debug.detailedlog/src/io/openems/edge/controller/debug/detailedlog/ControllerDebugDetailedLogImpl.java @@ -109,10 +109,8 @@ public void run() throws OpenemsNamedException { /* * create descriptive text */ - var channelText = ""; - switch (channel.channelDoc().getAccessMode()) { - case READ_ONLY: - case READ_WRITE: + var channelText = switch (channel.channelDoc().getAccessMode()) { + case READ_ONLY, READ_WRITE -> { var description = ""; if (channel instanceof EnumReadChannel) { try { @@ -122,29 +120,26 @@ public void run() throws OpenemsNamedException { description += "ERROR: " + e.getMessage(); } } - if (channel instanceof StateChannel - && ((StateChannel) channel).value().orElse(false) == true) { + if (channel instanceof StateChannel sc && sc.value().orElse(false) == true) { if (!description.isEmpty()) { description += "; "; } - description += ((StateChannel) channel).channelDoc().getText(); + description += sc.channelDoc().getText(); } - if (channel instanceof StateCollectorChannel - && ((StateCollectorChannel) channel).value().orElse(0) != 0) { + if (channel instanceof StateCollectorChannel scc && scc.value().orElse(0) != 0) { if (!description.isEmpty()) { description += "; "; } - description += ((StateCollectorChannel) channel).listStates(); + description += scc.listStates(); } - channelText = String.format("%15s %-3s %s", // + yield String.format("%15s %-3s %s", // channel.value().asStringWithoutUnit(), // unit, // description.isEmpty() ? "" : "(" + description + ")"); - break; - - case WRITE_ONLY: - channelText += "WRITE_ONLY"; } + case WRITE_ONLY // + -> "WRITE_ONLY"; + }; // Build complete line var line = String.format("%-" + WIDTH_FIRST + "s : %s", channel.channelId().id(), channelText); // Print the line only if is not equal to the last printed line diff --git a/io.openems.edge.controller.ess.cycle/src/io/openems/edge/controller/ess/cycle/statemachine/Context.java b/io.openems.edge.controller.ess.cycle/src/io/openems/edge/controller/ess/cycle/statemachine/Context.java index a97c045451b..6b2d7a93438 100644 --- a/io.openems.edge.controller.ess.cycle/src/io/openems/edge/controller/ess/cycle/statemachine/Context.java +++ b/io.openems.edge.controller.ess.cycle/src/io/openems/edge/controller/ess/cycle/statemachine/Context.java @@ -55,11 +55,13 @@ protected int getAcPower(ManagedSymmetricEss ess, HybridEssMode hybridEssMode, i return switch (this.config.hybridEssMode()) { case TARGET_AC -> this.config.power(); case TARGET_DC -> { - if (ess instanceof HybridEss) { - var pv = ess.getActivePower().orElse(0) - ((HybridEss) ess).getDcDischargePower().orElse(0); + yield switch (ess) { + case HybridEss he -> { + var pv = ess.getActivePower().orElse(0) - he.getDcDischargePower().orElse(0); yield pv + this.config.power(); } - yield this.config.power(); + default -> this.config.power(); + }; } }; } diff --git a/io.openems.edge.controller.ess.emergencycapacityreserve/src/io/openems/edge/controller/ess/emergencycapacityreserve/statemachine/Context.java b/io.openems.edge.controller.ess.emergencycapacityreserve/src/io/openems/edge/controller/ess/emergencycapacityreserve/statemachine/Context.java index 68f2031ba43..588d84b1bdb 100644 --- a/io.openems.edge.controller.ess.emergencycapacityreserve/src/io/openems/edge/controller/ess/emergencycapacityreserve/statemachine/Context.java +++ b/io.openems.edge.controller.ess.emergencycapacityreserve/src/io/openems/edge/controller/ess/emergencycapacityreserve/statemachine/Context.java @@ -24,6 +24,7 @@ public class Context extends AbstractContext= reserveSoc + 1 || soc == 100) { diff --git a/io.openems.edge.controller.ess.emergencycapacityreserve/src/io/openems/edge/controller/ess/emergencycapacityreserve/statemachine/StateMachine.java b/io.openems.edge.controller.ess.emergencycapacityreserve/src/io/openems/edge/controller/ess/emergencycapacityreserve/statemachine/StateMachine.java index 290e1fb1c47..c42fbe6677d 100644 --- a/io.openems.edge.controller.ess.emergencycapacityreserve/src/io/openems/edge/controller/ess/emergencycapacityreserve/statemachine/StateMachine.java +++ b/io.openems.edge.controller.ess.emergencycapacityreserve/src/io/openems/edge/controller/ess/emergencycapacityreserve/statemachine/StateMachine.java @@ -82,6 +82,7 @@ public void run(Context context) throws OpenemsNamedException { this.lastActiveState = this.getPreviousState(); } context.setLastActiveState(this.lastActiveState); + context.setPreviousState(this.getPreviousState()); super.run(context); } @@ -92,20 +93,13 @@ public StateMachine(State initialState) { @Override public StateHandler getStateHandler(State state) { return switch (state) { - case NO_LIMIT -> - new NoLimitHandler(); - case ABOVE_RESERVE_SOC -> - new AboveReserveSocHandler(); - case AT_RESERVE_SOC -> - new AtReserveSocHandler(); - case BELOW_RESERVE_SOC -> - new BelowReserveSocHandler(); - case FORCE_CHARGE_PV -> - new ForceChargePvHandler(); - case FORCE_CHARGE_GRID -> - new ForceChargeGridHandler(); - case UNDEFINED -> - new UndefinedHandler(); + case NO_LIMIT -> new NoLimitHandler(); + case ABOVE_RESERVE_SOC -> new AboveReserveSocHandler(); + case AT_RESERVE_SOC -> new AtReserveSocHandler(); + case BELOW_RESERVE_SOC -> new BelowReserveSocHandler(); + case FORCE_CHARGE_PV -> new ForceChargePvHandler(); + case FORCE_CHARGE_GRID -> new ForceChargeGridHandler(); + case UNDEFINED -> new UndefinedHandler(); }; } diff --git a/io.openems.edge.controller.ess.emergencycapacityreserve/test/io/openems/edge/controller/ess/emergencycapacityreserve/ControllerEssEmergencyCapacityReserveImplTest.java b/io.openems.edge.controller.ess.emergencycapacityreserve/test/io/openems/edge/controller/ess/emergencycapacityreserve/ControllerEssEmergencyCapacityReserveImplTest.java index 2ab88d2be77..30c0e7e27d6 100644 --- a/io.openems.edge.controller.ess.emergencycapacityreserve/test/io/openems/edge/controller/ess/emergencycapacityreserve/ControllerEssEmergencyCapacityReserveImplTest.java +++ b/io.openems.edge.controller.ess.emergencycapacityreserve/test/io/openems/edge/controller/ess/emergencycapacityreserve/ControllerEssEmergencyCapacityReserveImplTest.java @@ -606,20 +606,20 @@ public void testGridChargingOn() throws Exception { )// .next(new TestCase()// .input("ess0", SOC, 18).output(STATE_MACHINE, State.FORCE_CHARGE_GRID) // - .output("ess0", SET_ACTIVE_POWER_LESS_OR_EQUALS, 9100)// - .output(DEBUG_SET_ACTIVE_POWER_LESS_OR_EQUALS, 9100) // + .output("ess0", SET_ACTIVE_POWER_LESS_OR_EQUALS, -1000)// + .output(DEBUG_SET_ACTIVE_POWER_LESS_OR_EQUALS, -1000) // )// .next(new TestCase()// .input("ess0", SOC, 18)// .output(STATE_MACHINE, State.FORCE_CHARGE_GRID) // - .output("ess0", SET_ACTIVE_POWER_LESS_OR_EQUALS, 9000)// - .output(DEBUG_SET_ACTIVE_POWER_LESS_OR_EQUALS, 9000) // + .output("ess0", SET_ACTIVE_POWER_LESS_OR_EQUALS, -1000)// + .output(DEBUG_SET_ACTIVE_POWER_LESS_OR_EQUALS, -1000) // ) // From Below .next(new TestCase()// .input("ess0", SOC, 15).output(STATE_MACHINE, State.FORCE_CHARGE_GRID) // - .output("ess0", SET_ACTIVE_POWER_LESS_OR_EQUALS, 8900)// - .output(DEBUG_SET_ACTIVE_POWER_LESS_OR_EQUALS, 8900) // + .output("ess0", SET_ACTIVE_POWER_LESS_OR_EQUALS, -1100)// + .output(DEBUG_SET_ACTIVE_POWER_LESS_OR_EQUALS, -1100) // ) // let ramp run its course .next(new TestCase()// diff --git a/io.openems.edge.controller.ess.fastfrequencyreserve/src/io/openems/edge/controller/ess/fastfrequencyreserve/statemachine/DeactivationTimeHandler.java b/io.openems.edge.controller.ess.fastfrequencyreserve/src/io/openems/edge/controller/ess/fastfrequencyreserve/statemachine/DeactivationTimeHandler.java index aa01cbddbbb..98dd659b20c 100644 --- a/io.openems.edge.controller.ess.fastfrequencyreserve/src/io/openems/edge/controller/ess/fastfrequencyreserve/statemachine/DeactivationTimeHandler.java +++ b/io.openems.edge.controller.ess.fastfrequencyreserve/src/io/openems/edge/controller/ess/fastfrequencyreserve/statemachine/DeactivationTimeHandler.java @@ -10,7 +10,7 @@ public class DeactivationTimeHandler extends StateHandler { - private static final int ZERO_WATT_POWER = 0; //[0 W] + private static final int ZERO_WATT_POWER = 0; // [0 W] protected Instant deactivationStateStartTime; private static enum SubState { diff --git a/io.openems.edge.controller.ess.fastfrequencyreserve/test/io/openems/edge/controller/ess/fastfrequencyreserve/ControllerFastFrequencyReserveImplTest.java b/io.openems.edge.controller.ess.fastfrequencyreserve/test/io/openems/edge/controller/ess/fastfrequencyreserve/ControllerFastFrequencyReserveImplTest.java index e704c552b50..ac8b9abaa2e 100644 --- a/io.openems.edge.controller.ess.fastfrequencyreserve/test/io/openems/edge/controller/ess/fastfrequencyreserve/ControllerFastFrequencyReserveImplTest.java +++ b/io.openems.edge.controller.ess.fastfrequencyreserve/test/io/openems/edge/controller/ess/fastfrequencyreserve/ControllerFastFrequencyReserveImplTest.java @@ -1,6 +1,6 @@ package io.openems.edge.controller.ess.fastfrequencyreserve; -import static io.openems.edge.common.test.TestUtils.createDummyClock; +import static io.openems.common.test.TestUtils.createDummyClock; import static io.openems.edge.controller.ess.fastfrequencyreserve.ControllerFastFrequencyReserve.ChannelId.STATE_MACHINE; import static io.openems.edge.controller.ess.fastfrequencyreserve.enums.ActivationTime.LONG_ACTIVATION_RUN; import static io.openems.edge.controller.ess.fastfrequencyreserve.enums.SupportDuration.LONG_SUPPORT_DURATION; diff --git a/io.openems.edge.controller.ess.fixactivepower/src/io/openems/edge/controller/ess/fixactivepower/ControllerEssFixActivePowerImpl.java b/io.openems.edge.controller.ess.fixactivepower/src/io/openems/edge/controller/ess/fixactivepower/ControllerEssFixActivePowerImpl.java index 32c9fb30834..79e7acf8f15 100644 --- a/io.openems.edge.controller.ess.fixactivepower/src/io/openems/edge/controller/ess/fixactivepower/ControllerEssFixActivePowerImpl.java +++ b/io.openems.edge.controller.ess.fixactivepower/src/io/openems/edge/controller/ess/fixactivepower/ControllerEssFixActivePowerImpl.java @@ -133,20 +133,18 @@ public void run() throws OpenemsNamedException { * @return the AC power set-point */ protected static Integer getAcPower(ManagedSymmetricEss ess, HybridEssMode hybridEssMode, int power) { - switch (hybridEssMode) { - case TARGET_AC: - return power; - - case TARGET_DC: - if (ess instanceof HybridEss) { - var pv = ess.getActivePower().orElse(0) - ((HybridEss) ess).getDcDischargePower().orElse(0); - return pv + power; // Charge or Discharge - } else { - return power; + return switch (hybridEssMode) { + case TARGET_AC -> power; + + case TARGET_DC -> // + switch (ess) { + case HybridEss he -> { + var pv = ess.getActivePower().orElse(0) - he.getDcDischargePower().orElse(0); + yield pv + power; // Charge or Discharge } - } - - return null; /* should never happen */ + default -> power; + }; + }; } @Override diff --git a/io.openems.edge.controller.ess.fixstateofcharge/src/io/openems/edge/controller/ess/fixstateofcharge/api/AbstractFixStateOfCharge.java b/io.openems.edge.controller.ess.fixstateofcharge/src/io/openems/edge/controller/ess/fixstateofcharge/api/AbstractFixStateOfCharge.java index 5849daf0e9d..45ebdffbf6f 100644 --- a/io.openems.edge.controller.ess.fixstateofcharge/src/io/openems/edge/controller/ess/fixstateofcharge/api/AbstractFixStateOfCharge.java +++ b/io.openems.edge.controller.ess.fixstateofcharge/src/io/openems/edge/controller/ess/fixstateofcharge/api/AbstractFixStateOfCharge.java @@ -203,6 +203,7 @@ private Context handleStateMachine() { */ private void applyTargetPower(Float targetPower, float rampPower, int maxApparentPower) throws OpenemsNamedException { + final var ess = this.getEss(); var activePower = this.rampFilter.getFilteredValueAsInteger(targetPower, rampPower); this._setDebugSetActivePowerRaw(activePower); @@ -221,21 +222,16 @@ private void applyTargetPower(Float targetPower, float rampPower, int maxApparen activePower = this.calculateAcLimit(activePower); // Fit into min/max "EssPower" - if (this.getEss() instanceof ManagedSymmetricEss) { - var e = (ManagedSymmetricEss) this.getEss(); - var maxCharge = e.getPower().getMinPower(e, Phase.ALL, Pwr.ACTIVE); - var maxDischarge = e.getPower().getMaxPower(e, Phase.ALL, Pwr.ACTIVE); - activePower = TypeUtils.fitWithin(maxCharge, maxDischarge, activePower); - } else { - activePower = TypeUtils.fitWithin(maxApparentPower * -1, maxApparentPower, activePower); - } + var maxCharge = ess.getPower().getMinPower(ess, Phase.ALL, Pwr.ACTIVE); + var maxDischarge = ess.getPower().getMaxPower(ess, Phase.ALL, Pwr.ACTIVE); + activePower = TypeUtils.fitWithin(maxCharge, maxDischarge, activePower); if (activePower > 0) { - this.getEss().setActivePowerEquals(activePower); + ess.setActivePowerEquals(activePower); } else if (activePower < 0) { - this.getEss().setActivePowerEquals(activePower); + ess.setActivePowerEquals(activePower); } else { - this.getEss().setActivePowerEquals(activePower); + ess.setActivePowerEquals(activePower); } // Set debug channels diff --git a/io.openems.edge.controller.ess.fixstateofcharge/src/io/openems/edge/controller/ess/fixstateofcharge/statemachine/StateMachine.java b/io.openems.edge.controller.ess.fixstateofcharge/src/io/openems/edge/controller/ess/fixstateofcharge/statemachine/StateMachine.java index 7017b970771..627a2c2f4d1 100644 --- a/io.openems.edge.controller.ess.fixstateofcharge/src/io/openems/edge/controller/ess/fixstateofcharge/statemachine/StateMachine.java +++ b/io.openems.edge.controller.ess.fixstateofcharge/src/io/openems/edge/controller/ess/fixstateofcharge/statemachine/StateMachine.java @@ -78,23 +78,15 @@ public StateMachine(State initialState) { @Override public StateHandler getStateHandler(State state) { - switch (state) { - case IDLE: - return new IdleHander(); - case NOT_STARTED: - return new NotStartedHandler(); - case ABOVE_TARGET_SOC: - return new AboveTargetSocHandler(); - case BELOW_TARGET_SOC: - return new BelowTargetSocHandler(); - case AT_TARGET_SOC: - return new AtTargetSocHandler(); - case WITHIN_LOWER_TARGET_SOC_BOUNDARIES: - return new WithinLowerTargetSocBoundariesHandler(); - case WITHIN_UPPER_TARGET_SOC_BOUNDARIES: - return new WithinUpperTargetSocBoundariesHandler(); - } - throw new IllegalArgumentException("Unknown State [" + state + "]"); + return switch (state) { + case IDLE -> new IdleHander(); + case NOT_STARTED -> new NotStartedHandler(); + case ABOVE_TARGET_SOC -> new AboveTargetSocHandler(); + case BELOW_TARGET_SOC -> new BelowTargetSocHandler(); + case AT_TARGET_SOC -> new AtTargetSocHandler(); + case WITHIN_LOWER_TARGET_SOC_BOUNDARIES -> new WithinLowerTargetSocBoundariesHandler(); + case WITHIN_UPPER_TARGET_SOC_BOUNDARIES -> new WithinUpperTargetSocBoundariesHandler(); + }; } } \ No newline at end of file diff --git a/io.openems.edge.controller.ess.hybrid.surplusfeedtogrid/test/io/openems/edge/controller/ess/hybrid/surplusfeedtogrid/ControllerEssHybridSurplusFeedToGridImplTest.java b/io.openems.edge.controller.ess.hybrid.surplusfeedtogrid/test/io/openems/edge/controller/ess/hybrid/surplusfeedtogrid/ControllerEssHybridSurplusFeedToGridImplTest.java index 94d0e84fbb1..edb1435b1e8 100644 --- a/io.openems.edge.controller.ess.hybrid.surplusfeedtogrid/test/io/openems/edge/controller/ess/hybrid/surplusfeedtogrid/ControllerEssHybridSurplusFeedToGridImplTest.java +++ b/io.openems.edge.controller.ess.hybrid.surplusfeedtogrid/test/io/openems/edge/controller/ess/hybrid/surplusfeedtogrid/ControllerEssHybridSurplusFeedToGridImplTest.java @@ -38,7 +38,7 @@ public void test() throws Exception { test.next(new TestCase() // .output(SURPLUS_FEED_TO_GRID_IS_LIMITED, true) // .output("ess0", SET_ACTIVE_POWER_GREATER_OR_EQUALS, 2000)) // - + .deactivate(); } } \ No newline at end of file diff --git a/io.openems.edge.controller.ess.limiter14a/src/io/openems/edge/controller/ess/limiter14a/Config.java b/io.openems.edge.controller.ess.limiter14a/src/io/openems/edge/controller/ess/limiter14a/Config.java index 69f598db15b..c2768e430d8 100644 --- a/io.openems.edge.controller.ess.limiter14a/src/io/openems/edge/controller/ess/limiter14a/Config.java +++ b/io.openems.edge.controller.ess.limiter14a/src/io/openems/edge/controller/ess/limiter14a/Config.java @@ -16,7 +16,7 @@ @AttributeDefinition(name = "Is enabled?", description = "Is this Component enabled?") boolean enabled() default true; - + @AttributeDefinition(name = "Ess-ID", description = "ID of Ess.") String ess_id() default "ess0"; diff --git a/io.openems.edge.controller.ess.limiter14a/test/io/openems/edge/controller/ess/limiter14a/MyConfig.java b/io.openems.edge.controller.ess.limiter14a/test/io/openems/edge/controller/ess/limiter14a/MyConfig.java index c0c2a3ddab8..028564e3ea1 100644 --- a/io.openems.edge.controller.ess.limiter14a/test/io/openems/edge/controller/ess/limiter14a/MyConfig.java +++ b/io.openems.edge.controller.ess.limiter14a/test/io/openems/edge/controller/ess/limiter14a/MyConfig.java @@ -12,7 +12,7 @@ protected static class Builder { private Builder() { } - + public Builder setInputChannelAddress(String inputChannelAddress) { this.inputChannelAddress = inputChannelAddress; return this; @@ -22,7 +22,7 @@ public Builder setId(String id) { this.id = id; return this; } - + public Builder setEssId(String id) { this.essId = id; return this; diff --git a/io.openems.edge.controller.ess.limittotaldischarge/test/io/openems/edge/controller/ess/limittotaldischarge/ControllerEssLimitTotalDischargeImplTest.java b/io.openems.edge.controller.ess.limittotaldischarge/test/io/openems/edge/controller/ess/limittotaldischarge/ControllerEssLimitTotalDischargeImplTest.java index f240abc3ed9..acc57399ef6 100644 --- a/io.openems.edge.controller.ess.limittotaldischarge/test/io/openems/edge/controller/ess/limittotaldischarge/ControllerEssLimitTotalDischargeImplTest.java +++ b/io.openems.edge.controller.ess.limittotaldischarge/test/io/openems/edge/controller/ess/limittotaldischarge/ControllerEssLimitTotalDischargeImplTest.java @@ -1,6 +1,6 @@ package io.openems.edge.controller.ess.limittotaldischarge; -import static io.openems.edge.common.test.TestUtils.createDummyClock; +import static io.openems.common.test.TestUtils.createDummyClock; import static io.openems.edge.controller.ess.limittotaldischarge.ControllerEssLimitTotalDischarge.ChannelId.AWAITING_HYSTERESIS; import static io.openems.edge.ess.api.ManagedSymmetricEss.ChannelId.SET_ACTIVE_POWER_LESS_OR_EQUALS; import static io.openems.edge.ess.api.SymmetricEss.ChannelId.SOC; diff --git a/io.openems.edge.controller.ess.reactivepowervoltagecharacteristic/test/io/openems/edge/controller/ess/reactivepowervoltagecharacteristic/ControllerEssReactivePowerVoltageCharacteristicImplTest.java b/io.openems.edge.controller.ess.reactivepowervoltagecharacteristic/test/io/openems/edge/controller/ess/reactivepowervoltagecharacteristic/ControllerEssReactivePowerVoltageCharacteristicImplTest.java index 442be9ddfa2..0278054c009 100644 --- a/io.openems.edge.controller.ess.reactivepowervoltagecharacteristic/test/io/openems/edge/controller/ess/reactivepowervoltagecharacteristic/ControllerEssReactivePowerVoltageCharacteristicImplTest.java +++ b/io.openems.edge.controller.ess.reactivepowervoltagecharacteristic/test/io/openems/edge/controller/ess/reactivepowervoltagecharacteristic/ControllerEssReactivePowerVoltageCharacteristicImplTest.java @@ -1,8 +1,8 @@ package io.openems.edge.controller.ess.reactivepowervoltagecharacteristic; +import static io.openems.common.test.TestUtils.createDummyClock; import static io.openems.common.utils.JsonUtils.buildJsonArray; import static io.openems.common.utils.JsonUtils.buildJsonObject; -import static io.openems.edge.common.test.TestUtils.createDummyClock; import static io.openems.edge.ess.api.ManagedSymmetricEss.ChannelId.SET_REACTIVE_POWER_EQUALS; import static io.openems.edge.ess.api.SymmetricEss.ChannelId.MAX_APPARENT_POWER; import static io.openems.edge.meter.api.ElectricityMeter.ChannelId.VOLTAGE; diff --git a/io.openems.edge.controller.ess.standby/src/io/openems/edge/controller/ess/standby/statemachine/StateMachine.java b/io.openems.edge.controller.ess.standby/src/io/openems/edge/controller/ess/standby/statemachine/StateMachine.java index e0c53185f05..2570a45be3c 100644 --- a/io.openems.edge.controller.ess.standby/src/io/openems/edge/controller/ess/standby/statemachine/StateMachine.java +++ b/io.openems.edge.controller.ess.standby/src/io/openems/edge/controller/ess/standby/statemachine/StateMachine.java @@ -48,20 +48,13 @@ public StateMachine(State initialState) { @Override public StateHandler getStateHandler(State state) { - switch (state) { - case UNDEFINED: - return new UndefinedHandler(); - case DISCHARGE: - return new DischargeHandler(); - case SLOW_CHARGE_1: - return new SlowCharge1Handler(); - case FAST_CHARGE: - return new FastChargeHandler(); - case SLOW_CHARGE_2: - return new SlowCharge2Handler(); - case FINISHED: - return new FinishedHandler(); - } - throw new IllegalArgumentException("Unknown State [" + state + "]"); + return switch (state) { + case UNDEFINED -> new UndefinedHandler(); + case DISCHARGE -> new DischargeHandler(); + case SLOW_CHARGE_1 -> new SlowCharge1Handler(); + case FAST_CHARGE -> new FastChargeHandler(); + case SLOW_CHARGE_2 -> new SlowCharge2Handler(); + case FINISHED -> new FinishedHandler(); + }; } } diff --git a/io.openems.edge.controller.ess.timeofusetariff/src/io/openems/edge/controller/ess/timeofusetariff/TimeOfUseTariffController.java b/io.openems.edge.controller.ess.timeofusetariff/src/io/openems/edge/controller/ess/timeofusetariff/TimeOfUseTariffController.java index b241b53977a..b05feebdff4 100644 --- a/io.openems.edge.controller.ess.timeofusetariff/src/io/openems/edge/controller/ess/timeofusetariff/TimeOfUseTariffController.java +++ b/io.openems.edge.controller.ess.timeofusetariff/src/io/openems/edge/controller/ess/timeofusetariff/TimeOfUseTariffController.java @@ -11,7 +11,6 @@ import io.openems.edge.controller.ess.timeofusetariff.v1.EnergyScheduleHandlerV1; import io.openems.edge.energy.api.EnergySchedulable; -@SuppressWarnings("deprecation") public interface TimeOfUseTariffController extends Controller, EnergySchedulable, OpenemsComponent { public enum ChannelId implements io.openems.edge.common.channel.ChannelId { diff --git a/io.openems.edge.controller.ess.timeofusetariff/src/io/openems/edge/controller/ess/timeofusetariff/Utils.java b/io.openems.edge.controller.ess.timeofusetariff/src/io/openems/edge/controller/ess/timeofusetariff/Utils.java index 8c945077d45..45976c1da10 100644 --- a/io.openems.edge.controller.ess.timeofusetariff/src/io/openems/edge/controller/ess/timeofusetariff/Utils.java +++ b/io.openems.edge.controller.ess.timeofusetariff/src/io/openems/edge/controller/ess/timeofusetariff/Utils.java @@ -234,13 +234,14 @@ public static Integer calculateMaxChargeProductionPower(Sum sum) { * @return the set-point */ public static int calculateDelayDischargePower(ManagedSymmetricEss ess) { - if (ess instanceof HybridEss e) { + return switch (ess) { + case HybridEss e -> // Limit discharge to DC-PV power - return max(0, ess.getActivePower().orElse(0) - e.getDcDischargePower().orElse(0)); - } else { + max(0, ess.getActivePower().orElse(0) - e.getDcDischargePower().orElse(0)); + default -> // Limit discharge to 0 - return 0; - } + 0; + }; } /** diff --git a/io.openems.edge.controller.ess.timeofusetariff/test/io/openems/edge/controller/ess/timeofusetariff/TimeOfUseTariffControllerImplTest.java b/io.openems.edge.controller.ess.timeofusetariff/test/io/openems/edge/controller/ess/timeofusetariff/TimeOfUseTariffControllerImplTest.java index 941aaaf78f0..469536f9d5a 100644 --- a/io.openems.edge.controller.ess.timeofusetariff/test/io/openems/edge/controller/ess/timeofusetariff/TimeOfUseTariffControllerImplTest.java +++ b/io.openems.edge.controller.ess.timeofusetariff/test/io/openems/edge/controller/ess/timeofusetariff/TimeOfUseTariffControllerImplTest.java @@ -1,6 +1,6 @@ package io.openems.edge.controller.ess.timeofusetariff; -import static io.openems.edge.common.test.TestUtils.createDummyClock; +import static io.openems.common.test.TestUtils.createDummyClock; import static io.openems.edge.controller.ess.timeofusetariff.ControlMode.CHARGE_CONSUMPTION; import static io.openems.edge.controller.ess.timeofusetariff.Mode.AUTOMATIC; diff --git a/io.openems.edge.controller.evcs/src/io/openems/edge/controller/evcs/Utils.java b/io.openems.edge.controller.evcs/src/io/openems/edge/controller/evcs/Utils.java index a426a0f3186..6b185129d8b 100644 --- a/io.openems.edge.controller.evcs/src/io/openems/edge/controller/evcs/Utils.java +++ b/io.openems.edge.controller.evcs/src/io/openems/edge/controller/evcs/Utils.java @@ -18,7 +18,8 @@ import com.google.gson.JsonObject; import io.openems.common.exceptions.OpenemsError.OpenemsNamedException; -import io.openems.edge.controller.evcs.JSCalendar.Task; +import io.openems.common.jscalendar.JSCalendar; +import io.openems.common.jscalendar.JSCalendar.Task; import io.openems.edge.controller.evcs.Utils.EshContext.EshManualContext; import io.openems.edge.controller.evcs.Utils.EshContext.EshSmartContext; import io.openems.edge.energy.api.EnergyScheduleHandler; diff --git a/io.openems.edge.controller.evcs/test/io/openems/edge/controller/evcs/ControllerEvcsImplTest.java b/io.openems.edge.controller.evcs/test/io/openems/edge/controller/evcs/ControllerEvcsImplTest.java index 2adacb94a33..3a9bb67ad68 100644 --- a/io.openems.edge.controller.evcs/test/io/openems/edge/controller/evcs/ControllerEvcsImplTest.java +++ b/io.openems.edge.controller.evcs/test/io/openems/edge/controller/evcs/ControllerEvcsImplTest.java @@ -1,9 +1,9 @@ package io.openems.edge.controller.evcs; +import static io.openems.common.test.TestUtils.createDummyClock; import static io.openems.edge.common.sum.Sum.ChannelId.ESS_DISCHARGE_POWER; import static io.openems.edge.common.sum.Sum.ChannelId.ESS_SOC; import static io.openems.edge.common.sum.Sum.ChannelId.GRID_ACTIVE_POWER; -import static io.openems.edge.common.test.TestUtils.createDummyClock; import static io.openems.edge.controller.evcs.ControllerEvcs.ChannelId.AWAITING_HYSTERESIS; import static io.openems.edge.controller.evcs.Priority.CAR; import static io.openems.edge.evcs.api.ChargeMode.EXCESS_POWER; diff --git a/io.openems.edge.controller.highloadtimeslot/src/io/openems/edge/controller/highloadtimeslot/ControllerHighLoadTimeslotImpl.java b/io.openems.edge.controller.highloadtimeslot/src/io/openems/edge/controller/highloadtimeslot/ControllerHighLoadTimeslotImpl.java index 98c81d8c854..1fab94396a7 100644 --- a/io.openems.edge.controller.highloadtimeslot/src/io/openems/edge/controller/highloadtimeslot/ControllerHighLoadTimeslotImpl.java +++ b/io.openems.edge.controller.highloadtimeslot/src/io/openems/edge/controller/highloadtimeslot/ControllerHighLoadTimeslotImpl.java @@ -121,8 +121,8 @@ private int getPower(ManagedSymmetricEss ess) { /* * We are in a Charge period */ - switch (this.chargeState) { - case NORMAL: + return switch (this.chargeState) { + case NORMAL -> { /* * charge with configured charge-power */ @@ -133,9 +133,9 @@ private int getPower(ManagedSymmetricEss ess) { // activate Charge-hysteresis if no charge power (i.e. >= 0) is allowed this.chargeState = ChargeState.HYSTERESIS; } - return this.chargePower; - - case HYSTERESIS: + yield this.chargePower; + } + case HYSTERESIS -> { /* * block charging till configured hysteresisSoc */ @@ -145,17 +145,16 @@ private int getPower(ManagedSymmetricEss ess) { + "]. Switch to Charge-Normal state."); this.chargeState = ChargeState.NORMAL; } - return 0; - - case FORCE_CHARGE: + yield 0; + } + case FORCE_CHARGE -> { /* * force full charging just before the high-load timeslot starts */ this.logInfo(this.log, "Just before High-Load timeslot. Charge with [" + this.chargePower + "]"); - return this.chargePower; + yield this.chargePower; } - // we should never come here... - return 0; + }; } /** @@ -186,16 +185,11 @@ private boolean isHighLoadTimeslot(LocalDateTime dateTime) { * @return true on yes */ protected static boolean isActiveWeekday(WeekdayFilter activeDayFilter, LocalDateTime dateTime) { - switch (activeDayFilter) { - case EVERDAY: - return true; - case ONLY_WEEKDAYS: - return !isWeekend(dateTime); - case ONLY_WEEKEND: - return isWeekend(dateTime); - } - // should never happen - return false; + return switch (activeDayFilter) { + case EVERDAY -> true; + case ONLY_WEEKDAYS -> !isWeekend(dateTime); + case ONLY_WEEKEND -> isWeekend(dateTime); + }; } protected static boolean isActiveDate(LocalDate startDate, LocalDate endDate, LocalDateTime dateTime) { diff --git a/io.openems.edge.controller.io.analog/test/io/openems/edge/controller/io/analog/MyControllerTest.java b/io.openems.edge.controller.io.analog/test/io/openems/edge/controller/io/analog/MyControllerTest.java index e2ce7b1917c..3fc3bd26560 100644 --- a/io.openems.edge.controller.io.analog/test/io/openems/edge/controller/io/analog/MyControllerTest.java +++ b/io.openems.edge.controller.io.analog/test/io/openems/edge/controller/io/analog/MyControllerTest.java @@ -1,6 +1,6 @@ package io.openems.edge.controller.io.analog; -import static io.openems.edge.common.test.TestUtils.createDummyClock; +import static io.openems.common.test.TestUtils.createDummyClock; import java.time.temporal.ChronoUnit; diff --git a/io.openems.edge.controller.io.heating.room/.classpath b/io.openems.edge.controller.io.heating.room/.classpath new file mode 100644 index 00000000000..b4cffd0fe60 --- /dev/null +++ b/io.openems.edge.controller.io.heating.room/.classpath @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/io.openems.edge.controller.io.heating.room/.gitignore b/io.openems.edge.controller.io.heating.room/.gitignore new file mode 100644 index 00000000000..c2b941a96de --- /dev/null +++ b/io.openems.edge.controller.io.heating.room/.gitignore @@ -0,0 +1,2 @@ +/bin_test/ +/generated/ diff --git a/io.openems.edge.controller.io.heating.room/.project b/io.openems.edge.controller.io.heating.room/.project new file mode 100644 index 00000000000..b63b02b9297 --- /dev/null +++ b/io.openems.edge.controller.io.heating.room/.project @@ -0,0 +1,23 @@ + + + io.openems.edge.controller.io.heating.room + + + + + + org.eclipse.jdt.core.javabuilder + + + + + bndtools.core.bndbuilder + + + + + + org.eclipse.jdt.core.javanature + bndtools.core.bndnature + + diff --git a/io.openems.edge.controller.io.heating.room/.settings/org.eclipse.core.resources.prefs b/io.openems.edge.controller.io.heating.room/.settings/org.eclipse.core.resources.prefs new file mode 100644 index 00000000000..99f26c0203a --- /dev/null +++ b/io.openems.edge.controller.io.heating.room/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +encoding/=UTF-8 diff --git a/io.openems.edge.controller.io.heating.room/bnd.bnd b/io.openems.edge.controller.io.heating.room/bnd.bnd new file mode 100644 index 00000000000..80110260ed9 --- /dev/null +++ b/io.openems.edge.controller.io.heating.room/bnd.bnd @@ -0,0 +1,17 @@ +Bundle-Name: OpenEMS Edge Controller IO Heating Room +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.common,\ + io.openems.edge.controller.api,\ + io.openems.edge.io.api,\ + io.openems.edge.meter.api,\ + io.openems.edge.thermometer.api,\ + io.openems.edge.timedata.api,\ + +-testpath: \ + ${testpath} diff --git a/io.openems.edge.controller.io.heating.room/readme.adoc b/io.openems.edge.controller.io.heating.room/readme.adoc new file mode 100644 index 00000000000..849e0c1ff29 --- /dev/null +++ b/io.openems.edge.controller.io.heating.room/readme.adoc @@ -0,0 +1,45 @@ += IO Heating Room + +Controls electric floor and infrared heating in a room. + +The Controller activates electric floor and infrared heating in a room in order to keep a configured LOW or HIGH temperature. +The timings of LOW or HIGH are configured via a `schedule` configuration parameter. +It holds a JsonArray with JSCalendar information, e.g. + +---- +[ + { + "@type":"Task", + "start":"05:30:00", + "duration":"PT2H30M", + "recurrenceRules":[ + { + "frequency":"weekly", + "byDay":[ + "mo", + "tu", + "we", + "th", + "fr" + ] + } + ] + }, + { + "@type":"Task", + "start":"08:00:00", + "duration":"PT16H", + "recurrenceRules":[ + { + "frequency":"weekly", + "byDay":[ + "sa", + "su" + ] + } + ] + } +] +---- + +https://github.com/OpenEMS/openems/tree/develop/io.openems.edge.controller.io.heating.room[Source Code icon:github[]] \ No newline at end of file diff --git a/io.openems.edge.controller.io.heating.room/src/io/openems/edge/controller/io/heating/room/Config.java b/io.openems.edge.controller.io.heating.room/src/io/openems/edge/controller/io/heating/room/Config.java new file mode 100644 index 00000000000..b2360ac3c13 --- /dev/null +++ b/io.openems.edge.controller.io.heating.room/src/io/openems/edge/controller/io/heating/room/Config.java @@ -0,0 +1,73 @@ +package io.openems.edge.controller.io.heating.room; + +import org.osgi.service.metatype.annotations.AttributeDefinition; +import org.osgi.service.metatype.annotations.ObjectClassDefinition; + +@ObjectClassDefinition(// + name = "Controller Heating Room", // + description = "Controls electric floor and infrared heating in a room") +@interface Config { + + @AttributeDefinition(name = "Component-ID", description = "Unique ID of this Component") + String id() default "ctrlHeatingRoom0"; + + @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 = "Mode", description = "Heating control mode") + Mode mode() default Mode.AUTOMATIC; + + @AttributeDefinition(name = "JSON Schedule in AUTOMATIC Mode", description = "Takes a Json-Array in JSCalendar format") + String schedule() default ""; + + @AttributeDefinition(name = "Low Floor Temperature", description = "The target floor temperature in LOW mode (in 0.1 degree celsius)") + int lowFloorTemperature(); + + @AttributeDefinition(name = "Low Ambient Temperature", description = "The target ambient temperature in LOW mode (in 0.1 degree celsius)") + int lowAmbientTemperature(); + + @AttributeDefinition(name = "High Floor Temperature", description = "The target floor temperature in HIGH mode (in 0.1 degree celsius)") + int highFloorTemperature(); + + @AttributeDefinition(name = "High Ambient Temperature", description = "The target ambient temperature in HIGH mode (in 0.1 degree celsius)") + int highAmbientTemperature(); + + @AttributeDefinition(name = "Floor Thermometer ID", description = "Component-ID of the Floor Thermometer") + String floorThermometer_id(); + + @AttributeDefinition(name = "Ambient Thermometer ID", description = "Component-ID of the Ambient Air Thermometer") + String ambientThermometer_id(); + + @AttributeDefinition(name = "Floor Heating Relay(s)", description = "Channel addresses of the Relays for Floor Heating") + String[] floorRelays(); + + @AttributeDefinition(name = "Infrared Heating Relay(s)", description = "Channel addresses of the Relays for Infrared Heating") + String[] infraredRelays(); + + @AttributeDefinition(name = "Floor Heating Power", description = "The switched power of the floor heating (in Watt)") + int floorPower(); + + @AttributeDefinition(name = "Infrared Heating Power", description = "The switched power of the infrared heating (in Watt)") + int infraredPower(); + + @AttributeDefinition(name = "Has external ambient heating?", description = "Is there an external ambient heating in this room - like a wood stove") + boolean hasExternalAmbientHeating(); + + @AttributeDefinition(name = "Floor Thermometer target filter", description = "This is auto-generated by 'Floor Thermometer ID'") + String floorThermometer_target() default "(enabled=true)"; + + @AttributeDefinition(name = "Ambient Thermometer target filter", description = "This is auto-generated by 'Ambient Thermometer ID'") + String ambientThermometer_target() default "(enabled=true)"; + + @AttributeDefinition(name = "Floor Relay Components target filter", description = "This is auto-generated by 'Floor Heating Relay(s)'") + String floorRelayComponents_target() default "(enabled=true)"; + + @AttributeDefinition(name = "Infrared Relay Components target filter", description = "This is auto-generated by 'Infrared Heating Relay(s)'") + String infraredRelayComponents_target() default "(enabled=true)"; + + String webconsole_configurationFactory_nameHint() default "Controller Heating Room [{id}]"; + +} \ No newline at end of file diff --git a/io.openems.edge.controller.io.heating.room/src/io/openems/edge/controller/io/heating/room/ControllerIoRoomHeating.java b/io.openems.edge.controller.io.heating.room/src/io/openems/edge/controller/io/heating/room/ControllerIoRoomHeating.java new file mode 100644 index 00000000000..c2b48e2dfb4 --- /dev/null +++ b/io.openems.edge.controller.io.heating.room/src/io/openems/edge/controller/io/heating/room/ControllerIoRoomHeating.java @@ -0,0 +1,148 @@ +package io.openems.edge.controller.io.heating.room; + +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.value.Value; +import io.openems.edge.common.component.OpenemsComponent; +import io.openems.edge.controller.api.Controller; +import io.openems.edge.meter.api.ElectricityMeter; + +public interface ControllerIoRoomHeating extends Controller, ElectricityMeter, OpenemsComponent { + + public enum ChannelId implements io.openems.edge.common.channel.ChannelId { + FLOOR_ACTUAL(Doc.of(OpenemsType.INTEGER)), // + FLOOR_TARGET(Doc.of(OpenemsType.INTEGER)), // + AMBIENT_ACTUAL(Doc.of(OpenemsType.INTEGER)), // + AMBIENT_TARGET(Doc.of(OpenemsType.INTEGER)), // + ; + + private final Doc doc; + + private ChannelId(Doc doc) { + this.doc = doc; + } + + @Override + public Doc doc() { + return this.doc; + } + } + + /** + * Gets the Channel for {@link ChannelId#FLOOR_ACTUAL}. + * + * @return the Channel + */ + public default IntegerReadChannel getFloorActualChannel() { + return this.channel(ChannelId.FLOOR_ACTUAL); + } + + /** + * Gets the Floor Actual Temperature in [deci degC]. See + * {@link ChannelId#FLOOR_ACTUAL}. + * + * @return the Channel {@link Value} + */ + public default Value getFloorActual() { + return this.getFloorActualChannel().value(); + } + + /** + * Internal method to set the 'nextValue' on {@link ChannelId#FLOOR_ACTUAL} + * Channel. + * + * @param value the next value + */ + public default void _setFloorActual(Integer value) { + this.getFloorActualChannel().setNextValue(value); + } + + /** + * Gets the Channel for {@link ChannelId#FLOOR_TARGET}. + * + * @return the Channel + */ + public default IntegerReadChannel getFloorTargetChannel() { + return this.channel(ChannelId.FLOOR_TARGET); + } + + /** + * Gets the Floor Target Temperature in [deci degC]. See + * {@link ChannelId#FLOOR_TARGET}. + * + * @return the Channel {@link Value} + */ + public default Value getFloorTarget() { + return this.getFloorTargetChannel().value(); + } + + /** + * Internal method to set the 'nextValue' on {@link ChannelId#FLOOR_TARGET} + * Channel. + * + * @param value the next value + */ + public default void _setFloorTarget(Integer value) { + this.getFloorTargetChannel().setNextValue(value); + } + + /** + * Gets the Channel for {@link ChannelId#AMBIENT_ACTUAL}. + * + * @return the Channel + */ + public default IntegerReadChannel getAmbientActualChannel() { + return this.channel(ChannelId.AMBIENT_ACTUAL); + } + + /** + * Gets the Ambient Actual Temperature in [deci degC]. See + * {@link ChannelId#AMBIENT_ACTUAL}. + * + * @return the Channel {@link Value} + */ + public default Value getAmbientActual() { + return this.getAmbientActualChannel().value(); + } + + /** + * Internal method to set the 'nextValue' on {@link ChannelId#AMBIENT_ACTUAL} + * Channel. + * + * @param value the next value + */ + public default void _setAmbientActual(Integer value) { + this.getAmbientActualChannel().setNextValue(value); + } + + /** + * Gets the Channel for {@link ChannelId#AMBIENT_TARGET}. + * + * @return the Channel + */ + public default IntegerReadChannel getAmbientTargetChannel() { + return this.channel(ChannelId.AMBIENT_TARGET); + } + + /** + * Gets the Ambient Target Temperature in [deci degC]. See + * {@link ChannelId#AMBIENT_TARGET}. + * + * @return the Channel {@link Value} + */ + public default Value getAmbientTarget() { + return this.getAmbientTargetChannel().value(); + } + + /** + * Internal method to set the 'nextValue' on {@link ChannelId#AMBIENT_TARGET} + * Channel. + * + * @param value the next value + */ + public default void _setAmbientTarget(Integer value) { + this.getAmbientTargetChannel().setNextValue(value); + } + +} diff --git a/io.openems.edge.controller.io.heating.room/src/io/openems/edge/controller/io/heating/room/ControllerIoRoomHeatingImpl.java b/io.openems.edge.controller.io.heating.room/src/io/openems/edge/controller/io/heating/room/ControllerIoRoomHeatingImpl.java new file mode 100644 index 00000000000..ec20d7451b3 --- /dev/null +++ b/io.openems.edge.controller.io.heating.room/src/io/openems/edge/controller/io/heating/room/ControllerIoRoomHeatingImpl.java @@ -0,0 +1,472 @@ +package io.openems.edge.controller.io.heating.room; + +import static io.openems.edge.controller.io.heating.room.Utils.getNextHighPeriod; +import static java.time.format.DateTimeFormatter.ISO_LOCAL_DATE_TIME; + +import java.time.Clock; +import java.time.Duration; +import java.time.Instant; +import java.time.LocalDateTime; +import java.time.ZonedDateTime; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +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.ReferencePolicyOption; +import org.osgi.service.metatype.annotations.Designate; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.collect.ImmutableList; +import com.google.gson.JsonObject; + +import io.openems.common.exceptions.OpenemsError.OpenemsNamedException; +import io.openems.common.jscalendar.JSCalendar; +import io.openems.common.jscalendar.JSCalendar.Task; +import io.openems.common.types.ChannelAddress; +import io.openems.common.types.MeterType; +import io.openems.edge.common.channel.BooleanWriteChannel; +import io.openems.edge.common.channel.WriteChannel; +import io.openems.edge.common.component.AbstractOpenemsComponent; +import io.openems.edge.common.component.OpenemsComponent; +import io.openems.edge.controller.api.Controller; +import io.openems.edge.controller.io.heating.room.Utils.HighPeriod; +import io.openems.edge.io.api.DigitalOutput; +import io.openems.edge.meter.api.ElectricityMeter; +import io.openems.edge.thermometer.api.Thermometer; +import io.openems.edge.timedata.api.Timedata; +import io.openems.edge.timedata.api.TimedataProvider; +import io.openems.edge.timedata.api.utils.CalculateEnergyFromPower; + +@Designate(ocd = Config.class, factory = true) +@Component(// + name = "Controller.IO.Heating.Room", // + immediate = true, // + configurationPolicy = ConfigurationPolicy.REQUIRE // +) +public class ControllerIoRoomHeatingImpl extends AbstractOpenemsComponent + implements ControllerIoRoomHeating, Controller, ElectricityMeter, OpenemsComponent, TimedataProvider { + + private static final int MINIMUM_SWITCHING_TIME = 180; // [s] + + private final Logger log = LoggerFactory.getLogger(ControllerIoRoomHeatingImpl.class); + private final Clock clock; + private final CalculateEnergyFromPower calculateEnergy = new CalculateEnergyFromPower(this, + ElectricityMeter.ChannelId.ACTIVE_PRODUCTION_ENERGY); + + @Reference + private ConfigurationAdmin cm; + + @Reference + private Timedata timedata; + + @Reference(policyOption = ReferencePolicyOption.GREEDY) + private Thermometer floorThermometer; + + @Reference(policyOption = ReferencePolicyOption.GREEDY) + private Thermometer ambientThermometer; + + @Reference(policyOption = ReferencePolicyOption.GREEDY) + private List floorRelayComponents; + + @Reference(policyOption = ReferencePolicyOption.GREEDY) + private List infraredRelayComponents; + + private Config config = null; + private ImmutableList> schedule = ImmutableList.of(); + private final List floorRelays = new ArrayList<>(); + private final List infraredRelays = new ArrayList<>(); + + private HighPeriod highPeriod; + private RelayState lastFloorRelayState = null; + private RelayState lastInfraredRelayState = null; + + public ControllerIoRoomHeatingImpl(Clock clock) { + super(// + OpenemsComponent.ChannelId.values(), // + ElectricityMeter.ChannelId.values(), // + Controller.ChannelId.values(), // + ControllerIoRoomHeating.ChannelId.values() // + ); + this.clock = clock; + + // Set static Meter channels + this._setActiveConsumptionEnergy(0); + this._setReactivePower(0); + } + + public ControllerIoRoomHeatingImpl() { + this(Clock.systemDefaultZone()); + } + + @Activate + private void activate(ComponentContext context, Config config) throws OpenemsNamedException { + super.activate(context, config.id(), config.alias(), config.enabled()); + this.applyConfig(config); + } + + @Modified + private void modified(ComponentContext context, Config config) throws OpenemsNamedException { + this.applyConfig(config); + super.modified(context, config.id(), config.alias(), config.enabled()); + } + + @Deactivate + protected void deactivate() { + super.deactivate(); + } + + @Override + public synchronized void run() throws OpenemsNamedException { + this.applyHeatingLogic(); + this.updateMeterValues(); + } + + /** + * Applies the actual heating logic. + */ + private void applyHeatingLogic() { + /* + * Evaluate actual temperatures + */ + var floorActual = this.floorThermometer.getTemperature(); + var ambientActual = this.ambientThermometer.getTemperature(); + this._setFloorActual(floorActual.get()); + this._setAmbientActual(ambientActual.get()); + + /* + * Evaluate target temperatures + */ + final var actualMode = switch (this.config.mode()) { + case AUTOMATIC -> this.getActualModeFromSchedule(); + case MANUAL_HIGH -> ActualMode.HIGH; + case MANUAL_LOW -> ActualMode.LOW; + case OFF -> ActualMode.OFF; + }; + var floorTarget = switch (actualMode) { + case HIGH -> this.config.highFloorTemperature(); + case LOW -> this.config.lowFloorTemperature(); + case OFF -> null; + }; + var ambientTarget = switch (actualMode) { + case HIGH -> this.config.highAmbientTemperature(); + case LOW -> this.config.lowAmbientTemperature(); + case OFF -> null; + }; + this._setFloorTarget(floorTarget); + this._setAmbientTarget(ambientTarget); + + /* + * Control floor heating + */ + if (floorActual.isDefined() && floorTarget != null && floorActual.get() < floorTarget) { + if (this.config.hasExternalAmbientHeating() // + && ambientActual.isDefined() && ambientTarget != null && ambientActual.get() > ambientTarget) { + // Switch Floor heating OFF if there is external heating in the room and ambient + // target temperature is already met + this.switchFloorRelays(Switch.OFF); + } else { + this.switchFloorRelays(Switch.ON); + } + + } else { + this.switchFloorRelays(Switch.OFF); + } + + /* + * Control infrared heating + */ + if (ambientActual.isDefined() && ambientTarget != null && ambientActual.get() < ambientTarget) { + this.switchInfraredRelays(Switch.ON); + } else { + this.switchInfraredRelays(Switch.OFF); + } + } + + public static enum ActualMode { + OFF, LOW, HIGH; + } + + /** + * Gets the {@link ActualMode} from the Schedule. + * + * @return the {@link ActualMode} + */ + protected synchronized ActualMode getActualModeFromSchedule() { + var hp = this.highPeriod; + if (hp == null) { + return ActualMode.LOW; + } + var now = Instant.now(this.clock); + if (now.isBefore(hp.from())) { + return ActualMode.LOW; + } + if (now.isAfter(hp.to())) { + this.updateHighPeriod(); + return this.getActualModeFromSchedule(); + } + return ActualMode.HIGH; + } + + public static enum Switch { + ON, OFF; + } + + /** + * Switch the Floor Heating Relays. + * + * @param target the {@link Switch} target + */ + private void switchFloorRelays(Switch target) { + this.lastFloorRelayState = this.switchRelays(// + this.getFloorRelayChannels(), // + this.lastFloorRelayState, // + target); + } + + /** + * Switch the Infrared Heating Relays. + * + * @param target the {@link Switch} target + */ + private void switchInfraredRelays(Switch target) { + this.lastInfraredRelayState = this.switchRelays(// + this.getInfraredRelayChannels(), // + this.lastInfraredRelayState, // + target); + } + + private static record RelayState(Instant lastChange, Switch target) { + } + + /** + * Switches Relays ON or OFF. Does not switch faster than MINIMUM_SWITCHING_TIME + * and does not set the command if the Relay is already in correct state. + * + * @param channels the Relay channels + * @param lastRelayState the matching {@link RelayState} information object + * @param target the {@link Switch} target + * @return a new {@link RelayState} information object + */ + private RelayState switchRelays(List> channels, RelayState lastRelayState, Switch target) { + var now = Instant.now(this.clock); + if (lastRelayState != null + && Duration.between(lastRelayState.lastChange, now).getSeconds() < MINIMUM_SWITCHING_TIME) { + // Hysteresis is active + return lastRelayState; + } + + boolean value = target == Switch.ON; + for (var channel : channels) { + try { + if (channel.value().asOptional().equals(Optional.of(value))) { + // it is already in the desired state + } else { + channel.setNextWriteValue(value); + } + } catch (OpenemsNamedException e) { + this.logError(this.log, + "Unable to switch Relay [" + channel.address() + "] " + target.name() + ": " + e.getMessage()); + } + } + return new RelayState(now, target); + } + + /** + * Gets the Floor Heating Relay Channels. + * + * @return a list of {@link BooleanWriteChannel}s + */ + private List> getFloorRelayChannels() { + return getChannels(this.floorRelayComponents, this.floorRelays); // + } + + /** + * Gets the Infrared Heating Relay Channels. + * + * @return a list of {@link BooleanWriteChannel}s + */ + private List> getInfraredRelayChannels() { + return getChannels(this.infraredRelayComponents, this.infraredRelays); // + } + + /** + * Gets the Relay Channels from addresses. + * + * @param components the {@link DigitalOutput} components + * @param addresses the {@link ChannelAddress}es of the Relays + * @return a list of relay channels + */ + private static List> getChannels(List components, + List addresses) { + final List> result = new ArrayList<>(); + for (var address : addresses) { + for (var component : components) { + if (address.getComponentId().equals(component.id())) { + WriteChannel channel = component.channel(address.getChannelId()); + result.add(channel); + } + } + } + return result; + } + + @Override + public MeterType getMeterType() { + return MeterType.CONSUMPTION_METERED; + } + + /** + * Update the Meter values. + */ + private void updateMeterValues() { + /* + * Floor Power + */ + var floorIsOn = this.getFloorRelayChannels().stream() // + .map(c -> c.value()) // + .filter(v -> v.isDefined() && v.get()) // is any channel value true? + .findAny() // + .isPresent(); + final int floorPower; + if (floorIsOn) { + floorPower = this.config.floorPower(); + } else { + floorPower = 0; + } + + /* + * Infrared Power + */ + var infraredIsOn = this.getInfraredRelayChannels().stream() // + .map(c -> c.value()) // + .filter(v -> v.isDefined() && v.get()) // is any channel value true? + .findAny() // + .isPresent(); + final int infraredPower; + if (infraredIsOn) { + infraredPower = this.config.infraredPower(); + } else { + infraredPower = 0; + } + + /* + * Sum + */ + var power = floorPower + infraredPower; + this._setActivePower(power); + this.calculateEnergy.update(power); + } + + /** + * Applies the Configuration and updates reference target filters. + * + * @param config the {@link Config} + * @throws OpenemsNamedException on error + */ + private synchronized void applyConfig(Config config) throws OpenemsNamedException { + this.config = config; + + // Reset RelayStates + this.lastFloorRelayState = null; + this.lastInfraredRelayState = null; + + OpenemsComponent.updateReferenceFilter(this.cm, this.servicePid(), "floorThermometer", + this.config.floorThermometer_id()); + OpenemsComponent.updateReferenceFilter(this.cm, this.servicePid(), "ambientThermometer", + this.config.ambientThermometer_id()); + + // Parse Channel-Addresses + { + this.floorRelays.clear(); + for (String channel : config.floorRelays()) { + if (channel.isEmpty()) { + continue; + } + var address = ChannelAddress.fromString(channel); + this.floorRelays.add(address); + } + OpenemsComponent.updateReferenceFilter(this.cm, this.servicePid(), "floorRelayComponents", + this.floorRelays.stream().map(c -> c.getComponentId()).distinct().toArray(String[]::new)); + } + { + this.infraredRelays.clear(); + for (String channel : config.infraredRelays()) { + if (channel.isEmpty()) { + continue; + } + var address = ChannelAddress.fromString(channel); + this.infraredRelays.add(address); + } + OpenemsComponent.updateReferenceFilter(this.cm, this.servicePid(), "infraredRelayComponents", + this.infraredRelays.stream().map(c -> c.getComponentId()).distinct().toArray(String[]::new)); + } + + this.schedule = JSCalendar.Task.fromStringOrEmpty(config.schedule(), j -> j); + this.updateHighPeriod(); + } + + private synchronized void updateHighPeriod() { + var now = ZonedDateTime.now(this.clock); + this.highPeriod = getNextHighPeriod(now, this.schedule); + } + + @Override + public Timedata getTimedata() { + return this.timedata; + } + + @Override + public String debugLog() { + final var mode = this.config.mode(); + final var b = new StringBuilder(); // + switch (mode) { + case OFF -> b.append("Off"); + case MANUAL_HIGH -> b.append("Manual HIGH"); + case MANUAL_LOW -> b.append("Manual LOW"); + case AUTOMATIC -> { + var hp = this.highPeriod; + b.append("Auto|"); + if (hp == null) { + b.append("LOW|NoSchedule"); + } else { + var now = Instant.now(this.clock); + if (now.isBefore(hp.from())) { + b // + .append("LOW|NextHigh:") // + .append(LocalDateTime.ofInstant(hp.from(), this.clock.getZone()) + .format(ISO_LOCAL_DATE_TIME)); + } else if (now.isAfter(hp.to())) { + b.append("LOW|NoSchedule"); // + } else { + b // + .append("HIGH|Till:") // + .append(LocalDateTime.ofInstant(hp.to(), this.clock.getZone()).format(ISO_LOCAL_DATE_TIME)); + } + } + } + } + if (mode != Mode.OFF) { + b // + .append("|Floor:") // + .append(this.getFloorActual().asStringWithoutUnit()) // + .append("->") // + .append(this.getFloorTarget().asString()) // + .append("|Ambient:") // + .append(this.getAmbientActual().asStringWithoutUnit()) // + .append("->") // + .append(this.getAmbientTarget().asString()) // + .append("|") // + .append(this.getActivePower().asString()); + } + return b.toString(); + } +} diff --git a/io.openems.edge.controller.io.heating.room/src/io/openems/edge/controller/io/heating/room/Mode.java b/io.openems.edge.controller.io.heating.room/src/io/openems/edge/controller/io/heating/room/Mode.java new file mode 100644 index 00000000000..d248aeb2ecf --- /dev/null +++ b/io.openems.edge.controller.io.heating.room/src/io/openems/edge/controller/io/heating/room/Mode.java @@ -0,0 +1,33 @@ +package io.openems.edge.controller.io.heating.room; + +import io.openems.common.types.OptionsEnum; + +public enum Mode implements OptionsEnum { + OFF(0, "Off"), // + MANUAL_LOW(1, "Manual Low"), // + MANUAL_HIGH(2, "Manual High"), // + AUTOMATIC(3, "Automatic schedule control"); // + + private final int value; + private final String name; + + private Mode(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 OFF; + } +} \ No newline at end of file diff --git a/io.openems.edge.controller.io.heating.room/src/io/openems/edge/controller/io/heating/room/Utils.java b/io.openems.edge.controller.io.heating.room/src/io/openems/edge/controller/io/heating/room/Utils.java new file mode 100644 index 00000000000..18a92ea9ff1 --- /dev/null +++ b/io.openems.edge.controller.io.heating.room/src/io/openems/edge/controller/io/heating/room/Utils.java @@ -0,0 +1,29 @@ +package io.openems.edge.controller.io.heating.room; + +import java.time.Instant; +import java.time.ZonedDateTime; + +import com.google.common.collect.ImmutableList; +import com.google.gson.JsonObject; + +import io.openems.common.jscalendar.JSCalendar.Task; + +public class Utils { + + private Utils() { + } + + protected static record HighPeriod(Instant from, Instant to) { + } + + protected static HighPeriod getNextHighPeriod(ZonedDateTime now, ImmutableList> schedule) { + return schedule.stream() // + .map(task -> { + var next = task.getNextOccurence(now); + return new HighPeriod(next.toInstant(), next.plus(task.duration()).toInstant()); + }) // + .sorted((t0, t1) -> t0.from.compareTo(t1.from)) // + .findFirst() // + .orElse(null); + } +} diff --git a/io.openems.edge.controller.io.heating.room/test/.gitignore b/io.openems.edge.controller.io.heating.room/test/.gitignore new file mode 100644 index 00000000000..e69de29bb2d diff --git a/io.openems.edge.controller.io.heating.room/test/io/openems/edge/controller/io/heating/room/ControllerIoRoomHeatingImplTest.java b/io.openems.edge.controller.io.heating.room/test/io/openems/edge/controller/io/heating/room/ControllerIoRoomHeatingImplTest.java new file mode 100644 index 00000000000..9d548b7b8e3 --- /dev/null +++ b/io.openems.edge.controller.io.heating.room/test/io/openems/edge/controller/io/heating/room/ControllerIoRoomHeatingImplTest.java @@ -0,0 +1,234 @@ +package io.openems.edge.controller.io.heating.room; + +import static io.openems.common.test.TestUtils.createDummyClock; +import static io.openems.edge.controller.io.heating.room.Mode.AUTOMATIC; +import static io.openems.edge.controller.io.heating.room.Mode.MANUAL_LOW; +import static io.openems.edge.controller.io.heating.room.Mode.OFF; +import static java.time.temporal.ChronoUnit.HOURS; +import static java.time.temporal.ChronoUnit.MINUTES; +import static org.junit.Assert.assertEquals; + +import java.util.List; + +import org.junit.Test; + +import io.openems.common.function.ThrowingRunnable; +import io.openems.edge.common.test.AbstractComponentTest.TestCase; +import io.openems.edge.common.test.DummyConfigurationAdmin; +import io.openems.edge.controller.test.ControllerTest; +import io.openems.edge.io.test.DummyInputOutput; +import io.openems.edge.meter.api.ElectricityMeter; +import io.openems.edge.thermometer.api.Thermometer; +import io.openems.edge.thermometer.test.DummyThermometer; + +public class ControllerIoRoomHeatingImplTest { + + @Test + public void testLow() throws Exception { + final var clock = createDummyClock(); + final var io = new DummyInputOutput("io0"); + final var sut = new ControllerIoRoomHeatingImpl(clock); + new ControllerTest(sut) // + .addReference("cm", new DummyConfigurationAdmin()) // + .addReference("floorThermometer", new DummyThermometer("temp0")) // + .addReference("ambientThermometer", new DummyThermometer("temp1")) // + .addReference("floorRelayComponents", List.of(io)) // + .addReference("infraredRelayComponents", List.of(io)) // + .activate(MyConfig.create() // + .setId("ctrl0") // + .setMode(MANUAL_LOW) // + .setSchedule("") // + .setLowFloorTemperature(150) // + .setLowAmbientTemperature(160) // + .setHighFloorTemperature(210) // + .setHighAmbientTemperature(220) // + .setFloorThermometerId("temp0") // + .setAmbientThermometerId("temp1") // + .setFloorRelays("io0/InputOutput0", "io0/InputOutput1") // + .setInfraredRelays("io0/InputOutput2", "io0/InputOutput3") // + .setFloorPower(2600) // + .setInfraredPower(2000) // + .setHasExternalAmbientHeating(true) // + .build()) + .next(new TestCase() // + .onAfterProcessImage(assertLog(sut, + "Manual LOW|Floor:UNDEFINED->UNDEFINED|Ambient:UNDEFINED->UNDEFINED|UNDEFINED")) // + .input("temp0", Thermometer.ChannelId.TEMPERATURE, 160) // + .input("temp1", Thermometer.ChannelId.TEMPERATURE, 160) // + .output("io0", DummyInputOutput.ChannelId.INPUT_OUTPUT0, false) // + .output("io0", DummyInputOutput.ChannelId.INPUT_OUTPUT1, false) // + .output("io0", DummyInputOutput.ChannelId.INPUT_OUTPUT2, false) // + .output("io0", DummyInputOutput.ChannelId.INPUT_OUTPUT3, false) // + .output(ElectricityMeter.ChannelId.ACTIVE_POWER, 0)) // + + .next(new TestCase() // + .timeleap(clock, 3, MINUTES) // + .onAfterProcessImage(assertLog(sut, "Manual LOW|Floor:160->150|Ambient:160->160|0 W")) // + .input("temp0", Thermometer.ChannelId.TEMPERATURE, 140) // + .input("temp1", Thermometer.ChannelId.TEMPERATURE, 140) // + .output("io0", DummyInputOutput.ChannelId.INPUT_OUTPUT0, true) // + .output("io0", DummyInputOutput.ChannelId.INPUT_OUTPUT1, true) // + .output("io0", DummyInputOutput.ChannelId.INPUT_OUTPUT2, true) // + .output("io0", DummyInputOutput.ChannelId.INPUT_OUTPUT3, true)) // + + .next(new TestCase() // + .timeleap(clock, 3, MINUTES) // + .onAfterProcessImage(assertLog(sut, "Manual LOW|Floor:140->150|Ambient:140->160|0 W")) // + .input("io0", DummyInputOutput.ChannelId.INPUT_OUTPUT0, true) // + .input("io0", DummyInputOutput.ChannelId.INPUT_OUTPUT1, true) // + .input("io0", DummyInputOutput.ChannelId.INPUT_OUTPUT2, true) // + .input("io0", DummyInputOutput.ChannelId.INPUT_OUTPUT3, true) // + .output(ElectricityMeter.ChannelId.ACTIVE_POWER, 4600)) // + + .next(new TestCase() // + .timeleap(clock, 3, MINUTES) // + .onAfterProcessImage(assertLog(sut, "Manual LOW|Floor:140->150|Ambient:140->160|4600 W")) // + .input("temp0", Thermometer.ChannelId.TEMPERATURE, 150) // + .input("temp1", Thermometer.ChannelId.TEMPERATURE, 150) // + .output("io0", DummyInputOutput.ChannelId.INPUT_OUTPUT0, false) // + .output("io0", DummyInputOutput.ChannelId.INPUT_OUTPUT1, false) // + .output("io0", DummyInputOutput.ChannelId.INPUT_OUTPUT2, true) // + .output("io0", DummyInputOutput.ChannelId.INPUT_OUTPUT3, true)) // + + .next(new TestCase() // + .timeleap(clock, 3, MINUTES) // + .onAfterProcessImage(assertLog(sut, "Manual LOW|Floor:150->150|Ambient:150->160|4600 W")) // + .input("io0", DummyInputOutput.ChannelId.INPUT_OUTPUT0, false) // + .input("io0", DummyInputOutput.ChannelId.INPUT_OUTPUT1, false) // + .input("io0", DummyInputOutput.ChannelId.INPUT_OUTPUT2, true) // + .input("io0", DummyInputOutput.ChannelId.INPUT_OUTPUT3, true) // + .output(ElectricityMeter.ChannelId.ACTIVE_POWER, 2000)) // + + .next(new TestCase() // + .timeleap(clock, 3, MINUTES) // + .onAfterProcessImage(assertLog(sut, "Manual LOW|Floor:150->150|Ambient:150->160|2000 W")) // + .input("temp0", Thermometer.ChannelId.TEMPERATURE, 160) // + .input("temp1", Thermometer.ChannelId.TEMPERATURE, 170) // + .output("io0", DummyInputOutput.ChannelId.INPUT_OUTPUT0, false) // + .output("io0", DummyInputOutput.ChannelId.INPUT_OUTPUT1, false) // + .output("io0", DummyInputOutput.ChannelId.INPUT_OUTPUT2, false) // + .output("io0", DummyInputOutput.ChannelId.INPUT_OUTPUT3, false)) // + + .next(new TestCase() // + .timeleap(clock, 3, MINUTES) // + .onAfterProcessImage(assertLog(sut, "Manual LOW|Floor:160->150|Ambient:170->160|2000 W")) // + .input("io0", DummyInputOutput.ChannelId.INPUT_OUTPUT0, false) // + .input("io0", DummyInputOutput.ChannelId.INPUT_OUTPUT1, false) // + .input("io0", DummyInputOutput.ChannelId.INPUT_OUTPUT2, false) // + .input("io0", DummyInputOutput.ChannelId.INPUT_OUTPUT3, false) // + .output(ElectricityMeter.ChannelId.ACTIVE_POWER, 0)) // + + .next(new TestCase() // + .timeleap(clock, 3, MINUTES) // + .onAfterProcessImage(assertLog(sut, "Manual LOW|Floor:160->150|Ambient:170->160|0 W"))) // + + .deactivate(); + } + + @Test + public void testAuto() throws Exception { + final var clock = createDummyClock(); + final var io = new DummyInputOutput("io0"); + final var sut = new ControllerIoRoomHeatingImpl(clock); + new ControllerTest(sut) // + .addReference("cm", new DummyConfigurationAdmin()) // + .addReference("floorThermometer", new DummyThermometer("temp0")) // + .addReference("ambientThermometer", new DummyThermometer("temp1")) // + .addReference("floorRelayComponents", List.of(io)) // + .addReference("infraredRelayComponents", List.of(io)) // + .activate(MyConfig.create() // + .setId("ctrl0") // + .setMode(AUTOMATIC) // + .setSchedule(""" + [ + { + "@type":"Task", + "start":"01:00:00", + "duration":"PT1H", + "recurrenceRules":[ + { + "frequency":"daily" + } + ] + } + ]""") // + .setLowFloorTemperature(150) // + .setLowAmbientTemperature(160) // + .setHighFloorTemperature(210) // + .setHighAmbientTemperature(220) // + .setFloorThermometerId("temp0") // + .setAmbientThermometerId("temp1") // + .setFloorRelays("io0/InputOutput0") // + .setInfraredRelays("io0/InputOutput2") // + .setFloorPower(2600) // + .setInfraredPower(2000) // + .setHasExternalAmbientHeating(true) // + .build()) + .next(new TestCase() // + .onAfterProcessImage(assertLog(sut, // + "Auto|LOW|NextHigh:2020-01-01T01:00:00|Floor:UNDEFINED->UNDEFINED|Ambient:UNDEFINED->UNDEFINED|UNDEFINED"))) // + + .next(new TestCase() // + .timeleap(clock, 1, HOURS) // + .onAfterProcessImage(assertLog(sut, // + "Auto|HIGH|Till:2020-01-01T02:00:00|Floor:UNDEFINED->150|Ambient:UNDEFINED->160|0 W"))) // + + .next(new TestCase() // + .timeleap(clock, 61, MINUTES) // + .onAfterProcessImage(assertLog(sut, // + "Auto|LOW|NoSchedule|Floor:UNDEFINED->210|Ambient:UNDEFINED->220|0 W"))); + } + + @Test + public void testAutoWrong() throws Exception { + final var clock = createDummyClock(); + final var io = new DummyInputOutput("io0"); + final var sut = new ControllerIoRoomHeatingImpl(clock); + new ControllerTest(sut) // + .addReference("cm", new DummyConfigurationAdmin()) // + .addReference("floorThermometer", new DummyThermometer("temp0")) // + .addReference("ambientThermometer", new DummyThermometer("temp1")) // + .addReference("floorRelayComponents", List.of(io)) // + .addReference("infraredRelayComponents", List.of(io)) // + .activate(MyConfig.create() // + .setId("ctrl0") // + .setMode(AUTOMATIC) // + .setSchedule("") // + .setFloorThermometerId("temp0") // + .setAmbientThermometerId("temp1") // + .setFloorRelays("io0/InputOutput0") // + .setInfraredRelays("io0/InputOutput2") // + .build()) + .next(new TestCase() // + .onAfterProcessImage(assertLog(sut, // + "Auto|LOW|NoSchedule|Floor:UNDEFINED->UNDEFINED|Ambient:UNDEFINED->UNDEFINED|UNDEFINED"))); + } + + @Test + public void testOff() throws Exception { + final var clock = createDummyClock(); + final var io = new DummyInputOutput("io0"); + final var sut = new ControllerIoRoomHeatingImpl(clock); + new ControllerTest(sut) // + .addReference("cm", new DummyConfigurationAdmin()) // + .addReference("floorThermometer", new DummyThermometer("temp0")) // + .addReference("ambientThermometer", new DummyThermometer("temp1")) // + .addReference("floorRelayComponents", List.of(io)) // + .addReference("infraredRelayComponents", List.of(io)) // + .activate(MyConfig.create() // + .setId("ctrl0") // + .setMode(OFF) // + .setSchedule("") // + .setFloorThermometerId("temp0") // + .setAmbientThermometerId("temp1") // + .setFloorRelays("io0/InputOutput0") // + .setInfraredRelays("io0/InputOutput2") // + .build()) + .next(new TestCase() // + .onAfterProcessImage(assertLog(sut, "Off"))); + } + + private static ThrowingRunnable assertLog(ControllerIoRoomHeatingImpl sut, String message) { + return () -> assertEquals(message, sut.debugLog()); + } +} diff --git a/io.openems.edge.controller.io.heating.room/test/io/openems/edge/controller/io/heating/room/MyConfig.java b/io.openems.edge.controller.io.heating.room/test/io/openems/edge/controller/io/heating/room/MyConfig.java new file mode 100644 index 00000000000..e4222cc9504 --- /dev/null +++ b/io.openems.edge.controller.io.heating.room/test/io/openems/edge/controller/io/heating/room/MyConfig.java @@ -0,0 +1,204 @@ +package io.openems.edge.controller.io.heating.room; + +import static io.openems.common.utils.ConfigUtils.generateReferenceTargetFilter; + +import io.openems.common.test.AbstractComponentConfig; + +@SuppressWarnings("all") +public class MyConfig extends AbstractComponentConfig implements Config { + + protected static class Builder { + private String id; + private Mode mode; + private String schedule; + private int lowFloorTemperature; + private int lowAmbientTemperature; + private int highFloorTemperature; + private int highAmbientTemperature; + private String floorThermometerId; + private String ambientThermometerId; + private String[] floorRelays; + private String[] infraredRelays; + private int floorPower; + private int infraredPower; + private boolean hasExternalAmbientHeating; + + private Builder() { + } + + public Builder setId(String id) { + this.id = id; + return this; + } + + public Builder setMode(Mode mode) { + this.mode = mode; + return this; + } + + public Builder setSchedule(String schedule) { + this.schedule = schedule; + return this; + } + + public Builder setLowFloorTemperature(int lowFloorTemperature) { + this.lowFloorTemperature = lowFloorTemperature; + return this; + } + + public Builder setLowAmbientTemperature(int lowAmbientTemperature) { + this.lowAmbientTemperature = lowAmbientTemperature; + return this; + } + + public Builder setHighFloorTemperature(int highFloorTemperature) { + this.highFloorTemperature = highFloorTemperature; + return this; + } + + public Builder setHighAmbientTemperature(int highAmbientTemperature) { + this.highAmbientTemperature = highAmbientTemperature; + return this; + } + + public Builder setFloorThermometerId(String floorThermometerId) { + this.floorThermometerId = floorThermometerId; + return this; + } + + public Builder setAmbientThermometerId(String ambientThermometerId) { + this.ambientThermometerId = ambientThermometerId; + return this; + } + + public Builder setFloorRelays(String... floorRelays) { + this.floorRelays = floorRelays; + return this; + } + + public Builder setInfraredRelays(String... infraredRelays) { + this.infraredRelays = infraredRelays; + return this; + } + + public Builder setFloorPower(int floorPower) { + this.floorPower = floorPower; + return this; + } + + public Builder setInfraredPower(int infraredPower) { + this.infraredPower = infraredPower; + return this; + } + + public Builder setHasExternalAmbientHeating(boolean hasExternalAmbientHeating) { + this.hasExternalAmbientHeating = hasExternalAmbientHeating; + 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 Mode mode() { + return this.builder.mode; + } + + @Override + public String schedule() { + return this.builder.schedule; + } + + @Override + public int lowFloorTemperature() { + return this.builder.lowFloorTemperature; + } + + @Override + public int lowAmbientTemperature() { + return this.builder.lowAmbientTemperature; + } + + @Override + public int highFloorTemperature() { + return this.builder.highFloorTemperature; + } + + @Override + public int highAmbientTemperature() { + return this.builder.highAmbientTemperature; + } + + @Override + public String floorThermometer_id() { + return this.builder.floorThermometerId; + } + + @Override + public String ambientThermometer_id() { + return this.builder.ambientThermometerId; + } + + @Override + public String[] floorRelays() { + return this.builder.floorRelays; + } + + @Override + public String[] infraredRelays() { + return this.builder.infraredRelays; + } + + @Override + public int floorPower() { + return this.builder.floorPower; + } + + @Override + public int infraredPower() { + return this.builder.infraredPower; + } + + @Override + public boolean hasExternalAmbientHeating() { + return this.builder.hasExternalAmbientHeating; + } + + @Override + public String floorThermometer_target() { + return generateReferenceTargetFilter(this.id(), this.floorThermometer_id()); + } + + @Override + public String ambientThermometer_target() { + return generateReferenceTargetFilter(this.id(), this.ambientThermometer_id()); + } + + @Override + public String floorRelayComponents_target() { + return generateReferenceTargetFilter(this.id(), this.floorRelays()); + } + + @Override + public String infraredRelayComponents_target() { + return generateReferenceTargetFilter(this.id(), this.infraredRelays()); + } +} \ No newline at end of file diff --git a/io.openems.edge.controller.io.heating.room/test/io/openems/edge/controller/io/heating/room/UtilsTest.java b/io.openems.edge.controller.io.heating.room/test/io/openems/edge/controller/io/heating/room/UtilsTest.java new file mode 100644 index 00000000000..a29c84299f5 --- /dev/null +++ b/io.openems.edge.controller.io.heating.room/test/io/openems/edge/controller/io/heating/room/UtilsTest.java @@ -0,0 +1,76 @@ +package io.openems.edge.controller.io.heating.room; + +import static io.openems.edge.controller.io.heating.room.Utils.getNextHighPeriod; +import static org.junit.Assert.assertEquals; + +import java.time.ZoneId; +import java.time.ZonedDateTime; + +import org.junit.Test; + +import io.openems.common.jscalendar.JSCalendar; + +public class UtilsTest { + + @Test + public void test() { + var schedule = JSCalendar.Task.fromStringOrEmpty(""" + [ + { + "@type":"Task", + "start":"05:30:00", + "duration":"PT2H30M", + "recurrenceRules":[ + { + "frequency":"weekly", + "byDay":[ + "mo", + "tu", + "we", + "th", + "fr" + ] + } + ] + }, + { + "@type":"Task", + "start":"14:00:00", + "duration":"PT10H", + "recurrenceRules":[ + { + "frequency":"weekly", + "byDay":[ + "mo", + "tu", + "we", + "th", + "fr" + ] + } + ] + }, + { + "@type":"Task", + "start":"08:00:00", + "duration":"PT16H", + "recurrenceRules":[ + { + "frequency":"weekly", + "byDay":[ + "sa", + "su" + ] + } + ] + } + ]""", j -> j); + + assertEquals("HighPeriod[from=2025-01-06T04:30:00Z, to=2025-01-06T07:00:00Z]", getNextHighPeriod(// + ZonedDateTime.of(2025, 1, 6, 5, 29, 0, 0, ZoneId.of("Europe/Berlin")), schedule).toString()); + assertEquals("HighPeriod[from=2025-01-06T04:30:00Z, to=2025-01-06T07:00:00Z]", getNextHighPeriod(// + ZonedDateTime.of(2025, 1, 6, 5, 31, 0, 0, ZoneId.of("Europe/Berlin")), schedule).toString()); + assertEquals("HighPeriod[from=2025-01-06T13:00:00Z, to=2025-01-06T23:00:00Z]", getNextHighPeriod(// + ZonedDateTime.of(2025, 1, 6, 9, 0, 0, 0, ZoneId.of("Europe/Berlin")), schedule).toString()); + } +} diff --git a/io.openems.edge.controller.io.heatingelement/src/io/openems/edge/controller/io/heatingelement/ControllerIoHeatingElementImpl.java b/io.openems.edge.controller.io.heatingelement/src/io/openems/edge/controller/io/heatingelement/ControllerIoHeatingElementImpl.java index 3fddd82d2b0..ff717380cb4 100644 --- a/io.openems.edge.controller.io.heatingelement/src/io/openems/edge/controller/io/heatingelement/ControllerIoHeatingElementImpl.java +++ b/io.openems.edge.controller.io.heatingelement/src/io/openems/edge/controller/io/heatingelement/ControllerIoHeatingElementImpl.java @@ -118,24 +118,19 @@ private void updateConfig(Config config) { @Override public void run() throws OpenemsNamedException { - Status runState = Status.UNDEFINED; - // Handle Mode AUTOMATIC, MANUAL_OFF or MANUAL_ON - switch (this.config.mode()) { - case AUTOMATIC: - runState = this.modeAutomatic(); - break; - - case MANUAL_OFF: + var runState = switch (this.config.mode()) { + case AUTOMATIC // + -> this.modeAutomatic(); + case MANUAL_OFF -> { this.modeManualOff(); - runState = Status.INACTIVE; - break; - - case MANUAL_ON: + yield Status.INACTIVE; + } + case MANUAL_ON -> { this.modeManualOn(); - runState = Status.ACTIVE; - break; + yield Status.ACTIVE; } + }; // Calculate Phase Time var phase1Time = (int) this.phase1.getTotalDuration().getSeconds(); @@ -269,23 +264,16 @@ protected Status modeAutomatic() throws IllegalArgumentException, OpenemsNamedEx * @return the minimum total phase time [s] */ private static long calculateMinimumTotalPhaseTime(Config config) { - switch (config.workMode()) { - case TIME: - switch (config.defaultLevel()) { - case LEVEL_0: - return 0; - case LEVEL_1: - return config.minTime() * 3600; - case LEVEL_2: - return config.minTime() * 3600 * 2; - case LEVEL_3: - return config.minTime() * 3600 * 3; - } - case NONE: - return 0; - } - assert true; - return 0; + return switch (config.workMode()) { + case TIME // + -> switch (config.defaultLevel()) { + case LEVEL_0 -> 0; + case LEVEL_1 -> config.minTime() * 3600; + case LEVEL_2 -> config.minTime() * 3600 * 2; + case LEVEL_3 -> config.minTime() * 3600 * 3; + }; + case NONE -> 0; + }; } /** @@ -333,26 +321,26 @@ public void applyLevel(Level level) throws IllegalArgumentException, OpenemsName // Set phases accordingly switch (level) { - case LEVEL_0: + case LEVEL_0 -> { this.phase1.switchOff(); this.phase2.switchOff(); this.phase3.switchOff(); - break; - case LEVEL_1: + } + case LEVEL_1 -> { this.phase1.switchOn(); this.phase2.switchOff(); this.phase3.switchOff(); - break; - case LEVEL_2: + } + case LEVEL_2 -> { this.phase1.switchOn(); this.phase2.switchOn(); this.phase3.switchOff(); - break; - case LEVEL_3: + } + case LEVEL_3 -> { this.phase1.switchOn(); this.phase2.switchOn(); this.phase3.switchOn(); - break; + } } } @@ -418,16 +406,12 @@ protected void setOutput(Phase phase, boolean value) throws IllegalArgumentExcep * @throws OpenemsNamedException on error */ private ChannelAddress getChannelAddressForPhase(Phase phase) throws OpenemsNamedException { - switch (phase) { - case L1: - return ChannelAddress.fromString(this.config.outputChannelPhaseL1()); - case L2: - return ChannelAddress.fromString(this.config.outputChannelPhaseL2()); - case L3: - return ChannelAddress.fromString(this.config.outputChannelPhaseL3()); - } - assert true; // can never happen - return null; + return ChannelAddress.fromString(// + switch (phase) { + case L1 -> this.config.outputChannelPhaseL1(); + case L2 -> this.config.outputChannelPhaseL2(); + case L3 -> this.config.outputChannelPhaseL3(); + }); } /** diff --git a/io.openems.edge.controller.io.heatingelement/test/io/openems/edge/controller/io/heatingelement/ControllerHeatingElementImplTest4.java b/io.openems.edge.controller.io.heatingelement/test/io/openems/edge/controller/io/heatingelement/ControllerHeatingElementImplTest4.java index 6e5db300d23..76db186ac35 100644 --- a/io.openems.edge.controller.io.heatingelement/test/io/openems/edge/controller/io/heatingelement/ControllerHeatingElementImplTest4.java +++ b/io.openems.edge.controller.io.heatingelement/test/io/openems/edge/controller/io/heatingelement/ControllerHeatingElementImplTest4.java @@ -1,5 +1,6 @@ package io.openems.edge.controller.io.heatingelement; +import static io.openems.common.test.TestUtils.createDummyClock; import static io.openems.edge.common.sum.Sum.ChannelId.ESS_DISCHARGE_POWER; import static io.openems.edge.common.sum.Sum.ChannelId.GRID_ACTIVE_POWER; import static io.openems.edge.controller.io.heatingelement.ControllerIoHeatingElement.ChannelId.LEVEL; @@ -12,7 +13,6 @@ import io.openems.edge.common.sum.DummySum; import io.openems.edge.common.test.AbstractComponentTest.TestCase; import io.openems.edge.common.test.DummyComponentManager; -import io.openems.edge.common.test.TestUtils; import io.openems.edge.controller.io.heatingelement.enums.Level; import io.openems.edge.controller.io.heatingelement.enums.Mode; import io.openems.edge.controller.io.heatingelement.enums.WorkMode; @@ -21,12 +21,11 @@ public class ControllerHeatingElementImplTest4 { - private static TimeLeapClock clock; + private static final TimeLeapClock CLOCK = createDummyClock(); private static ControllerTest prepareTest(Mode mode, Level level) throws OpenemsNamedException, Exception { - clock = TestUtils.createDummyClock(); return new ControllerTest(new ControllerIoHeatingElementImpl()) // - .addReference("componentManager", new DummyComponentManager(clock)) // + .addReference("componentManager", new DummyComponentManager(CLOCK)) // .addReference("sum", new DummySum()) // .addComponent(new DummyInputOutput("io0")) // .activate(MyConfig.create() // @@ -51,16 +50,16 @@ public void testDischargeTakeIntoAccount() throws OpenemsNamedException, Excepti .input(GRID_ACTIVE_POWER, -2500)// .output(LEVEL, Level.LEVEL_1)) // .next(new TestCase() // - .timeleap(clock, 181, SECONDS)// + .timeleap(CLOCK, 181, SECONDS)// .input(GRID_ACTIVE_POWER, -2500)// .output(LEVEL, Level.LEVEL_2))// // Grid power reducing because of 2kW heating power .next(new TestCase()// - .timeleap(clock, 181, SECONDS)// + .timeleap(CLOCK, 181, SECONDS)// .input(GRID_ACTIVE_POWER, -500) // .output(LEVEL, Level.LEVEL_2)) // .next(new TestCase() // - .timeleap(clock, 181, SECONDS)// + .timeleap(CLOCK, 181, SECONDS)// .input(GRID_ACTIVE_POWER, -500) // .input(ESS_DISCHARGE_POWER, 2300) // .output(LEVEL, Level.LEVEL_1)) // @@ -75,7 +74,7 @@ public void realDataTest() throws OpenemsNamedException, Exception { .input(GRID_ACTIVE_POWER, -6000)// .output(LEVEL, Level.LEVEL_3)) // .next(new TestCase()// - .timeleap(clock, 181, SECONDS)// + .timeleap(CLOCK, 181, SECONDS)// .input(GRID_ACTIVE_POWER, 0)// .input(ESS_DISCHARGE_POWER, 2280)// .output(LEVEL, Level.LEVEL_1)) // diff --git a/io.openems.edge.controller.io.heatingelement/test/io/openems/edge/controller/io/heatingelement/ControllerIoHeatingElementImplTest.java b/io.openems.edge.controller.io.heatingelement/test/io/openems/edge/controller/io/heatingelement/ControllerIoHeatingElementImplTest.java index f874c0994e7..994a7aa400b 100644 --- a/io.openems.edge.controller.io.heatingelement/test/io/openems/edge/controller/io/heatingelement/ControllerIoHeatingElementImplTest.java +++ b/io.openems.edge.controller.io.heatingelement/test/io/openems/edge/controller/io/heatingelement/ControllerIoHeatingElementImplTest.java @@ -1,7 +1,7 @@ package io.openems.edge.controller.io.heatingelement; +import static io.openems.common.test.TestUtils.createDummyClock; import static io.openems.edge.common.sum.Sum.ChannelId.GRID_ACTIVE_POWER; -import static io.openems.edge.common.test.TestUtils.createDummyClock; import static io.openems.edge.controller.io.heatingelement.ControllerIoHeatingElement.ChannelId.PHASE1_TIME; import static io.openems.edge.controller.io.heatingelement.ControllerIoHeatingElement.ChannelId.PHASE2_TIME; import static io.openems.edge.controller.io.heatingelement.ControllerIoHeatingElement.ChannelId.PHASE3_TIME; diff --git a/io.openems.edge.controller.io.heatpump.sgready/test/io/openems/edge/controller/io/heatpump/sgready/ControllerIoHeatPumpSgReadyImplTest.java b/io.openems.edge.controller.io.heatpump.sgready/test/io/openems/edge/controller/io/heatpump/sgready/ControllerIoHeatPumpSgReadyImplTest.java index a1e14ab2de5..7a59a71d94b 100644 --- a/io.openems.edge.controller.io.heatpump.sgready/test/io/openems/edge/controller/io/heatpump/sgready/ControllerIoHeatPumpSgReadyImplTest.java +++ b/io.openems.edge.controller.io.heatpump.sgready/test/io/openems/edge/controller/io/heatpump/sgready/ControllerIoHeatPumpSgReadyImplTest.java @@ -1,9 +1,9 @@ package io.openems.edge.controller.io.heatpump.sgready; +import static io.openems.common.test.TestUtils.createDummyClock; import static io.openems.edge.common.sum.Sum.ChannelId.ESS_DISCHARGE_POWER; import static io.openems.edge.common.sum.Sum.ChannelId.ESS_SOC; import static io.openems.edge.common.sum.Sum.ChannelId.GRID_ACTIVE_POWER; -import static io.openems.edge.common.test.TestUtils.createDummyClock; import static io.openems.edge.controller.io.heatpump.sgready.ControllerIoHeatPumpSgReady.ChannelId.AWAITING_HYSTERESIS; import static io.openems.edge.controller.io.heatpump.sgready.ControllerIoHeatPumpSgReady.ChannelId.STATUS; import static io.openems.edge.io.test.DummyInputOutput.ChannelId.INPUT_OUTPUT0; diff --git a/io.openems.edge.core/.settings/org.eclipse.core.resources.prefs b/io.openems.edge.core/.settings/org.eclipse.core.resources.prefs index 2b7c020688d..345c44953dd 100644 --- a/io.openems.edge.core/.settings/org.eclipse.core.resources.prefs +++ b/io.openems.edge.core/.settings/org.eclipse.core.resources.prefs @@ -1,4 +1,6 @@ eclipse.preferences.version=1 encoding//src/io/openems/edge/core/appmanager/dependency/translation_de.properties=UTF-8 encoding//src/io/openems/edge/core/appmanager/translation_de.properties=UTF-8 +encoding//src/io/openems/edge/core/appmanager/translation_en.properties=UTF-8 +encoding//src/io/openems/edge/core/appmanager/validator/translation_de.properties=UTF-8 encoding/=UTF-8 diff --git a/io.openems.edge.core/bnd.bnd b/io.openems.edge.core/bnd.bnd index 58ebb64e861..c5001d1d1ae 100644 --- a/io.openems.edge.core/bnd.bnd +++ b/io.openems.edge.core/bnd.bnd @@ -5,6 +5,7 @@ Bundle-Version: 1.0.0.${tstamp} -buildpath: \ ${buildpath},\ + com.fazecast.jSerialComm,\ io.openems.common,\ io.openems.edge.common,\ io.openems.edge.controller.api,\ @@ -24,4 +25,4 @@ Bundle-Version: 1.0.0.${tstamp} -testpath: \ ${testpath},\ io.openems.wrapper.fastexcel,\ - io.openems.wrapper.opczip + io.openems.wrapper.opczip,\ \ No newline at end of file diff --git a/io.openems.edge.core/src/io/openems/edge/app/api/ModbusApiProps.java b/io.openems.edge.core/src/io/openems/edge/app/api/ModbusApiProps.java new file mode 100644 index 00000000000..a75928ed63a --- /dev/null +++ b/io.openems.edge.core/src/io/openems/edge/app/api/ModbusApiProps.java @@ -0,0 +1,188 @@ +package io.openems.edge.app.api; + +import static io.openems.edge.app.common.props.CommonProps.defaultDef; +import static io.openems.edge.core.appmanager.formly.enums.InputType.NUMBER; + +import java.util.ArrayList; +import java.util.List; + +import com.fazecast.jSerialComm.SerialPort; +import com.google.gson.JsonNull; +import com.google.gson.JsonPrimitive; + +import io.openems.common.session.Role; +import io.openems.common.utils.JsonUtils; +import io.openems.edge.app.common.props.ComponentProps; +import io.openems.edge.common.modbusslave.ModbusSlave; +import io.openems.edge.core.appmanager.AppDef; +import io.openems.edge.core.appmanager.ComponentManagerSupplier; +import io.openems.edge.core.appmanager.ComponentUtilSupplier; +import io.openems.edge.core.appmanager.Nameable; +import io.openems.edge.core.appmanager.OpenemsApp; +import io.openems.edge.core.appmanager.TranslationUtil; +import io.openems.edge.core.appmanager.Type.Parameter.BundleProvider; +import io.openems.edge.core.appmanager.formly.Exp; +import io.openems.edge.core.appmanager.formly.JsonFormlyUtil; +import io.openems.edge.core.appmanager.formly.builder.ReorderArrayBuilder.SelectOptionExpressions; + +public final class ModbusApiProps { + + /** + * Creates a {@link AppDef} to select {@link ModbusSlave} Components for a + * ModbusApi. + * + * @param the type of the {@link OpenemsApp} + * @return the {@link AppDef} + */ + public static AppDef pickModbusIds() { + return AppDef.copyOfGeneric(ComponentProps.pickOrderedArrayIds(ModbusSlave.class, component -> { + if ("_meta".equals(component.id())) { + return false; + } + return true; + }, (app, property, l, parameter, component) -> { + if ("_sum".equals(component.id())) { + final var lockedExpression = Exp.currentModelValue(property).asArray() // + .elementAt(0).equal(Exp.staticValue(component.id())); + return new SelectOptionExpressions(lockedExpression); + } + return null; + }, List.of((app, property, language, parameter) -> { + return JsonFormlyUtil.buildText() // + .setText(TranslationUtil.getTranslation(parameter.bundle(), "App.Api.Modbus.changeComponentHint")); + })), def -> def // + .setTranslatedLabel("component.id.plural") // + ); + } + + /** + * Creates a {@link AppDef} to select {@link ModbusSlave} Components for a + * ModbusApi. + * + * @param the type of the {@link OpenemsApp} + * @return the {@link AppDef} + */ + public static AppDef apiTimeout() { + return AppDef.copyOfGeneric(defaultDef(), def -> def // + .setTranslatedLabel("App.Api.apiTimeout.label") // + .setTranslatedDescription("App.Api.apiTimeout.description") // + .setDefaultValue(60) // + .setField(JsonFormlyUtil::buildInputFromNameable, (app, property, l, parameter, field) -> { + field.setInputType(NUMBER) // + .setMin(0); + })); // + } + + /** + * Creates a {@link AppDef} to select Port Name for ModbusRTU Api. + * + * @param the type of the {@link OpenemsApp} + * @return the {@link AppDef} + */ + public static AppDef portName() { + return AppDef.copyOfGeneric(defaultDef(), def -> def // + .setTranslatedLabel("App.Api.ModbusRtu.portName.label") // + .setTranslatedDescription("App.Api.ModbusRtu.portName.description") // + .setDefaultValue((app, property, l, parameter) -> { + SerialPort[] ports = SerialPort.getCommPorts(); + if (ports.length > 0) { + return new JsonPrimitive(ports[0].getSystemPortName()); + } + return JsonNull.INSTANCE; + }).setField(JsonFormlyUtil::buildSelectFromNameable, (app, property, l, parameter, field) -> { + SerialPort[] ports = SerialPort.getCommPorts(); + var portNames = new ArrayList(); + for (var port : ports) { + portNames.add(port.getSystemPortName()); + } + field.setOptions(portNames); + })); // + } + + /** + * Creates a {@link AppDef} to select baudrate for ModbusRTU Api. + * + * @param the type of the {@link OpenemsApp} + * @return the {@link AppDef} + */ + public static AppDef baudrate() { + return AppDef.copyOfGeneric(defaultDef(), def -> def // + .setTranslatedLabel("App.Api.ModbusRtu.baudrate.label") // + .setTranslatedDescription("App.Api.ModbusRtu.baudrate.description") // + .setDefaultValue(9600) // + .setField(JsonFormlyUtil::buildInputFromNameable, (app, property, l, parameter, field) -> { + field.setInputType(NUMBER) // + .setMin(0); + })); // + } + + /** + * Creates a {@link AppDef} to select Databits for ModbusRTU Api. + * + * @param the type of the {@link OpenemsApp} + * @return the {@link AppDef} + */ + public static AppDef databits() { + return AppDef.copyOfGeneric(defaultDef(), def -> def // + .setTranslatedLabel("App.Api.ModbusRtu.databits.label") // + .setTranslatedDescription("App.Api.ModbusRtu.databits.description") // + .setDefaultValue(8)); + } + + /** + * Creates a {@link AppDef} to select Stopbits for ModbusRTU Api. + * + * @param the type of the {@link OpenemsApp} + * @return the {@link AppDef} + */ + public static AppDef stopbits() { + return AppDef.copyOfGeneric(defaultDef(), def -> def // + .setTranslatedLabel("App.Api.ModbusRtu.stopbits.label") // + .setTranslatedDescription("App.Api.ModbusRtu.stopbits.description") // + .setDefaultValue("ONE") // + .setField(JsonFormlyUtil::buildSelectFromNameable, (app, prop, l, params, field) -> { + field.setOptions(List.of("ONE", "ONE_POINT_FIVE", "TWO")); + })); + } + + /** + * Creates a {@link AppDef} to select Parity for ModbusRTU Api. + * + * @param the type of the {@link OpenemsApp} + * @return the {@link AppDef} + */ + public static AppDef parity() { + return AppDef.copyOfGeneric(defaultDef(), def -> def // + .setTranslatedLabel("App.Api.ModbusRtu.parity.label") // + .setTranslatedDescription("App.Api.ModbusRtu.parity.description") // + .setDefaultValue("NONE") // + .setField(JsonFormlyUtil::buildSelectFromNameable, (app, prop, l, params, field) -> { + field.setOptions(List.of("NONE", "ODD", "EVEN", "MARK", "SPACE")); + })); + } + + /** + * Creates a {@link AppDef} to select Component Ids for ModbusApi. + * + * @param the type of the {@link OpenemsApp} + * @param componentName the component name + * @return the {@link AppDef} + */ + public static AppDef componentIds( + Nameable componentName) { + return AppDef.copyOfGeneric(ModbusApiProps.pickModbusIds(), def -> def // + .setDefaultValue((app, property, l, parameter) -> { + final var jsonArrayBuilder = JsonUtils.buildJsonArray() // + .add("_sum"); + + return jsonArrayBuilder.build(); + }) // + .bidirectional(componentName, "component.ids", ComponentManagerSupplier::getComponentManager) // + .appendIsAllowedToSee(AppDef.ofLeastRole(Role.ADMIN))); // + + } + + private ModbusApiProps() { + } + +} diff --git a/io.openems.edge.core/src/io/openems/edge/app/api/ModbusRtuApiReadOnly.java b/io.openems.edge.core/src/io/openems/edge/app/api/ModbusRtuApiReadOnly.java new file mode 100644 index 00000000000..35a002711ad --- /dev/null +++ b/io.openems.edge.core/src/io/openems/edge/app/api/ModbusRtuApiReadOnly.java @@ -0,0 +1,191 @@ +package io.openems.edge.app.api; + +import static io.openems.edge.app.common.props.CommonProps.alias; + +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.oem.OpenemsEdgeOem; +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.api.ModbusRtuApiReadOnly.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.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.BundleParameter; +import io.openems.edge.core.appmanager.dependency.Tasks; +import io.openems.edge.core.appmanager.dependency.aggregatetask.SchedulerByCentralOrderConfiguration.SchedulerComponent; + +/** + * Describes a App for ReadOnly Modbus/RTU Api. + * + *

    +  {
    +    "appId":"App.Api.ModbusRtu.ReadOnly",
    +    "alias":"Modbus/RTU-Api Read-Only",
    +    "instanceId": UUID,
    +    "image": base64,
    +    "properties":{
    +    	"ACTIVE": true,
    +    	"CONTROLLER_ID": "ctrlApiModbusRtu0"
    +    },
    +    "appDescriptor": {
    +    	"websiteUrl": {@link AppDescriptor#getWebsiteUrl()}
    +    }
    +  }
    + * 
    + */ +@Component(name = "App.Api.ModbusRtu.ReadOnly") +public class ModbusRtuApiReadOnly extends AbstractOpenemsAppWithProps + implements OpenemsApp { + + public static enum Property implements Type, Nameable { + // Component-IDs + CONTROLLER_ID(AppDef.componentId("ctrlApiModbusRtu0")), // + // Properties + ALIAS(alias()), // + API_TIMEOUT(ModbusApiProps.apiTimeout() // + .setRequired(true)), // + COMPONENT_IDS(ModbusApiProps.componentIds(CONTROLLER_ID) // + .setRequired(true)), // + PORT_NAME(ModbusApiProps.portName() // + .setRequired(true)), // + BAUDRATE(ModbusApiProps.baudrate() // + .setRequired(true)), // + DATABITS(ModbusApiProps.databits() // + .setRequired(true)), + STOPBITS(ModbusApiProps.stopbits() // + .setRequired(true)), // + PARITY(ModbusApiProps.parity() // + .setRequired(true)); // + + 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); + } + } + + @Activate + public ModbusRtuApiReadOnly(@Reference ComponentManager componentManager, ComponentContext context, + @Reference ConfigurationAdmin cm, @Reference ComponentUtil componentUtil) { + super(componentManager, context, cm, componentUtil); + } + + @Override + public AppDescriptor getAppDescriptor(OpenemsEdgeOem oem) { + return AppDescriptor.create() // + .setWebsiteUrl(oem.getAppWebsiteUrl(this.getAppId())) // + .build(); + } + + @Override + public OpenemsAppCategory[] getCategories() { + return new OpenemsAppCategory[] { OpenemsAppCategory.API }; + } + + @Override + public OpenemsAppCardinality getCardinality() { + return OpenemsAppCardinality.SINGLE; + } + + @Override + protected ThrowingTriFunction, Language, AppConfiguration, OpenemsNamedException> appPropertyConfigurationFactory() { + return (t, p, l) -> { + final var portName = this.getString(p, Property.PORT_NAME); + final var alias = this.getString(p, Property.ALIAS); + final var controllerId = this.getId(t, p, Property.CONTROLLER_ID); + final var apiTimeout = this.getInt(p, Property.API_TIMEOUT); + final var controllerIds = this.getJsonArray(p, Property.COMPONENT_IDS); + final var baudrate = this.getInt(p, Property.BAUDRATE); + final var databits = this.getInt(p, Property.DATABITS); + final var stopbits = this.getString(p, Property.STOPBITS); + final var parity = this.getString(p, Property.PARITY); + + // remove self if selected + for (var i = 0; i < controllerIds.size(); i++) { + if (controllerIds.get(i).getAsString().equals(controllerId)) { + controllerIds.remove(i); + break; + } + } + + final var components = Lists.newArrayList(// + new EdgeConfig.Component(controllerId, alias, "Controller.Api.ModbusRtu.ReadOnly", + JsonUtils.buildJsonObject() // + .addProperty("apiTimeout", apiTimeout) // + .add("component.ids", controllerIds) // + .addProperty("portName", portName) // + .addProperty("baudRate", baudrate) // + .addProperty("databits", databits) // + .addProperty("stopbits", stopbits) // + .addProperty("parity", parity) // + .build()) // + ); + + return AppConfiguration.create() // + .addTask(Tasks.component(components)) // + .addTask(Tasks.schedulerByCentralOrder(// + new SchedulerComponent(controllerId, "Controller.Api.ModbusRtu.ReadOnly", this.getAppId()))) // + .build(); + }; + } + + @Override + protected ModbusRtuApiReadOnly getApp() { + return this; + } + + @Override + protected Property[] propertyValues() { + return Property.values(); + } + + @Override + public OpenemsAppPermissions getAppPermissions() { + return OpenemsAppPermissions.create()// + .setCanDelete(Role.ADMIN)// + .setCanSee(Role.ADMIN)// + .build(); + } + +} \ No newline at end of file diff --git a/io.openems.edge.core/src/io/openems/edge/app/api/ModbusRtuApiReadWrite.java b/io.openems.edge.core/src/io/openems/edge/app/api/ModbusRtuApiReadWrite.java new file mode 100644 index 00000000000..12e4fa9f6b2 --- /dev/null +++ b/io.openems.edge.core/src/io/openems/edge/app/api/ModbusRtuApiReadWrite.java @@ -0,0 +1,197 @@ +package io.openems.edge.app.api; + +import static io.openems.edge.app.common.props.CommonProps.alias; + +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.oem.OpenemsEdgeOem; +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.api.ModbusRtuApiReadWrite.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.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.BundleParameter; +import io.openems.edge.core.appmanager.dependency.Tasks; +import io.openems.edge.core.appmanager.dependency.aggregatetask.SchedulerByCentralOrderConfiguration.SchedulerComponent; + +/** + * Describes a App for ReadWrite Modbus/Rtu Api. + * + *
    +  {
    +    "appId":"App.Api.ModbusRtu.ReadWrite",
    +    "alias":"Modbus/Rtu-Api Read-Write",
    +    "instanceId": UUID,
    +    "image": base64,
    +    "properties":{
    +    	"CONTROLLER_ID": "ctrlApiModbusRtu0",
    +    	"API_TIMEOUT": 60,
    +    	"COMPONENT_IDS": ["_sum", ...]
    +    },
    +    "dependencies": [
    +    	{
    +        	"key": "READ_ONLY",
    +        	"instanceId": UUID
    +    	}
    +    ],
    +    "appDescriptor": {
    +    	"websiteUrl": {@link AppDescriptor#getWebsiteUrl()}
    +    }
    +  }
    + * 
    + */ +@Component(name = "App.Api.ModbusRtu.ReadWrite") +public class ModbusRtuApiReadWrite extends AbstractOpenemsAppWithProps + implements OpenemsApp { + + public static enum Property implements Type { + // Component-IDs + CONTROLLER_ID(AppDef.componentId("ctrlApiModbusRtu0")), // + // Properties + ALIAS(alias()), // + API_TIMEOUT(ModbusApiProps.apiTimeout() // + .setRequired(true)), // + COMPONENT_IDS(ModbusApiProps.componentIds(CONTROLLER_ID) // + .setRequired(true)), // + PORT_NAME(ModbusApiProps.portName() // + .setRequired(true)), // + BAUDRATE(ModbusApiProps.baudrate() // + .setRequired(true)), // + DATABITS(ModbusApiProps.databits() // + .setRequired(true)), + STOPBITS(ModbusApiProps.stopbits() // + .setRequired(true)), // + PARITY(ModbusApiProps.parity() // + .setRequired(true)); // + + 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); + } + } + + @Activate + public ModbusRtuApiReadWrite(@Reference ComponentManager componentManager, ComponentContext context, + @Reference ConfigurationAdmin cm, @Reference ComponentUtil componentUtil) { + super(componentManager, context, cm, componentUtil); + } + + @Override + public AppDescriptor getAppDescriptor(OpenemsEdgeOem oem) { + return AppDescriptor.create() // + .setWebsiteUrl(oem.getAppWebsiteUrl(this.getAppId())) // + .build(); + } + + @Override + public OpenemsAppCategory[] getCategories() { + return new OpenemsAppCategory[] { OpenemsAppCategory.API }; + } + + @Override + public OpenemsAppCardinality getCardinality() { + return OpenemsAppCardinality.SINGLE; + } + + @Override + protected ThrowingTriFunction, Language, AppConfiguration, OpenemsNamedException> appPropertyConfigurationFactory() { + return (t, p, l) -> { + final var portName = this.getString(p, Property.PORT_NAME); + final var controllerId = this.getId(t, p, Property.CONTROLLER_ID); + final var apiTimeout = this.getInt(p, Property.API_TIMEOUT); + final var controllerIds = this.getJsonArray(p, Property.COMPONENT_IDS); + final var baudrate = this.getInt(p, Property.BAUDRATE); + final var databits = this.getInt(p, Property.DATABITS); + final var stopbits = this.getString(p, Property.STOPBITS); + final var parity = this.getString(p, Property.PARITY); + + // remove self if selected + for (var i = 0; i < controllerIds.size(); i++) { + if (controllerIds.get(i).getAsString().equals(controllerId)) { + controllerIds.remove(i); + break; + } + } + + final var components = Lists.newArrayList(// + new EdgeConfig.Component(controllerId, this.getName(l), "Controller.Api.ModbusRtu.ReadWrite", + JsonUtils.buildJsonObject() // + .addProperty("apiTimeout", apiTimeout) // + .add("component.ids", controllerIds) // + .addProperty("portName", portName) // + .addProperty("baudRate", baudrate) // + .addProperty("databits", databits) // + .addProperty("stopbits", stopbits) // + .addProperty("parity", parity) // + .build()) // + ); + + return AppConfiguration.create() // + .addTask(Tasks.component(components)) // + .addTask(Tasks.schedulerByCentralOrder(// + new SchedulerComponent(controllerId, "Controller.Api.ModbusRtu.ReadWrite", + this.getAppId()))) // + .build(); + }; + } + + @Override + protected ModbusRtuApiReadWrite getApp() { + return this; + } + + @Override + protected Property[] propertyValues() { + return Property.values(); + } + + @Override + public OpenemsAppPermissions getAppPermissions() { + return OpenemsAppPermissions.create()// + .setCanDelete(Role.ADMIN)// + .setCanSee(Role.ADMIN)// + .build(); + } + +} diff --git a/io.openems.edge.core/src/io/openems/edge/app/api/ModbusTcpApiProps.java b/io.openems.edge.core/src/io/openems/edge/app/api/ModbusTcpApiProps.java deleted file mode 100644 index e4266469c4e..00000000000 --- a/io.openems.edge.core/src/io/openems/edge/app/api/ModbusTcpApiProps.java +++ /dev/null @@ -1,51 +0,0 @@ -package io.openems.edge.app.api; - -import java.util.List; - -import io.openems.edge.app.common.props.ComponentProps; -import io.openems.edge.common.modbusslave.ModbusSlave; -import io.openems.edge.core.appmanager.AppDef; -import io.openems.edge.core.appmanager.ComponentUtilSupplier; -import io.openems.edge.core.appmanager.Nameable; -import io.openems.edge.core.appmanager.OpenemsApp; -import io.openems.edge.core.appmanager.TranslationUtil; -import io.openems.edge.core.appmanager.Type.Parameter.BundleProvider; -import io.openems.edge.core.appmanager.formly.Exp; -import io.openems.edge.core.appmanager.formly.JsonFormlyUtil; -import io.openems.edge.core.appmanager.formly.builder.ReorderArrayBuilder.SelectOptionExpressions; - -public final class ModbusTcpApiProps { - - /** - * Creates a {@link AppDef} to select {@link ModbusSlave} Components for a - * ModbusTcpApi. - * - * @param the type of the {@link OpenemsApp} - * @return the {@link AppDef} - */ - public static AppDef pickModbusIds() { - return AppDef.copyOfGeneric(ComponentProps.pickOrderedArrayIds(ModbusSlave.class, component -> { - if ("_meta".equals(component.id())) { - return false; - } - return true; - }, (app, property, l, parameter, component) -> { - if ("_sum".equals(component.id())) { - final var lockedExpression = Exp.currentModelValue(property).asArray() // - .elementAt(0).equal(Exp.staticValue(component.id())); - return new SelectOptionExpressions(lockedExpression); - } - return null; - }, List.of((app, property, language, parameter) -> { - return JsonFormlyUtil.buildText() // - .setText(TranslationUtil.getTranslation(parameter.bundle(), - "App.Api.ModbusTcp.changeComponentHint")); - })), def -> def // - .setTranslatedLabel("component.id.plural") // - ); - } - - private ModbusTcpApiProps() { - } - -} 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 4298f4ebf23..99fbcba7748 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 @@ -19,7 +19,6 @@ import io.openems.common.function.ThrowingTriFunction; import io.openems.common.oem.OpenemsEdgeOem; 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.api.ModbusTcpApiReadOnly.Property; @@ -29,7 +28,6 @@ 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.ComponentManagerSupplier; import io.openems.edge.core.appmanager.ComponentUtil; import io.openems.edge.core.appmanager.ConfigurationTarget; import io.openems.edge.core.appmanager.Nameable; @@ -74,14 +72,8 @@ public static enum Property implements Type def // - .setDefaultValue((app, property, l, parameter) -> { - return JsonUtils.buildJsonArray() // - .add("_sum") // - .build(); - }) // - .bidirectional(CONTROLLER_ID, "component.ids", ComponentManagerSupplier::getComponentManager) // - .appendIsAllowedToSee(AppDef.ofLeastRole(Role.ADMIN)))), // + COMPONENT_IDS(ModbusApiProps.componentIds(CONTROLLER_ID) // + .setRequired(true)) // ; private AppDef def; 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 4aca80fbfd8..3e5fbe09221 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 @@ -1,7 +1,6 @@ package io.openems.edge.app.api; -import static io.openems.edge.app.common.props.CommonProps.defaultDef; -import static io.openems.edge.core.appmanager.formly.enums.InputType.NUMBER; +import static io.openems.edge.app.common.props.CommonProps.alias; import java.util.Map; import java.util.function.Function; @@ -18,7 +17,6 @@ import io.openems.common.function.ThrowingTriFunction; import io.openems.common.oem.OpenemsEdgeOem; 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.api.ModbusTcpApiReadWrite.Property; @@ -28,7 +26,6 @@ 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.ComponentManagerSupplier; import io.openems.edge.core.appmanager.ComponentUtil; import io.openems.edge.core.appmanager.ConfigurationTarget; import io.openems.edge.core.appmanager.OpenemsApp; @@ -39,7 +36,6 @@ import io.openems.edge.core.appmanager.dependency.DependencyDeclaration; import io.openems.edge.core.appmanager.dependency.Tasks; import io.openems.edge.core.appmanager.dependency.aggregatetask.SchedulerByCentralOrderConfiguration.SchedulerComponent; -import io.openems.edge.core.appmanager.formly.JsonFormlyUtil; /** * Describes a App for ReadWrite Modbus/TCP Api. @@ -75,30 +71,11 @@ public static enum Property implements Type def // - .setTranslatedLabel("App.Api.apiTimeout.label") // - .setTranslatedDescription("App.Api.apiTimeout.description") // - .setDefaultValue(60) // - .setRequired(true) // - .setField(JsonFormlyUtil::buildInput, (app, property, l, parameter, field) -> { - field.setInputType(NUMBER) // - .setMin(0); - }) // - )), // - COMPONENT_IDS(AppDef.copyOfGeneric(ModbusTcpApiProps.pickModbusIds(), def -> def // - .setDefaultValue((app, property, l, parameter) -> { - final var jsonArrayBuilder = JsonUtils.buildJsonArray() // - .add("_sum"); - - // add ess ids - app.getComponentUtil().getEnabledComponentsOfStartingId("ess").stream() // - .sorted((o1, o2) -> o1.id().compareTo(o2.id())) // - .forEach(ess -> jsonArrayBuilder.add(ess.id())); - - return jsonArrayBuilder.build(); - }) // - .bidirectional(CONTROLLER_ID, "component.ids", ComponentManagerSupplier::getComponentManager) // - .appendIsAllowedToSee(AppDef.ofLeastRole(Role.ADMIN)))), // + ALIAS(alias()), // + API_TIMEOUT(ModbusApiProps.apiTimeout() // + .setRequired(true)), // + COMPONENT_IDS(ModbusApiProps.componentIds(CONTROLLER_ID) // + .setRequired(true)) // ; private final AppDef def; 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 index ae77b67d60c..8c3d153163c 100644 --- 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 @@ -1,13 +1,15 @@ package io.openems.edge.app.common.props; import static io.openems.edge.app.common.props.CommonProps.defaultDef; +import static io.openems.edge.core.appmanager.TranslationUtil.getTranslation; import static io.openems.edge.core.appmanager.formly.enums.InputType.NUMBER; import static io.openems.edge.core.appmanager.formly.enums.Validation.IP; +import static io.openems.edge.core.host.NetworkConfiguration.PATTERN_INET4ADDRESS; +import static java.util.stream.Collectors.joining; import java.util.ArrayList; import java.util.Arrays; import java.util.Optional; -import java.util.stream.Collectors; import com.google.gson.JsonPrimitive; @@ -21,7 +23,6 @@ import io.openems.edge.core.appmanager.HostSupplier; import io.openems.edge.core.appmanager.Nameable; import io.openems.edge.core.appmanager.OpenemsApp; -import io.openems.edge.core.appmanager.TranslationUtil; import io.openems.edge.core.appmanager.Type.Parameter.BundleProvider; import io.openems.edge.core.appmanager.formly.Case; import io.openems.edge.core.appmanager.formly.DefaultValueOptions; @@ -29,7 +30,6 @@ import io.openems.edge.core.appmanager.formly.JsonFormlyUtil; import io.openems.edge.core.appmanager.formly.expression.StringExpression; import io.openems.edge.core.appmanager.formly.expression.Variable; -import io.openems.edge.core.host.NetworkConfiguration; public final class CommunicationProps { @@ -78,13 +78,16 @@ AppDef excludingIp() { def -> def.setField(JsonFormlyUtil::buildInputFromNameable, (app, prop, l, param, f) -> { try { var ips = app.getHost().getSystemIPs(); - final var exclusionPattern = ips.stream().map(ip -> ip.getHostAddress())// - .map(ip -> ip.replace(".", "\\.")) // - .collect(Collectors.joining("|")); + if (ips.isEmpty()) { + f.setValidation(IP); + } else { + final var exclusionPattern = ips.stream().map(ip -> ip.getHostAddress())// + .map(ip -> ip.replace(".", "\\.")) // + .collect(joining("|")); - final var regex = "^(?!.*(?:" + exclusionPattern + ")$)" - + NetworkConfiguration.PATTERN_INET4ADDRESS; - f.setValidation(regex, TranslationUtil.getTranslation(param.bundle(), "communication.excludingIp")); + f.setValidation("^(?!.*(?:" + exclusionPattern + ")$)" + PATTERN_INET4ADDRESS, + getTranslation(param.bundle(), "communication.excludingIp")); + } } catch (OpenemsNamedException e) { f.setValidation(IP); } @@ -213,12 +216,12 @@ AppDef modbusGroup(// .notEqual(Exp.currentModelValue(modbusId)))); final var message = Exp.ifElse(filteredArray.length().equal(Exp.staticValue(1)), // - StringExpression.of(TranslationUtil.getTranslation(parameter.bundle(), + StringExpression.of(getTranslation(parameter.bundle(), "communication.modbusUnitId.alreadTaken.singular", filteredArray.join(", ").insideTranslation(), componentId)), // - StringExpression.of(TranslationUtil.getTranslation(parameter.bundle(), - "communication.modbusUnitId.alreadTaken.plural", - filteredArray.join(", ").insideTranslation(), componentId))); + StringExpression.of( + getTranslation(parameter.bundle(), "communication.modbusUnitId.alreadTaken.plural", + filteredArray.join(", ").insideTranslation(), componentId))); field.setCustomValidation(componentId, expression, message, modbusUnitId); diff --git a/io.openems.edge.core/src/io/openems/edge/app/core/AppMeta.java b/io.openems.edge.core/src/io/openems/edge/app/core/AppMeta.java new file mode 100644 index 00000000000..0031aef77b8 --- /dev/null +++ b/io.openems.edge.core/src/io/openems/edge/app/core/AppMeta.java @@ -0,0 +1,178 @@ +package io.openems.edge.app.core; + +import static io.openems.edge.app.common.props.CommonProps.alias; +import static io.openems.edge.app.common.props.CommonProps.defaultDef; + +import java.util.ArrayList; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Stream; + +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 io.openems.common.exceptions.OpenemsError.OpenemsNamedException; +import io.openems.common.function.ThrowingTriFunction; +import io.openems.common.oem.OpenemsEdgeOem; +import io.openems.common.session.Language; +import io.openems.common.session.Role; +import io.openems.common.types.CurrencyConfig; +import io.openems.common.types.EdgeConfig; +import io.openems.common.utils.JsonUtils; +import io.openems.edge.app.core.AppMeta.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.ComponentManagerSupplier; +import io.openems.edge.core.appmanager.ComponentUtil; +import io.openems.edge.core.appmanager.ConfigurationTarget; +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.OpenemsAppStatus; +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; +import io.openems.edge.core.appmanager.dependency.Tasks; +import io.openems.edge.core.appmanager.flag.Flag; +import io.openems.edge.core.appmanager.flag.Flags; +import io.openems.edge.core.appmanager.formly.JsonFormlyUtil; +import io.openems.edge.core.appmanager.formly.enums.DisplayType; + +@Component(name = "App.Core.Meta") +public class AppMeta extends AbstractOpenemsAppWithProps + implements OpenemsApp { + + public enum Property implements Type { + ALIAS(AppDef.copyOfGeneric(alias())), // + + CURRENCY(AppDef.copyOfGeneric(defaultDef(), def -> def// + .setTranslatedLabelWithAppPrefix(".currency.label") + .setField(JsonFormlyUtil::buildSelectFromNameable, (app, property, l, parameter, field) -> { + field.setOptions(Stream.of(CurrencyConfig.values()).map(Enum::name).toList()); + }) // + .bidirectional("_meta", "currency", ComponentManagerSupplier::getComponentManager))), // + IS_ESS_CHARGE_FROM_GRID_ALLOWED(AppDef.copyOfGeneric(defaultDef(), def -> def// + .setTranslatedLabelWithAppPrefix(".gridCharge.label") // + .setField(JsonFormlyUtil::buildFieldGroupFromNameable, (app, property, l, parameter, field) -> { + var bundle = parameter.bundle(); + field.setPopupInput(property, DisplayType.BOOLEAN); + field.setFieldGroup(JsonUtils.buildJsonArray() // + .add(JsonFormlyUtil.buildText() // + .setText(TranslationUtil.getTranslation(bundle, "App.Core.Meta.gridCharge.description")) + .build()) + .add(JsonFormlyUtil.buildCheckboxFromNameable(property) // + .setLabel(TranslationUtil.getTranslation(bundle, "App.Core.Meta.gridCharge.label")) // + .build()) + .build()); + }) // + .bidirectional("_meta", "isEssChargeFromGridAllowed", ComponentManagerSupplier::getComponentManager))), // + ; + + private 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); + } + } + + @Activate + public AppMeta(// + @Reference final ComponentManager componentManager, // + final ComponentContext componentContext, // + @Reference final ConfigurationAdmin cm, // + @Reference final ComponentUtil componentUtil // + ) { + super(componentManager, componentContext, cm, componentUtil); + } + + @Override + protected ThrowingTriFunction, Language, AppConfiguration, OpenemsNamedException> appPropertyConfigurationFactory() { + return (t, p, l) -> { + + final var currency = this.getEnum(p, CurrencyConfig.class, Property.CURRENCY); + final var isEssChargeFromGridAllowed = this.getBoolean(p, Property.IS_ESS_CHARGE_FROM_GRID_ALLOWED); + + final var components = new ArrayList(); + + components.add(new EdgeConfig.Component("_meta", "", "Core.Meta", // + JsonUtils.buildJsonObject() // + .addProperty("currency", currency) // + .addProperty("isEssChargeFromGridAllowed", isEssChargeFromGridAllowed) // + .build())); + + return AppConfiguration.create() // + .addTask(Tasks.component(components)) // + .build(); + }; + } + + @Override + public AppDescriptor getAppDescriptor(OpenemsEdgeOem oem) { + return AppDescriptor.create() // + .build(); + } + + @Override + public OpenemsAppCardinality getCardinality() { + return OpenemsAppCardinality.SINGLE; + } + + @Override + public OpenemsAppCategory[] getCategories() { + return new OpenemsAppCategory[] { OpenemsAppCategory.CORE }; + } + + @Override + protected AppMeta getApp() { + return this; + } + + @Override + protected Property[] propertyValues() { + return Property.values(); + } + + @Override + public OpenemsAppPermissions getAppPermissions() { + return OpenemsAppPermissions.create() // + .setCanDelete(Role.ADMIN) // TODO theoretically not even admin + .build(); + } + + @Override + public Flag[] flags() { + final var flags = new ArrayList<>(); + if (this.getStatus() == OpenemsAppStatus.BETA) { + flags.add(Flags.SHOW_AFTER_KEY_REDEEM); + } + flags.add(Flags.ALWAYS_INSTALLED); + return flags.toArray(Flag[]::new); + } + +} diff --git a/io.openems.edge.core/src/io/openems/edge/app/evcs/AlpitronicEvcs.java b/io.openems.edge.core/src/io/openems/edge/app/evcs/AlpitronicEvcs.java index 6148f1d85ec..94b0788f57a 100644 --- a/io.openems.edge.core/src/io/openems/edge/app/evcs/AlpitronicEvcs.java +++ b/io.openems.edge.core/src/io/openems/edge/app/evcs/AlpitronicEvcs.java @@ -83,8 +83,9 @@ *
    */ @Component(name = "App.Evcs.Alpitronic") -public class AlpitronicEvcs extends - AbstractOpenemsAppWithProps implements OpenemsApp, HostSupplier { +public class AlpitronicEvcs + extends AbstractOpenemsAppWithProps + implements OpenemsApp, HostSupplier { public static interface ParentProperty extends Type { diff --git a/io.openems.edge.core/src/io/openems/edge/app/evcs/readonly/MennekesEvcsReadOnly.java b/io.openems.edge.core/src/io/openems/edge/app/evcs/readonly/MennekesEvcsReadOnly.java index 181ef2565c7..ad111a4782a 100644 --- a/io.openems.edge.core/src/io/openems/edge/app/evcs/readonly/MennekesEvcsReadOnly.java +++ b/io.openems.edge.core/src/io/openems/edge/app/evcs/readonly/MennekesEvcsReadOnly.java @@ -19,7 +19,6 @@ import io.openems.common.function.ThrowingTriFunction; import io.openems.common.oem.OpenemsEdgeOem; 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.common.props.CommunicationProps; @@ -36,7 +35,6 @@ 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; @@ -167,11 +165,4 @@ protected Property[] propertyValues() { return Property.values(); } - @Override - public OpenemsAppPermissions getAppPermissions() { - return OpenemsAppPermissions.create()// - .setCanDelete(Role.ADMIN)// - .setCanSee(Role.ADMIN)// - .build(); - } } 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 aa5d3f2fe2f..6393780a8f1 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 @@ -11,11 +11,13 @@ import java.util.TreeMap; import java.util.function.Function; import java.util.stream.Collectors; +import java.util.stream.IntStream; import org.osgi.service.cm.ConfigurationAdmin; import org.osgi.service.component.ComponentConstants; import org.osgi.service.component.ComponentContext; +import com.google.common.base.CaseFormat; import com.google.common.collect.ImmutableMap; import com.google.gson.JsonElement; import com.google.gson.JsonObject; @@ -129,6 +131,60 @@ public AppConfiguration getAppConfiguration(ConfigurationTarget target, JsonObje return configuration; } + @Override + public String mapPropName(String prop, String componentId, OpenemsAppInstance instance) { + var enumMap = this.convertToMap(new ArrayList<>(), instance.properties); + var mappedPropName = this.mapPropNameWithMap(enumMap, prop, componentId); + return this.getPropertyByName(mappedPropName) == null ? null : mappedPropName; + } + + /** + * Convert JsonObject with Properties to Map. + * + * @param componentId id of the component + * @param prop the propertyname + * @param map map of the instance + * @return a typed {@link Map} of Properties + */ + private String mapPropNameWithMap(Map map, String prop, String componentId) { + return this.transformCase(prop); + } + + private String transformCase(String prop) { + var parsedPropName = prop; + if (prop.contains(".")) { + parsedPropName = pointedCaseToUpperUnderscore(prop); + } else { + parsedPropName = lowerCamelToUpperUnderscore(prop); + } + return parsedPropName; + } + + private static String pointedCaseToUpperUnderscore(String str) { + return str.replace('.', '_').toUpperCase(); + } + + private static boolean isLowerCamelCase(String str) { + if (str == null || str.length() == 0) { + return false; + } + boolean isFirstCharUpperCaseLetter = Character.isUpperCase(str.charAt(0)) || !Character.isLetter(str.charAt(0)); + if (!isFirstCharUpperCaseLetter && str.length() > 1) { + return IntStream.range(1, str.length() - 1) + .noneMatch(i -> !Character.isLetter(str.charAt(i)) + || Character.isUpperCase(str.charAt(i)) && Character.isUpperCase(str.charAt(i + 1))) + && Character.isLetter(str.charAt(str.length() - 1)); + } + return !isFirstCharUpperCaseLetter; + } + + private static String lowerCamelToUpperUnderscore(String str) { + if (isLowerCamelCase(str)) { + return CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE, str); + } + return str; + } + @Override public String getAppId() { return this.componentContext.getProperties().get(ComponentConstants.COMPONENT_NAME).toString(); @@ -371,6 +427,11 @@ protected static final Component getComponentWithFactoryId(List compo return components.stream().filter(t -> t.getFactoryId().equals(factoryId)).findFirst().orElse(null); } + @Override + public boolean assertCanEdit(String prop, User user) { + return true; + } + @Override public ComponentManager getComponentManager() { return this.componentManager; 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 index fa7043d8378..d75661808c9 100644 --- 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 @@ -6,6 +6,7 @@ import java.util.Optional; import java.util.function.Function; import java.util.function.Supplier; +import java.util.stream.Stream; import org.osgi.service.cm.ConfigurationAdmin; import org.osgi.service.component.ComponentContext; @@ -128,6 +129,16 @@ protected > E getEnum(// return this.getEnum(map, enumType, property, PROPERTY::def); } + @Override + public final String mapPropName(String prop, String componentId, OpenemsAppInstance instance) { + return Stream.of(this.propertyValues()).map(p -> p.def().getBidirectionalPropertyName()).filter(t -> { + if (t == null) { + return false; + } + return t.equals(prop); + }).findFirst().orElseGet(() -> super.mapPropName(prop, componentId, instance)); + } + protected boolean getBoolean(// final Map map, // final PROPERTY property, // @@ -269,6 +280,15 @@ public final T get() { } + @Override + public final boolean assertCanEdit(String propName, User user) { + final var prop = Stream.of(this.propertyValues())// + .filter(property -> property.name().equals(propName))// + .findFirst().orElseThrow(() -> new RuntimeException("Property " + propName + " does not exist")); + return prop.def().getIsAllowedToEdit().test(this.getApp(), prop, user.getLanguage(), + this.singletonParameter(user.getLanguage()).get(), user); + } + protected abstract APP getApp(); @Override 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 index d27333d5d14..99cc5a0d44d 100644 --- 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 @@ -143,8 +143,8 @@ private static final OpenemsNamedException getOpenemsException(Throwable e) { } private static final OpenemsNamedException getOpenemsException(Throwable e, boolean isRootException) { - if (e instanceof OpenemsNamedException) { - return (OpenemsNamedException) e; + if (e instanceof OpenemsNamedException one) { + return one; } if (e.getCause() != null) { 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 index 777c07abda9..5064d50abbe 100644 --- 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 @@ -169,6 +169,8 @@ public static interface FieldValuesConsumer { */ private FieldValuesSupplier description; + private String propertyName; + /** * Function to get the default value of the field (can be any JsonElement => * JsonArray, JsonPrimitiv(Number, String, Boolean, Character). @@ -360,6 +362,7 @@ PARAMETERO> AppDef copyOfGeneric(// def.bidirectionalValue = otherDef.bidirectionalValue; def.isAllowedToSee = otherDef.isAllowedToSee; def.isAllowedToEdit = otherDef.isAllowedToEdit; + def.propertyName = otherDef.propertyName; return def; } @@ -380,6 +383,10 @@ public AppDef setAllowedToSave(// return this; } + public AppDef setMinRole(final Role role) { + return this.appendIsAllowedToEdit(ofLeastRole(role)); + } + public final AppDef setTranslationBundleSupplier(// final Function bundleSupplier // ) { @@ -999,11 +1006,92 @@ public AppDef bidirectional(// final Function componentManagerFunction, // final Function mapper // ) { + return this.bidirectional(t -> { + final var a = t.get(propOfComponentId.name()); + return a == null ? null : a.getAsString(); + }, property, componentManagerFunction, mapper); + } + + /** + * 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 componentId the componentId + * @param property the property + * @param componentManagerFunction the componentmanagerFunction + * @return this + */ + public AppDef bidirectional(// + final String componentId, // + final String property, // + final Function componentManagerFunction // + ) { + return this.bidirectional(componentId, property, componentManagerFunction, Function.identity()); + } + + /** + * 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 componentId the componentId + * @param property the property + * @param componentManagerFunction the componentmanagerFunction + * @param mapper mapper + * @return this + */ + public AppDef bidirectional(// + final String componentId, // + final String property, // + final Function componentManagerFunction, // + final Function mapper // + ) { + return this.bidirectional(t -> componentId, property, componentManagerFunction, mapper); + } + + /** + * 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 componentIdSupplier the componentId supplier + * @param property the property + * @param componentManagerFunction the componentmanagerFunction + * @param mapper mapper + * + * @return this + */ + public AppDef bidirectional(// + final Function componentIdSupplier, // + final String property, // + final Function componentManagerFunction, // + final Function mapper // + ) { + this.propertyName = property; this.bidirectionalValue = (app, prop, l, param, properties) -> { if (properties == null) { return null; } - final var componentId = properties.get(propOfComponentId.name()); + final var componentId = componentIdSupplier.apply(properties); if (componentId == null) { return null; } @@ -1016,12 +1104,19 @@ public AppDef bidirectional(// return JsonNull.INSTANCE; }); + final var p = componentManager.getComponentProperties(componentId); try { - final var component = componentManager.getComponent(componentId.getAsString()); - return Optional.ofNullable(component.getComponentContext().getProperties().get(property)) // + final var component = componentManager.getComponent(componentId); + + return Optional.ofNullable(p.get(property)) // .map(JsonUtils::getAsJsonElement) // .map(mapper) // - .orElseGet(defaultValueSupplier); + .orElseGet(() -> { + return Optional.ofNullable(component.getComponentContext().getProperties().get(property)) // + .map(JsonUtils::getAsJsonElement) // + .map(mapper) // + .orElseGet(defaultValueSupplier); + }); } catch (OpenemsNamedException e) { return defaultValueSupplier.get(); } @@ -1031,6 +1126,10 @@ public AppDef bidirectional(// return this.self(); } + public String getBidirectionalPropertyName() { + return this.propertyName; + } + /** * Creates a simple mapper if the input {@link JsonElement} is a number it gets * multiplied with the given multiplicator. 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 25908265a55..8d74cdc6c96 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 @@ -9,10 +9,12 @@ import java.util.Iterator; import java.util.LinkedList; import java.util.List; +import java.util.Map; import java.util.Map.Entry; import java.util.Optional; import java.util.UUID; import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; @@ -61,6 +63,7 @@ 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.flag.Flags; 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,6 +71,8 @@ import io.openems.edge.core.appmanager.jsonrpc.GetAppDescriptor; import io.openems.edge.core.appmanager.jsonrpc.GetAppInstances; import io.openems.edge.core.appmanager.jsonrpc.GetApps; +import io.openems.edge.core.appmanager.jsonrpc.GetEstimatedConfiguration; +import io.openems.edge.core.appmanager.jsonrpc.UpdateAppConfig; import io.openems.edge.core.appmanager.jsonrpc.UpdateAppInstance; import io.openems.edge.core.appmanager.validator.Validator; @@ -90,8 +95,36 @@ public class AppManagerImpl extends AbstractOpenemsComponent implements AppManag @Reference private ConfigurationAdmin cm; - @Reference(policy = ReferencePolicy.DYNAMIC) - protected volatile List availableApps; + protected volatile List availableApps = new CopyOnWriteArrayList<>(); + + /** + * Binds newly available OpenemsApp. + * + * @param app the app + */ + @Reference(policy = ReferencePolicy.DYNAMIC, // + bind = "bindApp", unbind = "unbindApp", // + cardinality = ReferenceCardinality.MULTIPLE, // + policyOption = ReferencePolicyOption.GREEDY) + public void bindApp(OpenemsApp app) { + this.availableApps.add(app); + var alwaysInstalled = app.hasFlag(Flags.ALWAYS_INSTALLED); + if (alwaysInstalled) { + this.instantiatedApps + .add(new OpenemsAppInstance(app.getAppId(), "", UUID.randomUUID(), new JsonObject(), emptyList())); + } + } + + /** + * Unbinds no longer available apps. + * + * @param app the app + */ + public void unbindApp(OpenemsApp app) { + this.availableApps.remove(app); + var installedInstances = this.instantiatedApps.stream().filter(t -> t.appId == app.getAppId()).toList(); + this.instantiatedApps.removeAll(installedInstances); + } @Reference private ComponentServiceObjects csoAppManagerAppHelper; @@ -199,19 +232,24 @@ public final List getInstantiatedApps() { * @param apps that should be formatted * @return formatted apps string */ - private static String getJsonAppsString(List apps) { - return JsonUtils - .prettyToString(apps.stream().map(OpenemsAppInstance::toJsonObject).collect(JsonUtils.toJsonArray())); + private String getJsonAppsString(List apps) { + return JsonUtils.prettyToString(apps.stream() // + .filter(t -> !this.appIdIsAlwaysInstalled(t.appId)) // + .map(OpenemsAppInstance::toJsonObject) // + .collect(JsonUtils.toJsonArray())); } /** * Parses the configured apps to a List of {@link OpenemsAppInstance}s. * - * @param apps the app configuration from Config.json as {@link JsonArray} + * @param apps the app configuration from Config.json as + * {@link JsonArray} + * @param alwaysInstalledApps list of all apps that are always installed * @return List of {@link OpenemsAppInstance}s * @throws OpenemsNamedException on parse error */ - private static List parseInstantiatedApps(JsonArray apps) throws OpenemsNamedException { + private static List parseInstantiatedApps(JsonArray apps, List alwaysInstalledApps) + throws OpenemsNamedException { var errors = new ArrayList(); var result = new ArrayList(apps.size()); for (var appElement : apps) { @@ -237,6 +275,9 @@ private static List parseInstantiatedApps(JsonArray apps) th } result.add(new OpenemsAppInstance(appId, alias, instanceId, properties, dependecies)); } + var aip = alwaysInstalledApps.stream() + .map(t -> new OpenemsAppInstance(t, "", UUID.randomUUID(), new JsonObject(), emptyList())).toList(); + result.addAll(aip); if (!errors.isEmpty()) { throw new OpenemsException(errors.stream().collect(Collectors.joining("|"))); } @@ -253,8 +294,14 @@ private void applyConfig(Config config) { if (apps == null || apps.isBlank()) { apps = "[]"; // default to empty array } - var instApps = parseInstantiatedApps(JsonUtils.parseToJsonArray(apps)); + var alwaysInstalledApps = this.instantiatedApps.stream().filter(t -> { + return this.findAppById(t.appId)// + .map(a -> a.hasFlag(Flags.ALWAYS_INSTALLED))// + .orElse(false); + }).map(t -> t.appId).toList(); + + var instApps = parseInstantiatedApps(JsonUtils.parseToJsonArray(apps), alwaysInstalledApps); // always replace old apps with the new ones var currentApps = new ArrayList<>(this.instantiatedApps); @@ -829,6 +876,113 @@ public void buildJsonApiRoutes(JsonApiBuilder builder) { emptyList())); }); }, call -> this.handleAddAppInstanceRequest(call.get(EdgeKeys.USER_KEY), call.getRequest())); + + builder.handleRequest(new GetEstimatedConfiguration(), endpoint -> { + + endpoint.applyRequestBuilder(request -> { + request.addExample("Home 30", + new GetEstimatedConfiguration.Request("App.FENECON.Home.30", "FENECON Home 30", + JsonUtils.buildJsonObject() // + .addProperty("SAFETY_COUNTRY", "GERMANY") // + .addProperty("FEED_IN_TYPE", "EXTERNAL_LIMITATION") // + .addProperty("FEED_IN_SETTING", "QU_ENABLE_CURVE") // + .addProperty("HAS_MPPT_1", "true") // + .addProperty("ALIAS_MPPT_1", "String A and String B") // + .build())); + }); + + }, call -> { + final var request = call.getRequest(); + final var user = call.get(EdgeKeys.USER_KEY); + + final var app = this.findAppByIdOrError(request.appId()); + + final var configs = this.useAppManagerAppHelper(t -> { + return t.getInstallConfiguration(user, new OpenemsAppInstance(request.appId(), request.alias(), + UUID.randomUUID(), request.properties(), null), app); + }); + + return new GetEstimatedConfiguration.Response(configs); + }); + + builder.handleRequest(new UpdateAppConfig(), endpoint -> { + endpoint.setDescription(""" + Updates a AppInstance. + """.stripIndent()); + + endpoint.setGuards(EdgeGuards.roleIsAtleast(Role.OWNER)); + + }, call -> this.handleUpdateAppConfigRequest(call.get(EdgeKeys.USER_KEY), call.getRequest())); + } + + /** + * Find unique instanceId for given componentId}. + * + * @param componentId Id of the component the app configures + * @return the instanceId of the appInstance + * @throws OpenemsNamedException on error + */ + private OpenemsAppInstance findInstanceByComponentId(String componentId) throws OpenemsNamedException { + for (var appConfig : this.appConfigs()) { + var containsComponent = appConfig.getValue().getComponents().stream() + .anyMatch(t -> t.getId().equals(componentId)); + if (containsComponent) { + return appConfig.getKey(); + } + } + + return null; + } + + /** + * Handles {@link UpdateAppConfigRequest}. + * + * @param user the User + * @param request the {@link UpdateAppConfigRequest} Request + * @return the Future JSON-RPC Response + * @throws OpenemsNamedException on error + */ + public UpdateAppConfig.Response handleUpdateAppConfigRequest(User user, UpdateAppConfig.Request request) + throws OpenemsNamedException { + + final var appInstance = this.findInstanceByComponentId(request.componentId()); + + // update Component the old fashioned way if no app exists for the component + if (appInstance == null) { + return this.updateComponentDirectly(user, request); + } + final var app = this.findAppByIdOrError(appInstance.appId); + + final var requestProperties = request.properties().entrySet().stream() // + .map(entry -> Map.entry(app.mapPropName(entry.getKey(), request.componentId(), appInstance), + entry.getValue())) + .filter(entry -> entry.getKey() != null) + .collect(JsonUtils.toJsonObject(Entry::getKey, Entry::getValue)); + + for (var entry : appInstance.properties.entrySet()) { + if (requestProperties.has(entry.getKey())) { + continue; + } + requestProperties.add(entry.getKey(), entry.getValue()); + } + + // build UpdateAppInstance Request and pass the request to the + // handleUpdateAppInstanceRequest Method + var req = new UpdateAppInstance.Request(appInstance.instanceId, appInstance.alias, requestProperties); + this.handleUpdateAppInstanceRequest(user, req); + return new UpdateAppConfig.Response(); + } + + private UpdateAppConfig.Response updateComponentDirectly(User user, UpdateAppConfig.Request from) + throws OpenemsNamedException { + final var properties = from.properties(); + final var componentUpdateProps = new ArrayList(); + for (var key : properties.keySet()) { + componentUpdateProps.add(new UpdateComponentConfigRequest.Property(key, properties.get(key))); + } + final var updateRequest = new UpdateComponentConfigRequest(from.componentId(), componentUpdateProps); + this.componentManager.handleUpdateComponentConfigRequest(user, updateRequest); + return new UpdateAppConfig.Response(); } /** @@ -844,10 +998,38 @@ public UpdateAppInstance.Response handleUpdateAppInstanceRequest(User user, Upda return this.lockModifyingApps(() -> { final var oldApp = this.findInstanceByIdOrError(request.instanceId()); final var app = this.findAppByIdOrError(oldApp.appId); - app.getAppConfiguration(ConfigurationTarget.UPDATE, request.properties(), user.getLanguage()); - final var updatedInstance = new OpenemsAppInstance(oldApp.appId, request.alias(), oldApp.instanceId, - request.properties(), oldApp.dependencies); + final var props = request.properties(); + final JsonObject restOfProps; + + if (app instanceof AbstractOpenemsAppWithProps) { + restOfProps = AbstractOpenemsApp.fillUpProperties(app, oldApp.properties); + } else { + restOfProps = oldApp.properties; + } + final var notAllowedProperties = props.keySet().stream()// + .filter(key -> { + final var canEdit = app.assertCanEdit(key, user); + return !canEdit; + }) // + .filter(key -> { + final var element = restOfProps.get(key); + if (element == null) { + return false; + } + + // TODO special handling for arrays + return (!props.get(key).getAsString().equals(restOfProps.get(key).getAsString())); + }) // + .collect(Collectors.joining(", ")); + if (notAllowedProperties.length() > 0) { + throw new OpenemsException("User is not allowed to edit " + notAllowedProperties + "!"); + } + + app.getAppConfiguration(ConfigurationTarget.UPDATE, props, user.getLanguage()); + + final var updatedInstance = new OpenemsAppInstance(oldApp.appId, request.alias(), oldApp.instanceId, props, + oldApp.dependencies); var result = this.lastUpdate = this.useAppManagerAppHelper(appHelper -> { return appHelper.updateApp(user, oldApp, updatedInstance, app); @@ -858,7 +1040,7 @@ public UpdateAppInstance.Response handleUpdateAppInstanceRequest(User user, Upda this.instantiatedApps.removeAll(result.modifiedOrCreatedApps); this.instantiatedApps.addAll(result.modifiedOrCreatedApps); - return new Pair<>(true, new UpdateAppInstance.Response( + return new Pair<>(!this.appIdIsAlwaysInstalled(app.getAppId()), new UpdateAppInstance.Response( this.createInstanceWithFilledProperties(app, result.rootInstance), result.warnings)); }, (shouldUpdate) -> { if (shouldUpdate == null || !shouldUpdate) { @@ -873,6 +1055,18 @@ public UpdateAppInstance.Response handleUpdateAppInstanceRequest(User user, Upda }); } + /** + * Checks from AppId if the app has the Flag alwaysInstalled. + * + * @param appId appId of the app + * @return if the app is always installed + */ + public boolean appIdIsAlwaysInstalled(String appId) { + return this.findAppById(appId)// + .map(t -> t.hasFlag(Flags.ALWAYS_INSTALLED))// + .orElse(false); + } + /** * updated the AppManager configuration with the given app instances. * @@ -883,7 +1077,7 @@ public UpdateAppInstance.Response handleUpdateAppInstanceRequest(User user, Upda private void updateAppManagerConfiguration(User user, List apps) throws OpenemsNamedException { this.waitingForModified = true; AppManagerImpl.sortApps(apps); - var p = new Property("apps", getJsonAppsString(apps)); + var p = new Property("apps", this.getJsonAppsString(apps)); // user can be null using internal method this.componentManager.handleUpdateComponentConfigRequest(user, new UpdateComponentConfigRequest(SINGLETON_COMPONENT_ID, Arrays.asList(p))); 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 b47cac80875..d31a2c54c60 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 @@ -1,5 +1,7 @@ package io.openems.edge.core.appmanager; +import java.util.stream.Stream; + import org.osgi.service.component.ComponentConstants; import com.google.gson.JsonObject; @@ -14,6 +16,25 @@ public interface OpenemsApp { + /** + * Tests if a user is allowed to edit a property. + * + * @param prop The property to be tested + * @param user The user permissions are to be tested for + * @return true if user is allowed to edit, false otherwise + */ + public boolean assertCanEdit(String prop, User user); + + /** + * Maps the property name of a component to the coressponding app Property. + * + * @param prop The property to be mapped + * @param componentId the componentId + * @param instance instance of the app + * @return the mapped property name + */ + public String mapPropName(String prop, String componentId, OpenemsAppInstance instance); + /** * Gets the {@link AppAssistant} for this {@link OpenemsApp}. * @@ -123,6 +144,15 @@ public default Flag[] flags() { return new Flag[] {}; } + /** Checks whether the app has a passed flag set. + * + * @param flag the flag to be checked + * @return is the flag set + */ + public default boolean hasFlag(Flag flag) { + return Stream.of(this.flags()).anyMatch(f -> f.equals(flag)); + } + public static final String FALLBACK_IMAGE = """ data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAASwAAAEsCAYAAAB5fY5\ 1AAABhWlDQ1BJQ0MgUHJvZmlsZQAAKM+VkT1Iw1AUhU9TpVIqgu0g4pChOlkQFXGUKBbBQmkrtOpg8tI/aNKQpLg4Cq4FB38Wqw\ 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 ab591f359b6..3bd86a01dde 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 @@ -9,6 +9,11 @@ public enum OpenemsAppCategory { + /** + * Core. + */ + CORE("core"), + /** * Integrated Systems. */ @@ -23,7 +28,7 @@ public enum OpenemsAppCategory { * Electric vehicle charging station. */ EVCS("evcs"), - + /** * Read only Electric vehicle charging station. */ 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 index 3bf4fb6585d..b463729eb7d 100644 --- 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 @@ -156,10 +156,10 @@ public GetParameterValues(APP app, Language language) { */ public default Function translationBundleSupplier() { return p -> { - if (p instanceof BundleParameter) { - return ((BundleParameter) p).bundle; - } - return null; + return switch (p) { + case BundleParameter bp -> bp.bundle; + default -> null; + }; }; } 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 2d5eb15d54b..8be75ab8167 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 @@ -1,9 +1,13 @@ package io.openems.edge.core.appmanager.dependency; +import java.util.List; + import io.openems.common.exceptions.OpenemsError.OpenemsNamedException; import io.openems.edge.common.user.User; import io.openems.edge.core.appmanager.OpenemsApp; import io.openems.edge.core.appmanager.OpenemsAppInstance; +import io.openems.edge.core.appmanager.dependency.aggregatetask.AggregateTask; +import io.openems.edge.core.appmanager.dependency.aggregatetask.AggregateTask.AggregateTaskExecutionConfiguration; public interface AppManagerAppHelper { @@ -42,6 +46,21 @@ public UpdateValues updateApp(User user, OpenemsAppInstance oldInstance, Openems */ public UpdateValues deleteApp(User user, OpenemsAppInstance instance) throws OpenemsNamedException; + /** + * Gets a list of {@link AggregateTaskExecutionConfiguration} which are the + * expected steps that are executed when installing a app with the provided + * properties. + * + * @param user the executing user + * @param instance the settings of the new {@link OpenemsAppInstance} + * @param app the {@link OpenemsApp} + * @return a list of the configurations + * @throws OpenemsNamedException on error + */ + public List getInstallConfiguration(// + User user, OpenemsAppInstance instance, OpenemsApp app // + ) throws OpenemsNamedException; + /** * Only available during a call of one of the other methods. * 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 7ce7533c0f2..a7b7028d2f9 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 @@ -150,6 +150,47 @@ public UpdateValues deleteApp(User user, OpenemsAppInstance instance) throws Ope return this.usingTemporaryApps(user, () -> this.deleteAppInternal(user, instance)); } + @Override + public List getInstallConfiguration(// + User user, // + OpenemsAppInstance instance, // + OpenemsApp app // + ) throws OpenemsNamedException { + return this.getConfigurations(user, () -> this.updateAppInternal(user, null, instance, app)); + } + + private List getConfigurations(// + User user, // + ThrowingSupplier supplier // + ) throws OpenemsNamedException { + Objects.requireNonNull(supplier); + // to make sure the temporaryApps get set to null + this.resetTasks(); + this.temporaryApps = new TemporaryApps(); + OpenemsNamedException exception = null; + RuntimeException runtimeException = null; + try { + supplier.get(); + } catch (OpenemsNamedException e) { + exception = e; + } catch (RuntimeException e) { + runtimeException = e; + } + this.temporaryApps = null; + if (exception != null) { + this.log.error("An Exception occurred during handling the supplier.", exception); + throw exception; + } + if (runtimeException != null) { + this.log.error("An RuntimeException occurred during handling the supplier.", runtimeException); + throw runtimeException; + } + + return this.tasks.stream() // + .map(AggregateTask::getExecutionConfiguration) // + .toList(); + } + private UpdateValues usingTemporaryApps(User user, ThrowingSupplier supplier) throws OpenemsNamedException { Objects.requireNonNull(supplier); @@ -780,11 +821,11 @@ public AppIdKey(String appId, String key) { @Override public boolean equals(Object other) { - if (!(other instanceof AppIdKey)) { + if (!(other instanceof AppIdKey aik)) { return false; } - return ((AppIdKey) other).compareTo(this) == 0; + return aik.compareTo(this) == 0; } @Override 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 d29de120956..21903923df7 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 @@ -150,10 +150,10 @@ private void setCurrentlyRunning(boolean isCurrentlyRunning) { private static final AppManagerImpl getAppManagerImpl(ComponentManager componentManager) { var appManager = componentManager.getEnabledComponentsOfType(AppManager.class); - if (appManager.size() == 0 || !(appManager.get(0) instanceof AppManagerImpl)) { + if (appManager.size() == 0 || !(appManager.get(0) instanceof AppManagerImpl ami)) { return null; } - return (AppManagerImpl) appManager.get(0); + return ami; } private static final AppManagerAppHelper getAppManagerAppHelper() { diff --git a/io.openems.edge.core/src/io/openems/edge/core/appmanager/dependency/aggregatetask/AggregateTask.java b/io.openems.edge.core/src/io/openems/edge/core/appmanager/dependency/aggregatetask/AggregateTask.java index b5a42dd4944..e32e34e0495 100644 --- a/io.openems.edge.core/src/io/openems/edge/core/appmanager/dependency/aggregatetask/AggregateTask.java +++ b/io.openems.edge.core/src/io/openems/edge/core/appmanager/dependency/aggregatetask/AggregateTask.java @@ -5,6 +5,8 @@ import java.util.List; import java.util.Set; +import com.google.gson.JsonElement; + import io.openems.common.exceptions.OpenemsError.OpenemsNamedException; import io.openems.common.session.Language; import io.openems.edge.common.user.User; @@ -12,6 +14,28 @@ public interface AggregateTask { + /** + * Class representing the configuration of an already aggregated + * {@link AggregateTask}. + */ + public interface AggregateTaskExecutionConfiguration { + + /** + * The identifier of the configuration. + * + * @return a string which identifies this type of configuration + */ + public String identifier(); + + /** + * Creates a {@link JsonElement} of this configuration. + * + * @return the created {@link JsonElement} + */ + public JsonElement toJson(); + + } + public static record AggregateTaskExecuteConstraints(// /** * Tasks which need to run before this task. @@ -48,6 +72,14 @@ public static record AggregateTaskExecuteConstraints(// */ public void delete(User user, List otherAppConfigurations) throws OpenemsNamedException; + /** + * Gets the {@link AggregateTaskExecutionConfiguration} which can be used for + * debugging. + * + * @return the AggregateTaskExecutionConfiguration + */ + public AggregateTaskExecutionConfiguration getExecutionConfiguration(); + /** * Validates the expected configuration. * diff --git a/io.openems.edge.core/src/io/openems/edge/core/appmanager/dependency/aggregatetask/ComponentAggregateTaskImpl.java b/io.openems.edge.core/src/io/openems/edge/core/appmanager/dependency/aggregatetask/ComponentAggregateTaskImpl.java index 87fad0519b6..d7e878ddc73 100644 --- a/io.openems.edge.core/src/io/openems/edge/core/appmanager/dependency/aggregatetask/ComponentAggregateTaskImpl.java +++ b/io.openems.edge.core/src/io/openems/edge/core/appmanager/dependency/aggregatetask/ComponentAggregateTaskImpl.java @@ -4,6 +4,8 @@ import java.util.Collections; import java.util.LinkedList; import java.util.List; +import java.util.Map.Entry; +import java.util.Objects; import java.util.stream.Collectors; import org.osgi.service.component.annotations.Activate; @@ -11,6 +13,9 @@ import org.osgi.service.component.annotations.Reference; import org.osgi.service.component.annotations.ServiceScope; +import com.google.gson.JsonElement; +import com.google.gson.JsonNull; + import io.openems.common.exceptions.InvalidValueException; import io.openems.common.exceptions.OpenemsError.OpenemsNamedException; import io.openems.common.exceptions.OpenemsException; @@ -20,12 +25,14 @@ import io.openems.common.jsonrpc.request.UpdateComponentConfigRequest.Property; import io.openems.common.session.Language; import io.openems.common.types.EdgeConfig; +import io.openems.common.utils.JsonUtils; import io.openems.edge.common.component.ComponentManager; import io.openems.edge.common.user.User; import io.openems.edge.core.appmanager.AppConfiguration; import io.openems.edge.core.appmanager.ComponentUtilImpl; import io.openems.edge.core.appmanager.TranslationUtil; import io.openems.edge.core.appmanager.dependency.AppManagerAppHelperImpl; +import io.openems.edge.core.appmanager.jsonrpc.GetEstimatedConfiguration; @Component(// service = { // @@ -37,6 +44,36 @@ ) public class ComponentAggregateTaskImpl implements ComponentAggregateTask { + private record ComponentAggregatedExecutionConfiguration(// + List components // + ) implements AggregateTask.AggregateTaskExecutionConfiguration { + + private ComponentAggregatedExecutionConfiguration { + Objects.requireNonNull(components); + } + + @Override + public String identifier() { + return "Component"; + } + + @Override + public JsonElement toJson() { + if (this.components.isEmpty()) { + return JsonNull.INSTANCE; + } + return JsonUtils.buildJsonObject() // + .add("components", this.components.stream() // + .map(t -> new GetEstimatedConfiguration.Component(t.getFactoryId(), t.getId(), t.getAlias(), + t.getProperties().entrySet().stream() // + .collect(JsonUtils.toJsonObject(Entry::getKey, Entry::getValue)))) // + .map(GetEstimatedConfiguration.Component.serializer()::serialize) // + .collect(JsonUtils.toJsonArray())) // + .build(); + } + + } + private final ComponentManager componentManager; private List components; @@ -210,6 +247,11 @@ public void delete(User user, List otherAppConfigurations) thr } } + @Override + public AggregateTaskExecutionConfiguration getExecutionConfiguration() { + return new ComponentAggregatedExecutionConfiguration(this.components); + } + @Override public String getGeneralFailMessage(Language l) { final var bundle = AppManagerAppHelperImpl.getTranslationBundle(l); diff --git a/io.openems.edge.core/src/io/openems/edge/core/appmanager/dependency/aggregatetask/PersistencePredictorAggregateTaskImpl.java b/io.openems.edge.core/src/io/openems/edge/core/appmanager/dependency/aggregatetask/PersistencePredictorAggregateTaskImpl.java index 49bfb12f7ed..7ce66695a85 100644 --- a/io.openems.edge.core/src/io/openems/edge/core/appmanager/dependency/aggregatetask/PersistencePredictorAggregateTaskImpl.java +++ b/io.openems.edge.core/src/io/openems/edge/core/appmanager/dependency/aggregatetask/PersistencePredictorAggregateTaskImpl.java @@ -6,6 +6,7 @@ import java.util.HashSet; import java.util.List; +import java.util.Objects; import java.util.Optional; import java.util.Set; import java.util.stream.Stream; @@ -15,12 +16,15 @@ import org.osgi.service.component.annotations.Reference; import org.osgi.service.component.annotations.ServiceScope; +import com.google.gson.JsonElement; +import com.google.gson.JsonNull; import com.google.gson.JsonPrimitive; import io.openems.common.exceptions.OpenemsError.OpenemsNamedException; import io.openems.common.exceptions.OpenemsException; import io.openems.common.jsonrpc.request.UpdateComponentConfigRequest; import io.openems.common.session.Language; +import io.openems.common.utils.JsonUtils; import io.openems.edge.common.component.ComponentManager; import io.openems.edge.common.component.OpenemsComponent; import io.openems.edge.common.user.User; @@ -38,6 +42,42 @@ ) public class PersistencePredictorAggregateTaskImpl implements PersistencePredictorAggregateTask { + private record PersistencePredictorExecutionConfiguration(// + Set channelsToAdd, // + Set channelsToRemove // + ) implements AggregateTask.AggregateTaskExecutionConfiguration { + + private PersistencePredictorExecutionConfiguration { + Objects.requireNonNull(channelsToAdd); + Objects.requireNonNull(channelsToRemove); + } + + @Override + public String identifier() { + return "PersistencePredictor"; + } + + @Override + public JsonElement toJson() { + if (this.channelsToAdd.isEmpty() && this.channelsToRemove.isEmpty()) { + return JsonNull.INSTANCE; + } + return JsonUtils.buildJsonObject() // + .onlyIf(!this.channelsToAdd.isEmpty(), t -> { + t.add("channelsToAdd", this.channelsToAdd.stream() // + .map(JsonPrimitive::new) // + .collect(JsonUtils.toJsonArray())); + }) // + .onlyIf(!this.channelsToRemove.isEmpty(), t -> { + t.add("channelsToRemove", this.channelsToRemove.stream() // + .map(JsonPrimitive::new) // + .collect(JsonUtils.toJsonArray())); + }) // + .build(); + } + + } + private ComponentManager componentManager; private Set channelsToAdd; @@ -97,6 +137,11 @@ public void validate(// errors.add("Missing channels in predictor [" + String.join(";", missingChannels) + "]"); } + @Override + public AggregateTaskExecutionConfiguration getExecutionConfiguration() { + return new PersistencePredictorExecutionConfiguration(this.channelsToAdd, this.channelsToRemove); + } + @Override public String getGeneralFailMessage(Language l) { final var bundle = AppManagerAppHelperImpl.getTranslationBundle(l); diff --git a/io.openems.edge.core/src/io/openems/edge/core/appmanager/dependency/aggregatetask/SchedulerAggregateTaskImpl.java b/io.openems.edge.core/src/io/openems/edge/core/appmanager/dependency/aggregatetask/SchedulerAggregateTaskImpl.java index 2059bc85e89..41d903bbb14 100644 --- a/io.openems.edge.core/src/io/openems/edge/core/appmanager/dependency/aggregatetask/SchedulerAggregateTaskImpl.java +++ b/io.openems.edge.core/src/io/openems/edge/core/appmanager/dependency/aggregatetask/SchedulerAggregateTaskImpl.java @@ -3,6 +3,7 @@ import java.util.ArrayList; import java.util.LinkedList; import java.util.List; +import java.util.Objects; import java.util.Set; import org.osgi.service.component.annotations.Activate; @@ -10,8 +11,13 @@ import org.osgi.service.component.annotations.Reference; import org.osgi.service.component.annotations.ServiceScope; +import com.google.gson.JsonElement; +import com.google.gson.JsonNull; +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.edge.common.user.User; import io.openems.edge.core.appmanager.AppConfiguration; import io.openems.edge.core.appmanager.ComponentUtil; @@ -28,6 +34,33 @@ ) public class SchedulerAggregateTaskImpl implements SchedulerAggregateTask { + private record SchedulerExecutionConfiguration(// + List insertOrder // + ) implements AggregateTask.AggregateTaskExecutionConfiguration { + + private SchedulerExecutionConfiguration { + Objects.requireNonNull(insertOrder); + } + + @Override + public String identifier() { + return "Scheduler"; + } + + @Override + public JsonElement toJson() { + if (this.insertOrder.isEmpty()) { + return JsonNull.INSTANCE; + } + return JsonUtils.buildJsonObject() // + .add("insertOrder", this.insertOrder.stream() // + .map(JsonPrimitive::new) // + .collect(JsonUtils.toJsonArray())) + .build(); + } + + } + private final ComponentAggregateTask aggregateTask; private final ComponentUtil componentUtil; @@ -92,6 +125,11 @@ public void delete(User user, List otherAppConfigurations) thr this.componentUtil.removeIdsInSchedulerIfExisting(user, this.removeIds); } + @Override + public AggregateTaskExecutionConfiguration getExecutionConfiguration() { + return new SchedulerExecutionConfiguration(this.order); + } + @Override public String getGeneralFailMessage(Language l) { final var bundle = AppManagerAppHelperImpl.getTranslationBundle(l); diff --git a/io.openems.edge.core/src/io/openems/edge/core/appmanager/dependency/aggregatetask/SchedulerByCentralOrderAggregateTaskImpl.java b/io.openems.edge.core/src/io/openems/edge/core/appmanager/dependency/aggregatetask/SchedulerByCentralOrderAggregateTaskImpl.java index 253f2b98c45..4e500cbffdc 100644 --- a/io.openems.edge.core/src/io/openems/edge/core/appmanager/dependency/aggregatetask/SchedulerByCentralOrderAggregateTaskImpl.java +++ b/io.openems.edge.core/src/io/openems/edge/core/appmanager/dependency/aggregatetask/SchedulerByCentralOrderAggregateTaskImpl.java @@ -1,5 +1,6 @@ package io.openems.edge.core.appmanager.dependency.aggregatetask; +import static io.openems.common.utils.FunctionUtils.doNothing; import static java.util.stream.Collectors.groupingBy; import static java.util.stream.Collectors.mapping; import static java.util.stream.Collectors.toList; @@ -10,6 +11,7 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; +import java.util.Objects; import java.util.Set; import java.util.TreeSet; import java.util.function.Function; @@ -20,9 +22,13 @@ import org.osgi.service.component.annotations.Reference; import org.osgi.service.component.annotations.ServiceScope; +import com.google.gson.JsonElement; +import com.google.gson.JsonNull; + 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.edge.common.component.ComponentManager; import io.openems.edge.common.user.User; import io.openems.edge.core.appmanager.AppConfiguration; @@ -44,6 +50,37 @@ ) public class SchedulerByCentralOrderAggregateTaskImpl implements SchedulerByCentralOrderAggregateTask { + private record SchedulerByCentralOrderExecutionConfiguration(// + List insertOrder // + ) implements AggregateTask.AggregateTaskExecutionConfiguration { + + private SchedulerByCentralOrderExecutionConfiguration { + Objects.requireNonNull(insertOrder); + } + + @Override + public String identifier() { + return "SchedulerByCentralOrder"; + } + + @Override + public JsonElement toJson() { + if (this.insertOrder.isEmpty()) { + return JsonNull.INSTANCE; + } + return JsonUtils.buildJsonObject() // + .add("insertOrder", this.insertOrder.stream() // + .map(t -> JsonUtils.buildJsonObject() // + .addProperty("id", t.id()) // + .addProperty("factoryId", t.factoryId()) // + .addPropertyIfNotNull("createdByAppId", t.createdByAppId()) // + .build()) + .collect(JsonUtils.toJsonArray())) + .build(); + } + + } + private final ComponentManager componentManager; private final ComponentUtil componentUtil; private final AppManagerUtil appManagerUtil; @@ -68,6 +105,7 @@ public ProductionSchedulerOrderDefinition() { .filterByFactoryId("Controller.Api.ModbusTcp.ReadWrite") // .thenByCreatedAppId("App.Ess.GeneratingPlantController") // .rest()) // + .thenByFactoryId("Controller.Api.ModbusRtu.ReadWrite") // .thenByFactoryId("Controller.Api.Rest.ReadWrite") // .thenByFactoryId("Controller.Ess.GridOptimizedCharge") // .thenByFactoryId("Controller.Ess.Hybrid.Surplus-Feed-To-Grid") // @@ -98,7 +136,7 @@ public static class SchedulerOrderDefinition implements Comparator doNothing(); + + case PositionReturnType.Remove remove -> { return EMPTY_INT_ARRAY; } - if (result instanceof PositionReturnType.Right right) { + case PositionReturnType.Right right -> { final var array = new int[right.index.length + 1]; array[0] = index; System.arraycopy(right.index, 0, array, 1, right.index.length); return array; } + } } return EMPTY_INT_ARRAY; } @@ -416,6 +450,11 @@ public void delete(User user, List otherAppConfigurations) thr this.componentUtil.removeIdsInSchedulerIfExisting(user, this.getIdsToRemove(otherAppConfigurations)); } + @Override + public AggregateTaskExecutionConfiguration getExecutionConfiguration() { + return new SchedulerByCentralOrderExecutionConfiguration(this.schedulerComponents); + } + private List getIdsToRemove(List otherAppConfigurations) { final var otherIds = AppConfiguration .flatMap(otherAppConfigurations, SchedulerByCentralOrderAggregateTask.class, diff --git a/io.openems.edge.core/src/io/openems/edge/core/appmanager/dependency/aggregatetask/StaticIpAggregateTaskImpl.java b/io.openems.edge.core/src/io/openems/edge/core/appmanager/dependency/aggregatetask/StaticIpAggregateTaskImpl.java index b01d6dde1a3..bbe8a3c9896 100644 --- a/io.openems.edge.core/src/io/openems/edge/core/appmanager/dependency/aggregatetask/StaticIpAggregateTaskImpl.java +++ b/io.openems.edge.core/src/io/openems/edge/core/appmanager/dependency/aggregatetask/StaticIpAggregateTaskImpl.java @@ -2,6 +2,7 @@ import java.util.LinkedList; import java.util.List; +import java.util.Objects; import java.util.stream.Collectors; import org.osgi.service.component.annotations.Activate; @@ -9,8 +10,12 @@ import org.osgi.service.component.annotations.Reference; import org.osgi.service.component.annotations.ServiceScope; +import com.google.gson.JsonElement; +import com.google.gson.JsonNull; + import io.openems.common.exceptions.OpenemsError.OpenemsNamedException; import io.openems.common.session.Language; +import io.openems.common.utils.JsonUtils; import io.openems.edge.common.user.User; import io.openems.edge.core.appmanager.AppConfiguration; import io.openems.edge.core.appmanager.ComponentUtil; @@ -28,6 +33,40 @@ ) public class StaticIpAggregateTaskImpl implements StaticIpAggregateTask { + private record StaticIpExecutionConfiguration(// + List ips // + ) implements AggregateTask.AggregateTaskExecutionConfiguration { + + private StaticIpExecutionConfiguration { + Objects.requireNonNull(ips); + } + + @Override + public String identifier() { + return "StaticIp"; + } + + @Override + public JsonElement toJson() { + if (this.ips.isEmpty()) { + return JsonNull.INSTANCE; + } + return JsonUtils.buildJsonObject() // + .add("interfaces", this.ips.stream() // + .map(t -> JsonUtils.buildJsonObject() // + .addProperty("interface", t.interfaceName) // + .add("addresses", t.getIps().stream() // + .map(ip -> JsonUtils.buildJsonObject() // + .addProperty("address", ip.getInet4Address().getHostAddress()) // + .build()) // + .collect(JsonUtils.toJsonArray())) // + .build()) + .collect(JsonUtils.toJsonArray())) + .build(); + } + + } + private final boolean isWindows = System.getProperty("os.name").startsWith("Windows"); private final ComponentUtil componentUtil; @@ -69,6 +108,11 @@ public void delete(User user, List otherAppConfigurations) thr this.execute(user, otherAppConfigurations, null, this.ips2Delete); } + @Override + public AggregateTaskExecutionConfiguration getExecutionConfiguration() { + return new StaticIpExecutionConfiguration(this.ips); + } + private void execute(// final User user, // final List otherAppConfigurations, // diff --git a/io.openems.edge.core/src/io/openems/edge/core/appmanager/flag/Flags.java b/io.openems.edge.core/src/io/openems/edge/core/appmanager/flag/Flags.java index bb85f9bbcf2..57c4e53a00e 100644 --- a/io.openems.edge.core/src/io/openems/edge/core/appmanager/flag/Flags.java +++ b/io.openems.edge.core/src/io/openems/edge/core/appmanager/flag/Flags.java @@ -3,6 +3,8 @@ public final class Flags { public static final Flag SHOW_AFTER_KEY_REDEEM = new FlagRecord("showAfterKeyRedeem"); + + public static final Flag ALWAYS_INSTALLED = new FlagRecord("alwaysInstalled"); private Flags() { super(); diff --git a/io.openems.edge.core/src/io/openems/edge/core/appmanager/jsonrpc/GetEstimatedConfiguration.java b/io.openems.edge.core/src/io/openems/edge/core/appmanager/jsonrpc/GetEstimatedConfiguration.java new file mode 100644 index 00000000000..f2b10cf9853 --- /dev/null +++ b/io.openems.edge.core/src/io/openems/edge/core/appmanager/jsonrpc/GetEstimatedConfiguration.java @@ -0,0 +1,125 @@ +package io.openems.edge.core.appmanager.jsonrpc; + +import static io.openems.common.jsonrpc.serialization.JsonSerializerUtil.jsonObjectSerializer; +import static io.openems.common.utils.JsonUtils.toJsonArray; +import static java.util.Collections.emptyList; + +import java.util.List; +import java.util.Objects; + +import com.google.gson.JsonObject; + +import io.openems.common.jsonrpc.serialization.JsonSerializer; +import io.openems.common.utils.JsonUtils; +import io.openems.edge.common.jsonapi.EndpointRequestType; +import io.openems.edge.core.appmanager.dependency.aggregatetask.AggregateTask; +import io.openems.edge.core.appmanager.jsonrpc.GetEstimatedConfiguration.Request; +import io.openems.edge.core.appmanager.jsonrpc.GetEstimatedConfiguration.Response; + +public class GetEstimatedConfiguration implements EndpointRequestType { + + @Override + public String getMethod() { + return "getEstimatedConfiguration"; + } + + @Override + public JsonSerializer getRequestSerializer() { + return Request.serializer(); + } + + @Override + public JsonSerializer getResponseSerializer() { + return Response.serializer(); + } + + public static record Request(// + String appId, // + String alias, // + JsonObject properties // + ) { + + /** + * Returns a {@link JsonSerializer} for a + * {@link GetEstimatedConfiguration.Request}. + * + * @return the created {@link JsonSerializer} + */ + public static JsonSerializer serializer() { + return jsonObjectSerializer(Request.class, // + json -> new Request(// + json.getString("appId"), // + json.getString("alias"), // + json.getJsonObject("properties")), + obj -> JsonUtils.buildJsonObject() // + .addProperty("appId", obj.appId()) // + .addProperty("alias", obj.alias()) // + .add("properties", obj.properties()) // + .build()); + } + + } + + public record Response(// + List configurations // + ) { + + /** + * Returns a {@link JsonSerializer} for a + * {@link GetEstimatedConfiguration.Response}. + * + * @return the created {@link JsonSerializer} + */ + public static JsonSerializer serializer() { + return jsonObjectSerializer(Response.class, // + // TODO polymorphic serializer + json -> new Response(emptyList()), // + obj -> JsonUtils.buildJsonObject() // + .add("configurations", obj.configurations().stream() // + .map(t -> { + final var configJson = t.toJson(); + + if (configJson.isJsonNull()) { + return null; + } + + return JsonUtils.buildJsonObject() // + .addProperty("type", t.identifier()) // + .add("configuration", configJson) // + .build(); + }) // + .filter(Objects::nonNull) // + .collect(toJsonArray())) // + .build()); + } + } + + public record Component(String factoryId, String id, String alias, JsonObject properties) { + + /** + * Returns a {@link JsonSerializer} for a + * {@link GetEstimatedConfiguration.Component}. + * + * @return the created {@link JsonSerializer} + */ + public static JsonSerializer serializer() { + return jsonObjectSerializer(GetEstimatedConfiguration.Component.class, json -> { + return new GetEstimatedConfiguration.Component(// + json.getString("factoryId"), // + json.getString("id"), // + json.getString("alias"), // + json.getJsonObject("properties") // + ); + }, obj -> { + return JsonUtils.buildJsonObject() // + .addProperty("factoryId", obj.factoryId()) // + .addProperty("id", obj.id()) // + .addProperty("alias", obj.alias()) // + .add("properties", obj.properties()) // + .build(); + }); + } + + } + +} diff --git a/io.openems.edge.core/src/io/openems/edge/core/appmanager/jsonrpc/UpdateAppConfig.java b/io.openems.edge.core/src/io/openems/edge/core/appmanager/jsonrpc/UpdateAppConfig.java new file mode 100644 index 00000000000..0253c0742a3 --- /dev/null +++ b/io.openems.edge.core/src/io/openems/edge/core/appmanager/jsonrpc/UpdateAppConfig.java @@ -0,0 +1,102 @@ +package io.openems.edge.core.appmanager.jsonrpc; + +import static io.openems.common.jsonrpc.serialization.JsonSerializerUtil.jsonObjectSerializer; + +import com.google.gson.JsonObject; + +import io.openems.common.jsonrpc.serialization.JsonSerializer; +import io.openems.common.jsonrpc.serialization.JsonSerializerUtil; +import io.openems.common.utils.JsonUtils; +import io.openems.edge.common.jsonapi.EndpointRequestType; +import io.openems.edge.core.appmanager.OpenemsAppInstance; +import io.openems.edge.core.appmanager.jsonrpc.UpdateAppConfig.Request; +import io.openems.edge.core.appmanager.jsonrpc.UpdateAppConfig.Response; + +/** + * Updates an {@link OpenemsAppInstance}. + * + *

    + * Request: + * + *

    + * {
    + *   "jsonrpc": "2.0",
    + *   "id": "UUID",
    + *   "method": "updateAppConfig",
    + *   "params": {
    + *     "componentId": string (uuid),
    + *     "properties": {}
    + *   }
    + * }
    + * 
    + * + *

    + * Response: + * + *

    + * {
    + *   "jsonrpc": "2.0",
    + *   "id": "UUID",
    + *   "result": {
    + *     "instance": {@link OpenemsAppInstance#toJsonObject()}
    + *     "warnings": string[]
    + *   }
    + * }
    + * 
    + */ +public class UpdateAppConfig implements EndpointRequestType { + + @Override + public String getMethod() { + return "updateAppConfig"; + } + + @Override + public JsonSerializer getRequestSerializer() { + return Request.serializer(); + } + + @Override + public JsonSerializer getResponseSerializer() { + return Response.serializer(); + } + + public record Request(// + String componentId, // + JsonObject properties // + ) { + + /** + * Returns a {@link JsonSerializer} for a {@link UpdateAppInstance.Request}. + * + * @return the created {@link JsonSerializer} + */ + public static JsonSerializer serializer() { + return jsonObjectSerializer(UpdateAppConfig.Request.class, // + json -> new UpdateAppConfig.Request(// + json.getString("componentId"), // + json.getJsonObject("properties")), // + obj -> JsonUtils.buildJsonObject() // + .addProperty("componentId", obj.componentId()) // + .add("properties", obj.properties()) // + .build()); + } + + } + + public record Response(// + + ) { + + /** + * Returns a {@link JsonSerializer} for a {@link UpdateAppInstance.Response}. + * + * @return the created {@link JsonSerializer} + */ + public static JsonSerializer serializer() { + return JsonSerializerUtil.emptyObjectSerializer(Response::new); + } + + } + +} 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 e9795f28fb0..620bdbb678a 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 @@ -15,6 +15,7 @@ ess = Speichersystemsteuerung openemsDeviceHardware = OpenEMS Geräte Hardware timedata = Timedata test = Test +core = Core # Global alias = Alias @@ -77,15 +78,30 @@ formly.validation.requireChecked = Diese Checkbox ist erforderlich! App.Api.apiTimeout.label = Api-Timeout App.Api.apiTimeout.description = Legt die Zeitüberschreitung in Sekunden für Aktualisierungen in den von dieser Api eingestellten Kanälen fest. -App.Api.ModbusTcp.changeComponentHint = Hinweis: Beim Einfügen einer Komponente ändert sich auch die Modbus Tabelle! +App.Api.Modbus.componentIds.description = Komponenten, die über die Schnittstelle verfügbar gemacht werden sollen. +App.Api.Modbus.componentIds.label = Komponenten-IDs +App.Api.Modbus.changeComponentHint = Hinweis: Beim Einfügen einer Komponente ändert sich auch die Modbus Tabelle! App.Api.ModbusTcp.ReadOnly.Name = Modbus/TCP lesend App.Api.ModbusTcp.ReadOnly.Name.short = Modbus/TCP lesend - App.Api.ModbusTcp.ReadWrite.Name = Modbus/TCP Schreibzugriff App.Api.ModbusTcp.ReadWrite.Name.short = Modbus/TCP Schreibzugriff -App.Api.ModbusTcp.ReadWrite.componentIds.label = Component-IDs -App.Api.ModbusTcp.ReadWrite.componentIds.description = Komponenten, die über die Schnittstelle verfügbar gemacht werden sollen. + +App.Api.ModbusRtu.ReadOnly.Name = Modbus/RTU lesend +App.Api.ModbusRtu.ReadOnly.Name.short = Modbus/RTU lesend +App.Api.ModbusRtu.ReadWrite.Name = Modbus/RTU Schreibzugriff +App.Api.ModbusRtu.ReadWrite.Name.short = Modbus/RTU Schreibzugriff + +App.Api.ModbusRtu.portName.label = Port-Name +App.Api.ModbusRtu.portName.description = Der Name des seriellen Ports - z.B. '/dev/ttyUSB0' oder 'COM3' +App.Api.ModbusRtu.baudrate.label = Baudrate +App.Api.ModbusRtu.baudrate.description = Die Baudrate - z.B. 9600, 19200, 38400, 57600 oder 115200 +App.Api.ModbusRtu.databits.label = Datenbits +App.Api.ModbusRtu.databits.description = Die Anzahl der Datenbits - z.B. 8 +App.Api.ModbusRtu.stopbits.label = Stoppbits +App.Api.ModbusRtu.stopbits.description = Die Anzahl der Stoppbits - '1', '1.5' oder '2' +App.Api.ModbusRtu.parity.label = Parität +App.Api.ModbusRtu.parity.description = Die Parität - 'keine', 'gerade', 'ungerade', 'mark' oder 'space' App.Api.Mqtt.Name = MQTT-Api lesend App.Api.Mqtt.Name.short = MQTT-Api lesend @@ -120,6 +136,13 @@ App.Timedata.InfluxDb.isReadOnly.description = Aktiviert Read Only Modus. Dann w App.Timedata.InfluxDb.bucket.label = Bucket App.Timedata.InfluxDb.bucket.description = Der Bucket-Name; für InfluxDB v1: 'Datenbank/retentionPolicy', z. B. 'db/daten' +# Core +App.Core.Meta.Name = Meta +App.Core.Meta.Name.short = Meta + +App.Core.Meta.currency.label = Währung +App.Core.Meta.gridCharge.label = Ist Beladung aus dem Netz erlaubt? +App.Core.Meta.gridCharge.description = ACHTUNG: Die aktive Beladung der Batterie aus dem Netz über die technisch notwendige Erhaltungsladung hinaus erfordert eine entsprechende Anmeldung des Speichersystems. Im Zweifel wenden Sie sich hierzu bitte an Ihren Installateur. Mit Betätigung des blauen \\\"Speichern\\\"-Buttons bestätigen Sie, dass Sie diese Prüfung durchgeführt haben.

    Beachten Sie: Voraussetzung für die Inanspruchnahme einer Förderung nach dem Gesetz für den Ausbau erneuerbarer Energien (EEG) ist, dass im Speicher ausschließlich Strom zwischengespeichert wird, der aus erneuerbaren Energien und/oder Grubengas stammt. Bei Aktivierung dieser Funktion wird der Speicher mit Netzstrom geladen. Dieser Netzstrom wird, je nach Stromlieferungsvertrag, ggf. auch aus fossilen Energieträgern und/oder Atomkraft gewonnen. Daher können wir nicht gewährleisten, dass der Speicher ausschließlich mit Strom aus erneuerbaren Energien und/oder Grubengas geladen wird # Evcs App.Evcs.controller.alias = Ladestation Steuerung @@ -253,7 +276,7 @@ App.IntegratedSystem.ctRatioFirst.label = Wandler-Primärstrom (200A - 5000A/5A) App.IntegratedSystem.shadowManagementDisabled.label = Schattenmanagement deaktivieren App.IntegratedSystem.shadowManagementDisabled.description = Nur wenn Optimierer verbaut sind, muss das Schattenmanagement deaktiviert werden App.IntegratedSystem.hasEssLimiter14a.label = Hat Limitierer für §14a -App.IntegratedSystem.naProtectionEnabled.label = NA-Schutz aktiviert? +App.IntegratedSystem.naProtectionEnabled.label = Fernabschaltung aktivieren (Zentraler NA Schutz) App.IntegratedSystem.modbusToBattery.alias = Kommunikation mit der Batterie App.IntegratedSystem.modbusToBatteryN.alias = Kommunikation mit den Batterien 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 03f34b1bafa..5441df63c3a 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 @@ -15,6 +15,7 @@ ess = Energy Storage controller openemsDeviceHardware = OpenEMS Device Hardware timedata = Timedata test = Test +core = Core # Global alias = Alias @@ -77,15 +78,30 @@ formly.validation.requireChecked = This checkbox is required! App.Api.apiTimeout.label = Api-Timeout App.Api.apiTimeout.description = Sets the timeout in seconds for updates on Channels set by this Api. +App.Api.Modbus.componentIds.description = Components that should be made available via Modbus. +App.Api.Modbus.componentIds.label = Component-IDs App.Api.ModbusTcp.changeComponentHint = Note: When inserting a component, the Modbus table also changes! +App.Api.ModbusRtu.ReadOnly.Name = Modbus/RTU reading +App.Api.ModbusRtu.ReadOnly.Name.short = Modbus/RTU reading +App.Api.ModbusRtu.ReadWrite.Name = Modbus/RTU write access +App.Api.ModbusRtu.ReadWrite.Name.short = Modbus/RTU write access + App.Api.ModbusTcp.ReadOnly.Name = Modbus/TCP reading App.Api.ModbusTcp.ReadOnly.Name.short = Modbus/TCP reading - App.Api.ModbusTcp.ReadWrite.Name = Modbus/TCP write access App.Api.ModbusTcp.ReadWrite.Name.short = 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. + +App.Api.ModbusRtu.portName.label = Port-Name +App.Api.ModbusRtu.portName.description = The name of the serial port - e.g. '/dev/ttyUSB0' or 'COM3' +App.Api.ModbusRtu.baudrate.label = Baudrate +App.Api.ModbusRtu.baudrate.description = The baudrate - e.g. 9600, 19200, 38400, 57600 or 115200 +App.Api.ModbusRtu.databits.label = Databits +App.Api.ModbusRtu.databits.description = The number of databits - e.g. 8 +App.Api.ModbusRtu.stopbits.label = Stopbits +App.Api.ModbusRtu.stopbits.description = The number of stopbits - '1', '1.5' or '2'. +App.Api.ModbusRtu.parity.label = Parity +App.Api.ModbusRtu.parity.description = The parity - 'none', 'even', 'odd', 'mark' or 'space' App.Api.Mqtt.Name = MQTT-Api reading App.Api.Mqtt.Name.short = MQTT-Api reading @@ -120,6 +136,13 @@ App.Timedata.InfluxDb.isReadOnly.description = Activates the read-only mode. The App.Timedata.InfluxDb.bucket.label = Bucket App.Timedata.InfluxDb.bucket.description = The bucket name; for InfluxDB v1: 'database/retentionPolicy', e.g. 'db/data' +# Core +App.Core.Meta.Name = Meta +App.Core.Meta.Name.short = Meta + +App.Core.Meta.currency.label = Currency +App.Core.Meta.gridCharge.label = Is charging from the grid allowed? +App.Core.Meta.gridCharge.description =
    WARNING: Actively charging the battery from the grid beyond the technically necessary maintenance charge requires appropriate registration of the storage system. If in doubt, please consult your installer. By pressing the blue \\\"Save\\\" button, you confirm that you have conducted this check.

    Please note: A requirement for receiving subsidies under the Renewable Energy Sources Act (EEG) is that only electricity generated from renewable energies and/or mine gas is stored in the system. When this function is activated, the storage system is charged with grid electricity. This grid electricity may, depending on your electricity supply contract, include energy from fossil fuels and/or nuclear power. Therefore, we cannot guarantee that the storage system will only be charged with electricity from renewable energies and/or mine gas. # Evcs App.Evcs.controller.alias = Charging station control @@ -252,8 +275,8 @@ App.IntegratedSystem.gridMeterType.option.commercialMeter = Home 3-phase sensor App.IntegratedSystem.ctRatioFirst.label = CT-Ratio (200A - 5000A/5A) App.IntegratedSystem.shadowManagementDisabled.label = Deactivate shadow management App.IntegratedSystem.shadowManagementDisabled.description = Only if optimisers are installed, shadow management must be deactivated -App.IntegratedSystem.hasEssLimiter14a.label = Has limiter for §14a -App.IntegratedSystem.naProtectionEnabled.label = NA-protection enabled? +App.IntegratedSystem.hasEssLimiter14a.label = Has limiter for §14a +App.IntegratedSystem.naProtectionEnabled.label = Activate remote shutdown (central NA protection) App.IntegratedSystem.modbusToBattery.alias = Communication with the battery App.IntegratedSystem.modbusToBatteryN.alias = Communication with the batteries 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 352f8c2433e..978dd49be85 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 @@ -57,10 +57,10 @@ public boolean check() { } private AppManagerImpl getAppManagerImpl() { - if (this.appManager == null || !(this.appManager instanceof AppManagerImpl)) { + if (this.appManager == null || !(this.appManager instanceof AppManagerImpl ami)) { return null; } - return (AppManagerImpl) this.appManager; + return ami; } @Override 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 58508a84ac1..c13bc5cd574 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 @@ -64,12 +64,11 @@ public boolean check() { this.errorType = ErrorType.OTHER; return false; } - if (!(this.appManager instanceof AppManagerImpl)) { + if (!(this.appManager instanceof AppManagerImpl appManagerImpl)) { this.errorMessage = "Wrong AppManager active!"; this.errorType = ErrorType.OTHER; return false; } - var appManagerImpl = (AppManagerImpl) this.appManager; var instantiatedApps = appManagerImpl.getInstantiatedApps(); switch (this.openemsApp.getCardinality()) { @@ -118,20 +117,15 @@ private OpenemsAppCategory getMatchingCategorie(AppManagerUtil appManagerUtil, @Override public String getErrorMessage(Language language) { - switch (this.errorType) { - case SAME_APP: - return AbstractCheckable.getTranslation(language, "Validator.Checkable.CheckCardinality.Message.Single", - this.openemsApp.getAppId()); - case SAME_CATEGORIE: - return AbstractCheckable.getTranslation(language, - "Validator.Checkable.CheckCardinality.Message.SingleInCategorie", - this.matchingCategory.getReadableName(language)); - case OTHER: - return this.errorMessage; - case NONE: - return null; - } - return null; + return switch (this.errorType) { + case SAME_APP -> getTranslation(language, // + "Validator.Checkable.CheckCardinality.Message.Single", this.openemsApp.getAppId()); + case SAME_CATEGORIE -> getTranslation(language, // + "Validator.Checkable.CheckCardinality.Message.SingleInCategorie", + this.matchingCategory.getReadableName(language)); + case OTHER -> this.errorMessage; + case NONE -> null; + }; } @Override diff --git a/io.openems.edge.core/src/io/openems/edge/core/componentmanager/ComponentManagerImpl.java b/io.openems.edge.core/src/io/openems/edge/core/componentmanager/ComponentManagerImpl.java index 3029e0d6a04..0c963faf1ea 100644 --- a/io.openems.edge.core/src/io/openems/edge/core/componentmanager/ComponentManagerImpl.java +++ b/io.openems.edge.core/src/io/openems/edge/core/componentmanager/ComponentManagerImpl.java @@ -1,5 +1,6 @@ package io.openems.edge.core.componentmanager; +import static java.util.Collections.emptyMap; import static java.util.stream.Collectors.toMap; import java.io.IOException; @@ -12,7 +13,9 @@ import java.util.Dictionary; import java.util.Hashtable; import java.util.List; +import java.util.Map; import java.util.Map.Entry; +import java.util.stream.Collectors; import java.util.stream.Stream; import org.osgi.framework.BundleContext; @@ -54,6 +57,7 @@ import io.openems.common.types.ChannelAddress; import io.openems.common.types.EdgeConfig; import io.openems.common.utils.JsonUtils; +import io.openems.common.utils.StreamUtils; import io.openems.edge.common.channel.Channel; import io.openems.edge.common.channel.EnumDoc; import io.openems.edge.common.channel.StateChannelDoc; @@ -156,6 +160,19 @@ protected void deactivate() { } } + @Override + public Map getComponentProperties(String componentId) { + Configuration config; + try { + config = this.getExistingConfigForId(componentId); + } catch (OpenemsNamedException e) { + return emptyMap(); + } + + return StreamUtils.dictionaryToStream(config.getProperties()) + .collect(Collectors.toMap(Entry::getKey, Entry::getValue)); + } + @Override public List getEnabledComponents() { return this.getComponentsViaService("(&(enabled=true)(!(service.factoryPid=Core.ComponentManager)))"); @@ -536,7 +553,7 @@ public void handleCreateComponentConfigRequest(User user, CreateComponentConfigR Dictionary properties = new Hashtable<>(); for (Property property : request.getProperties()) { var value = JsonUtils.getAsBestType(property.getValue()); - if (value instanceof Object[] && ((Object[]) value).length == 0) { + if (value instanceof Object[] os && os.length == 0) { value = new String[0]; } properties.put(property.getName(), value); @@ -581,7 +598,7 @@ public void handleUpdateComponentConfigRequest(User user, UpdateComponentConfigR } else { // Add updated Property var value = JsonUtils.getAsBestType(property.getValue()); - if (value instanceof Object[] && ((Object[]) value).length == 0) { + if (value instanceof Object[] os && os.length == 0) { value = new String[0]; } properties.put(property.getName(), value); diff --git a/io.openems.edge.core/src/io/openems/edge/core/componentmanager/EdgeConfigWorker.java b/io.openems.edge.core/src/io/openems/edge/core/componentmanager/EdgeConfigWorker.java index 6c90e120dab..61369c15207 100644 --- a/io.openems.edge.core/src/io/openems/edge/core/componentmanager/EdgeConfigWorker.java +++ b/io.openems.edge.core/src/io/openems/edge/core/componentmanager/EdgeConfigWorker.java @@ -1,5 +1,7 @@ package io.openems.edge.core.componentmanager; +import static io.openems.common.utils.JsonUtils.getAsOptionalString; + import java.io.IOException; import java.util.ArrayDeque; import java.util.Dictionary; @@ -7,6 +9,7 @@ import java.util.HashSet; import java.util.Map; import java.util.Map.Entry; +import java.util.Objects; import java.util.Queue; import java.util.Set; import java.util.TreeMap; @@ -261,22 +264,20 @@ private boolean readConfigurations(EdgeConfig.ActualEdgeConfig.Builder builder, this.log.warn(config.getPid() + ": Properties is 'null'"); continue; } - // Read Component-ID - String componentId = null; - var componentIdObj = properties.get("id"); - if (componentIdObj instanceof String) { - // Read 'id' property - componentId = (String) componentIdObj; - } else { - // Singleton - for (OpenemsComponent component : this.parent.getAllComponents()) { - if (config.getPid().equals(component.serviceFactoryPid())) { - componentId = component.id(); - break; - } - } + // Read Component-ID + var componentId = switch (properties.get("id")) { + case String s -> s; // Read 'id' property + case null, default -> { + // NOTE: for some reason JRE throws a "java.lang.VerifyError: Inconsistent + // stackmap frames at branch target 273" when yielding the value directly + var id = this.parent.getAllComponents().stream() // + .filter(c -> Objects.equals(config.getPid(), c.serviceFactoryPid())) // + .map(OpenemsComponent::id) // + .findFirst().orElse(null); + yield id; } + }; if (componentId == null) { // Use default value for 'id' property @@ -286,7 +287,7 @@ private boolean readConfigurations(EdgeConfig.ActualEdgeConfig.Builder builder, } var factory = builder.getFactories().get(factoryPid); if (factory != null) { - var defaultValue = JsonUtils.getAsOptionalString(factory.getPropertyDefaultValue("id")); + var defaultValue = getAsOptionalString(factory.getPropertyDefaultValue("id")); if (defaultValue.isPresent()) { componentId = defaultValue.get(); } @@ -304,19 +305,14 @@ private boolean readConfigurations(EdgeConfig.ActualEdgeConfig.Builder builder, var componentAlias = componentId; { var componentAliasObj = properties.get("alias"); - if (componentAliasObj instanceof String && !((String) componentAliasObj).trim().isEmpty()) { - componentAlias = (String) componentAliasObj; + if (componentAliasObj instanceof String s && !s.trim().isEmpty()) { + componentAlias = s; } } - String factoryPid; - if (config.getFactoryPid() != null) { - // Get Factory - factoryPid = config.getFactoryPid(); - } else { - // Singleton Component - factoryPid = config.getPid(); - } + var factoryPid = config.getFactoryPid() != null // + ? config.getFactoryPid() // Get Factory + : config.getPid(); // Singleton Component // Read Factory var factory = builder.getFactories().get(factoryPid); diff --git a/io.openems.edge.core/src/io/openems/edge/core/componentmanager/jsonrpc/ChannelExportXlsxResponse.java b/io.openems.edge.core/src/io/openems/edge/core/componentmanager/jsonrpc/ChannelExportXlsxResponse.java index 6722f9c9fc0..09d77d90368 100644 --- a/io.openems.edge.core/src/io/openems/edge/core/componentmanager/jsonrpc/ChannelExportXlsxResponse.java +++ b/io.openems.edge.core/src/io/openems/edge/core/componentmanager/jsonrpc/ChannelExportXlsxResponse.java @@ -84,19 +84,17 @@ protected static byte[] generatePayload(OpenemsComponent component) throws Opene description += "ERROR: " + e.getMessage(); } - } else if (channel instanceof StateChannel - && ((StateChannel) channel).value().orElse(false) == true) { + } else if (channel instanceof StateChannel sc && sc.value().orElse(false) == true) { if (!description.isEmpty()) { description += "; "; } - description += ((StateChannel) channel).channelDoc().getText(); + description += sc.channelDoc().getText(); - } else if (channel instanceof StateCollectorChannel - && ((StateCollectorChannel) channel).value().orElse(0) != 0) { + } else if (channel instanceof StateCollectorChannel scc && scc.value().orElse(0) != 0) { if (!description.isEmpty()) { description += "; "; } - description += ((StateCollectorChannel) channel).listStates(); + description += scc.listStates(); } ws.value(row, COL_CHANNEL_ID, channel.channelId().id()); diff --git a/io.openems.edge.core/src/io/openems/edge/core/host/HostImpl.java b/io.openems.edge.core/src/io/openems/edge/core/host/HostImpl.java index e9b516ae383..6b5a3092765 100644 --- a/io.openems.edge.core/src/io/openems/edge/core/host/HostImpl.java +++ b/io.openems.edge.core/src/io/openems/edge/core/host/HostImpl.java @@ -37,8 +37,7 @@ import io.openems.edge.core.host.jsonrpc.ExecuteSystemCommandRequest; import io.openems.edge.core.host.jsonrpc.ExecuteSystemRestartRequest; import io.openems.edge.core.host.jsonrpc.ExecuteSystemUpdateRequest; -import io.openems.edge.core.host.jsonrpc.GetIpAddresses; -import io.openems.edge.core.host.jsonrpc.GetIpAddresses.Response; +import io.openems.edge.core.host.jsonrpc.GetNetworkInfo; import io.openems.edge.core.host.jsonrpc.GetNetworkConfigRequest; import io.openems.edge.core.host.jsonrpc.GetNetworkConfigResponse; import io.openems.edge.core.host.jsonrpc.GetSystemUpdateStateRequest; @@ -188,13 +187,13 @@ public void buildJsonApiRoutes(JsonApiBuilder builder) { ExecuteSystemRestartRequest.from(call.getRequest())).get(); }); - builder.handleRequest(new GetIpAddresses(), endpoint -> { + builder.handleRequest(new GetNetworkInfo(), endpoint -> { endpoint.setDescription(""" - Gets the current ip addresses. + Gets the networkinfo. """.stripIndent()); endpoint.setGuards(EdgeGuards.roleIsAtleast(Role.OWNER)); - }, call -> new Response(this.getSystemIPs())); + }, call -> this.operatingSystem.getNetworkInfo()); } diff --git a/io.openems.edge.core/src/io/openems/edge/core/host/OperatingSystem.java b/io.openems.edge.core/src/io/openems/edge/core/host/OperatingSystem.java index c4244dea1c6..45831a521f0 100644 --- a/io.openems.edge.core/src/io/openems/edge/core/host/OperatingSystem.java +++ b/io.openems.edge.core/src/io/openems/edge/core/host/OperatingSystem.java @@ -12,6 +12,7 @@ import io.openems.edge.core.host.jsonrpc.ExecuteSystemCommandResponse; import io.openems.edge.core.host.jsonrpc.ExecuteSystemRestartRequest; import io.openems.edge.core.host.jsonrpc.ExecuteSystemRestartResponse; +import io.openems.edge.core.host.jsonrpc.GetNetworkInfo; import io.openems.edge.core.host.jsonrpc.SetNetworkConfigRequest; public interface OperatingSystem { @@ -70,7 +71,15 @@ public CompletableFuture handleExecuteSystemRe * @throws OpenemsNamedException on error */ public List getSystemIPs() throws OpenemsNamedException; - + + /** + * Gets Network Info. + * + * @return Response of GetIpAddresses + * @throws OpenemsNamedException on error + */ + public GetNetworkInfo.Response getNetworkInfo() throws OpenemsNamedException; + /** * Gets the current operating system version. * diff --git a/io.openems.edge.core/src/io/openems/edge/core/host/OperatingSystemDebianSystemd.java b/io.openems.edge.core/src/io/openems/edge/core/host/OperatingSystemDebianSystemd.java index 46dbeb79b59..bb8f799a90c 100644 --- a/io.openems.edge.core/src/io/openems/edge/core/host/OperatingSystemDebianSystemd.java +++ b/io.openems.edge.core/src/io/openems/edge/core/host/OperatingSystemDebianSystemd.java @@ -1,5 +1,7 @@ package io.openems.edge.core.host; +import static io.openems.common.jsonrpc.serialization.JsonSerializerUtil.jsonObjectSerializer; +import static io.openems.common.utils.FunctionUtils.doNothing; import static java.lang.Runtime.getRuntime; import static java.util.concurrent.CompletableFuture.runAsync; import static java.util.concurrent.CompletableFuture.supplyAsync; @@ -32,17 +34,19 @@ import java.util.function.Consumer; import java.util.function.Supplier; import java.util.regex.Pattern; +import java.util.stream.Collectors; import java.util.stream.Stream; -import java.util.stream.StreamSupport; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.gson.JsonElement; +import com.google.gson.JsonObject; import io.openems.common.exceptions.OpenemsError.OpenemsNamedException; import io.openems.common.exceptions.OpenemsException; import io.openems.common.function.ThrowingConsumer; +import io.openems.common.jsonrpc.serialization.JsonSerializer; import io.openems.common.types.ConfigurationProperty; import io.openems.common.utils.InetAddressUtils; import io.openems.common.utils.JsonUtils; @@ -55,6 +59,9 @@ import io.openems.edge.core.host.jsonrpc.ExecuteSystemCommandResponse.SystemCommandResponse; import io.openems.edge.core.host.jsonrpc.ExecuteSystemRestartRequest; import io.openems.edge.core.host.jsonrpc.ExecuteSystemRestartResponse; +import io.openems.edge.core.host.jsonrpc.GetNetworkInfo; +import io.openems.edge.core.host.jsonrpc.GetNetworkInfo.NetworkInfoWrapper; +import io.openems.edge.core.host.jsonrpc.GetNetworkInfo.Route; import io.openems.edge.core.host.jsonrpc.SetNetworkConfigRequest; /** @@ -467,7 +474,7 @@ protected static NetworkInterface parseSystemdNetworkdConfigurationFile(L // holds the latest found address final var tmpAddress = new AtomicReference(); - for (String line : lines) { + for (var line : lines) { line = line.trim(); if (line.isBlank()) { continue; @@ -477,27 +484,22 @@ protected static NetworkInterface parseSystemdNetworkdConfigurationFile(L * Find current configuration block */ if (line.startsWith("[")) { - switch (line) { - case MATCH_SECTION: - currentBlock = Block.MATCH; - break; - case NETWORK_SECTION: - currentBlock = Block.NETWORK; - break; - case ADDRESS_SECTION: + currentBlock = switch (line) { + case MATCH_SECTION // + -> Block.MATCH; + case NETWORK_SECTION // + -> Block.NETWORK; + case ADDRESS_SECTION -> { tmpAddress.set(null); - currentBlock = Block.ADDRESS; - break; - case ROUTE_SECTION: - currentBlock = Block.ROUTE; - break; - case DHCP_SECTION: - currentBlock = Block.DHCP; - break; - default: - currentBlock = Block.UNDEFINED; - break; + yield Block.ADDRESS; } + case ROUTE_SECTION // + -> Block.ROUTE; + case DHCP_SECTION // + -> Block.DHCP; + default // + -> Block.UNDEFINED; + }; continue; } @@ -505,12 +507,12 @@ protected static NetworkInterface parseSystemdNetworkdConfigurationFile(L * Parse Block */ switch (currentBlock) { - case MATCH: + case MATCH -> { onMatchString(MATCH_NAME, line, property -> { name.set(property); }); - break; - case NETWORK: + } + case NETWORK -> { onMatchString(NETWORK_DHCP, line, property -> { dhcp.set(ConfigurationProperty.of(property.toLowerCase().equals("yes"))); }); @@ -531,8 +533,8 @@ protected static NetworkInterface parseSystemdNetworkdConfigurationFile(L addressDetails.add(Inet4AddressWithSubnetmask.fromString("" /* empty default label */, property)); addresses.set(ConfigurationProperty.of(addressDetails)); }); - break; - case ADDRESS: + } + case ADDRESS -> { onMatchString(NETWORK_ADDRESS, line, property -> { // Storing here temporarily so that we can use it if when we find label. var address = Inet4AddressWithSubnetmask.fromString("" /* empty default label */, property); @@ -561,24 +563,21 @@ protected static NetworkInterface parseSystemdNetworkdConfigurationFile(L address.getSubnetmaskAsCidr()); addressDetails.add(address); }); - break; - case ROUTE: + } + case ROUTE -> { onMatchInet4Address(NETWORK_GATEWAY, line, property -> { gateway.set(ConfigurationProperty.of(property)); }); onMatchString(GATEWAY_METRIC, line, property -> { metric.set(ConfigurationProperty.of(Integer.parseInt(property))); }); - break; - case DHCP: + } + case DHCP -> { onMatchString(ROUTE_METRIC, line, property -> { metric.set(ConfigurationProperty.of(Integer.parseInt(property))); }); - break; - case UNDEFINED: - break; - default: - break; + } + case UNDEFINED -> doNothing(); } } return new NetworkInterface<>(name.get(), // @@ -588,50 +587,122 @@ protected static NetworkInterface parseSystemdNetworkdConfigurationFile(L @Override public List getSystemIPs() throws OpenemsNamedException { - var req = ExecuteSystemCommandRequest.withoutAuthentication("ip -j -4 address show", false, 5); + var reqIpShow = ExecuteSystemCommandRequest.withoutAuthentication("ip -j -4 address show", false, 5); try { - var result = this.handleExecuteSystemCommandRequest(req).get().getResult().toString(); - return parseIpJson(result); + var resultIpShow = this.handleExecuteSystemCommandRequest(reqIpShow).get().getResult().toString(); + return parseShowJson(resultIpShow).stream().flatMap(t -> t.ips().stream().map(d -> d.getInet4Address())) + .toList(); } catch (InterruptedException | ExecutionException e) { return Collections.emptyList(); } } - /** - * Parses the json returned by ip address get command. - * - * @param result the json to be parsed - * @return a list of parsed ips - * @throws OpenemsNamedException on error - */ - protected static List parseIpJson(String result) throws OpenemsNamedException { - final var stdout = JsonUtils.getAsJsonArray(JsonUtils.getAsJsonObject(JsonUtils.parse(result)), "stdout"); + @Override + public GetNetworkInfo.Response getNetworkInfo() throws OpenemsNamedException { + var reqIpShow = ExecuteSystemCommandRequest.withoutAuthentication("ip -j -4 address show", false, 5); + var reqIpRoute = ExecuteSystemCommandRequest.withoutAuthentication("ip -j route", false, 5); + try { + var resultIpShow = this.handleExecuteSystemCommandRequest(reqIpShow).get().getResult().toString(); + var resultIpRoute = this.handleExecuteSystemCommandRequest(reqIpRoute).get().getResult().toString(); + return new GetNetworkInfo.Response(parseShowJson(resultIpShow), parseRouteJson(resultIpRoute)); + } catch (InterruptedException | ExecutionException e) { + return new GetNetworkInfo.Response(Collections.emptyList(), Collections.emptyList()); + } + + } + + protected static List parseIpJson(String json) throws OpenemsNamedException { + final var stdout = JsonUtils.getAsJsonArray(JsonUtils.getAsJsonObject(JsonUtils.parse(json)), "stdout"); final var networkData = stdout.get(0).getAsString(); final var networkDataJson = JsonUtils.parseOptional(networkData); if (networkDataJson.isPresent() && networkDataJson.get().isJsonArray()) { final var networkInterfaces = JsonUtils.getAsJsonArray(JsonUtils.parse(networkData)); - if (networkData.startsWith("[")) { - return networkInterfaces.asList().stream().map(JsonElement::getAsJsonObject) - .map(interfaceObject -> interfaceObject.getAsJsonArray("addr_info")) - .flatMap(addrInfoArray -> StreamSupport.stream(addrInfoArray.spliterator(), false)) - .map(JsonElement::getAsJsonObject) - .filter(addrInfoObject -> "inet".equals(addrInfoObject.get("family").getAsString())) - .map(addrInfoObject -> addrInfoObject.get("local").getAsString()) // - .mapMulti((t, u) -> { - try { - u.accept((Inet4Address) Inet4Address.getByName(t)); - } catch (UnknownHostException e) { - // do nothing - } - }) // - .toList();// + return JsonUtils.stream(networkInterfaces)// + .map(JsonElement::getAsJsonObject)// + .toList(); } } + return Collections.emptyList(); } + protected static List parseRouteJson(String routeJson) throws OpenemsNamedException { + final var networkData = parseIpJson(routeJson); + if (networkData == null) { + return Collections.emptyList(); + } + return networkData.stream().map(t -> routeSerializer().deserialize(t)).toList(); + } + + private static JsonSerializer routeSerializer() { + return jsonObjectSerializer(GetNetworkInfo.Route.class, json -> { + Inet4Address prefsrc; + try { + // TODO: use inet4 method + prefsrc = (Inet4Address) Inet4Address.getByName(json.getString("prefsrc")); + } catch (UnknownHostException e) { + prefsrc = null; + } + return new GetNetworkInfo.Route(// + json.getString("dst"), // + json.getString("dev"), // + json.getString("protocol"), // + // TODO: use orElse in JsonPath once available + JsonUtils.getAsOptionalString(json.get(), "scope").orElse("link"), // + prefsrc, // + // TODO: use orElse in JsonPath once available and int method + JsonUtils.getAsOptionalInt(json.get(), "metric").orElse(DEFAULT_METRIC)); + }, obj -> { + return JsonUtils.buildJsonObject() // + .addProperty("dst", obj.dst())// + .addProperty("dev", obj.dev())// + .addProperty("protocol", obj.protocol())// + .addProperty("scope", obj.scope())// + .addProperty("prefsrc", obj.prefsrc().getHostAddress())// + .addProperty("metric", obj.metric())// + .build(); + }); + } + + /** + * Parses the json returned by ip address get command. + * + * @param resultIpShow the json to be parsed + * @return a list of parsed ips + * @throws OpenemsNamedException on error + */ + protected static List parseShowJson(String resultIpShow) throws OpenemsNamedException { + final var networkInterfaces = parseIpJson(resultIpShow); + if (networkInterfaces == null) { + return Collections.emptyList(); + } + + final var networkDataRaw = networkInterfaces.stream() + .collect(Collectors.toMap(t -> t.get("ifname").getAsString(), interfaceObject -> { + var addrInfoArray = interfaceObject.getAsJsonArray("addr_info"); + return JsonUtils.stream(addrInfoArray)// + .map(JsonElement::getAsJsonObject)// + .filter(addrInfoObject -> "inet".equals(addrInfoObject.get("family").getAsString())) // + .toList(); // + })); + return networkDataRaw.entrySet().stream().map(entry -> { + var ipsForKey = entry.getValue().stream().mapMulti((t, u) -> { + try { + Inet4Address i4Address = (Inet4Address) Inet4Address.getByName(t.get("local").getAsString()); + int subnetmask = t.get("prefixlen").getAsInt(); + String family = t.get("family").getAsString(); + u.accept(new Inet4AddressWithSubnetmask(family, i4Address, subnetmask)); + } catch (Exception e) { + // do nothing + } + }).toList(); + return new NetworkInfoWrapper(entry.getKey(), ipsForKey); + }).toList(); + + } + @Override public CompletableFuture getOperatingSystemVersion() { final var sc = new SystemCommand(// diff --git a/io.openems.edge.core/src/io/openems/edge/core/host/OperatingSystemMac.java b/io.openems.edge.core/src/io/openems/edge/core/host/OperatingSystemMac.java index 2300905d9ae..fdde5cc2159 100644 --- a/io.openems.edge.core/src/io/openems/edge/core/host/OperatingSystemMac.java +++ b/io.openems.edge.core/src/io/openems/edge/core/host/OperatingSystemMac.java @@ -13,6 +13,7 @@ import io.openems.edge.core.host.jsonrpc.ExecuteSystemCommandRequest; import io.openems.edge.core.host.jsonrpc.ExecuteSystemCommandResponse; import io.openems.edge.core.host.jsonrpc.ExecuteSystemRestartRequest; +import io.openems.edge.core.host.jsonrpc.GetNetworkInfo.Response; import io.openems.edge.core.host.jsonrpc.SetNetworkConfigRequest; public class OperatingSystemMac implements OperatingSystem { @@ -26,7 +27,7 @@ public NetworkConfiguration getNetworkConfiguration() throws OpenemsNamedExcepti public void handleSetNetworkConfigRequest(User user, NetworkConfiguration oldNetworkConfiguration, SetNetworkConfigRequest request) throws OpenemsNamedException { throw new NotImplementedException("SetNetworkConfigRequest is not implemented for Mac"); - + } @Override @@ -57,4 +58,9 @@ public CompletableFuture getOperatingSystemVersion() { return CompletableFuture.completedFuture(System.getProperty("os.name")); } + @Override + public Response getNetworkInfo() throws OpenemsNamedException { + throw new NotImplementedException("This request is not implemented for mac"); + } + } diff --git a/io.openems.edge.core/src/io/openems/edge/core/host/OperatingSystemWindows.java b/io.openems.edge.core/src/io/openems/edge/core/host/OperatingSystemWindows.java index e099353f493..cb719210824 100644 --- a/io.openems.edge.core/src/io/openems/edge/core/host/OperatingSystemWindows.java +++ b/io.openems.edge.core/src/io/openems/edge/core/host/OperatingSystemWindows.java @@ -14,6 +14,7 @@ import io.openems.edge.core.host.jsonrpc.ExecuteSystemCommandResponse; import io.openems.edge.core.host.jsonrpc.ExecuteSystemRestartRequest; import io.openems.edge.core.host.jsonrpc.SetNetworkConfigRequest; +import io.openems.edge.core.host.jsonrpc.GetNetworkInfo.Response; /** * OperatingSystem implementation for Windows. @@ -57,7 +58,12 @@ public CompletableFuture handleExecuteSystemRe public List getSystemIPs() throws OpenemsNamedException { return Collections.emptyList(); } - + + @Override + public Response getNetworkInfo() throws OpenemsNamedException { + throw new NotImplementedException("This request is not implemented for Windows"); + } + public CompletableFuture getOperatingSystemVersion() { return CompletableFuture.completedFuture(System.getProperty("os.name")); } diff --git a/io.openems.edge.core/src/io/openems/edge/core/host/jsonrpc/GetIpAddresses.java b/io.openems.edge.core/src/io/openems/edge/core/host/jsonrpc/GetIpAddresses.java deleted file mode 100644 index b7b118ba4b8..00000000000 --- a/io.openems.edge.core/src/io/openems/edge/core/host/jsonrpc/GetIpAddresses.java +++ /dev/null @@ -1,68 +0,0 @@ -package io.openems.edge.core.host.jsonrpc; - -import static io.openems.common.jsonrpc.serialization.JsonSerializerUtil.emptyObjectSerializer; -import static io.openems.common.jsonrpc.serialization.JsonSerializerUtil.jsonObjectSerializer; - -import java.net.Inet4Address; -import java.util.List; - -import com.google.gson.JsonArray; - -import io.openems.common.jsonrpc.serialization.JsonSerializer; -import io.openems.common.utils.JsonUtils; -import io.openems.edge.common.jsonapi.EndpointRequestType; -import io.openems.edge.core.host.jsonrpc.GetIpAddresses.Request; -import io.openems.edge.core.host.jsonrpc.GetIpAddresses.Response; - -public class GetIpAddresses implements EndpointRequestType { - public record Request() { - - /** - * Returns a {@link JsonSerializer} for a {@link GetIpAddresses.Request}. - * - * @return the created {@link JsonSerializer} - */ - public static JsonSerializer serializer() { - return emptyObjectSerializer(Request::new); - } - } - - public record Response(List ips) { - - /** - * Returns a {@link JsonSerializer} for a {@link GetIpAddresses.Response}. - * - * @return the created {@link JsonSerializer} - */ - public static JsonSerializer seriliazer() { - return jsonObjectSerializer(GetIpAddresses.Response.class, json -> { - return new Response(List.of()); - }, obj -> { - return JsonUtils.buildJsonObject()// - .add("ips", buildInterfaceArray(obj.ips()))// - .build(); - }); - } - - private static JsonArray buildInterfaceArray(List ips) { - var builder = JsonUtils.buildJsonArray(); - ips.stream().map((ip) -> ip.getHostAddress()).forEach(builder::add); - return builder.build(); - } - } - - @Override - public String getMethod() { - return "getIpAddresses"; - } - - @Override - public JsonSerializer getRequestSerializer() { - return Request.serializer(); - } - - @Override - public JsonSerializer getResponseSerializer() { - return Response.seriliazer(); - } -} diff --git a/io.openems.edge.core/src/io/openems/edge/core/host/jsonrpc/GetNetworkInfo.java b/io.openems.edge.core/src/io/openems/edge/core/host/jsonrpc/GetNetworkInfo.java new file mode 100644 index 00000000000..dac17f9aaf7 --- /dev/null +++ b/io.openems.edge.core/src/io/openems/edge/core/host/jsonrpc/GetNetworkInfo.java @@ -0,0 +1,153 @@ +package io.openems.edge.core.host.jsonrpc; + +import static io.openems.common.jsonrpc.serialization.JsonSerializerUtil.emptyObjectSerializer; +import static io.openems.common.jsonrpc.serialization.JsonSerializerUtil.jsonObjectSerializer; + +import java.net.Inet4Address; +import java.net.UnknownHostException; +import java.util.List; + +import io.openems.common.jsonrpc.serialization.JsonSerializer; +import io.openems.common.utils.JsonUtils; +import io.openems.edge.common.jsonapi.EndpointRequestType; +import io.openems.edge.core.host.Inet4AddressWithSubnetmask; +import io.openems.edge.core.host.jsonrpc.GetNetworkInfo.Request; +import io.openems.edge.core.host.jsonrpc.GetNetworkInfo.Response; + +public class GetNetworkInfo implements EndpointRequestType { + + @Override + public String getMethod() { + return "getNetworkInfo"; + } + + public record Request() { + + /** + * Returns a {@link JsonSerializer} for a {@link GetNetworkInfo.Request}. + * + * @return the created {@link JsonSerializer} + */ + public static JsonSerializer serializer() { + return emptyObjectSerializer(Request::new); + } + } + + public record NetworkInfoWrapper(String hardwareInterface, List ips) { + + /** + * Returns a {@link JsonSerializer} for a {@link GetNetworkInfo.Route}. + * + * @return the created {@link JsonSerializer} + */ + public static JsonSerializer serializer() { + return jsonObjectSerializer(GetNetworkInfo.NetworkInfoWrapper.class, json -> { + JsonUtils.stream(json.getJsonArray("ips")).map(entry -> { + var ip = entry.getAsJsonObject(); + try { + var inet = (Inet4Address) Inet4Address.getByName(ip.get("prefsrc").getAsString()); + return new Inet4AddressWithSubnetmask(// + ip.get("family").getAsString(), // + inet, // + ip.get("subnetmask").getAsInt()); + } catch (UnknownHostException e) { + // TODO: use Get Inet4Address Method once available + return null; + } + }); + return new GetNetworkInfo.NetworkInfoWrapper(json.getString("hardwareInterface"), List.of()); + }, obj -> { + return JsonUtils.buildJsonObject() // + .addProperty("hardwareInterface", obj.hardwareInterface())// + .add("ips", // + obj.ips().stream().map(ip -> { + return JsonUtils.buildJsonObject()// + .addProperty("family", ip.getLabel())// + .addProperty("address", ip.getInet4Address().getHostAddress())// + .addProperty("subnetmask", ip.getSubnetmaskAsCidr())// + .build(); + }).collect(JsonUtils.toJsonArray()))// + .build(); + }); + } + + } + + public record Route(String dst, // + String dev, // + String protocol, // + String scope, // + Inet4Address prefsrc, // + int metric // + ) { + + /** + * Returns a {@link JsonSerializer} for a {@link GetNetworkInfo.Route}. + * + * @return the created {@link JsonSerializer} + */ + public static JsonSerializer serializer() { + return jsonObjectSerializer(GetNetworkInfo.Route.class, json -> { + Inet4Address prefsrc; + try { + // TODO: use inet4 method + prefsrc = (Inet4Address) Inet4Address.getByName(json.getString("prefsrc")); + } catch (UnknownHostException e) { + prefsrc = null; + } + return new GetNetworkInfo.Route(// + json.getString("dst"), // + json.getString("dev"), // + json.getString("protocol"), // + json.getString("scope"), // + prefsrc, // + // TODO: use int method once implemented + json.get().get("metric") == null ? 0 : json.get().get("metric").getAsInt()); + }, obj -> { + return JsonUtils.buildJsonObject() // + .addProperty("dst", obj.dst())// + .addProperty("dev", obj.dev())// + .addProperty("protocol", obj.protocol())// + .addProperty("scope", obj.scope())// + .addProperty("prefsrc", obj.prefsrc().getHostAddress())// + .addProperty("metric", obj.metric())// + .build(); + }); + } + + } + + public record Response(List ips, List route) { + + /** + * Returns a {@link JsonSerializer} for a {@link GetNetworkInfo.Response}. + * + * @return the created {@link JsonSerializer} + */ + public static JsonSerializer serializer() { + return jsonObjectSerializer(GetNetworkInfo.Response.class, json -> { + return new Response(// + json.getList("networkInterfaces", NetworkInfoWrapper.serializer()), // + json.getList("routes", Route.serializer()) // + ); + }, obj -> { + return JsonUtils.buildJsonObject()// + .add("networkInterfaces", + NetworkInfoWrapper.serializer().toListSerializer().serialize(obj.ips()))// + .add("routes", Route.serializer().toListSerializer().serialize(obj.route()))// + .build(); + }); + } + + } + + @Override + public JsonSerializer getRequestSerializer() { + return Request.serializer(); + } + + @Override + public JsonSerializer getResponseSerializer() { + return Response.serializer(); + } +} diff --git a/io.openems.edge.core/src/io/openems/edge/core/predictormanager/PredictorManagerImpl.java b/io.openems.edge.core/src/io/openems/edge/core/predictormanager/PredictorManagerImpl.java index a674023dd02..6d7edc442e5 100644 --- a/io.openems.edge.core/src/io/openems/edge/core/predictormanager/PredictorManagerImpl.java +++ b/io.openems.edge.core/src/io/openems/edge/core/predictormanager/PredictorManagerImpl.java @@ -162,26 +162,18 @@ private Prediction getPredictionSum(Sum.ChannelId channelId) { // Sum up "ActivePower" prediction of all ElectricityMeter List meters = this.componentManager.getEnabledComponentsOfType(ElectricityMeter.class) .stream() // - .filter(meter -> { - switch (meter.getMeterType()) { - case GRID: - case CONSUMPTION_METERED: - case MANAGED_CONSUMPTION_METERED: - case CONSUMPTION_NOT_METERED: - return false; - case PRODUCTION: - case PRODUCTION_AND_CONSUMPTION: - // Get only Production meters - return true; - } - // should never come here - return false; - }).toList(); + .filter(meter -> switch (meter.getMeterType()) { + case GRID, CONSUMPTION_METERED, MANAGED_CONSUMPTION_METERED, CONSUMPTION_NOT_METERED // + -> false; + case PRODUCTION, PRODUCTION_AND_CONSUMPTION // + -> true; // Get only Production meters + }) // + .toList(); var predictions = new Prediction[meters.size()]; for (var i = 0; i < meters.size(); i++) { var meter = meters.get(i); - predictions[i] = this - .getPrediction(new ChannelAddress(meter.id(), ElectricityMeter.ChannelId.ACTIVE_POWER.id())); + predictions[i] = this.getPrediction(// + new ChannelAddress(meter.id(), ElectricityMeter.ChannelId.ACTIVE_POWER.id())); } yield sum(predictions); } diff --git a/io.openems.edge.core/src/io/openems/edge/core/sum/SumImpl.java b/io.openems.edge.core/src/io/openems/edge/core/sum/SumImpl.java index 4910b1f965e..fb10de3ec36 100644 --- a/io.openems.edge.core/src/io/openems/edge/core/sum/SumImpl.java +++ b/io.openems.edge.core/src/io/openems/edge/core/sum/SumImpl.java @@ -1,5 +1,6 @@ package io.openems.edge.core.sum; +import static io.openems.common.utils.FunctionUtils.doNothing; import static io.openems.edge.core.sum.ExtremeEverValues.Range.NEGATIVE; import static io.openems.edge.core.sum.ExtremeEverValues.Range.POSTIVE; @@ -202,13 +203,12 @@ private void calculateChannelValues() { // Consumption final var managedConsumptionActivePower = new CalculateIntegerSum(); - for (OpenemsComponent component : this.componentManager.getEnabledComponents()) { - if (component instanceof SymmetricEss) { - /* - * Ess - */ - var ess = (SymmetricEss) component; - + for (var component : this.componentManager.getEnabledComponents()) { + switch (component) { + /* + * Ess + */ + case SymmetricEss ess -> { if (ess instanceof MetaEss) { // ignore this Ess continue; @@ -222,64 +222,63 @@ private void calculateChannelValues() { essActiveDischargeEnergy.addValue(ess.getActiveDischargeEnergyChannel()); essCapacity.addValue(ess.getCapacityChannel()); - if (ess instanceof AsymmetricEss) { - var e = (AsymmetricEss) ess; + switch (ess) { + case AsymmetricEss e -> { essActivePowerL1.addValue(e.getActivePowerL1Channel()); essActivePowerL2.addValue(e.getActivePowerL2Channel()); essActivePowerL3.addValue(e.getActivePowerL3Channel()); - } else { + } + default -> { essActivePowerL1.addValue(ess.getActivePowerChannel(), CalculateIntegerSum.DIVIDE_BY_THREE); essActivePowerL2.addValue(ess.getActivePowerChannel(), CalculateIntegerSum.DIVIDE_BY_THREE); essActivePowerL3.addValue(ess.getActivePowerChannel(), CalculateIntegerSum.DIVIDE_BY_THREE); } + } - if (ess instanceof HybridEss) { - var e = (HybridEss) ess; + switch (ess) { + case HybridEss e -> { essDcChargeEnergy.addValue(e.getDcChargeEnergyChannel()); essDcDischargeEnergy.addValue(e.getDcDischargeEnergyChannel()); essDcDischargePower.addValue(e.getDcDischargePowerChannel()); - } else { + } + default -> { essDcChargeEnergy.addValue(ess.getActiveChargeEnergyChannel()); essDcDischargeEnergy.addValue(ess.getActiveDischargeEnergyChannel()); essDcDischargePower.addValue(ess.getActivePowerChannel()); } + } + } - } else if (component instanceof ElectricityMeter meter) { - if (component instanceof VirtualMeter) { - if (!((VirtualMeter) component).addToSum()) { - // Ignore VirtualMeter if "addToSum" is not activated (default) - continue; - } + /* + * Meter + */ + case ElectricityMeter meter -> { + if (component instanceof VirtualMeter vm && !vm.addToSum()) { + // Ignore VirtualMeter if "addToSum" is not activated (default) + continue; } - /* - * Meter - */ switch (meter.getMeterType()) { - case PRODUCTION_AND_CONSUMPTION: - // TODO PRODUCTION_AND_CONSUMPTION + case PRODUCTION_AND_CONSUMPTION -> // TODO // Production Power is positive, Consumption is negative - break; + doNothing(); - case CONSUMPTION_METERED: - // TODO CONSUMPTION_METERED + case CONSUMPTION_METERED -> // TODO // Consumption is positive - break; + doNothing(); - case MANAGED_CONSUMPTION_METERED: // + case MANAGED_CONSUMPTION_METERED -> { if (meter instanceof MetaEvcs) { - // ignore this Evcs - } else { - managedConsumptionActivePower.addValue(meter.getActivePowerChannel()); + continue; } - break; + managedConsumptionActivePower.addValue(meter.getActivePowerChannel()); + } - case CONSUMPTION_NOT_METERED: - // TODO CONSUMPTION_NOT_METERED + case CONSUMPTION_NOT_METERED -> // TODO // Consumption is positive - break; + doNothing(); - case GRID: + case GRID -> { /* * Grid-Meter */ @@ -289,9 +288,9 @@ private void calculateChannelValues() { gridActivePowerL1.addValue(meter.getActivePowerL1Channel()); gridActivePowerL2.addValue(meter.getActivePowerL2Channel()); gridActivePowerL3.addValue(meter.getActivePowerL3Channel()); - break; + } - case PRODUCTION: + case PRODUCTION -> { /* * Production-Meter */ @@ -301,24 +300,27 @@ private void calculateChannelValues() { productionAcActivePowerL1.addValue(meter.getActivePowerL1Channel()); productionAcActivePowerL2.addValue(meter.getActivePowerL2Channel()); productionAcActivePowerL3.addValue(meter.getActivePowerL3Channel()); - break; - } + } + } - } else if (component instanceof EssDcCharger) { - /* - * Ess DC-Charger - */ - var charger = (EssDcCharger) component; + /* + * Ess DC-Charger + */ + case EssDcCharger charger -> { productionDcActualPower.addValue(charger.getActualPowerChannel()); productionDcActiveEnergy.addValue(charger.getActualEnergyChannel()); + } - } else if (component instanceof TimeOfUseTariff tou) { - /* - * Time-of-Use-Tariff - */ + /* + * Time-of-Use-Tariff + */ + case TimeOfUseTariff tou -> { gridBuyPrice.addValue(tou.getPrices().getFirst()); } + + default -> doNothing(); + } } /* @@ -431,7 +433,7 @@ private void calculateChannelValues() { private void calculateState() { var highestLevel = Level.OK; var hasIgnoredComponentStates = false; - for (OpenemsComponent component : this.componentManager.getEnabledComponents()) { + for (var component : this.componentManager.getEnabledComponents()) { if (component == this) { // ignore myself continue; diff --git a/io.openems.edge.core/test/io/openems/edge/app/TestPermissions.java b/io.openems.edge.core/test/io/openems/edge/app/TestPermissions.java new file mode 100644 index 00000000000..d24a423569b --- /dev/null +++ b/io.openems.edge.core/test/io/openems/edge/app/TestPermissions.java @@ -0,0 +1,163 @@ +package io.openems.edge.app; + +import static io.openems.edge.app.common.props.CommonProps.defaultDef; + +import java.util.ArrayList; +import java.util.Map; +import java.util.ResourceBundle; +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.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.oem.OpenemsEdgeOem; +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.TestPermissions.Property; +import io.openems.edge.app.TestPermissions.TestPermissionsParameter; +import io.openems.edge.app.common.props.CommonProps; +import io.openems.edge.common.component.ComponentManager; +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.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.BundleProvider; +import io.openems.edge.core.appmanager.dependency.Tasks; +import io.openems.edge.core.appmanager.formly.JsonFormlyUtil; +import io.openems.edge.core.appmanager.formly.builder.ReorderArrayBuilder; +import io.openems.edge.core.appmanager.formly.enums.DisplayType; + +/** + * Tests AppPropertyPermissions. + */ +@org.osgi.service.component.annotations.Component(name = "App.Test.TestPermissions") +public class TestPermissions extends AbstractOpenemsAppWithProps + implements OpenemsApp { + + public record TestPermissionsParameter(// + ResourceBundle bundle // + ) implements BundleProvider { + + } + + public static enum Property implements Type { + ID(AppDef.componentId("id0")), ADMIN_ONLY(AppDef.copyOfGeneric(CommonProps.defaultDef(), def -> def // + .setMinRole(Role.ADMIN))), // + INSTALLER_ONLY(AppDef.copyOfGeneric(CommonProps.defaultDef(), def -> def // + .setMinRole(Role.INSTALLER))), // + EVERYONE(AppDef.copyOfGeneric(CommonProps.defaultDef())), // + UPDATE_ARRAY(AppDef.copyOfGeneric(defaultDef(), def -> def // + .setTranslatedLabel("component.id.plural") // + .setField(JsonFormlyUtil::buildFieldGroupFromNameable, (app, property, l, parameter, field) -> { + field.setPopupInput(property, DisplayType.STRING); + + final var arrayBuilder = new ReorderArrayBuilder(property); // + final var fields = JsonUtils.buildJsonArray() // + .add(arrayBuilder.build()); + + field.setFieldGroup(fields.build()); + })).setDefaultValue((app, property, l, parameter) -> { + return JsonUtils.buildJsonArray().add("val1").add("val2").build(); + })), + + ;// + + 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, TestPermissionsParameter> getParamter() { + return t -> { + return new TestPermissionsParameter(// + createResourceBundle(t.language) // + ); + }; + } + + } + + @Activate + public TestPermissions(// + @Reference ComponentManager componentManager, // + ComponentContext componentContext, // + @Reference ConfigurationAdmin cm, // + @Reference ComponentUtil componentUtil // + ) { + super(componentManager, componentContext, cm, componentUtil); + } + + @Override + protected ThrowingTriFunction, Language, AppConfiguration, OpenemsNamedException> appPropertyConfigurationFactory() { + return (t, p, l) -> { + + final var components = new ArrayList(); + // final var updateArray = this.getJsonArray(p, Property.UPDATE_ARRAY); + components.add(new EdgeConfig.Component(this.getId(t, p, Property.ADMIN_ONLY, "id0"), "alias", "factoryId", // + new JsonObject())); + components.add( + new EdgeConfig.Component(this.getId(t, p, Property.INSTALLER_ONLY, "id0"), "alias", "factoryId", // + new JsonObject())); + components.add(new EdgeConfig.Component(this.getId(t, p, Property.EVERYONE, "id0"), "alias", "factoryId", // + new JsonObject())); + return AppConfiguration.create() // + .addTask(Tasks.component(components)) // + .build(); + }; + } + + @Override + public AppDescriptor getAppDescriptor(OpenemsEdgeOem oem) { + return AppDescriptor.create() // + .setWebsiteUrl(oem.getAppWebsiteUrl(this.getAppId())) // + .build(); + } + + @Override + public OpenemsAppCategory[] getCategories() { + return new OpenemsAppCategory[] { OpenemsAppCategory.TEST }; + } + + @Override + public OpenemsAppCardinality getCardinality() { + return OpenemsAppCardinality.SINGLE; + } + + @Override + protected TestPermissions getApp() { + return this; + } + + @Override + protected Property[] propertyValues() { + return Property.values(); + } + +} 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 874f365b240..f0bba295098 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 @@ -44,8 +44,8 @@ public void testDeactivateReadOnly() throws Exception { var readOnlyApp = this.appManagerTestBundle.sut.getInstantiatedApps().get(0); if (readOnlyApp.properties.has("ACTIVE")) { - var isActiv = readOnlyApp.properties.get("ACTIVE").getAsBoolean(); - assertTrue(isActiv); + var isActive = readOnlyApp.properties.get("ACTIVE").getAsBoolean(); + assertTrue(isActive); } // create ReadWrite app @@ -66,8 +66,8 @@ public void testDeactivateReadOnly() throws Exception { readOnlyApp = this.appManagerTestBundle.sut.getInstantiatedApps().get(0); assertTrue(readOnlyApp.properties.has("ACTIVE")); - var isActiv = readOnlyApp.properties.get("ACTIVE").getAsBoolean(); - assertFalse(isActiv); + var isActive = readOnlyApp.properties.get("ACTIVE").getAsBoolean(); + assertFalse(isActive); // remove ReadWrite to see if the ReadOnly gets activated this.appManagerTestBundle.sut.handleDeleteAppInstanceRequest(DUMMY_ADMIN, @@ -77,8 +77,8 @@ public void testDeactivateReadOnly() throws Exception { readOnlyApp = this.appManagerTestBundle.sut.getInstantiatedApps().get(0); if (readOnlyApp.properties.has("ACTIVE")) { - isActiv = readOnlyApp.properties.get("ACTIVE").getAsBoolean(); - assertTrue(isActiv); + isActive = readOnlyApp.properties.get("ACTIVE").getAsBoolean(); + assertTrue(isActive); } } diff --git a/io.openems.edge.core/test/io/openems/edge/app/integratedsystem/TestFeneconHome10Gen2.java b/io.openems.edge.core/test/io/openems/edge/app/integratedsystem/TestFeneconHome10Gen2.java index 831cd630988..7cae58845f1 100644 --- a/io.openems.edge.core/test/io/openems/edge/app/integratedsystem/TestFeneconHome10Gen2.java +++ b/io.openems.edge.core/test/io/openems/edge/app/integratedsystem/TestFeneconHome10Gen2.java @@ -99,7 +99,8 @@ public final void testCreateAndUpdateFullHome() throws Exception { } /** - * Gets a {@link JsonObject} with the full settings for a {@link FeneconHome10Gen2}. + * Gets a {@link JsonObject} with the full settings for a + * {@link FeneconHome10Gen2}. * * @return the settings object */ diff --git a/io.openems.edge.core/test/io/openems/edge/app/integratedsystem/TestFeneconHome20.java b/io.openems.edge.core/test/io/openems/edge/app/integratedsystem/TestFeneconHome20.java index 609fd1b8a38..7fb5c681fed 100644 --- a/io.openems.edge.core/test/io/openems/edge/app/integratedsystem/TestFeneconHome20.java +++ b/io.openems.edge.core/test/io/openems/edge/app/integratedsystem/TestFeneconHome20.java @@ -57,26 +57,14 @@ public void testCreateAndUpdateHomeFullSettings() throws Exception { // check properties of created apps for (var instance : this.appManagerTestBundle.sut.getInstantiatedApps()) { - int expectedDependencies; - switch (instance.appId) { - case "App.FENECON.Home.20": - expectedDependencies = 4; - break; - case "App.PvSelfConsumption.GridOptimizedCharge": - expectedDependencies = 0; - break; - case "App.PvSelfConsumption.SelfConsumptionOptimization": - expectedDependencies = 0; - break; - 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!"); - } + var expectedDependencies = switch (instance.appId) { + case "App.FENECON.Home.20" -> 4; + case "App.PvSelfConsumption.GridOptimizedCharge" -> 0; + case "App.PvSelfConsumption.SelfConsumptionOptimization" -> 0; + case "App.Meter.Socomec" -> 0; + case "App.Ess.PrepareBatteryExtension" -> 0; + default -> throw new Exception("App with ID[" + instance.appId + "] should not have been created!"); + }; if (expectedDependencies == 0 && instance.dependencies == null) { continue; } @@ -157,26 +145,14 @@ private final OpenemsAppInstance createFullHome() throws Exception { // check properties of created apps for (var instance : this.appManagerTestBundle.sut.getInstantiatedApps()) { - int expectedDependencies; - switch (instance.appId) { - case "App.FENECON.Home.20": - expectedDependencies = 4; - break; - case "App.PvSelfConsumption.GridOptimizedCharge": - expectedDependencies = 0; - break; - case "App.PvSelfConsumption.SelfConsumptionOptimization": - expectedDependencies = 0; - break; - 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!"); - } + var expectedDependencies = switch (instance.appId) { + case "App.FENECON.Home.20" -> 4; + case "App.PvSelfConsumption.GridOptimizedCharge" -> 0; + case "App.PvSelfConsumption.SelfConsumptionOptimization" -> 0; + case "App.Meter.Socomec" -> 0; + case "App.Ess.PrepareBatteryExtension" -> 0; + default -> throw new Exception("App with ID[" + instance.appId + "] should not have been created!"); + }; if (expectedDependencies == 0 && instance.dependencies == null) { continue; } diff --git a/io.openems.edge.core/test/io/openems/edge/app/integratedsystem/TestFeneconHome30.java b/io.openems.edge.core/test/io/openems/edge/app/integratedsystem/TestFeneconHome30.java index 0c349b74428..f698c3a218f 100644 --- a/io.openems.edge.core/test/io/openems/edge/app/integratedsystem/TestFeneconHome30.java +++ b/io.openems.edge.core/test/io/openems/edge/app/integratedsystem/TestFeneconHome30.java @@ -67,26 +67,14 @@ public void testCreateAndUpdateHomeFullSettings() throws Exception { // check properties of created apps for (var instance : this.appManagerTestBundle.sut.getInstantiatedApps()) { - int expectedDependencies; - switch (instance.appId) { - case "App.FENECON.Home.30": - expectedDependencies = 4; - break; - case "App.PvSelfConsumption.GridOptimizedCharge": - expectedDependencies = 0; - break; - case "App.PvSelfConsumption.SelfConsumptionOptimization": - expectedDependencies = 0; - break; - 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!"); - } + var expectedDependencies = switch (instance.appId) { + case "App.FENECON.Home.30" -> 4; + case "App.PvSelfConsumption.GridOptimizedCharge" -> 0; + case "App.PvSelfConsumption.SelfConsumptionOptimization" -> 0; + case "App.Meter.Socomec" -> 0; + case "App.Ess.PrepareBatteryExtension" -> 0; + default -> throw new Exception("App with ID[" + instance.appId + "] should not have been created!"); + }; if (expectedDependencies == 0 && instance.dependencies == null) { continue; } 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 7701feb9a12..dc8384768c9 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,7 +1,11 @@ package io.openems.edge.core.appmanager; +import static io.openems.common.utils.JsonUtils.getAsJsonArray; +import static io.openems.common.utils.JsonUtils.getAsString; +import static io.openems.common.utils.JsonUtils.toJsonArray; import static io.openems.common.utils.ReflectionUtils.setAttributeViaReflection; import static io.openems.common.utils.ReflectionUtils.setStaticAttributeViaReflection; +import static java.util.stream.Collectors.joining; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; @@ -13,7 +17,6 @@ import java.util.Map; import java.util.function.Consumer; import java.util.function.Function; -import java.util.stream.Collectors; import org.osgi.framework.Bundle; import org.osgi.framework.ServiceReference; @@ -276,7 +279,7 @@ public void assertNoValidationErrors() throws Exception { if (!this.appValidateWorker.defectiveApps.isEmpty()) { throw new Exception(this.appValidateWorker.defectiveApps.entrySet().stream() // .map(e -> e.getKey() + "[" + e.getValue() + "]") // - .collect(Collectors.joining("|"))); + .collect(joining("|"))); } } @@ -284,8 +287,10 @@ public void assertNoValidationErrors() throws Exception { * Prints out the instantiated {@link OpenemsAppInstance}s. */ public void printApps() { - JsonUtils.prettyPrint(this.sut.getInstantiatedApps().stream().map(OpenemsAppInstance::toJsonObject) - .collect(JsonUtils.toJsonArray())); + JsonUtils.prettyPrint(// + this.sut.getInstantiatedApps().stream() // + .map(OpenemsAppInstance::toJsonObject) // + .collect(toJsonArray())); } /** @@ -300,9 +305,9 @@ public JsonArray getAppsFromConfig() throws IOException, OpenemsNamedException { final var config = this.cm.getConfiguration(this.sut.servicePid()); final var configObj = config.getProperties().get("apps"); if (configObj instanceof JsonPrimitive json) { - return JsonUtils.getAsJsonArray(JsonUtils.parse(JsonUtils.getAsString(json))); + return getAsJsonArray(JsonUtils.parse(getAsString(json))); } - return JsonUtils.getAsJsonArray(JsonUtils.parse(configObj.toString())); + return getAsJsonArray(JsonUtils.parse(configObj.toString())); } /** @@ -654,7 +659,7 @@ private final void modifyWithCurrentConfig() throws OpenemsNamedException { final var config = MyConfig.create() // .setApps(this.instantiatedApps.stream() // .map(OpenemsAppInstance::toJsonObject) // - .collect(JsonUtils.toJsonArray()) // + .collect(toJsonArray()) // .toString()) .setKey("0000-0000-0000-0000") // .build(); diff --git a/io.openems.edge.core/test/io/openems/edge/core/appmanager/AppPropertyPermissionsTest.java b/io.openems.edge.core/test/io/openems/edge/core/appmanager/AppPropertyPermissionsTest.java new file mode 100644 index 00000000000..601c29cf203 --- /dev/null +++ b/io.openems.edge.core/test/io/openems/edge/core/appmanager/AppPropertyPermissionsTest.java @@ -0,0 +1,82 @@ +package io.openems.edge.core.appmanager; + +import static io.openems.edge.common.test.DummyUser.DUMMY_ADMIN; +import static io.openems.edge.common.test.DummyUser.DUMMY_INSTALLER; +import static io.openems.edge.common.test.DummyUser.DUMMY_OWNER; + +import org.junit.Before; +import org.junit.Test; + +import com.google.common.collect.ImmutableList; + +import io.openems.common.exceptions.OpenemsError.OpenemsNamedException; +import io.openems.common.exceptions.OpenemsException; +import io.openems.common.utils.JsonUtils; +import io.openems.edge.app.TestPermissions; +import io.openems.edge.core.appmanager.jsonrpc.AddAppInstance; +import io.openems.edge.core.appmanager.jsonrpc.UpdateAppConfig; + +public class AppPropertyPermissionsTest { + + private AppManagerTestBundle appManagerTestBundle; + + private TestPermissions testPermissions; + + @Before + public void setUp() throws Exception { + this.appManagerTestBundle = new AppManagerTestBundle(null, null, t -> { + return ImmutableList.of(// + this.testPermissions = Apps.testPermissions(t) // + ); + }); + this.appManagerTestBundle.sut.handleAddAppInstanceRequest(DUMMY_ADMIN, + new AddAppInstance.Request(this.testPermissions.getAppId(), "key", "alias", JsonUtils.buildJsonObject() // + .addProperty(TestPermissions.Property.ID.name(), "id0") + .addProperty(TestPermissions.Property.ADMIN_ONLY.name(), "val0") // + .addProperty(TestPermissions.Property.INSTALLER_ONLY.name(), "val0") // + .addProperty(TestPermissions.Property.EVERYONE.name(), "val0") // + .build())) + .instance(); + } + + @Test(expected = OpenemsException.class) + public void testAdminOnlyAsInstaller() throws OpenemsNamedException { + final var req = this.request("ADMIN_ONLY"); + this.appManagerTestBundle.sut.handleUpdateAppConfigRequest(DUMMY_INSTALLER, req); + } + + @Test + public void testAdminOnlyAsAdmin() throws OpenemsNamedException { + final var req = this.request("ADMIN_ONLY"); + this.appManagerTestBundle.sut.handleUpdateAppConfigRequest(DUMMY_ADMIN, req); + } + + @Test(expected = OpenemsException.class) + public void testInstallerOnlyAsOwner() throws OpenemsNamedException { + final var req = this.request("INSTALLER_ONLY"); + this.appManagerTestBundle.sut.handleUpdateAppConfigRequest(DUMMY_OWNER, req); + } + + @Test + public void testInstallerOnlyAsAdmin() throws OpenemsNamedException { + final var req = this.request("INSTALLER_ONLY"); + this.appManagerTestBundle.sut.handleUpdateAppConfigRequest(DUMMY_ADMIN, req); + } + + @Test + public void testEveryoneAsOwner() throws OpenemsNamedException { + final var req = this.request("EVERYONE"); + this.appManagerTestBundle.sut.handleUpdateAppConfigRequest(DUMMY_OWNER, req); + } + + private UpdateAppConfig.Request request(String val) { + final var ja = JsonUtils.buildJsonArray().add("val3").add("val4").build(); + final var jo = JsonUtils.buildJsonObject().add(val, JsonUtils.getAsJsonElement("val1")) + .add("UPDATE_ARRAY", ja) + .build(); + + final var req = new UpdateAppConfig.Request("id0", jo); + return req; + } + +} 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 index 3d776848849..6bf3134da74 100644 --- 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 @@ -12,6 +12,9 @@ import io.openems.edge.app.TestBDependencyToC; import io.openems.edge.app.TestC; import io.openems.edge.app.TestMultipleIds; +import io.openems.edge.app.TestPermissions; +import io.openems.edge.app.api.ModbusRtuApiReadOnly; +import io.openems.edge.app.api.ModbusRtuApiReadWrite; import io.openems.edge.app.api.ModbusTcpApiReadOnly; import io.openems.edge.app.api.ModbusTcpApiReadWrite; import io.openems.edge.app.api.RestJsonApiReadOnly; @@ -321,6 +324,16 @@ public static final TechbaseCm4sGen2 techbaseCm4sGen2(AppManagerTestBundle t) { return app(t, TechbaseCm4sGen2::new, "App.OpenemsHardware.CM4S.Gen2"); } + /** + * Test method for creating a {@link TestPermissions}. + * + * @param t the {@link AppManagerTestBundle} + * @return the {@link OpenemsApp} instance + */ + public static final TestPermissions testPermissions(AppManagerTestBundle t) { + return app(t, TestPermissions::new, "App.Test.TestPermissions"); + } + // Test /** @@ -385,6 +398,26 @@ public static final ModbusTcpApiReadWrite modbusTcpApiReadWrite(AppManagerTestBu return app(t, ModbusTcpApiReadWrite::new, "App.Api.ModbusTcp.ReadWrite"); } + /** + * Test method for creating a {@link ModbusRtuApiReadOnly}. + * + * @param t the {@link AppManagerTestBundle} + * @return the {@link OpenemsApp} instance + */ + public static final ModbusRtuApiReadOnly modbusRtuApiReadOnly(AppManagerTestBundle t) { + return app(t, ModbusRtuApiReadOnly::new, "App.Api.ModbusRtu.ReadOnly"); + } + + /** + * Test method for creating a {@link ModbusRtuApiReadWrite}. + * + * @param t the {@link AppManagerTestBundle} + * @return the {@link OpenemsApp} instance + */ + public static final ModbusRtuApiReadWrite modbusRtuApiReadWrite(AppManagerTestBundle t) { + return app(t, ModbusRtuApiReadWrite::new, "App.Api.ModbusRtu.ReadWrite"); + } + /** * Test method for creating a {@link RestJsonApiReadOnly}. * diff --git a/io.openems.edge.core/test/io/openems/edge/core/appmanager/DummyApp.java b/io.openems.edge.core/test/io/openems/edge/core/appmanager/DummyApp.java index 245f4d5d20a..4965436cfa5 100644 --- a/io.openems.edge.core/test/io/openems/edge/core/appmanager/DummyApp.java +++ b/io.openems.edge.core/test/io/openems/edge/core/appmanager/DummyApp.java @@ -8,6 +8,7 @@ import io.openems.common.exceptions.OpenemsError.OpenemsNamedException; import io.openems.common.function.ThrowingTriFunction; +import io.openems.common.function.TriFunction; import io.openems.common.oem.OpenemsEdgeOem; import io.openems.common.session.Language; import io.openems.edge.common.user.User; @@ -26,6 +27,7 @@ public class DummyApp implements OpenemsApp { private final AppAssistant appAssistant; private final AppDescriptor appDescriptor; private final ThrowingTriFunction configuration; + private final TriFunction propName; public static class DummyAppBuilder { @@ -42,6 +44,7 @@ public static class DummyAppBuilder { private AppAssistant appAssistant; private AppDescriptor appDescriptor; private ThrowingTriFunction configuration; + private TriFunction propName; private DummyAppBuilder() { } @@ -115,6 +118,11 @@ public DummyAppBuilder setConfiguration( return this; } + public DummyAppBuilder setPropName(TriFunction propName) { + this.propName = propName; + return this; + } + public DummyApp build() { final var name = this.name == null ? this.appId : this.name; return new DummyApp(// @@ -128,8 +136,8 @@ public DummyApp build() { this.properties.toArray(OpenemsAppPropertyDefinition[]::new), // this.appAssistant == null ? AppAssistant.create(name).build() : this.appAssistant, // this.appDescriptor == null ? AppDescriptor.create().build() : this.appDescriptor, // - this.configuration == null ? (t, u, s) -> AppConfiguration.empty() : this.configuration // - ); + this.configuration == null ? (t, u, s) -> AppConfiguration.empty() : this.configuration, // + this.propName == null ? (t, u, s) -> t : this.propName); } } @@ -155,8 +163,8 @@ public DummyApp(// AppAssistant appAssistant, // AppDescriptor appDescriptor, // ThrowingTriFunction configuration // - ) { + Language, AppConfiguration, OpenemsNamedException> configuration, // + TriFunction mapPropName) { super(); this.appId = appId; this.categories = categories; @@ -169,6 +177,7 @@ public DummyApp(// this.appAssistant = appAssistant; this.appDescriptor = appDescriptor; this.configuration = configuration; + this.propName = mapPropName; } @Override @@ -232,4 +241,13 @@ public OpenemsAppPermissions getAppPermissions() { return this.appPermissions; } + @Override + public String mapPropName(String prop, String componentId, OpenemsAppInstance instance) { + return this.propName.apply(prop, componentId, instance); + } + + @Override + public boolean assertCanEdit(String prop, User user) { + return true; + } } diff --git a/io.openems.edge.core/test/io/openems/edge/core/appmanager/DummyAppManagerAppHelper.java b/io.openems.edge.core/test/io/openems/edge/core/appmanager/DummyAppManagerAppHelper.java index 9ad1f56bc01..91ab3fa14c2 100644 --- a/io.openems.edge.core/test/io/openems/edge/core/appmanager/DummyAppManagerAppHelper.java +++ b/io.openems.edge.core/test/io/openems/edge/core/appmanager/DummyAppManagerAppHelper.java @@ -14,6 +14,7 @@ import io.openems.edge.core.appmanager.dependency.TemporaryApps; import io.openems.edge.core.appmanager.dependency.UpdateValues; import io.openems.edge.core.appmanager.dependency.aggregatetask.AggregateTask; +import io.openems.edge.core.appmanager.dependency.aggregatetask.AggregateTask.AggregateTaskExecutionConfiguration; public class DummyAppManagerAppHelper implements AppManagerAppHelper { @@ -63,6 +64,12 @@ public UpdateValues deleteApp(User user, OpenemsAppInstance instance) throws Ope return this.impl.deleteApp(user, instance); } + @Override + public List getInstallConfiguration(User user, OpenemsAppInstance instance, + OpenemsApp app) throws OpenemsNamedException { + return this.impl.getInstallConfiguration(user, instance, app); + } + @Override public TemporaryApps getTemporaryApps() { return this.impl.getTemporaryApps(); diff --git a/io.openems.edge.core/test/io/openems/edge/core/appmanager/DummyPseudoComponentManager.java b/io.openems.edge.core/test/io/openems/edge/core/appmanager/DummyPseudoComponentManager.java index 9aba2d766eb..e2c8af440f4 100644 --- a/io.openems.edge.core/test/io/openems/edge/core/appmanager/DummyPseudoComponentManager.java +++ b/io.openems.edge.core/test/io/openems/edge/core/appmanager/DummyPseudoComponentManager.java @@ -36,6 +36,7 @@ import io.openems.common.types.EdgeConfig.ActualEdgeConfig; import io.openems.common.types.EdgeConfig.Component; import io.openems.common.utils.JsonUtils; +import io.openems.common.utils.StreamUtils; import io.openems.edge.common.channel.Channel; import io.openems.edge.common.component.ComponentManager; import io.openems.edge.common.component.OpenemsComponent; @@ -389,4 +390,15 @@ public ServiceReference getServiceReference() { } + @Override + public Map getComponentProperties(String componentId) { + try { + var dic = this.getComponent(componentId).getComponentContext().getProperties(); + return StreamUtils.dictionaryToStream(dic) // + .collect(Collectors.toMap(Entry::getKey, Entry::getValue)); + } catch (OpenemsNamedException e) { + return Collections.emptyMap(); + } + } + } diff --git a/io.openems.edge.core/test/io/openems/edge/core/appmanager/UpdateComponentDirectlyTest.java b/io.openems.edge.core/test/io/openems/edge/core/appmanager/UpdateComponentDirectlyTest.java new file mode 100644 index 00000000000..dc0f9136cd0 --- /dev/null +++ b/io.openems.edge.core/test/io/openems/edge/core/appmanager/UpdateComponentDirectlyTest.java @@ -0,0 +1,48 @@ +package io.openems.edge.core.appmanager; + +import static io.openems.edge.common.test.DummyUser.DUMMY_ADMIN; + +import java.util.List; + +import org.junit.Before; +import org.junit.Test; + +import com.google.common.collect.ImmutableList; + +import io.openems.common.exceptions.OpenemsError.OpenemsNamedException; +import io.openems.common.jsonrpc.request.CreateComponentConfigRequest; +import io.openems.common.jsonrpc.request.UpdateComponentConfigRequest; +import io.openems.common.types.EdgeConfig; +import io.openems.common.utils.JsonUtils; +import io.openems.edge.core.appmanager.AppManagerTestBundle.PseudoComponentManagerFactory; +import io.openems.edge.core.appmanager.jsonrpc.UpdateAppConfig; + +public class UpdateComponentDirectlyTest { + private AppManagerTestBundle appManagerTestBundle; + + @Before + public void setUp() throws Exception { + this.appManagerTestBundle = new AppManagerTestBundle(null, null, t -> { + return ImmutableList.of(// + + ); + }, null, new PseudoComponentManagerFactory()); + } + + @Test + public void testAdminOnlyAsInstaller() throws OpenemsNamedException { + final var testTest = List.of(new UpdateComponentConfigRequest.Property("id", "evcs1"), + new UpdateComponentConfigRequest.Property("debugMode", false)); + this.appManagerTestBundle.componentManger.handleCreateComponentConfigRequest(DUMMY_ADMIN, + new CreateComponentConfigRequest("Evcs.Keba.KeContact", testTest)); + this.appManagerTestBundle.sut.handleUpdateAppConfigRequest(DUMMY_ADMIN, + new UpdateAppConfig.Request("evcs1", JsonUtils.buildJsonObject().addProperty("debugMode", true)// + .build())); + final var properties = JsonUtils.buildJsonObject()// + .addProperty("debugMode", true)// + .build(); + this.appManagerTestBundle + .assertComponentExist(new EdgeConfig.Component("evcs1", "", "Evcs.Keba.KeContact", properties)); + + } +} diff --git a/io.openems.edge.core/test/io/openems/edge/core/host/IpAddressTest.java b/io.openems.edge.core/test/io/openems/edge/core/host/IpAddressTest.java index 292e2533934..4c50afa9ca6 100644 --- a/io.openems.edge.core/test/io/openems/edge/core/host/IpAddressTest.java +++ b/io.openems.edge.core/test/io/openems/edge/core/host/IpAddressTest.java @@ -8,25 +8,34 @@ public class IpAddressTest { + private String jsonInput = "{\"stdout\":[\"[{\\\"ifindex\\\":1,\\\"ifname\\\":\\\"lo\\\",\\\"flags\\\":[\\\"LOOPBACK\\\",\\\"UP\\\",\\\"LOWER_UP\\\"],\\\"mtu\\\":65536,\\\"qdisc\\\":\\\"noqueue\\\",\\\"operstate\\\":\\\"UNKNOWN\\\",\\\"group\\\":\\\"default\\\",\\\"txqlen\\\":1000,\\\"addr_info\\\":[{\\\"family\\\":\\\"inet\\\",\\\"local\\\":\\\"127.0.0.1\\\",\\\"prefixlen\\\":8,\\\"scope\\\":\\\"host\\\",\\\"label\\\":\\\"lo\\\",\\\"valid_life_time\\\":4294967295,\\\"preferred_life_time\\\":4294967295}]},{\\\"ifindex\\\":2,\\\"ifname\\\":\\\"eth0\\\",\\\"flags\\\":[\\\"BROADCAST\\\",\\\"MULTICAST\\\",\\\"UP\\\",\\\"LOWER_UP\\\"],\\\"mtu\\\":1500,\\\"qdisc\\\":\\\"pfifo_fast\\\",\\\"operstate\\\":\\\"UP\\\",\\\"group\\\":\\\"default\\\",\\\"txqlen\\\":1000,\\\"addr_info\\\":[{\\\"family\\\":\\\"inet\\\",\\\"local\\\":\\\"169.254.97.140\\\",\\\"prefixlen\\\":16,\\\"broadcast\\\":\\\"169.254.255.255\\\",\\\"scope\\\":\\\"link\\\",\\\"label\\\":\\\"eth0\\\",\\\"valid_life_time\\\":4294967295,\\\"preferred_life_time\\\":4294967295},{\\\"family\\\":\\\"inet\\\",\\\"local\\\":\\\"192.168.100.100\\\",\\\"prefixlen\\\":24,\\\"broadcast\\\":\\\"192.168.100.255\\\",\\\"scope\\\":\\\"global\\\",\\\"label\\\":\\\"eth0\\\",\\\"valid_life_time\\\":4294967295,\\\"preferred_life_time\\\":4294967295},{\\\"family\\\":\\\"inet\\\",\\\"local\\\":\\\"192.168.25.10\\\",\\\"prefixlen\\\":24,\\\"broadcast\\\":\\\"192.168.25.255\\\",\\\"scope\\\":\\\"global\\\",\\\"label\\\":\\\"Evcs\\\",\\\"valid_life_time\\\":4294967295,\\\"preferred_life_time\\\":4294967295},{\\\"family\\\":\\\"inet\\\",\\\"local\\\":\\\"10.0.3.217\\\",\\\"prefixlen\\\":16,\\\"broadcast\\\":\\\"10.0.255.255\\\",\\\"scope\\\":\\\"global\\\",\\\"dynamic\\\":true,\\\"label\\\":\\\"eth0\\\",\\\"valid_life_time\\\":21474407,\\\"preferred_life_time\\\":21474407}]}]\"],\"stderr\":[],\"exitcode\":0}\n"; + private String routeInput = " {\"stdout\":[\"[{\\\"dst\\\":\\\"default\\\",\\\"gateway\\\":\\\"10.0.0.1\\\",\\\"dev\\\":\\\"eth0\\\",\\\"protocol\\\":\\\"dhcp\\\",\\\"prefsrc\\\":\\\"10.0.3.217\\\",\\\"metric\\\":1024,\\\"flags\\\":[]},{\\\"dst\\\":\\\"10.0.0.0/16\\\",\\\"dev\\\":\\\"eth0\\\",\\\"protocol\\\":\\\"kernel\\\",\\\"scope\\\":\\\"link\\\",\\\"prefsrc\\\":\\\"10.0.3.217\\\",\\\"flags\\\":[]},{\\\"dst\\\":\\\"10.0.0.1\\\",\\\"dev\\\":\\\"eth0\\\",\\\"protocol\\\":\\\"dhcp\\\",\\\"scope\\\":\\\"link\\\",\\\"prefsrc\\\":\\\"10.0.3.217\\\",\\\"metric\\\":1024,\\\"flags\\\":[]},{\\\"dst\\\":\\\"169.254.0.0/16\\\",\\\"dev\\\":\\\"eth0\\\",\\\"protocol\\\":\\\"kernel\\\",\\\"scope\\\":\\\"link\\\",\\\"prefsrc\\\":\\\"169.254.97.140\\\",\\\"flags\\\":[]},{\\\"dst\\\":\\\"192.168.25.0/24\\\",\\\"dev\\\":\\\"eth0\\\",\\\"protocol\\\":\\\"kernel\\\",\\\"scope\\\":\\\"link\\\",\\\"prefsrc\\\":\\\"192.168.25.10\\\",\\\"flags\\\":[]},{\\\"dst\\\":\\\"192.168.100.0/24\\\",\\\"dev\\\":\\\"eth0\\\",\\\"protocol\\\":\\\"kernel\\\",\\\"scope\\\":\\\"link\\\",\\\"prefsrc\\\":\\\"192.168.100.100\\\",\\\"flags\\\":[]}]\"],\"stderr\":[],\"exitcode\":0}"; + private String emptyInput = "{" // + + " \"stdout\": [" // + + " \"[]\"" // + + " ]," // + + " \"stderr\": []," // + + " \"exitcode\": 0" // + + "}"; // + private String failedInput = "{" // + + " \"stdout\": [" // + + " \"Device eth4 does not exist\"" // + + " ]," // + + " \"stderr\": []," // + + " \"exitcode\": 0" // + + "}"; // + + @Test + public void testShow() throws OpenemsNamedException { + assertEquals("2 NetworkInterfaces", 2, OperatingSystemDebianSystemd.parseShowJson(this.jsonInput).size()); + + assertEquals("0 NetworkInterfaces", 0, OperatingSystemDebianSystemd.parseShowJson(this.emptyInput).size()); + + assertEquals("0 NetworkInterfaces", 0, OperatingSystemDebianSystemd.parseShowJson(this.failedInput).size()); + } + @Test - public void test() throws OpenemsNamedException { - String jsonInput = "{\"stdout\":[\"[{\\\"ifindex\\\":1,\\\"ifname\\\":\\\"lo\\\",\\\"flags\\\":[\\\"LOOPBACK\\\",\\\"UP\\\",\\\"LOWER_UP\\\"],\\\"mtu\\\":65536,\\\"qdisc\\\":\\\"noqueue\\\",\\\"operstate\\\":\\\"UNKNOWN\\\",\\\"group\\\":\\\"default\\\",\\\"txqlen\\\":1000,\\\"addr_info\\\":[{\\\"family\\\":\\\"inet\\\",\\\"local\\\":\\\"127.0.0.1\\\",\\\"prefixlen\\\":8,\\\"scope\\\":\\\"host\\\",\\\"label\\\":\\\"lo\\\",\\\"valid_life_time\\\":4294967295,\\\"preferred_life_time\\\":4294967295}]},{\\\"ifindex\\\":2,\\\"ifname\\\":\\\"eth0\\\",\\\"flags\\\":[\\\"BROADCAST\\\",\\\"MULTICAST\\\",\\\"UP\\\",\\\"LOWER_UP\\\"],\\\"mtu\\\":1500,\\\"qdisc\\\":\\\"pfifo_fast\\\",\\\"operstate\\\":\\\"UP\\\",\\\"group\\\":\\\"default\\\",\\\"txqlen\\\":1000,\\\"addr_info\\\":[{\\\"family\\\":\\\"inet\\\",\\\"local\\\":\\\"169.254.97.140\\\",\\\"prefixlen\\\":16,\\\"broadcast\\\":\\\"169.254.255.255\\\",\\\"scope\\\":\\\"link\\\",\\\"label\\\":\\\"eth0\\\",\\\"valid_life_time\\\":4294967295,\\\"preferred_life_time\\\":4294967295},{\\\"family\\\":\\\"inet\\\",\\\"local\\\":\\\"192.168.100.100\\\",\\\"prefixlen\\\":24,\\\"broadcast\\\":\\\"192.168.100.255\\\",\\\"scope\\\":\\\"global\\\",\\\"label\\\":\\\"eth0\\\",\\\"valid_life_time\\\":4294967295,\\\"preferred_life_time\\\":4294967295},{\\\"family\\\":\\\"inet\\\",\\\"local\\\":\\\"192.168.25.10\\\",\\\"prefixlen\\\":24,\\\"broadcast\\\":\\\"192.168.25.255\\\",\\\"scope\\\":\\\"global\\\",\\\"label\\\":\\\"Evcs\\\",\\\"valid_life_time\\\":4294967295,\\\"preferred_life_time\\\":4294967295},{\\\"family\\\":\\\"inet\\\",\\\"local\\\":\\\"10.0.3.217\\\",\\\"prefixlen\\\":16,\\\"broadcast\\\":\\\"10.0.255.255\\\",\\\"scope\\\":\\\"global\\\",\\\"dynamic\\\":true,\\\"label\\\":\\\"eth0\\\",\\\"valid_life_time\\\":21474407,\\\"preferred_life_time\\\":21474407}]}]\"],\"stderr\":[],\"exitcode\":0}\n"; - assertEquals("5 Ip Addresses", 5, OperatingSystemDebianSystemd.parseIpJson(jsonInput).size()); - String emptyInput = "{" // - + " \"stdout\": [" // - + " \"[]\"" // - + " ]," // - + " \"stderr\": []," // - + " \"exitcode\": 0" // - + "}"; // - assertEquals("0 Ip Addresses", 0, OperatingSystemDebianSystemd.parseIpJson(emptyInput).size()); - String failedInput = "{" // - + " \"stdout\": [" // - + " \"Device eth4 does not exist\"" // - + " ]," // - + " \"stderr\": []," // - + " \"exitcode\": 0" // - + "}"; // - assertEquals("0 Ip Addresses", 0, OperatingSystemDebianSystemd.parseIpJson(failedInput).size()); + public void testRoute() throws OpenemsNamedException { + assertEquals("6 Routing Infos", 6, OperatingSystemDebianSystemd.parseRouteJson(this.routeInput).size()); } } diff --git a/io.openems.edge.core/test/io/openems/edge/core/meta/MyConfig.java b/io.openems.edge.core/test/io/openems/edge/core/meta/MyConfig.java index 9ff2a139fdb..a2c92b9de2b 100644 --- a/io.openems.edge.core/test/io/openems/edge/core/meta/MyConfig.java +++ b/io.openems.edge.core/test/io/openems/edge/core/meta/MyConfig.java @@ -19,7 +19,7 @@ public Builder setCurrency(CurrencyConfig currency) { this.currency = currency; return this; } - + public Builder setIsEssChargeFromGridAllowed(boolean isEssChargeFromGridAllowed) { this.isEssChargeFromGridAllowed = isEssChargeFromGridAllowed; return this; diff --git a/io.openems.edge.core/test/io/openems/edge/core/predictormanager/PredictorManagerImplTest.java b/io.openems.edge.core/test/io/openems/edge/core/predictormanager/PredictorManagerImplTest.java index 3bc99e30cdc..9075da90e4f 100644 --- a/io.openems.edge.core/test/io/openems/edge/core/predictormanager/PredictorManagerImplTest.java +++ b/io.openems.edge.core/test/io/openems/edge/core/predictormanager/PredictorManagerImplTest.java @@ -1,6 +1,6 @@ package io.openems.edge.core.predictormanager; -import static io.openems.edge.common.test.TestUtils.createDummyClock; +import static io.openems.common.test.TestUtils.createDummyClock; import static io.openems.edge.predictor.api.prediction.Prediction.EMPTY_PREDICTION; import static java.time.temporal.ChronoUnit.DAYS; import static org.junit.Assert.assertArrayEquals; diff --git a/io.openems.edge.core/test/io/openems/edge/core/sum/ExtremeEverValuesTest.java b/io.openems.edge.core/test/io/openems/edge/core/sum/ExtremeEverValuesTest.java index 4befb39052f..aa35aa7da51 100644 --- a/io.openems.edge.core/test/io/openems/edge/core/sum/ExtremeEverValuesTest.java +++ b/io.openems.edge.core/test/io/openems/edge/core/sum/ExtremeEverValuesTest.java @@ -1,7 +1,7 @@ package io.openems.edge.core.sum; +import static io.openems.common.test.TestUtils.createDummyClock; import static io.openems.edge.common.test.TestUtils.activateNextProcessImage; -import static io.openems.edge.common.test.TestUtils.createDummyClock; import static io.openems.edge.common.test.TestUtils.withValue; import static io.openems.edge.core.sum.ExtremeEverValues.Range.NEGATIVE; import static io.openems.edge.core.sum.ExtremeEverValues.Range.POSTIVE; diff --git a/io.openems.edge.edge2edge/src/io/openems/edge/edge2edge/ess/Edge2EdgeEss.java b/io.openems.edge.edge2edge/src/io/openems/edge/edge2edge/ess/Edge2EdgeEss.java index f80c88ee79a..bc21f46680e 100644 --- a/io.openems.edge.edge2edge/src/io/openems/edge/edge2edge/ess/Edge2EdgeEss.java +++ b/io.openems.edge.edge2edge/src/io/openems/edge/edge2edge/ess/Edge2EdgeEss.java @@ -12,11 +12,13 @@ public interface Edge2EdgeEss extends OpenemsComponent { public enum ChannelId implements io.openems.edge.common.channel.ChannelId { MINIMUM_POWER_SET_POINT(Doc.of(OpenemsType.FLOAT) // - .accessMode(AccessMode.READ_ONLY)// - .unit(Unit.WATT)), // + .accessMode(AccessMode.READ_ONLY) // + .unit(Unit.WATT) // + .text("Minimum available active power")), // MAXIMUM_POWER_SET_POINT(Doc.of(OpenemsType.FLOAT) // .accessMode(AccessMode.READ_ONLY)// - .unit(Unit.WATT)), // + .unit(Unit.WATT) // + .text("Maximum available electrical power")), // REMOTE_SET_ACTIVE_POWER_EQUALS(Doc.of(OpenemsType.FLOAT) // .accessMode(AccessMode.WRITE_ONLY)// .unit(Unit.WATT)), // diff --git a/io.openems.edge.energy.api/src/io/openems/edge/energy/api/simulation/EnergyFlow.java b/io.openems.edge.energy.api/src/io/openems/edge/energy/api/simulation/EnergyFlow.java index c5fe1c3774f..0f47cffd3e5 100644 --- a/io.openems.edge.energy.api/src/io/openems/edge/energy/api/simulation/EnergyFlow.java +++ b/io.openems.edge.energy.api/src/io/openems/edge/energy/api/simulation/EnergyFlow.java @@ -196,15 +196,14 @@ public static class Model { * @return a new {@link EnergyFlow.Model} */ public static EnergyFlow.Model from(OneSimulationContext osc, Period period) { - final int factor; // TODO replace with switch in Java 21 - if (period instanceof GlobalSimulationsContext.Period.Hour) { - factor = 4; - } else { - factor = 1; - } + final var factor = switch (period) { + case GlobalSimulationsContext.Period.Hour p -> 4; + case GlobalSimulationsContext.Period.Quarter p -> 1; + }; final var essGlobal = osc.global.ess(); final var essOne = osc.ess; final var grid = osc.global.grid(); + return new EnergyFlow.Model(// /* production */ period.production(), // /* consumption */ period.consumption(), // diff --git a/io.openems.edge.energy.api/src/io/openems/edge/energy/api/test/DummyGlobalSimulationsContext.java b/io.openems.edge.energy.api/src/io/openems/edge/energy/api/test/DummyGlobalSimulationsContext.java index 9328ae82a66..e6b87c2935c 100644 --- a/io.openems.edge.energy.api/src/io/openems/edge/energy/api/test/DummyGlobalSimulationsContext.java +++ b/io.openems.edge.energy.api/src/io/openems/edge/energy/api/test/DummyGlobalSimulationsContext.java @@ -1,6 +1,7 @@ package io.openems.edge.energy.api.test; import static com.google.common.collect.ImmutableList.toImmutableList; +import static io.openems.common.test.TestUtils.createDummyClock; import static io.openems.edge.energy.api.EnergyUtils.filterEshsWithDifferentStates; import java.time.ZonedDateTime; @@ -10,7 +11,6 @@ import com.google.common.collect.ImmutableMap; import io.openems.common.test.TimeLeapClock; -import io.openems.edge.common.test.TestUtils; import io.openems.edge.energy.api.EnergyScheduleHandler; import io.openems.edge.energy.api.RiskLevel; import io.openems.edge.energy.api.simulation.GlobalSimulationsContext; @@ -22,7 +22,7 @@ public class DummyGlobalSimulationsContext { private DummyGlobalSimulationsContext() { } - public static final TimeLeapClock CLOCK = TestUtils.createDummyClock(); + public static final TimeLeapClock CLOCK = createDummyClock(); public static final ZonedDateTime TIME = ZonedDateTime.now(CLOCK); /** diff --git a/io.openems.edge.energy/src/io/openems/edge/energy/optimizer/Optimizer.java b/io.openems.edge.energy/src/io/openems/edge/energy/optimizer/Optimizer.java index 17a80bec581..178c01edb15 100644 --- a/io.openems.edge.energy/src/io/openems/edge/energy/optimizer/Optimizer.java +++ b/io.openems.edge.energy/src/io/openems/edge/energy/optimizer/Optimizer.java @@ -3,7 +3,7 @@ import static io.jenetics.engine.Limits.byExecutionTime; import static io.jenetics.engine.Limits.byFixedGeneration; import static io.openems.common.utils.ThreadPoolUtils.shutdownAndAwaitTermination; -import static io.openems.edge.energy.optimizer.SimulationResult.EMPTY; +import static io.openems.edge.energy.optimizer.SimulationResult.EMPTY_SIMULATION_RESULT; import static io.openems.edge.energy.optimizer.Utils.calculateExecutionLimitSeconds; import static io.openems.edge.energy.optimizer.Utils.calculateSleepMillis; import static io.openems.edge.energy.optimizer.Utils.createSimulator; @@ -50,7 +50,7 @@ public class Optimizer implements Runnable { private final AtomicBoolean rescheduleCurrentPeriod = new AtomicBoolean(false); private Simulator simulator = null; - private SimulationResult simulationResult = EMPTY; + private SimulationResult simulationResult = EMPTY_SIMULATION_RESULT; private ScheduledFuture future; public Optimizer(Supplier logVerbosity, @@ -94,13 +94,20 @@ public synchronized void deactivate() { */ public void triggerReschedule(String reason) { // NOTE: This is what happens here: - // [_cycle ] INFO [dge.energy.optimizer.Optimizer] OPTIMIZER Trigger Reschedule. Reason: ControllerEvcsImpl::onEvcsStatusChange from 6:The charging limit reached to 1:Not ready for Charging - // [thread-1] INFO [dge.energy.optimizer.Optimizer] OPTIMIZER Optimizer::run() InterruptedException: null - // [thread-1] INFO [dge.energy.optimizer.Optimizer] OPTIMIZER Simulation gave no result! - // [thread-1] INFO [dge.energy.optimizer.Optimizer] OPTIMIZER Run Quick Optimization... - // [thread-1] INFO [dge.energy.optimizer.Optimizer] OPTIMIZER updateSimulator()... - - // TODO On interrupt: keep best "regularOptimization" up till now as input for next InitialPopulation + // [_cycle ] INFO [dge.energy.optimizer.Optimizer] OPTIMIZER Trigger Reschedule. + // Reason: ControllerEvcsImpl::onEvcsStatusChange from 6:The charging limit + // reached to 1:Not ready for Charging + // [thread-1] INFO [dge.energy.optimizer.Optimizer] OPTIMIZER Optimizer::run() + // InterruptedException: null + // [thread-1] INFO [dge.energy.optimizer.Optimizer] OPTIMIZER Simulation gave no + // result! + // [thread-1] INFO [dge.energy.optimizer.Optimizer] OPTIMIZER Run Quick + // Optimization... + // [thread-1] INFO [dge.energy.optimizer.Optimizer] OPTIMIZER + // updateSimulator()... + + // TODO On interrupt: keep best "regularOptimization" up till now as input for + // next InitialPopulation this.traceLog(() -> "Trigger Reschedule. Reason: " + reason); this.rescheduleCurrentPeriod.set(true); this.activate(); // interrupt + reschedule @@ -108,9 +115,9 @@ public void triggerReschedule(String reason) { @Override public void run() { - var simulationResult = SimulationResult.EMPTY; + var simulationResult = EMPTY_SIMULATION_RESULT; try { - if (this.rescheduleCurrentPeriod.getAndSet(false) || this.simulationResult == EMPTY) { + if (this.rescheduleCurrentPeriod.getAndSet(false) || this.simulationResult == EMPTY_SIMULATION_RESULT) { this.traceLog(() -> "Run Quick Optimization..."); simulationResult = this.runQuickOptimization(); } else { @@ -140,7 +147,7 @@ private Simulator updateSimulator() throws InterruptedException { simulator -> this.simulator = simulator, // error -> { this.traceLog(error); - this.applySimulationResult(EMPTY); + this.applySimulationResult(EMPTY_SIMULATION_RESULT); }); final var simulator = this.simulator; if (simulator == null) { @@ -165,10 +172,10 @@ private Simulator updateSimulator() throws InterruptedException { protected SimulationResult runQuickOptimization() throws InterruptedException, ExecutionException { var simulator = this.updateSimulator(); if (simulator == null) { - return SimulationResult.EMPTY; + return EMPTY_SIMULATION_RESULT; } - if (this.simulationResult == EMPTY) { + if (this.simulationResult == EMPTY_SIMULATION_RESULT) { this.traceLog(() -> "reschedule because previous simulationresult is EMPTY"); } else { this.traceLog(() -> "triggerReschedule() had been called -> reschedule"); @@ -195,7 +202,7 @@ protected SimulationResult runRegularOptimization() throws InterruptedException, } var simulator = this.updateSimulator(); if (simulator == null) { - return SimulationResult.EMPTY; + return EMPTY_SIMULATION_RESULT; } this.traceLog(() -> "Run Simulation"); @@ -227,7 +234,7 @@ protected CompletableFuture runSimulation(Simulator simulator, * @param simulationResult the {@link SimulationResult} */ protected void applySimulationResult(SimulationResult simulationResult) { - if (simulationResult == EMPTY /* no result */) { + if (simulationResult == EMPTY_SIMULATION_RESULT /* no result */) { this.traceLog(() -> "Simulation gave no result!"); } diff --git a/io.openems.edge.energy/src/io/openems/edge/energy/optimizer/SimulationResult.java b/io.openems.edge.energy/src/io/openems/edge/energy/optimizer/SimulationResult.java index 4928906bd03..628bb672553 100644 --- a/io.openems.edge.energy/src/io/openems/edge/energy/optimizer/SimulationResult.java +++ b/io.openems.edge.energy/src/io/openems/edge/energy/optimizer/SimulationResult.java @@ -56,7 +56,8 @@ public static Period from(GlobalSimulationsContext.Period context, EnergyFlow en /** * An empty {@link SimulationResult}. */ - public static final SimulationResult EMPTY = new SimulationResult(0., ImmutableSortedMap.of(), ImmutableMap.of()); + public static final SimulationResult EMPTY_SIMULATION_RESULT = new SimulationResult(0., // + ImmutableSortedMap.of(), ImmutableMap.of()); /** * Re-Simulate a {@link Genotype} to create a {@link SimulationResult}. @@ -98,23 +99,28 @@ private static SimulationResult from(GlobalSimulationsContext gsc, int[][] sched */ public static SimulationResult fromQuarters(GlobalSimulationsContext gsc, int[][] schedule) { if (gsc == null || schedule.length == 0) { - return SimulationResult.EMPTY; + return EMPTY_SIMULATION_RESULT; } // Convert to Quarters final var quarterPeriods = gsc.periods().stream() // - .flatMap(period -> period instanceof GlobalSimulationsContext.Period.Hour ph // - ? ph.quarterPeriods().stream() - : Stream.of(period)) // + .flatMap(period -> switch (period) { + case GlobalSimulationsContext.Period.Hour ph // + -> ph.quarterPeriods().stream(); + case GlobalSimulationsContext.Period.Quarter pq // + -> Stream.of(period); + }) // .collect(ImmutableList.toImmutableList()); final GlobalSimulationsContext quarterGsc = new GlobalSimulationsContext(gsc.clock(), gsc.riskLevel(), gsc.startTime(), gsc.eshs(), gsc.eshsWithDifferentStates(), gsc.grid(), gsc.ess(), gsc.evcss(), quarterPeriods); final var quarterSchedule = IntStream.range(0, gsc.periods().size()) // - .flatMap(periodIndex // - -> gsc.periods().get(periodIndex) instanceof GlobalSimulationsContext.Period.Hour ph // - ? ph.quarterPeriods().stream().mapToInt(ignore -> periodIndex) // repeat - : IntStream.of(periodIndex)) // + .flatMap(periodIndex -> switch (gsc.periods().get(periodIndex)) { + case GlobalSimulationsContext.Period.Hour ph // + -> ph.quarterPeriods().stream().mapToInt(ignore -> periodIndex); // repeat + case GlobalSimulationsContext.Period.Quarter pq // + -> IntStream.of(periodIndex); + }) // .mapToObj(periodIndex // -> IntStream.range(0, gsc.eshsWithDifferentStates().size()) // .map(eshIndex -> { diff --git a/io.openems.edge.energy/src/io/openems/edge/energy/optimizer/Simulator.java b/io.openems.edge.energy/src/io/openems/edge/energy/optimizer/Simulator.java index fbdaa6fa30e..865c9858ade 100644 --- a/io.openems.edge.energy/src/io/openems/edge/energy/optimizer/Simulator.java +++ b/io.openems.edge.energy/src/io/openems/edge/energy/optimizer/Simulator.java @@ -3,7 +3,7 @@ import static com.google.common.base.MoreObjects.toStringHelper; import static io.jenetics.engine.EvolutionResult.toBestResult; import static io.openems.edge.energy.optimizer.InitialPopulation.generateInitialPopulation; -import static io.openems.edge.energy.optimizer.SimulationResult.EMPTY; +import static io.openems.edge.energy.optimizer.SimulationResult.EMPTY_SIMULATION_RESULT; import static java.lang.Thread.currentThread; import java.util.concurrent.Executor; @@ -25,6 +25,7 @@ import io.jenetics.SinglePointCrossover; import io.jenetics.engine.Engine; import io.jenetics.engine.EvolutionStream; +import io.openems.common.utils.FunctionUtils; import io.openems.edge.energy.api.EnergyScheduleHandler; import io.openems.edge.energy.api.EnergyScheduleHandler.AbstractEnergyScheduleHandler; import io.openems.edge.energy.api.simulation.EnergyFlow; @@ -128,11 +129,11 @@ public static double simulatePeriod(OneSimulationContext simulation, int[][] sch double cost = 0.; var eshIndex = 0; for (var esh : eshs) { - if (esh instanceof EnergyScheduleHandler.WithDifferentStates e) { - // Simulate with state given by Genotype - cost += e.simulatePeriod(simulation, period, model, schedule[periodIndex][eshIndex++]); - } else if (esh instanceof EnergyScheduleHandler.WithOnlyOneState e) { - e.simulatePeriod(simulation, period, model); + switch (esh) { + case EnergyScheduleHandler.WithDifferentStates e // + -> cost += e.simulatePeriod(simulation, period, model, schedule[periodIndex][eshIndex++]); + case EnergyScheduleHandler.WithOnlyOneState e // + -> e.simulatePeriod(simulation, period, model); } } @@ -167,9 +168,12 @@ public static double simulatePeriod(OneSimulationContext simulation, int[][] sch bestScheduleCollector.allPeriods.accept(srp); eshIndex = 0; for (var esh : eshs) { - if (esh instanceof EnergyScheduleHandler.WithDifferentStates e) { - bestScheduleCollector.eshStates.accept(new EshToState(e, srp, // + switch (esh) { + case EnergyScheduleHandler.WithDifferentStates e // + -> bestScheduleCollector.eshStates.accept(new EshToState(e, srp, // e.postProcessPeriod(period, simulation, energyFlow, schedule[periodIndex][eshIndex++]))); + case EnergyScheduleHandler.WithOnlyOneState e // + -> FunctionUtils.doNothing(); } } } @@ -198,7 +202,7 @@ public SimulationResult getBestSchedule(SimulationResult previousResult, boolean Function, EvolutionStream> evolutionStreamInterceptor) { final var codec = EshCodec.of(this.gsc, previousResult, isCurrentPeriodFixed); if (codec == null) { - return EMPTY; + return EMPTY_SIMULATION_RESULT; } // Decide for single- or multi-threading @@ -238,7 +242,9 @@ public SimulationResult getBestSchedule(SimulationResult previousResult, boolean // Start the evaluation var bestGt = stream // .collect(toBestResult(codec)); - + if (bestGt == null) { + return EMPTY_SIMULATION_RESULT; + } return SimulationResult.fromQuarters(this.gsc, bestGt); } diff --git a/io.openems.edge.energy/src/io/openems/edge/energy/v1/optimizer/SimulatorV1.java b/io.openems.edge.energy/src/io/openems/edge/energy/v1/optimizer/SimulatorV1.java index 52145544f2e..185de986bdc 100644 --- a/io.openems.edge.energy/src/io/openems/edge/energy/v1/optimizer/SimulatorV1.java +++ b/io.openems.edge.energy/src/io/openems/edge/energy/v1/optimizer/SimulatorV1.java @@ -143,9 +143,7 @@ protected static StateMachine[] getBestSchedule(ParamsV1 p, long executionLimitS Integer limit) { // Return pure BALANCING Schedule if no predictions are available if (!paramsAreValid(p)) { - return p.optimizePeriods().stream() // - .map(op -> StateMachine.BALANCING) // - .toArray(StateMachine[]::new); + return createFallbackSchedule(p); } var gtf = Genotype.of(IntegerChromosome.of(IntegerGene.of(0, p.states().length)), p.optimizePeriods().size()); // @@ -171,8 +169,23 @@ protected static StateMachine[] getBestSchedule(ParamsV1 p, long executionLimitS } var bestGt = stream // .collect(toBestGenotype()); + if (bestGt == null) { + return createFallbackSchedule(p); + } return IntStream.range(0, p.optimizePeriods().size()) // .mapToObj(period -> p.states()[bestGt.get(period).get(0).intValue()]) // .toArray(StateMachine[]::new); } + + /** + * Creates a pure BALANCING schedule. + * + * @param p the {@link ParamsV1} + * @return the schedule + */ + private static StateMachine[] createFallbackSchedule(ParamsV1 p) { + return p.optimizePeriods().stream() // + .map(op -> StateMachine.BALANCING) // + .toArray(StateMachine[]::new); + } } diff --git a/io.openems.edge.energy/test/io/openems/edge/energy/EnergySchedulerImplTest.java b/io.openems.edge.energy/test/io/openems/edge/energy/EnergySchedulerImplTest.java index a4ad94e99c3..7e5b0717e03 100644 --- a/io.openems.edge.energy/test/io/openems/edge/energy/EnergySchedulerImplTest.java +++ b/io.openems.edge.energy/test/io/openems/edge/energy/EnergySchedulerImplTest.java @@ -1,8 +1,8 @@ package io.openems.edge.energy; +import static io.openems.common.test.TestUtils.createDummyClock; import static io.openems.common.utils.DateUtils.roundDownToQuarter; import static io.openems.common.utils.ReflectionUtils.getValueViaReflection; -import static io.openems.edge.common.test.TestUtils.createDummyClock; import static io.openems.edge.energy.LogVerbosity.TRACE; import static io.openems.edge.energy.api.EnergyConstants.SUM_PRODUCTION; import static io.openems.edge.energy.api.EnergyConstants.SUM_UNMANAGED_CONSUMPTION; diff --git a/io.openems.edge.energy/test/io/openems/edge/energy/optimizer/EshCodecTest.java b/io.openems.edge.energy/test/io/openems/edge/energy/optimizer/EshCodecTest.java index 943c4bac6fb..b7a11512859 100644 --- a/io.openems.edge.energy/test/io/openems/edge/energy/optimizer/EshCodecTest.java +++ b/io.openems.edge.energy/test/io/openems/edge/energy/optimizer/EshCodecTest.java @@ -1,5 +1,7 @@ package io.openems.edge.energy.optimizer; +import static io.openems.edge.energy.optimizer.SimulationResult.EMPTY_SIMULATION_RESULT; +import static io.openems.edge.energy.optimizer.SimulatorTest.DUMMY_SIMULATOR; import static java.util.stream.Collectors.joining; import static java.util.stream.IntStream.range; import static org.junit.Assert.assertEquals; @@ -11,9 +13,9 @@ public class EshCodecTest { @Test public void test() { - final var simulator = SimulatorTest.DUMMY_SIMULATOR; + final var simulator = DUMMY_SIMULATOR; final var gsc = simulator.gsc; - final var codec = EshCodec.of(gsc, SimulationResult.EMPTY, false); + final var codec = EshCodec.of(gsc, EMPTY_SIMULATION_RESULT, false); var gt = codec.encoding().newInstance(); @@ -41,7 +43,7 @@ public void test() { @Test public void testNulls() { - final var simulator = SimulatorTest.DUMMY_SIMULATOR; + final var simulator = DUMMY_SIMULATOR; final var gsc = simulator.gsc; final var codec = EshCodec.of(gsc, InitialPopulationTest.PREVIOUS_RESULT, true); assertNull(codec.encode(new int[0][0])); @@ -56,7 +58,7 @@ public void testNulls() { @Test public void testPreviousResult() { - final var simulator = SimulatorTest.DUMMY_SIMULATOR; + final var simulator = DUMMY_SIMULATOR; final var gsc = simulator.gsc; final var codec = EshCodec.of(gsc, InitialPopulationTest.PREVIOUS_RESULT, true); diff --git a/io.openems.edge.energy/test/io/openems/edge/energy/optimizer/InitialPopulationTest.java b/io.openems.edge.energy/test/io/openems/edge/energy/optimizer/InitialPopulationTest.java index 0975bb54738..015b0fd48c2 100644 --- a/io.openems.edge.energy/test/io/openems/edge/energy/optimizer/InitialPopulationTest.java +++ b/io.openems.edge.energy/test/io/openems/edge/energy/optimizer/InitialPopulationTest.java @@ -1,6 +1,6 @@ package io.openems.edge.energy.optimizer; -import static io.openems.edge.common.test.TestUtils.createDummyClock; +import static io.openems.common.test.TestUtils.createDummyClock; import static io.openems.edge.energy.optimizer.EshCodec.schedulesToStringArray; import static io.openems.edge.energy.optimizer.InitialPopulation.variationsFromExistingSimulationResult; import static io.openems.edge.energy.optimizer.InitialPopulation.variationsOfAllStatesDefault; diff --git a/io.openems.edge.energy/test/io/openems/edge/energy/optimizer/OptimizerTest.java b/io.openems.edge.energy/test/io/openems/edge/energy/optimizer/OptimizerTest.java index 0a4843d3bfb..2486c8f3a36 100644 --- a/io.openems.edge.energy/test/io/openems/edge/energy/optimizer/OptimizerTest.java +++ b/io.openems.edge.energy/test/io/openems/edge/energy/optimizer/OptimizerTest.java @@ -1,8 +1,8 @@ package io.openems.edge.energy.optimizer; import static io.jenetics.engine.Limits.byFixedGeneration; +import static io.openems.common.test.TestUtils.createDummyClock; import static io.openems.common.utils.ReflectionUtils.getValueViaReflection; -import static io.openems.edge.common.test.TestUtils.createDummyClock; import static io.openems.edge.energy.EnergySchedulerImplTest.getOptimizer; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; diff --git a/io.openems.edge.energy/test/io/openems/edge/energy/optimizer/SimulatorTest.java b/io.openems.edge.energy/test/io/openems/edge/energy/optimizer/SimulatorTest.java index 16496d95f2a..ff4c950310d 100644 --- a/io.openems.edge.energy/test/io/openems/edge/energy/optimizer/SimulatorTest.java +++ b/io.openems.edge.energy/test/io/openems/edge/energy/optimizer/SimulatorTest.java @@ -2,6 +2,7 @@ import static io.jenetics.engine.Limits.byFixedGeneration; import static io.openems.edge.energy.api.EnergyUtils.socToEnergy; +import static io.openems.edge.energy.optimizer.SimulationResult.EMPTY_SIMULATION_RESULT; import static org.junit.Assert.assertEquals; import java.util.Random; @@ -71,7 +72,7 @@ public void before() { public static SimulationResult generateDummySimulationResult() { final var simulator = DUMMY_SIMULATOR; - return simulator.getBestSchedule(SimulationResult.EMPTY, true /* isCurrentPeriodFixed */, // + return simulator.getBestSchedule(EMPTY_SIMULATION_RESULT, true /* isCurrentPeriodFixed */, // engine -> engine // .populationSize(1), // stream -> stream // diff --git a/io.openems.edge.energy/test/io/openems/edge/energy/optimizer/UtilsTest.java b/io.openems.edge.energy/test/io/openems/edge/energy/optimizer/UtilsTest.java index 91706a287ee..c4a45a1c673 100644 --- a/io.openems.edge.energy/test/io/openems/edge/energy/optimizer/UtilsTest.java +++ b/io.openems.edge.energy/test/io/openems/edge/energy/optimizer/UtilsTest.java @@ -1,6 +1,6 @@ package io.openems.edge.energy.optimizer; -import static io.openems.edge.common.test.TestUtils.createDummyClock; +import static io.openems.common.test.TestUtils.createDummyClock; import static io.openems.edge.energy.optimizer.Utils.calculateExecutionLimitSeconds; import static io.openems.edge.energy.optimizer.Utils.calculateSleepMillis; import static io.openems.edge.energy.optimizer.Utils.sortByScheduler; diff --git a/io.openems.edge.energy/test/io/openems/edge/energy/optimizer/app/RunOptimizerFromLogApp.java b/io.openems.edge.energy/test/io/openems/edge/energy/optimizer/app/RunOptimizerFromLogApp.java index 1d985f6e1ac..de3583a4498 100644 --- a/io.openems.edge.energy/test/io/openems/edge/energy/optimizer/app/RunOptimizerFromLogApp.java +++ b/io.openems.edge.energy/test/io/openems/edge/energy/optimizer/app/RunOptimizerFromLogApp.java @@ -1,8 +1,8 @@ package io.openems.edge.energy.optimizer.app; import static io.jenetics.engine.Limits.byExecutionTime; -import static io.openems.edge.controller.evcs.JSCalendar.RecurrenceFrequency.WEEKLY; -import static io.openems.edge.energy.optimizer.SimulationResult.EMPTY; +import static io.openems.common.jscalendar.JSCalendar.RecurrenceFrequency.WEEKLY; +import static io.openems.edge.energy.optimizer.SimulationResult.EMPTY_SIMULATION_RESULT; import static io.openems.edge.energy.optimizer.app.AppUtils.parseGlobalSimulationsContextFromLogString; import static java.time.DayOfWeek.FRIDAY; import static java.time.DayOfWeek.MONDAY; @@ -16,6 +16,7 @@ import com.google.common.collect.ImmutableList; +import io.openems.common.jscalendar.JSCalendar; import io.openems.edge.controller.ess.emergencycapacityreserve.ControllerEssEmergencyCapacityReserveImpl; import io.openems.edge.controller.ess.fixactivepower.ControllerEssFixActivePowerImpl; import io.openems.edge.controller.ess.gridoptimizedcharge.ControllerEssGridOptimizedChargeImpl; @@ -23,7 +24,6 @@ import io.openems.edge.controller.ess.limittotaldischarge.ControllerEssLimitTotalDischargeImpl; import io.openems.edge.controller.ess.timeofusetariff.ControlMode; import io.openems.edge.controller.ess.timeofusetariff.TimeOfUseTariffControllerImpl; -import io.openems.edge.controller.evcs.JSCalendar; import io.openems.edge.controller.evcs.Utils.EshContext.EshSmartContext; import io.openems.edge.energy.api.EnergyScheduleHandler; import io.openems.edge.energy.api.EnergyUtils; @@ -101,7 +101,8 @@ public class RunOptimizerFromLogApp { public static void main(String[] args) throws Exception { var simulator = new Simulator(parseGlobalSimulationsContextFromLogString(LOG, ESHS)); - var simulationResult = simulator.getBestSchedule(EMPTY, false /* isCurrentPeriodFixed */, null, // + var simulationResult = simulator.getBestSchedule(EMPTY_SIMULATION_RESULT, // + false /* isCurrentPeriodFixed */, null, // stream -> stream // .limit(byExecutionTime(ofSeconds(EXECUTION_LIMIT_SECONDS)))); diff --git a/io.openems.edge.energy/test/io/openems/edge/energy/v1/optimizer/EnergyFlowV1Test.java b/io.openems.edge.energy/test/io/openems/edge/energy/v1/optimizer/EnergyFlowV1Test.java index e9749f1848d..b0de70323b6 100644 --- a/io.openems.edge.energy/test/io/openems/edge/energy/v1/optimizer/EnergyFlowV1Test.java +++ b/io.openems.edge.energy/test/io/openems/edge/energy/v1/optimizer/EnergyFlowV1Test.java @@ -58,8 +58,8 @@ public void prepareParams() { // essChargeInChargeGrid = 2375 } - private static EnergyFlowV1 execute(TriFunction function, int essInitial, - ParamsV1.Builder pb) { + private static EnergyFlowV1 execute(TriFunction function, + int essInitial, ParamsV1.Builder pb) { var p = pb.build(); return function.apply(p, p.optimizePeriods().get(0), essInitial); } diff --git a/io.openems.edge.ess.api/src/io/openems/edge/ess/api/ManagedSymmetricEss.java b/io.openems.edge.ess.api/src/io/openems/edge/ess/api/ManagedSymmetricEss.java index 36565ec140f..d840fe149d3 100644 --- a/io.openems.edge.ess.api/src/io/openems/edge/ess/api/ManagedSymmetricEss.java +++ b/io.openems.edge.ess.api/src/io/openems/edge/ess/api/ManagedSymmetricEss.java @@ -68,6 +68,7 @@ public enum ChannelId implements io.openems.edge.common.channel.ChannelId { SET_ACTIVE_POWER_EQUALS(new IntegerDoc() // .unit(Unit.WATT) // .accessMode(AccessMode.WRITE_ONLY) // + .text("Write command for a charge power (-) or discharge power (+). Range e.g. [-5000 to 5000]") // .onChannelSetNextWrite( new PowerConstraint("SetActivePowerEquals", Phase.ALL, Pwr.ACTIVE, Relationship.EQUALS))), @@ -120,6 +121,7 @@ public void accept(ManagedSymmetricEss ess, Integer value) throws OpenemsNamedEx SET_REACTIVE_POWER_EQUALS(new IntegerDoc() // .unit(Unit.VOLT_AMPERE_REACTIVE) // .accessMode(AccessMode.WRITE_ONLY) // + .text("Write command for the reactive power") // .onChannelSetNextWrite( new PowerConstraint("SetReactivePowerEquals", Phase.ALL, Pwr.REACTIVE, Relationship.EQUALS))), // /** @@ -135,6 +137,7 @@ public void accept(ManagedSymmetricEss ess, Integer value) throws OpenemsNamedEx SET_ACTIVE_POWER_LESS_OR_EQUALS(new IntegerDoc() // .unit(Unit.WATT) // .accessMode(AccessMode.WRITE_ONLY) // + .text("Write command for a minimum charge power (-) or maximum discharge power (+). Range e.g. [-5000 to 5000]") // .onChannelSetNextWrite(new PowerConstraint("SetActivePowerLessOrEquals", Phase.ALL, Pwr.ACTIVE, Relationship.LESS_OR_EQUALS))), // /** @@ -150,6 +153,7 @@ public void accept(ManagedSymmetricEss ess, Integer value) throws OpenemsNamedEx SET_ACTIVE_POWER_GREATER_OR_EQUALS(new IntegerDoc() // .unit(Unit.WATT) // .accessMode(AccessMode.WRITE_ONLY) // + .text("Write command for a maximum charge power (-) or minimum discharge power (+). Range e.g. [-5000 to 5000]") // .onChannelSetNextWrite(new PowerConstraint("SetActivePowerGreaterOrEquals", Phase.ALL, Pwr.ACTIVE, Relationship.GREATER_OR_EQUALS))), // /** @@ -165,6 +169,7 @@ public void accept(ManagedSymmetricEss ess, Integer value) throws OpenemsNamedEx SET_REACTIVE_POWER_LESS_OR_EQUALS(new IntegerDoc() // .unit(Unit.VOLT_AMPERE_REACTIVE) // .accessMode(AccessMode.WRITE_ONLY) // + .text("Write command for the maximum reactive power") // .onChannelSetNextWrite(new PowerConstraint("SetReactivePowerLessOrEquals", Phase.ALL, Pwr.REACTIVE, Relationship.LESS_OR_EQUALS))), // /** @@ -180,6 +185,7 @@ public void accept(ManagedSymmetricEss ess, Integer value) throws OpenemsNamedEx SET_REACTIVE_POWER_GREATER_OR_EQUALS(new IntegerDoc() // .unit(Unit.VOLT_AMPERE_REACTIVE) // .accessMode(AccessMode.WRITE_ONLY) // + .text("Write command for the maximum reactive power") // .onChannelSetNextWrite(new PowerConstraint("SetReactivePowerGreaterOrEquals", Phase.ALL, Pwr.REACTIVE, Relationship.GREATER_OR_EQUALS))), // /** diff --git a/io.openems.edge.ess.api/src/io/openems/edge/ess/api/SymmetricEss.java b/io.openems.edge.ess.api/src/io/openems/edge/ess/api/SymmetricEss.java index 4f14108fd5e..04e27c3b2e1 100644 --- a/io.openems.edge.ess.api/src/io/openems/edge/ess/api/SymmetricEss.java +++ b/io.openems.edge.ess.api/src/io/openems/edge/ess/api/SymmetricEss.java @@ -32,7 +32,8 @@ public enum ChannelId implements io.openems.edge.common.channel.ChannelId { */ SOC(Doc.of(OpenemsType.INTEGER) // .unit(Unit.PERCENT) // - .persistencePriority(PersistencePriority.HIGH)), + .persistencePriority(PersistencePriority.HIGH) // + .text("State of Charge of the energy storage system")), // /** * Capacity. * @@ -57,7 +58,8 @@ public enum ChannelId implements io.openems.edge.common.channel.ChannelId { *
*/ GRID_MODE(Doc.of(GridMode.values()) // - .persistencePriority(PersistencePriority.HIGH)), + .persistencePriority(PersistencePriority.HIGH) // + .text("Current power grid mode; 1:On-Grid, 2:Off-Grid")), // /** * Active Power. * @@ -71,7 +73,9 @@ public enum ChannelId implements io.openems.edge.common.channel.ChannelId { ACTIVE_POWER(Doc.of(OpenemsType.INTEGER) // .unit(Unit.WATT) // .persistencePriority(PersistencePriority.HIGH) // - .text("Negative values for Charge; positive for Discharge") // + .text("Discharge or charging Power (including DC-PV power, if applicable)." + + " For the actual charging or discharging power of the battery, please refer to address" + + " \"ess0/DcDischargePower\". Negative values for charge; positive for discharge.") // ), /** * Reactive Power. @@ -85,6 +89,7 @@ public enum ChannelId implements io.openems.edge.common.channel.ChannelId { REACTIVE_POWER(Doc.of(OpenemsType.INTEGER) // .unit(Unit.VOLT_AMPERE_REACTIVE) // .persistencePriority(PersistencePriority.HIGH) // + .text("Current value of the reactive power")// ), /** * Holds the currently maximum possible apparent power. This value is commonly @@ -138,7 +143,8 @@ public enum ChannelId implements io.openems.edge.common.channel.ChannelId { */ MIN_CELL_VOLTAGE(Doc.of(OpenemsType.INTEGER) // .unit(Unit.MILLIVOLT) // - .persistencePriority(PersistencePriority.HIGH)), + .persistencePriority(PersistencePriority.HIGH) // + .text("Minimum cell voltage")), // /** * Max Cell Voltage. * @@ -153,7 +159,8 @@ public enum ChannelId implements io.openems.edge.common.channel.ChannelId { */ MAX_CELL_VOLTAGE(Doc.of(OpenemsType.INTEGER) // .unit(Unit.MILLIVOLT) // - .persistencePriority(PersistencePriority.HIGH)), + .persistencePriority(PersistencePriority.HIGH) // + .text("Maximum cell voltage")), // /** * Min Cell Temperature. * @@ -168,7 +175,8 @@ public enum ChannelId implements io.openems.edge.common.channel.ChannelId { */ MIN_CELL_TEMPERATURE(Doc.of(OpenemsType.INTEGER) // .unit(Unit.DEGREE_CELSIUS) // - .persistencePriority(PersistencePriority.HIGH)), + .persistencePriority(PersistencePriority.HIGH) // + .text("Minimum cell temperature")), // /** * Max Cell Temperature. * @@ -183,7 +191,8 @@ public enum ChannelId implements io.openems.edge.common.channel.ChannelId { */ MAX_CELL_TEMPERATURE(Doc.of(OpenemsType.INTEGER) // .unit(Unit.DEGREE_CELSIUS) // - .persistencePriority(PersistencePriority.HIGH)); + .persistencePriority(PersistencePriority.HIGH) // + .text("Maximum cell temperature")); // private final Doc doc; diff --git a/io.openems.edge.ess.api/src/io/openems/edge/ess/power/api/EssType.java b/io.openems.edge.ess.api/src/io/openems/edge/ess/power/api/EssType.java index ccb6753c0a8..8164114d4b1 100644 --- a/io.openems.edge.ess.api/src/io/openems/edge/ess/power/api/EssType.java +++ b/io.openems.edge.ess.api/src/io/openems/edge/ess/power/api/EssType.java @@ -16,15 +16,11 @@ public enum EssType { * @return the {@link EssType} */ public static EssType getEssType(ManagedSymmetricEss ess) { - if (ess instanceof MetaEss) { - return META; - } - if (ess instanceof ManagedSinglePhaseEss) { - return EssType.SINGLE_PHASE; - } else if (ess instanceof ManagedAsymmetricEss) { - return EssType.ASYMMETRIC; - } else { - return EssType.SYMMETRIC; - } + return switch (ess) { + case MetaEss me -> META; + case ManagedSinglePhaseEss mspe -> SINGLE_PHASE; + case ManagedAsymmetricEss mae -> ASYMMETRIC; + default -> SYMMETRIC; + }; } } diff --git a/io.openems.edge.ess.api/src/io/openems/edge/ess/power/api/Inverter.java b/io.openems.edge.ess.api/src/io/openems/edge/ess/power/api/Inverter.java index bcc6a2fd3a8..e89e7f7901a 100644 --- a/io.openems.edge.ess.api/src/io/openems/edge/ess/power/api/Inverter.java +++ b/io.openems.edge.ess.api/src/io/openems/edge/ess/power/api/Inverter.java @@ -17,45 +17,40 @@ public static Inverter[] of(boolean symmetricMode, ManagedSymmetricEss ess, EssT var essId = ess.id(); if (symmetricMode) { // Symmetric Mode -> always return a symmetric ThreePhaseInverter - switch (essType) { - case SINGLE_PHASE: - case ASYMMETRIC: - case SYMMETRIC: - return new Inverter[] { new ThreePhaseInverter(essId) }; - - case META: - return new Inverter[0]; - } + return switch (essType) { + case SINGLE_PHASE, ASYMMETRIC, SYMMETRIC // + -> new Inverter[] { new ThreePhaseInverter(essId) }; + case META // + -> new Inverter[0]; + }; } else { // Asymmetric Mode - switch (essType) { - case SINGLE_PHASE: + return switch (essType) { + case SINGLE_PHASE -> { var phase = ((ManagedSinglePhaseEss) ess).getPhase().getPowerApiPhase(); - return new Inverter[] { // - phase == Phase.L1 ? new SinglePhaseInverter(essId, Phase.L1) + yield new Inverter[] { // + phase == Phase.L1 // + ? new SinglePhaseInverter(essId, Phase.L1) : new DummyInverter(essId, Phase.L1), - phase == Phase.L2 ? new SinglePhaseInverter(essId, Phase.L2) + phase == Phase.L2 // + ? new SinglePhaseInverter(essId, Phase.L2) : new DummyInverter(essId, Phase.L2), - phase == Phase.L3 ? new SinglePhaseInverter(essId, Phase.L3) + phase == Phase.L3 // + ? new SinglePhaseInverter(essId, Phase.L3) : new DummyInverter(essId, Phase.L3), // }; - - case ASYMMETRIC: - return new Inverter[] { // - new SinglePhaseInverter(essId, Phase.L1), // - new SinglePhaseInverter(essId, Phase.L2), // - new SinglePhaseInverter(essId, Phase.L3) // - }; - - case META: - return new Inverter[0]; - - case SYMMETRIC: - return new Inverter[] { new ThreePhaseInverter(essId) }; } + case ASYMMETRIC -> new Inverter[] { // + new SinglePhaseInverter(essId, Phase.L1), // + new SinglePhaseInverter(essId, Phase.L2), // + new SinglePhaseInverter(essId, Phase.L3) // + }; + case META // + -> new Inverter[0]; + case SYMMETRIC // + -> new Inverter[] { new ThreePhaseInverter(essId) }; + }; } - // should never come here - return new Inverter[0]; } private final String essId; diff --git a/io.openems.edge.ess.api/src/io/openems/edge/ess/test/DummyPower.java b/io.openems.edge.ess.api/src/io/openems/edge/ess/test/DummyPower.java index c9950264502..31d845bd9e1 100644 --- a/io.openems.edge.ess.api/src/io/openems/edge/ess/test/DummyPower.java +++ b/io.openems.edge.ess.api/src/io/openems/edge/ess/test/DummyPower.java @@ -107,7 +107,7 @@ public void setMaxApparentPower(int maxApparentPower) { @Override public int getMaxPower(ManagedSymmetricEss ess, Phase phase, Pwr pwr) { var result = this.maxApparentPower; - for (ManagedSymmetricEss e : this.esss) { + for (var e : this.esss) { result = TypeUtils.min(result, e.getMaxApparentPower().get(), e.getAllowedDischargePower().get()); } return result; @@ -116,7 +116,7 @@ public int getMaxPower(ManagedSymmetricEss ess, Phase phase, Pwr pwr) { @Override public int getMinPower(ManagedSymmetricEss ess, Phase phase, Pwr pwr) { var result = this.maxApparentPower; - for (ManagedSymmetricEss e : this.esss) { + for (var e : this.esss) { result = TypeUtils.min(result, e.getMaxApparentPower().get(), TypeUtils.multiply(e.getAllowedChargePower().get(), -1)); } @@ -135,11 +135,6 @@ public PidFilter getPidFilter() { @Override public boolean isPidEnabled() { - if (this.pidFilter instanceof DisabledPidFilter) { - return false; - } - - return true; + return !(this.pidFilter instanceof DisabledPidFilter); } - } diff --git a/io.openems.edge.ess.cluster/src/io/openems/edge/ess/cluster/ChannelManager.java b/io.openems.edge.ess.cluster/src/io/openems/edge/ess/cluster/ChannelManager.java index 163b38facb9..08c3bef61c2 100644 --- a/io.openems.edge.ess.cluster/src/io/openems/edge/ess/cluster/ChannelManager.java +++ b/io.openems.edge.ess.cluster/src/io/openems/edge/ess/cluster/ChannelManager.java @@ -193,8 +193,8 @@ private void calculate(BiFunction aggregator, List es final BiConsumer, Value> callback = (oldValue, newValue) -> { T result = null; for (SymmetricEss ess : esss) { - if (ess instanceof ManagedSymmetricEss) { - Channel channel = ((ManagedSymmetricEss) ess).channel(channelId); + if (ess instanceof ManagedSymmetricEss mse) { + Channel channel = mse.channel(channelId); result = aggregator.apply(result, channel.getNextValue().get()); } } @@ -202,8 +202,8 @@ private void calculate(BiFunction aggregator, List es channel.setNextValue(result); }; for (SymmetricEss ess : esss) { - if (ess instanceof ManagedSymmetricEss) { - this.addOnChangeListener((ManagedSymmetricEss) ess, channelId, callback); + if (ess instanceof ManagedSymmetricEss mse) { + this.addOnChangeListener(mse, channelId, callback); } } } @@ -225,8 +225,8 @@ private void calculate(BiFunction aggregator, List es final BiConsumer, Value> callback = (oldValue, newValue) -> { T result = null; for (SymmetricEss ess : esss) { - if (ess instanceof AsymmetricEss) { - Channel channel = ((AsymmetricEss) ess).channel(asymmetricChannelId); + if (ess instanceof AsymmetricEss ae) { + Channel channel = ae.channel(asymmetricChannelId); result = aggregator.apply(result, channel.getNextValue().get()); } else { // SymmetricEss @@ -238,8 +238,8 @@ private void calculate(BiFunction aggregator, List es channel.setNextValue(result); }; for (SymmetricEss ess : esss) { - if (ess instanceof AsymmetricEss) { - this.addOnChangeListener((AsymmetricEss) ess, asymmetricChannelId, callback); + if (ess instanceof AsymmetricEss ae) { + this.addOnChangeListener(ae, asymmetricChannelId, callback); } else { this.addOnChangeListener(ess, symmetricChannelId, callback); } diff --git a/io.openems.edge.ess.cluster/src/io/openems/edge/ess/cluster/EssClusterImpl.java b/io.openems.edge.ess.cluster/src/io/openems/edge/ess/cluster/EssClusterImpl.java index 1f97b086105..12fa10d57e4 100644 --- a/io.openems.edge.ess.cluster/src/io/openems/edge/ess/cluster/EssClusterImpl.java +++ b/io.openems.edge.ess.cluster/src/io/openems/edge/ess/cluster/EssClusterImpl.java @@ -131,8 +131,8 @@ public void applyPower(int activePowerL1, int reactivePowerL1, int activePowerL2 public int getPowerPrecision() { Integer result = null; for (var ess : this.esss) { - if (ess instanceof ManagedSymmetricEss) { - result = TypeUtils.min(result, ((ManagedSymmetricEss) ess).getPowerPrecision()); + if (ess instanceof ManagedSymmetricEss ase) { + result = TypeUtils.min(result, ase.getPowerPrecision()); } } return TypeUtils.orElse(result, 1); diff --git a/io.openems.edge.ess.core/src/io/openems/edge/ess/core/power/EssPowerImpl.java b/io.openems.edge.ess.core/src/io/openems/edge/ess/core/power/EssPowerImpl.java index 3cea0e39de1..b5d6b38deb9 100644 --- a/io.openems.edge.ess.core/src/io/openems/edge/ess/core/power/EssPowerImpl.java +++ b/io.openems.edge.ess.core/src/io/openems/edge/ess/core/power/EssPowerImpl.java @@ -1,5 +1,7 @@ package io.openems.edge.ess.core.power; +import static io.openems.edge.ess.core.power.data.LogUtil.debugLogConstraints; + import java.util.List; import org.apache.commons.math3.optim.nonlinear.scalar.GoalType; @@ -30,7 +32,6 @@ import io.openems.edge.common.filter.PidFilter; import io.openems.edge.ess.api.ManagedSymmetricEss; import io.openems.edge.ess.core.power.data.ConstraintUtil; -import io.openems.edge.ess.core.power.data.LogUtil; import io.openems.edge.ess.core.power.solver.CalculatePowerExtrema; import io.openems.edge.ess.power.api.Coefficient; import io.openems.edge.ess.power.api.Constraint; @@ -153,11 +154,11 @@ public synchronized Constraint addConstraintAndValidate(Constraint constraint) t this.data.removeConstraint(constraint); if (this.debugMode) { var allConstraints = this.data.getConstraintsForAllInverters(); - LogUtil.debugLogConstraints(this.log, "Unable to validate with following constraints:", allConstraints); + debugLogConstraints(this.log, "Unable to validate with following constraints:", allConstraints); this.logWarn(this.log, "Failed to add Constraint: " + constraint); } - if (e instanceof PowerException) { - ((PowerException) e).setReason(constraint); + if (e instanceof PowerException pe) { + pe.setReason(constraint); } throw e; } diff --git a/io.openems.edge.ess.core/src/io/openems/edge/ess/core/power/Solver.java b/io.openems.edge.ess.core/src/io/openems/edge/ess/core/power/Solver.java index 2e89950ee29..6af9c0298e8 100644 --- a/io.openems.edge.ess.core/src/io/openems/edge/ess/core/power/Solver.java +++ b/io.openems.edge.ess.core/src/io/openems/edge/ess/core/power/Solver.java @@ -1,5 +1,10 @@ package io.openems.edge.ess.core.power; +import static io.openems.edge.ess.power.api.SolverStrategy.OPTIMIZE_BY_KEEPING_ALL_EQUAL; +import static io.openems.edge.ess.power.api.SolverStrategy.OPTIMIZE_BY_KEEPING_ALL_NEAR_EQUAL; +import static io.openems.edge.ess.power.api.SolverStrategy.OPTIMIZE_BY_KEEPING_TARGET_DIRECTION_AND_MAXIMIZING_IN_ORDER; +import static io.openems.edge.ess.power.api.SolverStrategy.OPTIMIZE_BY_MOVING_TOWARDS_TARGET; + import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -161,34 +166,27 @@ public void solve(SolverStrategy strategy) { var targetInverters = this.optimizers.reduceNumberOfUsedInverters.apply(allInverters, targetDirection, this.solveWithDisabledInverters); - switch (strategy) { - case UNDEFINED: - case ALL_CONSTRAINTS: - case NONE: - solution = this.tryStrategies(targetDirection, allInverters, targetInverters, allConstraints); - break; + solution = switch (strategy) { + case UNDEFINED, ALL_CONSTRAINTS, NONE // + -> this.tryStrategies(targetDirection, allInverters, targetInverters, allConstraints); - case OPTIMIZE_BY_MOVING_TOWARDS_TARGET: - solution = this.tryStrategies(targetDirection, allInverters, targetInverters, allConstraints, - SolverStrategy.OPTIMIZE_BY_MOVING_TOWARDS_TARGET, - SolverStrategy.OPTIMIZE_BY_KEEPING_TARGET_DIRECTION_AND_MAXIMIZING_IN_ORDER); - break; + case OPTIMIZE_BY_MOVING_TOWARDS_TARGET // + -> this.tryStrategies(targetDirection, allInverters, targetInverters, allConstraints, + OPTIMIZE_BY_MOVING_TOWARDS_TARGET, + OPTIMIZE_BY_KEEPING_TARGET_DIRECTION_AND_MAXIMIZING_IN_ORDER); - case OPTIMIZE_BY_KEEPING_TARGET_DIRECTION_AND_MAXIMIZING_IN_ORDER: - solution = this.tryStrategies(targetDirection, allInverters, targetInverters, allConstraints, - SolverStrategy.OPTIMIZE_BY_KEEPING_TARGET_DIRECTION_AND_MAXIMIZING_IN_ORDER, - SolverStrategy.OPTIMIZE_BY_MOVING_TOWARDS_TARGET); - break; + case OPTIMIZE_BY_KEEPING_TARGET_DIRECTION_AND_MAXIMIZING_IN_ORDER // + -> this.tryStrategies(targetDirection, allInverters, targetInverters, allConstraints, + OPTIMIZE_BY_KEEPING_TARGET_DIRECTION_AND_MAXIMIZING_IN_ORDER, + OPTIMIZE_BY_MOVING_TOWARDS_TARGET); - case OPTIMIZE_BY_KEEPING_ALL_EQUAL: - case OPTIMIZE_BY_KEEPING_ALL_NEAR_EQUAL: - solution = this.tryStrategies(targetDirection, allInverters, targetInverters, allConstraints, - SolverStrategy.OPTIMIZE_BY_KEEPING_ALL_EQUAL, // - SolverStrategy.OPTIMIZE_BY_KEEPING_ALL_NEAR_EQUAL, // - SolverStrategy.OPTIMIZE_BY_KEEPING_TARGET_DIRECTION_AND_MAXIMIZING_IN_ORDER, - SolverStrategy.OPTIMIZE_BY_MOVING_TOWARDS_TARGET); - break; - } + case OPTIMIZE_BY_KEEPING_ALL_EQUAL, OPTIMIZE_BY_KEEPING_ALL_NEAR_EQUAL // + -> this.tryStrategies(targetDirection, allInverters, targetInverters, allConstraints, + OPTIMIZE_BY_KEEPING_ALL_EQUAL, // + OPTIMIZE_BY_KEEPING_ALL_NEAR_EQUAL, // + OPTIMIZE_BY_KEEPING_TARGET_DIRECTION_AND_MAXIMIZING_IN_ORDER, + OPTIMIZE_BY_MOVING_TOWARDS_TARGET); // // + }; } catch (NoFeasibleSolutionException | UnboundedSolutionException e) { if (this.debugMode) { @@ -332,7 +330,7 @@ private void applySolution(Map finalSolution) { } } - if (ess instanceof ManagedAsymmetricEss && (invL1 != null || invL2 != null || invL3 != null)) { + if (ess instanceof ManagedAsymmetricEss e && (invL1 != null || invL2 != null || invL3 != null)) { /* * Call applyPower() of ManagedAsymmetricEss */ @@ -347,7 +345,6 @@ private void applySolution(Map finalSolution) { invL3 = new PowerTuple(); } - var e = (ManagedAsymmetricEss) ess; // set debug channels on Ess e._setDebugSetActivePower(invL1.getActivePower() + invL2.getActivePower() + invL3.getActivePower()); e._setDebugSetReactivePower( diff --git a/io.openems.edge.ess.core/src/io/openems/edge/ess/core/power/data/ConstraintUtil.java b/io.openems.edge.ess.core/src/io/openems/edge/ess/core/power/data/ConstraintUtil.java index f409852b23e..c6dc6e9561c 100644 --- a/io.openems.edge.ess.core/src/io/openems/edge/ess/core/power/data/ConstraintUtil.java +++ b/io.openems.edge.ess.core/src/io/openems/edge/ess/core/power/data/ConstraintUtil.java @@ -1,5 +1,9 @@ package io.openems.edge.ess.core.power.data; +import static io.openems.edge.ess.core.power.data.ApparentPowerConstraintUtil.generateConstraints; +import static io.openems.edge.ess.power.api.EssType.SYMMETRIC; +import static io.openems.edge.ess.power.api.EssType.getEssType; + import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -19,14 +23,13 @@ import io.openems.edge.ess.power.api.Coefficients; import io.openems.edge.ess.power.api.Constraint; import io.openems.edge.ess.power.api.DummyInverter; -import io.openems.edge.ess.power.api.EssType; import io.openems.edge.ess.power.api.Inverter; import io.openems.edge.ess.power.api.LinearCoefficient; import io.openems.edge.ess.power.api.Phase; import io.openems.edge.ess.power.api.Pwr; import io.openems.edge.ess.power.api.Relationship; -public class ConstraintUtil { +public final class ConstraintUtil { private static final Logger LOG = LoggerFactory.getLogger(ConstraintUtil.class); @@ -66,11 +69,11 @@ public static Constraint createSimpleConstraint(Coefficients coefficients, Strin public static List createDisableConstraintsForInactiveInverters(Coefficients coefficients, Collection inverters) throws OpenemsException { List result = new ArrayList<>(); - for (Inverter inv : inverters) { + for (var inv : inverters) { var essId = inv.getEssId(); var phase = inv.getPhase(); for (Pwr pwr : Pwr.values()) { - result.add(ConstraintUtil.createSimpleConstraint(coefficients, // + result.add(createSimpleConstraint(coefficients, // essId + ": Disable " + pwr.getSymbol() + phase.getSymbol(), // essId, phase, pwr, Relationship.EQUALS, 0)); } @@ -91,7 +94,7 @@ public static List createDisableConstraintsForInactiveInverters(Coef public static List createGenericEssConstraints(Coefficients coefficients, List esss, boolean symmetricMode) throws OpenemsException { List result = new ArrayList<>(); - for (ManagedSymmetricEss ess : esss) { + for (var ess : esss) { if (ess instanceof MetaEss) { // ignore @@ -99,12 +102,12 @@ public static List createGenericEssConstraints(Coefficients coeffici } // Allowed Charge Power - result.add(ConstraintUtil.createSimpleConstraint(coefficients, ess.id() + ": Allowed Charge", // + result.add(createSimpleConstraint(coefficients, ess.id() + ": Allowed Charge", // ess.id(), Phase.ALL, Pwr.ACTIVE, Relationship.GREATER_OR_EQUALS, // ess.getAllowedChargePower().orElse(0))); // Allowed Charge Power - result.add(ConstraintUtil.createSimpleConstraint(coefficients, ess.id() + ": Allowed Discharge", // + result.add(createSimpleConstraint(coefficients, ess.id() + ": Allowed Discharge", // ess.id(), Phase.ALL, Pwr.ACTIVE, Relationship.LESS_OR_EQUALS, // ess.getAllowedDischargePower().orElse(0))); @@ -112,16 +115,14 @@ public static List createGenericEssConstraints(Coefficients coeffici int maxApparentPower = ess.getMaxApparentPower().orElse(0); if (ess instanceof ManagedAsymmetricEss && !symmetricMode && !(ess instanceof ManagedSinglePhaseEss)) { var maxApparentPowerPerPhase = maxApparentPower / 3d; - for (Phase phase : Phase.values()) { + for (var phase : Phase.values()) { if (phase == Phase.ALL) { continue; // do not add Max Apparent Power Constraint for ALL phases } - result.addAll(ApparentPowerConstraintUtil.generateConstraints(coefficients, ess.id(), phase, - maxApparentPowerPerPhase)); + result.addAll(generateConstraints(coefficients, ess.id(), phase, maxApparentPowerPerPhase)); } } else { - result.addAll(ApparentPowerConstraintUtil.generateConstraints(coefficients, ess.id(), Phase.ALL, - maxApparentPower)); + result.addAll(generateConstraints(coefficients, ess.id(), Phase.ALL, maxApparentPower)); } } return result; @@ -140,7 +141,7 @@ public static List createStaticEssConstraints(List onStaticConstraintsFailed) { List result = new ArrayList<>(); var isFailed = false; - for (ManagedSymmetricEss ess : esss) { + for (var ess : esss) { try { Collections.addAll(result, ess.getStaticConstraints()); } catch (OpenemsNamedException e) { @@ -173,8 +174,8 @@ public static List createSumOfPhasesConstraints(Coefficients coeffic // Symmetric Mode } else { // Asymmetric Mode - for (ManagedSymmetricEss ess : esss) { - for (Pwr pwr : Pwr.values()) { + for (var ess : esss) { + for (var pwr : Pwr.values()) { // creates two constraint of the form // 1*P - 1*L1 - 1*L2 - 1*L3 = 0 // 1*Q - 1*L1 - 1*L2 - 1*L3 = 0 @@ -203,14 +204,14 @@ public static List createSumOfPhasesConstraints(Coefficients coeffic public static List createSymmetricEssConstraints(Coefficients coefficients, List esss, boolean symmetricMode) throws OpenemsException { List result = new ArrayList<>(); - for (ManagedSymmetricEss ess : esss) { - var essType = EssType.getEssType(ess); - if (!symmetricMode && essType == EssType.SYMMETRIC) { + for (var ess : esss) { + var essType = getEssType(ess); + if (!symmetricMode && essType == SYMMETRIC) { /* * Symmetric-Mode is deactivated and this is a Symmetric ESS: Add Symmetric * Constraints */ - for (Pwr pwr : Pwr.values()) { + for (var pwr : Pwr.values()) { // creates two constraint of the form // 1*L1 - 1*L2 = 0 // 1*L1 - 1*L3 = 0 @@ -248,10 +249,10 @@ public static List createSinglePhaseEssConstraints(Coefficients coef // Symmetric Mode } else { // Asymmetric Mode - for (Inverter inv : inverters) { + for (var inv : inverters) { if (inv instanceof DummyInverter) { - for (Pwr pwr : Pwr.values()) { - result.add(ConstraintUtil.createSimpleConstraint(coefficients, // + for (var pwr : Pwr.values()) { + result.add(createSimpleConstraint(coefficients, // inv.getEssId() + ": Dummy " + pwr.getSymbol() + inv.getPhase().getSymbol(), inv.getEssId(), inv.getPhase(), pwr, Relationship.EQUALS, 0)); } @@ -274,19 +275,18 @@ public static List createSinglePhaseEssConstraints(Coefficients coef public static List createMetaEssConstraints(Coefficients coefficients, List esss, boolean symmetricMode) throws OpenemsException { List result = new ArrayList<>(); - for (ManagedSymmetricEss ess : esss) { - if (ess instanceof MetaEss) { - var e = (MetaEss) ess; + for (var ess : esss) { + if (ess instanceof MetaEss e) { if (symmetricMode) { // Symmetric Mode - for (Pwr pwr : Pwr.values()) { - result.add(ConstraintUtil.createOneClusterConstraint(coefficients, e, Phase.ALL, pwr)); + for (var pwr : Pwr.values()) { + result.add(createOneClusterConstraint(coefficients, e, Phase.ALL, pwr)); } } else { // Asymmetric Mode - for (Phase phase : Phase.values()) { + for (var phase : Phase.values()) { for (Pwr pwr : Pwr.values()) { - result.add(ConstraintUtil.createOneClusterConstraint(coefficients, e, phase, pwr)); + result.add(createOneClusterConstraint(coefficients, e, phase, pwr)); } } } @@ -309,10 +309,9 @@ private static Constraint createOneClusterConstraint(Coefficients coefficients, throws OpenemsException { List cos = new ArrayList<>(); cos.add(new LinearCoefficient(coefficients.of(e.id(), phase, pwr), 1)); - for (String subEssId : e.getEssIds()) { + for (var subEssId : e.getEssIds()) { cos.add(new LinearCoefficient(coefficients.of(subEssId, phase, pwr), -1)); } return new Constraint(e.id() + ": Sum of " + pwr.getSymbol() + phase.getSymbol(), cos, Relationship.EQUALS, 0); } - } diff --git a/io.openems.edge.ess.core/src/io/openems/edge/ess/core/power/optimizers/KeepAllNearEqual.java b/io.openems.edge.ess.core/src/io/openems/edge/ess/core/power/optimizers/KeepAllNearEqual.java index c78b33fda9d..7df5bd305a6 100644 --- a/io.openems.edge.ess.core/src/io/openems/edge/ess/core/power/optimizers/KeepAllNearEqual.java +++ b/io.openems.edge.ess.core/src/io/openems/edge/ess/core/power/optimizers/KeepAllNearEqual.java @@ -167,7 +167,7 @@ private static double getPowerSetPoint(List esss, List ess instanceof MetaEss)// + .filter(MetaEss.class::isInstance)// .findFirst().get().id(); var noPowerSetPoint = Double.NaN; diff --git a/io.openems.edge.ess.core/src/io/openems/edge/ess/core/power/optimizers/KeepTargetDirectionAndMaximizeInOrder.java b/io.openems.edge.ess.core/src/io/openems/edge/ess/core/power/optimizers/KeepTargetDirectionAndMaximizeInOrder.java index cece7eb2643..65e86fece72 100644 --- a/io.openems.edge.ess.core/src/io/openems/edge/ess/core/power/optimizers/KeepTargetDirectionAndMaximizeInOrder.java +++ b/io.openems.edge.ess.core/src/io/openems/edge/ess/core/power/optimizers/KeepTargetDirectionAndMaximizeInOrder.java @@ -1,15 +1,20 @@ package io.openems.edge.ess.core.power.optimizers; +import static io.openems.edge.ess.core.power.data.ConstraintUtil.createSimpleConstraint; +import static io.openems.edge.ess.power.api.Relationship.EQUALS; +import static io.openems.edge.ess.power.api.Relationship.GREATER_OR_EQUALS; +import static io.openems.edge.ess.power.api.Relationship.LESS_OR_EQUALS; +import static org.apache.commons.math3.optim.nonlinear.scalar.GoalType.MAXIMIZE; +import static org.apache.commons.math3.optim.nonlinear.scalar.GoalType.MINIMIZE; + import java.util.ArrayList; import java.util.List; import org.apache.commons.math3.optim.PointValuePair; import org.apache.commons.math3.optim.linear.NoFeasibleSolutionException; import org.apache.commons.math3.optim.linear.UnboundedSolutionException; -import org.apache.commons.math3.optim.nonlinear.scalar.GoalType; import io.openems.common.exceptions.OpenemsException; -import io.openems.edge.ess.core.power.data.ConstraintUtil; import io.openems.edge.ess.core.power.data.TargetDirection; import io.openems.edge.ess.core.power.solver.CalculatePowerExtrema; import io.openems.edge.ess.core.power.solver.ConstraintSolver; @@ -17,7 +22,6 @@ import io.openems.edge.ess.power.api.Constraint; import io.openems.edge.ess.power.api.Inverter; import io.openems.edge.ess.power.api.Pwr; -import io.openems.edge.ess.power.api.Relationship; public class KeepTargetDirectionAndMaximizeInOrder { @@ -41,39 +45,32 @@ public static PointValuePair apply(Coefficients coefficients, List all // Add Zero-Constraint for all Inverters that are not Target for (Inverter inv : allInverters) { if (!targetInverters.contains(inv)) { - constraints.add(ConstraintUtil.createSimpleConstraint(coefficients, // + constraints.add(createSimpleConstraint(coefficients, // inv.toString() + ": is not a target inverter", // - inv.getEssId(), inv.getPhase(), Pwr.ACTIVE, Relationship.EQUALS, 0)); - constraints.add(ConstraintUtil.createSimpleConstraint(coefficients, // + inv.getEssId(), inv.getPhase(), Pwr.ACTIVE, EQUALS, 0)); + constraints.add(createSimpleConstraint(coefficients, // inv.toString() + ": is not a target inverter", // - inv.getEssId(), inv.getPhase(), Pwr.REACTIVE, Relationship.EQUALS, 0)); + inv.getEssId(), inv.getPhase(), Pwr.REACTIVE, EQUALS, 0)); } } var result = ConstraintSolver.solve(coefficients, constraints); - var relationship = Relationship.EQUALS; - switch (targetDirection) { - case CHARGE: - relationship = Relationship.LESS_OR_EQUALS; - break; - case DISCHARGE: - relationship = Relationship.GREATER_OR_EQUALS; - break; - case KEEP_ZERO: - relationship = Relationship.EQUALS; - break; - } + var relationship = switch (targetDirection) { + case CHARGE -> LESS_OR_EQUALS; + case DISCHARGE -> GREATER_OR_EQUALS; + case KEEP_ZERO -> EQUALS; + }; - for (Inverter inv : targetInverters) { + for (var inv : targetInverters) { // Create Constraint to force Ess positive/negative/zero according to // targetDirection result = addContraintIfProblemStillSolves(result, constraints, coefficients, - ConstraintUtil.createSimpleConstraint(coefficients, // + createSimpleConstraint(coefficients, // inv.toString() + ": Force ActivePower " + targetDirection.name(), // inv.getEssId(), inv.getPhase(), Pwr.ACTIVE, relationship, 0)); result = addContraintIfProblemStillSolves(result, constraints, coefficients, - ConstraintUtil.createSimpleConstraint(coefficients, // + createSimpleConstraint(coefficients, // inv.toString() + ": Force ReactivePower " + targetDirection.name(), // inv.getEssId(), inv.getPhase(), Pwr.REACTIVE, relationship, 0)); } @@ -83,27 +80,25 @@ public static PointValuePair apply(Coefficients coefficients, List all } // Try maximizing all inverters in order in target direction - for (Inverter inv : targetInverters) { - GoalType goal; - if (targetDirection == TargetDirection.CHARGE) { - goal = GoalType.MINIMIZE; - } else { - goal = GoalType.MAXIMIZE; - } + for (var inv : targetInverters) { + var goal = switch (targetDirection) { + case CHARGE -> MINIMIZE; + case DISCHARGE, KEEP_ZERO -> MAXIMIZE; + }; var activePowerTarget = CalculatePowerExtrema.from(coefficients, allConstraints, inv.getEssId(), inv.getPhase(), Pwr.ACTIVE, goal); result = addContraintIfProblemStillSolves(result, constraints, coefficients, - ConstraintUtil.createSimpleConstraint(coefficients, // + createSimpleConstraint(coefficients, // inv.toString() + ": Set ActivePower " + goal.name() + " value", // - inv.getEssId(), inv.getPhase(), Pwr.ACTIVE, Relationship.EQUALS, activePowerTarget)); + inv.getEssId(), inv.getPhase(), Pwr.ACTIVE, EQUALS, activePowerTarget)); var reactivePowerTarget = CalculatePowerExtrema.from(coefficients, allConstraints, inv.getEssId(), inv.getPhase(), Pwr.REACTIVE, goal); result = addContraintIfProblemStillSolves(result, constraints, coefficients, - ConstraintUtil.createSimpleConstraint(coefficients, // + createSimpleConstraint(coefficients, // inv.toString() + ": Set ReactivePower " + goal.name() + " value", // - inv.getEssId(), inv.getPhase(), Pwr.REACTIVE, Relationship.EQUALS, reactivePowerTarget)); + inv.getEssId(), inv.getPhase(), Pwr.REACTIVE, EQUALS, reactivePowerTarget)); } return result; diff --git a/io.openems.edge.ess.core/test/io/openems/edge/ess/core/power/NearEqualSolverTest.java b/io.openems.edge.ess.core/test/io/openems/edge/ess/core/power/NearEqualSolverTest.java index 9766ada10cf..2e9a0b3446b 100644 --- a/io.openems.edge.ess.core/test/io/openems/edge/ess/core/power/NearEqualSolverTest.java +++ b/io.openems.edge.ess.core/test/io/openems/edge/ess/core/power/NearEqualSolverTest.java @@ -8,7 +8,6 @@ public class NearEqualSolverTest { @Test public void solverTest() { - double[] essUpperLimit = { 10000, 10000, 10000, 1900 }; double[] essLowerLimit = { 0, 0, 0, 1800 }; double setValue = 50000; diff --git a/io.openems.edge.ess.fenecon.commercial40/src/io/openems/edge/ess/fenecon/commercial40/SurplusFeedInHandler.java b/io.openems.edge.ess.fenecon.commercial40/src/io/openems/edge/ess/fenecon/commercial40/SurplusFeedInHandler.java index fc10921573d..fa03794f847 100644 --- a/io.openems.edge.ess.fenecon.commercial40/src/io/openems/edge/ess/fenecon/commercial40/SurplusFeedInHandler.java +++ b/io.openems.edge.ess.fenecon.commercial40/src/io/openems/edge/ess/fenecon/commercial40/SurplusFeedInHandler.java @@ -58,13 +58,13 @@ protected Integer run(List chargers, Config config, Co } // State-Machine - switch (this.state) { - case UNDEFINED: - case DEACTIVATED: + return switch (this.state) { + case UNDEFINED, DEACTIVATED -> { this.applyPvPowerLimit(chargers, config, false); - return null; + yield null; + } - case ACTIVATED: { + case ACTIVATED -> { if (areSurplusConditionsMet) { this.startedGoingDeactivated = null; } else { @@ -74,10 +74,10 @@ protected Integer run(List chargers, Config config, Co var pvPower = this.getPvPower(chargers); var power = pvPower + this.getIncreasePower(config, pvPower); this.applyPvPowerLimit(chargers, config, true); - return power; + yield power; } - case GOING_DEACTIVATED: { + case GOING_DEACTIVATED -> { var goingDeactivatedSinceMinutes = Duration.between(this.startedGoingDeactivated, LocalDateTime.now()) .toMinutes(); // slowly reduce the surplus-feed-in-power from 100 to 0 % @@ -89,19 +89,17 @@ protected Integer run(List chargers, Config config, Co this.setState(SurplusFeedInStateMachine.PASSED_OFF_TIME); } this.applyPvPowerLimit(chargers, config, false); - return power; + yield power; } - case PASSED_OFF_TIME: + case PASSED_OFF_TIME -> { if (LocalTime.now().isBefore(offTime)) { this.setState(SurplusFeedInStateMachine.DEACTIVATED); } this.applyPvPowerLimit(chargers, config, false); - return null; + yield null; } - - // should never come here - return null; + }; } /** diff --git a/io.openems.edge.ess.generic/src/io/openems/edge/ess/generic/common/AbstractChannelManager.java b/io.openems.edge.ess.generic/src/io/openems/edge/ess/generic/common/AbstractChannelManager.java index c77a5496cc1..987886bd258 100644 --- a/io.openems.edge.ess.generic/src/io/openems/edge/ess/generic/common/AbstractChannelManager.java +++ b/io.openems.edge.ess.generic/src/io/openems/edge/ess/generic/common/AbstractChannelManager.java @@ -66,28 +66,30 @@ private void addBatteryInverterListener(ManagedSymmetricBatteryInverter batteryI SymmetricBatteryInverter.ChannelId.REACTIVE_POWER, // SymmetricEss.ChannelId.REACTIVE_POWER); - if (batteryInverter instanceof HybridManagedSymmetricBatteryInverter) { - this.addCopyListener(batteryInverter, // + switch (batteryInverter) { + case HybridManagedSymmetricBatteryInverter hmsbi -> { + this.addCopyListener(hmsbi, // HybridManagedSymmetricBatteryInverter.ChannelId.DC_CHARGE_ENERGY, // HybridEss.ChannelId.DC_CHARGE_ENERGY); - this.addCopyListener(batteryInverter, // + this.addCopyListener(hmsbi, // HybridManagedSymmetricBatteryInverter.ChannelId.DC_DISCHARGE_ENERGY, // HybridEss.ChannelId.DC_DISCHARGE_ENERGY); - this.addCopyListener(batteryInverter, // + this.addCopyListener(hmsbi, // HybridManagedSymmetricBatteryInverter.ChannelId.DC_DISCHARGE_POWER, // HybridEss.ChannelId.DC_DISCHARGE_POWER); - - } else { - this.addCopyListener(batteryInverter, // + } + case ManagedSymmetricBatteryInverter msbi -> { + this.addCopyListener(msbi, // SymmetricBatteryInverter.ChannelId.ACTIVE_CHARGE_ENERGY, // HybridEss.ChannelId.DC_CHARGE_ENERGY); - this.addCopyListener(batteryInverter, // + this.addCopyListener(msbi, // SymmetricBatteryInverter.ChannelId.ACTIVE_DISCHARGE_ENERGY, // HybridEss.ChannelId.DC_DISCHARGE_ENERGY); - this.addCopyListener(batteryInverter, // + this.addCopyListener(msbi, // SymmetricBatteryInverter.ChannelId.ACTIVE_POWER, // HybridEss.ChannelId.DC_DISCHARGE_POWER); } + } } private void addBatteryListener(ClockProvider clockProvider, Battery battery, SymmetricBatteryInverter inverter) { diff --git a/io.openems.edge.ess.generic/src/io/openems/edge/ess/generic/common/AbstractGenericManagedEss.java b/io.openems.edge.ess.generic/src/io/openems/edge/ess/generic/common/AbstractGenericManagedEss.java index 669ceaa08f0..3bf694c2da1 100644 --- a/io.openems.edge.ess.generic/src/io/openems/edge/ess/generic/common/AbstractGenericManagedEss.java +++ b/io.openems.edge.ess.generic/src/io/openems/edge/ess/generic/common/AbstractGenericManagedEss.java @@ -114,8 +114,8 @@ protected void genericDebugLog(StringBuilder sb) { // Get DC-PV-Power for Hybrid ESS Integer dcPvPower = null; var batteryInverter = this.getBatteryInverter(); - if (batteryInverter instanceof HybridManagedSymmetricBatteryInverter) { - dcPvPower = ((HybridManagedSymmetricBatteryInverter) batteryInverter).getDcPvPower(); + if (batteryInverter instanceof HybridManagedSymmetricBatteryInverter hybrid) { + dcPvPower = hybrid.getDcPvPower(); } sb // @@ -124,9 +124,8 @@ protected void genericDebugLog(StringBuilder sb) { // For HybridEss show actual Battery charge power and PV production power if (dcPvPower != null) { - HybridEss me = this; sb // - .append("|Battery:").append(me.getDcDischargePower().asString()) // + .append("|Battery:").append(this.getDcDischargePower().asString()) // .append("|PV:").append(dcPvPower); } @@ -190,12 +189,11 @@ public Constraint[] getStaticConstraints() throws OpenemsNamedException { } @Override - public Integer getSurplusPower() { - var batteryInverter = this.getBatteryInverter(); - if (batteryInverter instanceof HybridManagedSymmetricBatteryInverter) { - return ((HybridManagedSymmetricBatteryInverter) batteryInverter).getSurplusPower(); - } - return null; + public final Integer getSurplusPower() { + return switch (this.getBatteryInverter()) { + case HybridManagedSymmetricBatteryInverter hybrid -> hybrid.getSurplusPower(); + case null, default -> null; + }; } @Override diff --git a/io.openems.edge.ess.generic/src/io/openems/edge/ess/generic/offgrid/statemachine/StateMachine.java b/io.openems.edge.ess.generic/src/io/openems/edge/ess/generic/offgrid/statemachine/StateMachine.java index 693fcfbff3f..1d2ba20135f 100644 --- a/io.openems.edge.ess.generic/src/io/openems/edge/ess/generic/offgrid/statemachine/StateMachine.java +++ b/io.openems.edge.ess.generic/src/io/openems/edge/ess/generic/offgrid/statemachine/StateMachine.java @@ -62,32 +62,19 @@ public StateMachine(OffGridState initialState) { @Override public StateHandler getStateHandler(OffGridState state) { - switch (state) { - case UNDEFINED: - return new UndefinedHandler(); - case STARTED_IN_OFF_GRID: - return new StartedInOffGridHandler(); - case STARTED_IN_ON_GRID: - return new StartedInOnGridHandler(); - case START_BATTERY_INVERTER_IN_OFF_GRID: - return new StartBatteryInverterInOffGridHandler(); - case START_BATTERY_INVERTER_IN_ON_GRID: - return new StartBatteryInverterInOnGridHandler(); - case START_BATTERY_IN_OFF_GRID: - return new StartBatteryInOffGridHandler(); - case START_BATTERY_IN_ON_GRID: - return new StartBatteryInOnGridHandler(); - case STOPPED: - return new StoppedHandler(); - case STOP_BATTERY: - return new StopBatteryHandler(); - case STOP_BATTERY_INVERTER: - return new StopBatteryInverterHandler(); - case ERROR: - return new ErrorHandler(); - case GRID_SWITCH: - return new GridSwitchHandler(); - } - throw new IllegalArgumentException("Unknown State [" + state + "]"); + return switch (state) { + case UNDEFINED -> new UndefinedHandler(); + case STARTED_IN_OFF_GRID -> new StartedInOffGridHandler(); + case STARTED_IN_ON_GRID -> new StartedInOnGridHandler(); + case START_BATTERY_INVERTER_IN_OFF_GRID -> new StartBatteryInverterInOffGridHandler(); + case START_BATTERY_INVERTER_IN_ON_GRID -> new StartBatteryInverterInOnGridHandler(); + case START_BATTERY_IN_OFF_GRID -> new StartBatteryInOffGridHandler(); + case START_BATTERY_IN_ON_GRID -> new StartBatteryInOnGridHandler(); + case STOPPED -> new StoppedHandler(); + case STOP_BATTERY -> new StopBatteryHandler(); + case STOP_BATTERY_INVERTER -> new StopBatteryInverterHandler(); + case ERROR -> new ErrorHandler(); + case GRID_SWITCH -> new GridSwitchHandler(); + }; } } diff --git a/io.openems.edge.ess.generic/src/io/openems/edge/ess/generic/offgrid/statemachine/UndefinedHandler.java b/io.openems.edge.ess.generic/src/io/openems/edge/ess/generic/offgrid/statemachine/UndefinedHandler.java index f0d391e24d4..cfa9ad194d5 100644 --- a/io.openems.edge.ess.generic/src/io/openems/edge/ess/generic/offgrid/statemachine/UndefinedHandler.java +++ b/io.openems.edge.ess.generic/src/io/openems/edge/ess/generic/offgrid/statemachine/UndefinedHandler.java @@ -11,28 +11,20 @@ public OffGridState runAndGetNextState(Context context) { var ess = context.getParent(); ess._setStartStop(StartStop.UNDEFINED); - switch (ess.getStartStopTarget()) { - case UNDEFINED: - // Stuck in UNDEFINED State - return OffGridState.UNDEFINED; - - case START: - // force START - if (ess.hasFaults()) { - // Has Faults -> error handling - return OffGridState.ERROR; - } else { - // No Faults -> Check the Relay States - return OffGridState.GRID_SWITCH; - } - - case STOP: - // force STOP - return OffGridState.STOP_BATTERY_INVERTER; - } - - assert false; - return OffGridState.UNDEFINED; // can never happen + return switch (ess.getStartStopTarget()) { + case UNDEFINED // Stuck in UNDEFINED State + -> OffGridState.UNDEFINED; + + case START// force START + -> ess.hasFaults() + // Has Faults -> error handling + ? OffGridState.ERROR + // No Faults -> Check the Relay States + : OffGridState.GRID_SWITCH; + + case STOP // force STOP + -> OffGridState.STOP_BATTERY_INVERTER; + }; } } diff --git a/io.openems.edge.ess.generic/src/io/openems/edge/ess/generic/symmetric/ChannelManager.java b/io.openems.edge.ess.generic/src/io/openems/edge/ess/generic/symmetric/ChannelManager.java index ffbccd9ea76..266a7bd3997 100644 --- a/io.openems.edge.ess.generic/src/io/openems/edge/ess/generic/symmetric/ChannelManager.java +++ b/io.openems.edge.ess.generic/src/io/openems/edge/ess/generic/symmetric/ChannelManager.java @@ -20,27 +20,29 @@ public void activate(ClockProvider clockProvider, Battery battery, ManagedSymmetricBatteryInverter batteryInverter) { super.activate(clockProvider, battery, batteryInverter); - if (batteryInverter instanceof HybridManagedSymmetricBatteryInverter) { - this.addCopyListener(batteryInverter, // + switch (batteryInverter) { + case HybridManagedSymmetricBatteryInverter hmsbi -> { + this.addCopyListener(hmsbi, // HybridManagedSymmetricBatteryInverter.ChannelId.DC_CHARGE_ENERGY, // HybridEss.ChannelId.DC_CHARGE_ENERGY); - this.addCopyListener(batteryInverter, // + this.addCopyListener(hmsbi, // HybridManagedSymmetricBatteryInverter.ChannelId.DC_DISCHARGE_ENERGY, // HybridEss.ChannelId.DC_DISCHARGE_ENERGY); - this.addCopyListener(batteryInverter, // + this.addCopyListener(hmsbi, // HybridManagedSymmetricBatteryInverter.ChannelId.DC_DISCHARGE_POWER, // HybridEss.ChannelId.DC_DISCHARGE_POWER); - - } else { - this.addCopyListener(batteryInverter, // + } + case ManagedSymmetricBatteryInverter msbi -> { + this.addCopyListener(msbi, // SymmetricBatteryInverter.ChannelId.ACTIVE_CHARGE_ENERGY, // HybridEss.ChannelId.DC_CHARGE_ENERGY); - this.addCopyListener(batteryInverter, // + this.addCopyListener(msbi, // SymmetricBatteryInverter.ChannelId.ACTIVE_DISCHARGE_ENERGY, // HybridEss.ChannelId.DC_DISCHARGE_ENERGY); - this.addCopyListener(batteryInverter, // + this.addCopyListener(msbi, // SymmetricBatteryInverter.ChannelId.ACTIVE_POWER, // HybridEss.ChannelId.DC_DISCHARGE_POWER); } + } } } diff --git a/io.openems.edge.ess.generic/src/io/openems/edge/ess/generic/symmetric/EssGenericManagedSymmetricImpl.java b/io.openems.edge.ess.generic/src/io/openems/edge/ess/generic/symmetric/EssGenericManagedSymmetricImpl.java index c13369e663c..621bab75ec0 100644 --- a/io.openems.edge.ess.generic/src/io/openems/edge/ess/generic/symmetric/EssGenericManagedSymmetricImpl.java +++ b/io.openems.edge.ess.generic/src/io/openems/edge/ess/generic/symmetric/EssGenericManagedSymmetricImpl.java @@ -23,7 +23,6 @@ import io.openems.common.exceptions.OpenemsError.OpenemsNamedException; import io.openems.edge.battery.api.Battery; -import io.openems.edge.batteryinverter.api.HybridManagedSymmetricBatteryInverter; import io.openems.edge.batteryinverter.api.ManagedSymmetricBatteryInverter; import io.openems.edge.common.component.ComponentManager; import io.openems.edge.common.component.OpenemsComponent; @@ -156,14 +155,6 @@ protected ManagedSymmetricBatteryInverter getBatteryInverter() { return this.batteryInverter; } - @Override - public Integer getSurplusPower() { - if (this.batteryInverter instanceof HybridManagedSymmetricBatteryInverter) { - return ((HybridManagedSymmetricBatteryInverter) this.batteryInverter).getSurplusPower(); - } - return null; - } - @Override protected ComponentManager getComponentManager() { return this.componentManager; diff --git a/io.openems.edge.ess.generic/src/io/openems/edge/ess/generic/symmetric/statemachine/StateMachine.java b/io.openems.edge.ess.generic/src/io/openems/edge/ess/generic/symmetric/statemachine/StateMachine.java index 166e52771cf..dd38b350814 100644 --- a/io.openems.edge.ess.generic/src/io/openems/edge/ess/generic/symmetric/statemachine/StateMachine.java +++ b/io.openems.edge.ess.generic/src/io/openems/edge/ess/generic/symmetric/statemachine/StateMachine.java @@ -55,24 +55,15 @@ public StateMachine(State initialState) { @Override public StateHandler getStateHandler(State state) { - switch (state) { - case UNDEFINED: - return new UndefinedHandler(); - case START_BATTERY: - return new StartBatteryHandler(); - case START_BATTERY_INVERTER: - return new StartBatteryInverterHandler(); - case STARTED: - return new StartedHandler(); - case STOP_BATTERY_INVERTER: - return new StopBatteryInverterHandler(); - case STOP_BATTERY: - return new StopBatteryHandler(); - case STOPPED: - return new StoppedHandler(); - case ERROR: - return new ErrorHandler(); - } - throw new IllegalArgumentException("Unknown State [" + state + "]"); + return switch (state) { + case UNDEFINED -> new UndefinedHandler(); + case START_BATTERY -> new StartBatteryHandler(); + case START_BATTERY_INVERTER -> new StartBatteryInverterHandler(); + case STARTED -> new StartedHandler(); + case STOP_BATTERY_INVERTER -> new StopBatteryInverterHandler(); + case STOP_BATTERY -> new StopBatteryHandler(); + case STOPPED -> new StoppedHandler(); + case ERROR -> new ErrorHandler(); + }; } } \ No newline at end of file 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 4e9b7cee5ed..3902b41ced3 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 @@ -704,7 +704,8 @@ public static ModbusSlaveNatureTable getModbusSlaveNatureTable(AccessMode access .build(); } - /** Defines if the evcs is read only. + /** + * Defines if the evcs is read only. * * @return true if the evcs is read-only */ diff --git a/io.openems.edge.evcs.api/src/io/openems/edge/evcs/api/ManagedEvcs.java b/io.openems.edge.evcs.api/src/io/openems/edge/evcs/api/ManagedEvcs.java index 160f71c0591..4ced0ba38ad 100644 --- a/io.openems.edge.evcs.api/src/io/openems/edge/evcs/api/ManagedEvcs.java +++ b/io.openems.edge.evcs.api/src/io/openems/edge/evcs/api/ManagedEvcs.java @@ -263,8 +263,8 @@ public enum ChannelId implements io.openems.edge.common.channel.ChannelId { evcs.setChargePowerLimit(filterOutput); - if (evcs instanceof ManagedEvcs) { - ((ManagedEvcs) evcs).logDebug("Filter: " + value + " -> " + filterOutput); + if (evcs instanceof ManagedEvcs me) { + me.logDebug("Filter: " + value + " -> " + filterOutput); } } })), // diff --git a/io.openems.edge.evcs.api/test/io/openems/edge/evcs/api/AbstractManagedEvcsTest.java b/io.openems.edge.evcs.api/test/io/openems/edge/evcs/api/AbstractManagedEvcsTest.java index c8d060cae6f..573ef70cd38 100644 --- a/io.openems.edge.evcs.api/test/io/openems/edge/evcs/api/AbstractManagedEvcsTest.java +++ b/io.openems.edge.evcs.api/test/io/openems/edge/evcs/api/AbstractManagedEvcsTest.java @@ -62,8 +62,7 @@ public void abstractManagedEvcsTest() throws Exception { // validator checks the write value // (.output(ManagedEvcs.ChannelId.SET_CHARGE_POWER_LIMIT, 15000)) assertEquals("Check next value of setChargePowerLimit", 15000, // - (EVCS0.channel(SET_CHARGE_POWER_LIMIT)).getNextValue() - .orElse(0).intValue()); + (EVCS0.channel(SET_CHARGE_POWER_LIMIT)).getNextValue().orElse(0).intValue()); test // .next(new TestCase("Check ChargeState after 'getMinimumTimeTillCharingLimitTaken'") // @@ -195,8 +194,7 @@ public void abstractManagedEvcsWithFilterTest() throws Exception { // (.output(ManagedEvcs.ChannelId.SET_CHARGE_POWER_LIMIT, // initialResult)) assertEquals("Check next value of setChargePowerLimit", initialResult, // - (EVCS2.channel(SET_CHARGE_POWER_LIMIT)).getNextValue() - .orElse(0).intValue()); + (EVCS2.channel(SET_CHARGE_POWER_LIMIT)).getNextValue().orElse(0).intValue()); int increasingValue = (int) (MAXIMUM * EVCS2.getEvcsPower().getIncreaseRate()); test // diff --git a/io.openems.edge.evcs.cluster/src/io/openems/edge/evcs/cluster/EvcsClusterPeakShavingImpl.java b/io.openems.edge.evcs.cluster/src/io/openems/edge/evcs/cluster/EvcsClusterPeakShavingImpl.java index ef62076353d..d5e768efef3 100644 --- a/io.openems.edge.evcs.cluster/src/io/openems/edge/evcs/cluster/EvcsClusterPeakShavingImpl.java +++ b/io.openems.edge.evcs.cluster/src/io/openems/edge/evcs/cluster/EvcsClusterPeakShavingImpl.java @@ -193,9 +193,9 @@ private synchronized void updateSortedEvcss() { * @param evcs Electric Vehicle Charging Station */ private void resetClusteredState(Evcs evcs) { - if (evcs instanceof ManagedEvcs) { - ((ManagedEvcs) evcs)._setIsClustered(false); - ((ManagedEvcs) evcs)._setSetChargePowerRequest(null); + if (evcs instanceof ManagedEvcs me) { + me._setIsClustered(false); + me._setSetChargePowerRequest(null); } evcs._setMaximumPower(null); } @@ -206,8 +206,8 @@ private void resetClusteredState(Evcs evcs) { * @param evcs Electric Vehicle Charging Station */ private void setClusteredState(Evcs evcs) { - if (evcs instanceof ManagedEvcs) { - ((ManagedEvcs) evcs)._setIsClustered(true); + if (evcs instanceof ManagedEvcs me) { + me._setIsClustered(true); } } @@ -259,8 +259,8 @@ private void calculateChannelValues() { minFixedHardwarePower.addValue(evcs.getFixedMinimumHardwarePowerChannel()); maxFixedHardwarePower.addValue(evcs.getFixedMaximumHardwarePowerChannel()); minPower.addValue(evcs.getMinimumPowerChannel()); - if (evcs instanceof ManagedEvcs) { - evcsClusterStatus.addValue(((ManagedEvcs) evcs).getChargeState().asEnum()); + if (evcs instanceof ManagedEvcs me) { + evcsClusterStatus.addValue(me.getChargeState().asEnum()); } } @@ -336,8 +336,7 @@ protected void limitEvcss() { */ List activeEvcss = new ArrayList<>(); for (var evcs : this.getSortedEvcss()) { - if (evcs instanceof ManagedEvcs) { - var managedEvcs = (ManagedEvcs) evcs; + if (evcs instanceof ManagedEvcs managedEvcs) { int requestedPower = managedEvcs.getSetChargePowerRequestChannel().getNextWriteValue().orElse(0); // Ignore evcs with no request @@ -572,11 +571,11 @@ private void logInfoInDebugmode(String string) { @Override public void run() throws OpenemsNamedException { // Read maximum ESS Discharge power at the current position in the Cycle - if (this.ess instanceof ManagedSymmetricEss e) { - this.maxEssDischargePower = e.getPower().getMaxPower(e, Phase.ALL, Pwr.ACTIVE); - - } else { - this.maxEssDischargePower = this.ess.getMaxApparentPower().orElse(0); - } + this.maxEssDischargePower = switch (this.ess) { + case ManagedSymmetricEss e // + -> e.getPower().getMaxPower(e, Phase.ALL, Pwr.ACTIVE); + case SymmetricEss e // + -> e.getMaxApparentPower().orElse(0); + }; } } diff --git a/io.openems.edge.evcs.hardybarth/src/io/openems/edge/evcs/hardybarth/HardyBarthReadUtils.java b/io.openems.edge.evcs.hardybarth/src/io/openems/edge/evcs/hardybarth/HardyBarthReadUtils.java index 3f0c194c5a1..1777480da1c 100644 --- a/io.openems.edge.evcs.hardybarth/src/io/openems/edge/evcs/hardybarth/HardyBarthReadUtils.java +++ b/io.openems.edge.evcs.hardybarth/src/io/openems/edge/evcs/hardybarth/HardyBarthReadUtils.java @@ -27,6 +27,7 @@ public class HardyBarthReadUtils { private final EvcsHardyBarthImpl parent; private int errorCounter = 0; + private int undefinedErrorCounter = 0; public HardyBarthReadUtils(EvcsHardyBarthImpl parent) { this.parent = parent; @@ -58,9 +59,20 @@ protected void setEvcsChannelIds(JsonElement json, PhaseRotation phaseRotation) "secc", "port0", "metering", "energy", "active_import", "actual")); // Current - final var currentL1 = getAsIntOrElse(json, 0, "secc", "port0", "metering", "current", "ac", "l1", "actual"); - final var currentL2 = getAsIntOrElse(json, 0, "secc", "port0", "metering", "current", "ac", "l2", "actual"); - final var currentL3 = getAsIntOrElse(json, 0, "secc", "port0", "metering", "current", "ac", "l3", "actual"); + final var currentL1 = getAsInteger(json, 1, "secc", "port0", "metering", "current", "ac", "l1", "actual"); + final var currentL2 = getAsInteger(json, 1, "secc", "port0", "metering", "current", "ac", "l2", "actual"); + final var currentL3 = getAsInteger(json, 1, "secc", "port0", "metering", "current", "ac", "l3", "actual"); + + // Checks if value are null and if they are checks if its the third error or + // more + // and otherwise returns, so that no new values are written this cycle + // TODO: find a better long term solution + if (currentL1 == null || currentL2 == null || currentL3 == null) { + this.parent.logDebug("Invalid current values detected"); + if (this.handleUndefinedError()) { + return; + } + } // Power final var activePowerL1 = getAsInteger(json, SCALE_FACTOR_MINUS_1, // @@ -75,6 +87,20 @@ protected void setEvcsChannelIds(JsonElement json, PhaseRotation phaseRotation) final var voltageL2 = activePowerL2 == null ? null : round(activePowerL2 * 1_000_000F / currentL2); final var voltageL3 = activePowerL3 == null ? null : round(activePowerL3 * 1_000_000F / currentL3); + if (activePowerL1 == null || activePowerL2 == null || activePowerL3 == null) { + this.parent.logDebug("Active power values are null"); + if (this.handleUndefinedError()) { + return; + } + } + + if (voltageL1 == null || voltageL2 == null || voltageL3 == null) { + this.parent.logDebug("Voltage values are null"); + if (this.handleUndefinedError()) { + return; + } + } + var rp = RotatedPhases.from(phaseRotation, // voltageL1, currentL1, activePowerL1, // voltageL2, currentL2, activePowerL2, // @@ -101,7 +127,16 @@ protected void setEvcsChannelIds(JsonElement json, PhaseRotation phaseRotation) "secc", "port0", "metering", "power", "active_total", "actual")) // .map(p -> p < 100 ? 0 : p) // Ignore the consumption of the charger itself .orElse(null); + + if (activePower == null) { + this.parent.logDebug("Active Power invalid"); + if (this.handleUndefinedError()) { + return; + } + } + this.parent._setActivePower(activePower); + this.undefinedErrorCounter = 0; // STATUS var status = getValueFromJson(STRING, json, value -> { @@ -163,13 +198,9 @@ private static Integer getAsInteger(JsonElement json, float scaleFactor, String. jsonPaths); } - private static int getAsIntOrElse(JsonElement json, int orElse, String... jsonPaths) { - var result = getValueFromJson(INTEGER, json, // - value -> TypeUtils.getAsType(INTEGER, value), // - jsonPaths); - return result == null // - ? orElse // - : result; + private boolean handleUndefinedError() { + this.undefinedErrorCounter++; + return this.undefinedErrorCounter <= 3; } /** diff --git a/io.openems.edge.evcs.hardybarth/test/io/openems/edge/evcs/hardybarth/EvcsHardyBarthImplTest.java b/io.openems.edge.evcs.hardybarth/test/io/openems/edge/evcs/hardybarth/EvcsHardyBarthImplTest.java index 8ecb6c334bc..1d352a5a9b5 100644 --- a/io.openems.edge.evcs.hardybarth/test/io/openems/edge/evcs/hardybarth/EvcsHardyBarthImplTest.java +++ b/io.openems.edge.evcs.hardybarth/test/io/openems/edge/evcs/hardybarth/EvcsHardyBarthImplTest.java @@ -107,6 +107,55 @@ public void test() throws Exception { ); } + @Test + public void testHandleUndefinedCheck() throws Exception { + final var phaseRotation = L2_L3_L1; + var sut = new EvcsHardyBarthImpl(); + var ru = sut.readUtils; + new ComponentTest(sut) // + .addReference("httpBridgeFactory", ofDummyBridge()) // + .activate(MyConfig.create() // + .setId("evcs0") // + .setIp("192.168.8.101") // + .setMaxHwCurrent(32_000) // + .setMinHwCurrent(6_000) // + .setPhaseRotation(phaseRotation).build()) + + .next(new TestCase() // + .onBeforeProcessImage(() -> ru + .handleGetApiCallResponse(new HttpResponse(OK, API_RESPONSE), phaseRotation)) // + .output(ElectricityMeter.ChannelId.ACTIVE_POWER, 3192) // + .output(ElectricityMeter.ChannelId.ACTIVE_POWER_L1, 1044) // + .output(ElectricityMeter.ChannelId.ACTIVE_POWER_L2, 1075) // + .output(ElectricityMeter.ChannelId.ACTIVE_POWER_L3, 1073) // + .output(ElectricityMeter.ChannelId.CURRENT, 14_770) // + .output(ElectricityMeter.ChannelId.CURRENT_L1, 4_770) // + .output(ElectricityMeter.ChannelId.CURRENT_L2, 5_000) // + .output(ElectricityMeter.ChannelId.CURRENT_L3, 5_000) // + .output(ElectricityMeter.ChannelId.VOLTAGE, 216_156) // + .output(ElectricityMeter.ChannelId.VOLTAGE_L1, 218_868) // + .output(ElectricityMeter.ChannelId.VOLTAGE_L2, 215_000) // + .output(ElectricityMeter.ChannelId.VOLTAGE_L3, 214_600) // + ) + // Values are not overwritten when empty/null response from api + .next(new TestCase() // + .onBeforeProcessImage(() -> ru.handleGetApiCallResponse( + new HttpResponse(OK, EMPTY_API_RESPONSE), phaseRotation)) // + .output(ElectricityMeter.ChannelId.ACTIVE_POWER, 3192) // + .output(ElectricityMeter.ChannelId.ACTIVE_POWER_L1, 1044) // + .output(ElectricityMeter.ChannelId.ACTIVE_POWER_L2, 1075) // + .output(ElectricityMeter.ChannelId.ACTIVE_POWER_L3, 1073) // + .output(ElectricityMeter.ChannelId.CURRENT, 14_770) // + .output(ElectricityMeter.ChannelId.CURRENT_L1, 4_770) // + .output(ElectricityMeter.ChannelId.CURRENT_L2, 5_000) // + .output(ElectricityMeter.ChannelId.CURRENT_L3, 5_000) // + .output(ElectricityMeter.ChannelId.VOLTAGE, 216_156) // + .output(ElectricityMeter.ChannelId.VOLTAGE_L1, 218_868) // + .output(ElectricityMeter.ChannelId.VOLTAGE_L2, 215_000) // + .output(ElectricityMeter.ChannelId.VOLTAGE_L3, 214_600) // + ); + } + private static final String API_RESPONSE = """ { "device":{ @@ -275,4 +324,174 @@ public void test() throws Exception { } } """; + + private static final String EMPTY_API_RESPONSE = """ + { + "device":{ + "product":null, + "modelname":null, + "hardware_version":null, + "software_version":null, + "vcs_version":null, + "hostname":null, + "mac_address":null, + "serial":null, + "uuid":null, + "internal_id":null + }, + "secc":{ + "port0":{ + "ci":{ + "evse":{ + "basic":{ + "grid_current_limit":{ + "actual":null + }, + "phase_count":null, + "physical_current_limit":null, + "offered_current_limit":null + }, + "phase":{ + "actual":null + } + }, + "charge":{ + "cp":{ + "status":null + }, + "plug":{ + "status":null + }, + "contactor":{ + "status":null + }, + "pwm":{ + "status":null + } + } + }, + "salia":{ + "chargemode":null, + "thermal":null, + "mem":null, + "uptime":null, + "load":null, + "chargedata":null, + "authmode":null, + "firmwarestate":null, + "firmwareprogress":null, + "heartbeat":null, + "pausecharging":null + }, + "session":{ + "authorization_status":null + }, + "contactor":{ + "state":{ + "hlc_target":null, + "actual":null, + "target":null + }, + "error":null + }, + "metering":{ + "meter":{ + "serialnumber":null, + "type":null, + "available":null + }, + "eichrecht_protocol":null, + "power":{ + "active":{ + "ac":{ + "l1":{ + "actual":null + }, + "l2":{ + "actual":null + }, + "l3":{ + "actual":null + } + } + }, + "active_total":{ + "actual":null + } + }, + "current":{ + "ac":{ + "l1":{ + "actual":null + }, + "l2":{ + "actual":null + }, + "l3":{ + "actual":null + } + } + }, + "energy":{ + "active_total":{ + "actual":null + }, + "active_export":{ + "actual":null + }, + "active_import":{ + "actual":null + } + } + }, + "emergency_shutdown":null, + "rcd":{ + "feedback":{ + "available":null + }, + "state":{ + "actual":null + }, + "recloser":{ + "available":null + } + }, + "plug_lock":{ + "state":{ + "actual":null, + "target":null + }, + "error":null + }, + "availability":{ + "actual":null + }, + "cp":{ + "pwm_state":{ + "actual":null + }, + "state":null, + "duty_cycle":null + }, + "rfid":{ + "available":null, + "authorizereq":null + }, + "diode_present":null, + "cable_current_limit":null, + "ready_for_slac":null, + "ev_present":null, + "ventilation":{ + "state":{ + "actual":null + }, + "available":null + }, + "charging":null, + "grid_current_limit":null + } + } + } + """; + } diff --git a/io.openems.edge.evcs.keba.kecontact/src/io/openems/edge/evcs/keba/kecontact/EvcsKebaKeContact.java b/io.openems.edge.evcs.keba.kecontact/src/io/openems/edge/evcs/keba/kecontact/EvcsKebaKeContact.java index 97f8a70c07c..4e2487d2df0 100644 --- a/io.openems.edge.evcs.keba.kecontact/src/io/openems/edge/evcs/keba/kecontact/EvcsKebaKeContact.java +++ b/io.openems.edge.evcs.keba.kecontact/src/io/openems/edge/evcs/keba/kecontact/EvcsKebaKeContact.java @@ -15,7 +15,6 @@ import io.openems.edge.common.modbusslave.ModbusType; import io.openems.edge.evcs.api.Evcs; import io.openems.edge.evcs.api.ManagedEvcs; -import io.openems.edge.evcs.api.Status; import io.openems.edge.meter.api.ElectricityMeter; public interface EvcsKebaKeContact @@ -46,13 +45,12 @@ public enum ChannelId implements io.openems.edge.common.channel.ChannelId { /* * Report 2 */ - STATUS_KEBA(Doc.of(Status.values()) // - .text("Current state of the charging station")), + R2_STATE(Doc.of(R2State.values())), // ERROR_1(Doc.of(OpenemsType.INTEGER) // .text("Detail code for state ERROR; exceptions see FAQ on www.kecontact.com")), // ERROR_2(Doc.of(OpenemsType.INTEGER) // .text("Detail code for state ERROR; exceptions see FAQ on www.kecontact.com")), // - PLUG(Doc.of(Plug.values())), // + R2_PLUG(Doc.of(R2Plug.values())), // ENABLE_SYS(Doc.of(OpenemsType.BOOLEAN) // .text("Enable state for charging (contains Enable input, RFID, UDP,..)")), // ENABLE_USER(Doc.of(OpenemsType.BOOLEAN) // @@ -145,10 +143,10 @@ private ModbusSlaveNatureTable getModbusSlaveNatureTable(AccessMode accessMode) .channel(16, EvcsKebaKeContact.ChannelId.SERIAL, ModbusType.STRING16) .channel(32, EvcsKebaKeContact.ChannelId.FIRMWARE, ModbusType.STRING16) .channel(48, EvcsKebaKeContact.ChannelId.COM_MODULE, ModbusType.STRING16) - .channel(64, EvcsKebaKeContact.ChannelId.STATUS_KEBA, ModbusType.UINT16) + .channel(64, EvcsKebaKeContact.ChannelId.R2_STATE, ModbusType.UINT16) .channel(65, EvcsKebaKeContact.ChannelId.ERROR_1, ModbusType.UINT16) .channel(66, EvcsKebaKeContact.ChannelId.ERROR_2, ModbusType.UINT16) - .channel(67, EvcsKebaKeContact.ChannelId.PLUG, ModbusType.UINT16) + .channel(67, EvcsKebaKeContact.ChannelId.R2_PLUG, ModbusType.UINT16) .channel(68, EvcsKebaKeContact.ChannelId.ENABLE_SYS, ModbusType.UINT16) .channel(69, EvcsKebaKeContact.ChannelId.ENABLE_USER, ModbusType.UINT16) .channel(70, EvcsKebaKeContact.ChannelId.MAX_CURR_PERCENT, ModbusType.UINT16) @@ -159,7 +157,7 @@ private ModbusSlaveNatureTable getModbusSlaveNatureTable(AccessMode accessMode) .channel(75, EvcsKebaKeContact.ChannelId.TIMEOUT_CT, ModbusType.UINT16) // .uint16Reserved(76) // .channel(77, EvcsKebaKeContact.ChannelId.OUTPUT, ModbusType.UINT16) - .channel(78, EvcsKebaKeContact.ChannelId.INPUT, ModbusType.UINT16) + .channel(78, EvcsKebaKeContact.ChannelId.INPUT, ModbusType.UINT16) // .build(); } } diff --git a/io.openems.edge.evcs.keba.kecontact/src/io/openems/edge/evcs/keba/kecontact/Plug.java b/io.openems.edge.evcs.keba.kecontact/src/io/openems/edge/evcs/keba/kecontact/R2Plug.java similarity index 53% rename from io.openems.edge.evcs.keba.kecontact/src/io/openems/edge/evcs/keba/kecontact/Plug.java rename to io.openems.edge.evcs.keba.kecontact/src/io/openems/edge/evcs/keba/kecontact/R2Plug.java index 1ca34e1c7a6..148a3540b86 100644 --- a/io.openems.edge.evcs.keba.kecontact/src/io/openems/edge/evcs/keba/kecontact/Plug.java +++ b/io.openems.edge.evcs.keba.kecontact/src/io/openems/edge/evcs/keba/kecontact/R2Plug.java @@ -2,18 +2,41 @@ import io.openems.common.types.OptionsEnum; -public enum Plug implements OptionsEnum { +public enum R2Plug implements OptionsEnum { UNDEFINED(-1, "Undefined"), // + /** + * No cable is plugged. + */ UNPLUGGED(0, "Unplugged"), // + /** + * Cable is plugged into charging station. + */ PLUGGED_ON_EVCS(1, "Plugged on EVCS"), // + /** + * Cable is plugged into charging station and locked. + * + *

+ * This is the default idle state for all devices with permanently attached + * cable. + */ PLUGGED_ON_EVCS_AND_LOCKED(3, "Plugged on EVCS and locked"), // + /** + * Cable is plugged into charging station and vehicle but not locked. + */ PLUGGED_ON_EVCS_AND_ON_EV(5, "Plugged on EVCS and on EV"), // + /** + * Cable is plugged into charging station and vehicle, furthermore the cable is + * locked. + * + *

+ * Charging is not possible until plug state "7" is reached. + */ PLUGGED_ON_EVCS_AND_ON_EV_AND_LOCKED(7, "Plugged on EVCS and on EV and locked"); private final int value; private final String name; - private Plug(int value, String name) { + private R2Plug(int value, String name) { this.value = value; this.name = name; } diff --git a/io.openems.edge.evcs.keba.kecontact/src/io/openems/edge/evcs/keba/kecontact/R2State.java b/io.openems.edge.evcs.keba.kecontact/src/io/openems/edge/evcs/keba/kecontact/R2State.java new file mode 100644 index 00000000000..ac27b229300 --- /dev/null +++ b/io.openems.edge.evcs.keba.kecontact/src/io/openems/edge/evcs/keba/kecontact/R2State.java @@ -0,0 +1,56 @@ +package io.openems.edge.evcs.keba.kecontact; + +import io.openems.common.types.OptionsEnum; + +public enum R2State implements OptionsEnum { + UNDEFINED(-1, "Undefined"), // + /** + * Startup. + */ + STARTUP(0, "Startup"), // + /** + * Not ready for charging. Charging station is not connected to a vehicle, is + * locked by the authorization function or another mechanism. + */ + NOT_READY(1, "Not ready"), // + /** + * Ready for charging and waiting for reaction from vehicle. + */ + READY(2, "Ready"), // + /** + * Charging. + */ + CHARGING(3, "Charging"), // + /** + * Error is present. + */ + ERROR(4, "Error"), // + /** + * Charging process temporarily interrupted because temperature is too high or + * any other voter denies. + */ + INTERRUPTED(5, "Interrupted"); + + private final int value; + private final String name; + + private R2State(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; + } +} \ No newline at end of file diff --git a/io.openems.edge.evcs.keba.kecontact/src/io/openems/edge/evcs/keba/kecontact/ReadHandler.java b/io.openems.edge.evcs.keba.kecontact/src/io/openems/edge/evcs/keba/kecontact/ReadHandler.java index 69208c18c90..a19fca836c3 100644 --- a/io.openems.edge.evcs.keba.kecontact/src/io/openems/edge/evcs/keba/kecontact/ReadHandler.java +++ b/io.openems.edge.evcs.keba.kecontact/src/io/openems/edge/evcs/keba/kecontact/ReadHandler.java @@ -1,5 +1,6 @@ package io.openems.edge.evcs.keba.kecontact; +import static io.openems.common.utils.FunctionUtils.doNothing; import static io.openems.common.utils.JsonUtils.getAsOptionalInt; import static io.openems.common.utils.JsonUtils.getAsOptionalLong; import static io.openems.common.utils.JsonUtils.getAsOptionalString; @@ -31,6 +32,7 @@ public class ReadHandler implements Consumer { private final Logger log = LoggerFactory.getLogger(ReadHandler.class); private final EvcsKebaKeContactImpl parent; + private final EnergySessionHandler energySessionHandler = new EnergySessionHandler(); private boolean receiveReport1 = false; private boolean receiveReport2 = false; @@ -98,45 +100,45 @@ public void accept(String message) { */ case "2" -> { this.receiveReport2 = true; - this.setInt(EvcsKebaKeContact.ChannelId.STATUS_KEBA, j, "State"); + + // Parse Status and Plug immediately + this.setInt(EvcsKebaKeContact.ChannelId.R2_STATE, j, "State"); + final R2State r2State = keba.channel(EvcsKebaKeContact.ChannelId.R2_STATE).getNextValue().asEnum(); + final R2Plug r2Plug = this.setPlug(j); // Value "setenergy" not used, because it is reset by the currtime 0 1 command // Set Evcs status - Channel stateChannel = keba.channel(EvcsKebaKeContact.ChannelId.STATUS_KEBA); - Channel plugChannel = keba.channel(EvcsKebaKeContact.ChannelId.PLUG); - - Plug plug = plugChannel.value().asEnum(); - Status status = stateChannel.value().asEnum(); - if (plug.equals(Plug.PLUGGED_ON_EVCS_AND_ON_EV_AND_LOCKED)) { - - // Charging is rejected (by the Software) if the plug is connected but the EVCS - // still not ready for charging. - if (status.equals(Status.NOT_READY_FOR_CHARGING)) { - status = Status.CHARGING_REJECTED; - } + var status = switch (r2Plug) { + case PLUGGED_ON_EVCS, PLUGGED_ON_EVCS_AND_LOCKED, PLUGGED_ON_EVCS_AND_ON_EV, UNDEFINED, UNPLUGGED // + -> Status.NOT_READY_FOR_CHARGING; + case PLUGGED_ON_EVCS_AND_ON_EV_AND_LOCKED -> { /* * Check if the maximum energy limit is reached, informs the user and sets the * status */ - int limit = keba.getSetEnergyLimit().orElse(0); - int energy = keba.getEnergySession().orElse(0); - if (energy >= limit && limit != 0) { - status = Status.ENERGY_LIMIT_REACHED; + var limit = keba.getSetEnergyLimit().get(); + var energy = keba.getEnergySession().get(); + if (limit != null && energy != null && energy >= limit) { + yield Status.ENERGY_LIMIT_REACHED; } - } else { - // Plug not fully connected - status = Status.NOT_READY_FOR_CHARGING; + yield switch (r2State) { + case UNDEFINED -> Status.UNDEFINED; + case STARTUP -> Status.STARTING; + case NOT_READY -> Status.NOT_READY_FOR_CHARGING; + case INTERRUPTED, READY -> Status.READY_FOR_CHARGING; + case CHARGING -> Status.CHARGING; + case ERROR -> Status.ERROR; + }; } + }; keba._setStatus(status); - var errorState = status == Status.ERROR == true; - keba.channel(EvcsKebaKeContact.ChannelId.CHARGINGSTATION_STATE_ERROR).setNextValue(errorState); + keba.channel(EvcsKebaKeContact.ChannelId.CHARGINGSTATION_STATE_ERROR).setNextValue(status == Status.ERROR); this.setInt(EvcsKebaKeContact.ChannelId.ERROR_1, j, "Error1"); this.setInt(EvcsKebaKeContact.ChannelId.ERROR_2, j, "Error2"); - this.setInt(EvcsKebaKeContact.ChannelId.PLUG, j, "Plug"); this.setBoolean(EvcsKebaKeContact.ChannelId.ENABLE_SYS, j, "Enable sys"); this.setBoolean(EvcsKebaKeContact.ChannelId.ENABLE_USER, j, "Enable user"); this.setInt(EvcsKebaKeContact.ChannelId.MAX_CURR_PERCENT, j, "Max curr %"); @@ -198,9 +200,10 @@ public void accept(String message) { .map(e -> round(e * 0.1F)) // .orElse(null)); keba._setEnergySession(// - getAsOptionalInt(j, "E pres") // - .map(e -> round(e * 0.1F)) // - .orElse(null)); + this.energySessionHandler.updateFromReport3(// + getAsOptionalInt(j, "E pres") // + .map(e -> round(e * 0.1F)) // + .orElse(null))); // TODO use COS_PHI to calculate ReactivePower this.setInt(EvcsKebaKeContact.ChannelId.COS_PHI, j, "PF"); @@ -240,10 +243,10 @@ public void accept(String message) { */ default -> { if (j.has("State")) { - this.setInt(EvcsKebaKeContact.ChannelId.STATUS_KEBA, j, "State"); + this.setInt(EvcsKebaKeContact.ChannelId.R2_STATE, j, "State"); } if (j.has("Plug")) { - this.setInt(EvcsKebaKeContact.ChannelId.PLUG, j, "Plug"); + this.setPlug(j); } if (j.has("Input")) { this.setBoolean(EvcsKebaKeContact.ChannelId.INPUT, j, "Input"); @@ -384,6 +387,14 @@ private void setString(ChannelId channelId, JsonObject jMessage, String name) { this.set(channelId, getAsOptionalString(jMessage, name).orElse(null)); } + private R2Plug setPlug(JsonObject jMessage) { + final var channelId = EvcsKebaKeContact.ChannelId.R2_PLUG; + this.setInt(channelId, jMessage, "Plug"); + final R2Plug r2Plug = this.parent.channel(channelId).getNextValue().asEnum(); + this.energySessionHandler.updatePlug(r2Plug); + return r2Plug; + } + private void setInt(ChannelId channelId, JsonObject jMessage, String name) { this.set(channelId, getAsOptionalInt(jMessage, name).orElse(null)); } @@ -423,4 +434,36 @@ public boolean hasResultandReset(Report report) { } return result; } + + protected static class EnergySessionHandler { + private R2Plug r2Plug = R2Plug.UNDEFINED; + private Integer ePresOnUnplugged = null; + + protected synchronized void updatePlug(R2Plug r2Plug) { + this.r2Plug = r2Plug; + } + + public synchronized Integer updateFromReport3(Integer ePres) { + switch (this.r2Plug) { + case UNPLUGGED, // no cable + PLUGGED_ON_EVCS, PLUGGED_ON_EVCS_AND_LOCKED // not plugged on EV + -> this.ePresOnUnplugged = ePres > 0 ? ePres : null; + case UNDEFINED, // unsure + PLUGGED_ON_EVCS_AND_ON_EV, PLUGGED_ON_EVCS_AND_ON_EV_AND_LOCKED // plugged on EV + -> doNothing(); + } + if (this.ePresOnUnplugged == null) { + return ePres; + } + if (ePres == null) { + return null; + } + if (this.ePresOnUnplugged <= ePres) { + return null; + } + // reset + this.ePresOnUnplugged = null; + return ePres; + } + } } diff --git a/io.openems.edge.evcs.keba.kecontact/test/io/openems/edge/evcs/keba/kecontact/EvcsKebaKeContactImplTest.java b/io.openems.edge.evcs.keba.kecontact/test/io/openems/edge/evcs/keba/kecontact/EvcsKebaKeContactImplTest.java index db60737ebb8..5ed2f067016 100644 --- a/io.openems.edge.evcs.keba.kecontact/test/io/openems/edge/evcs/keba/kecontact/EvcsKebaKeContactImplTest.java +++ b/io.openems.edge.evcs.keba.kecontact/test/io/openems/edge/evcs/keba/kecontact/EvcsKebaKeContactImplTest.java @@ -1,8 +1,8 @@ package io.openems.edge.evcs.keba.kecontact; import static io.openems.edge.evcs.api.PhaseRotation.L2_L3_L1; -import static io.openems.edge.evcs.api.Status.CHARGING_REJECTED; -import static io.openems.edge.evcs.keba.kecontact.Plug.PLUGGED_ON_EVCS_AND_ON_EV_AND_LOCKED; +import static io.openems.edge.evcs.keba.kecontact.R2Plug.PLUGGED_ON_EVCS_AND_ON_EV_AND_LOCKED; +import static io.openems.edge.evcs.keba.kecontact.R2State.INTERRUPTED; import org.junit.Test; @@ -42,10 +42,10 @@ public void test() throws Exception { .next(new TestCase() // .onBeforeProcessImage(() -> rh.accept(REPORT_2)) // - .output(EvcsKebaKeContact.ChannelId.STATUS_KEBA, CHARGING_REJECTED) // + .output(EvcsKebaKeContact.ChannelId.R2_STATE, INTERRUPTED) // .output(EvcsKebaKeContact.ChannelId.ERROR_1, 0) // .output(EvcsKebaKeContact.ChannelId.ERROR_2, 0) // - .output(EvcsKebaKeContact.ChannelId.PLUG, PLUGGED_ON_EVCS_AND_ON_EV_AND_LOCKED) // + .output(EvcsKebaKeContact.ChannelId.R2_PLUG, PLUGGED_ON_EVCS_AND_ON_EV_AND_LOCKED) // .output(EvcsKebaKeContact.ChannelId.ENABLE_SYS, false) // .output(EvcsKebaKeContact.ChannelId.ENABLE_USER, false) // .output(EvcsKebaKeContact.ChannelId.MAX_CURR_PERCENT, 1_000) // diff --git a/io.openems.edge.evcs.keba.kecontact/test/io/openems/edge/evcs/keba/kecontact/ReadHandlerTest.java b/io.openems.edge.evcs.keba.kecontact/test/io/openems/edge/evcs/keba/kecontact/ReadHandlerTest.java new file mode 100644 index 00000000000..f54d9e5d28c --- /dev/null +++ b/io.openems.edge.evcs.keba.kecontact/test/io/openems/edge/evcs/keba/kecontact/ReadHandlerTest.java @@ -0,0 +1,39 @@ +package io.openems.edge.evcs.keba.kecontact; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +import org.junit.Test; + +public class ReadHandlerTest { + + @Test + public void testEnergySessionHandler() { + var sut = new ReadHandler.EnergySessionHandler(); + sut.updatePlug(R2Plug.UNDEFINED); + assertNull(sut.updateFromReport3(null)); + + assertEquals(990, sut.updateFromReport3(990).intValue()); + + sut.updatePlug(R2Plug.PLUGGED_ON_EVCS_AND_ON_EV); + assertEquals(1000, sut.updateFromReport3(1000).intValue()); + + sut.updatePlug(R2Plug.UNPLUGGED); + assertNull(sut.updateFromReport3(1010)); + + sut.updatePlug(R2Plug.PLUGGED_ON_EVCS_AND_ON_EV); + assertNull(sut.updateFromReport3(1020)); + + sut.updatePlug(R2Plug.PLUGGED_ON_EVCS_AND_ON_EV_AND_LOCKED); + assertEquals(500, sut.updateFromReport3(500).intValue()); + + sut.updatePlug(R2Plug.UNPLUGGED); + assertNull(sut.updateFromReport3(510)); + + sut.updatePlug(R2Plug.PLUGGED_ON_EVCS_AND_ON_EV_AND_LOCKED); + assertNull(sut.updateFromReport3(510)); + + sut.updatePlug(R2Plug.PLUGGED_ON_EVCS_AND_ON_EV_AND_LOCKED); + assertEquals(20, sut.updateFromReport3(20).intValue()); + } +} diff --git a/io.openems.edge.evcs.keba.kecontact/test/io/openems/edge/evcs/keba/kecontact/ReadWorkerTest.java b/io.openems.edge.evcs.keba.kecontact/test/io/openems/edge/evcs/keba/kecontact/ReadWorkerTest.java index 713c77047dc..9d39b3073a4 100644 --- a/io.openems.edge.evcs.keba.kecontact/test/io/openems/edge/evcs/keba/kecontact/ReadWorkerTest.java +++ b/io.openems.edge.evcs.keba.kecontact/test/io/openems/edge/evcs/keba/kecontact/ReadWorkerTest.java @@ -59,7 +59,7 @@ public void testReportsFarInFuture() { int result = ReadWorker.getCycleTimeLogic(lastReport1, lastReport2, lastReport3, this.now); assertEquals(0, result); } - + @Test public void testEdgeCaseReportNearNow() { LocalDateTime lastReport1 = this.now.minusSeconds(Report.REPORT1.getRequestSeconds() - 1); diff --git a/io.openems.edge.evcs.mennekes/src/io/openems/edge/evcs/mennekes/AvailableState.java b/io.openems.edge.evcs.mennekes/src/io/openems/edge/evcs/mennekes/AvailableState.java deleted file mode 100644 index 9a2f1d227b0..00000000000 --- a/io.openems.edge.evcs.mennekes/src/io/openems/edge/evcs/mennekes/AvailableState.java +++ /dev/null @@ -1,45 +0,0 @@ -package io.openems.edge.evcs.mennekes; - -import io.openems.common.types.OptionsEnum; - -/** - * Shows the status of the Mennekes charger. - */ -public enum AvailableState implements OptionsEnum { - UNDEFINED(-1, "Undefined"), // - AVAILABLE(0, "Available"), // - PREPARING_TAG_ID_READY(1, "Ready to prepare the tag ID"), // - PREPARING_EV_READY(2, "Charging"), // - CHARGING(3, "Charging"), // - SUSPENDED_EV(4, "Suspended electric vehicle"), // - SUSPENDED_EV_SE(5, "Suspended electric vehicle se"), // - FINISHING(6, "Finishing"), // - RESERVED(7, "Reseved"), // - UNAVAILABLE(8, "Unavailable"), // - UNAVAILABLE_FW_UPDATE(9, "Unavailable firmware update"), // - FAULTED(10, "Faulted"), // - UNAVAILABLE_CONNECTION_OBJECT(11, "Unavailable connection"); - - private final int value; - private final String name; - - private AvailableState(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.mennekes/src/io/openems/edge/evcs/mennekes/EvcsMennekes.java b/io.openems.edge.evcs.mennekes/src/io/openems/edge/evcs/mennekes/EvcsMennekes.java index cc43b4f95cd..67b40e48ad9 100644 --- a/io.openems.edge.evcs.mennekes/src/io/openems/edge/evcs/mennekes/EvcsMennekes.java +++ b/io.openems.edge.evcs.mennekes/src/io/openems/edge/evcs/mennekes/EvcsMennekes.java @@ -6,14 +6,9 @@ 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.BooleanReadChannel; -import io.openems.edge.common.channel.Channel; 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.StateChannel; -import io.openems.edge.common.channel.StringReadChannel; -import io.openems.edge.common.channel.value.Value; import io.openems.edge.common.component.OpenemsComponent; /** @@ -27,14 +22,14 @@ public interface EvcsMennekes extends OpenemsComponent { public enum ChannelId implements io.openems.edge.common.channel.ChannelId { /** - * Apply charge power limit. + * Apply charge current limit. * *

* WriteChannel for the modbus register to apply the charge power given by the * applyChargePowerLimit method */ APPLY_CURRENT_LIMIT(Doc.of(OpenemsType.INTEGER) // - .unit(Unit.WATT) // + .unit(Unit.AMPERE) // .accessMode(AccessMode.READ_WRITE)), // FIRMWARE_VERSION(Doc.of(OpenemsType.STRING)// @@ -306,18 +301,6 @@ public enum ChannelId implements io.openems.edge.common.channel.ChannelId { VEHICLE_STATE(Doc.of(VehicleState.values())// .initialValue(VehicleState.UNDEFINED)), // - /** - * CP AVAILABILITY. - * - *

    - *
  • Interface: MennekesAmtron - *
  • Type: Boolean - *
  • Unit: None - *
- */ - CP_AVAILABILITY(Doc.of(OpenemsType.BOOLEAN)// - .unit(Unit.NONE)), // - /** * SAFE_CURRENT. * @@ -414,36 +397,6 @@ public default void setApplyCurrentLimit(Integer value) throws OpenemsNamedExcep this.getApplyCurrentLimitChannel().setNextWriteValue(value); } - /** - * Gets the Channel for {@link ChannelId#FIRMWARE_VERSION}. - * - * @return returns the channel - * - */ - public default StringReadChannel getFirmwareVersionChannel() { - return this.channel(ChannelId.FIRMWARE_VERSION); - } - - /** - * Internal method to get the 'nextValue' of {@link ChannelId#FIRMWARE_VERSION} - * Channel. - * - * @return value of firmware version value - */ - public default Value getFirmwareVersionValue() { - return this.getFirmwareVersionChannel().getNextValue(); - } - - /** - * Internal method to set the 'nextValue' on {@link ChannelId#FIRMWARE_VERSION} - * Channel. - * - * @param value the next value - */ - public default void _setFirmwareVersion(String value) { - this.getFirmwareVersionChannel().setNextValue(value); - } - /** * Gets the Channel for {@link ChannelId#RAW_FIRMWARE_VERSION}. * @@ -452,95 +405,4 @@ public default void _setFirmwareVersion(String value) { public default StateChannel getFirmwareOutdatedChannel() { return this.channel(ChannelId.FIRMWARE_OUTDATED); } - - /** - * Gets the Channel for {@link ChannelId#OCPP_CP_STATUS}. - * - * @return the Channel - */ - public default Channel getOcppCpStatusChannel() { - return this.channel(ChannelId.OCPP_CP_STATUS); - } - - /** - * Gets the OCPP Status of the EVCS charging station. See - * {@link ChannelId#OCPP_CP_STATUS}. - * - * @return the Channel {@link Value} - */ - public default MennekesOcppState getOcppCpStatus() { - return this.getOcppCpStatusChannel().value().asEnum(); - } - - /** - * Gets the Channel for {@link ChannelId#CP_AVAILABILITY}. - * - * @return the Channel - */ - - public default BooleanReadChannel getCpAvailabilityChannel() { - return this.channel(ChannelId.CP_AVAILABILITY); - } - - /** - * Gets the Channel for {@link ChannelId#MAX_CURRENT_EV}. - * - * @return the Channel - */ - - public default IntegerReadChannel getMaxCurrentEvChannel() { - return this.channel(ChannelId.MAX_CURRENT_EV); - } - - /** - * Gets the Channel for {@link ChannelId#VEHICLE_STATE}. - * - * @return the Channel - */ - - public default Channel getVehicleStateChannel() { - return this.channel(ChannelId.VEHICLE_STATE); - } - - /** - * Gets the Channel for {@link ChannelId#MIN_CURRENT_LIMIT}. - * - * @return the Channel - */ - - public default IntegerReadChannel getMinCurrentLimitChannel() { - return this.channel(ChannelId.MIN_CURRENT_LIMIT); - } - - /** - * Gets the Minimum current limit in [A] of the AC charger. See - * {@link ChannelId#MIN_CURRENT_LIMIT}. - * - * @return the Channel {@link Value} - */ - - public default Value getMinCurrentLimit() { - return this.getMinCurrentLimitChannel().value(); - } - - /** - * Internal method to set the 'nextValue' on {@link ChannelId#EMS_CURRENT_LIMIT} - * Channel. Sets the value in Ampere as an Integer-Value. - * - * @return returns the EMS current limit - */ - - public default Value getEmsCurrentLimit() { - return this.getEmsCurrentLimitChannel().value(); - } - - /** - * Gets the Channel for {@link ChannelId#EMS_CURRENT_LIMIT}. - * - * @return the Channel - */ - public default IntegerReadChannel getEmsCurrentLimitChannel() { - return this.channel(ChannelId.EMS_CURRENT_LIMIT); - } - } diff --git a/io.openems.edge.evcs.mennekes/src/io/openems/edge/evcs/mennekes/MennekesErrorStates.java b/io.openems.edge.evcs.mennekes/src/io/openems/edge/evcs/mennekes/MennekesErrorStates.java deleted file mode 100644 index 1aa8dbf96c1..00000000000 --- a/io.openems.edge.evcs.mennekes/src/io/openems/edge/evcs/mennekes/MennekesErrorStates.java +++ /dev/null @@ -1,84 +0,0 @@ -package io.openems.edge.evcs.mennekes; - -import io.openems.common.types.OptionsEnum; -import io.openems.edge.evcs.mennekes.EvcsMennekes.ChannelId; - -public enum MennekesErrorStates implements OptionsEnum { - UNDEFINED(0x0, // - "Undefined", null), // - ERR_RCMB_TRIGGERED(0x1, // - "Residual current detected via sensor", ChannelId.ERR_RCMB_TRIGGERED), // - ERR_VEHICLE_STATE_E(0x2, // - "Vehicle signals error", ChannelId.ERR_VEHICLE_STATE_E), // - ERR_MODE3_DIDE_CHECK(0x4, // - "ReseVehicle diode check failed - tamper detection", ChannelId.ERR_MODE3_DIODE_CHECK), // - ERR_MCB_TYPE2_TRIGGERED(0x8, // - "MCB of type 2 socket triggered", ChannelId.ERR_MCB_TYPE2_TRIGGERED), // - ERR_MCB_SCHUKO_TRIGGERED(0x10, // - "MCB of domestic socket triggered", ChannelId.ERR_MCB_SCHUKO_TRIGGERED), // - ERR_RCD_TRIGGERED(0x20, // - "RCD triggered", ChannelId.ERR_RCD_TRIGGERED), // - ERR_CONTACTOR_WELD(0x40, // - "Contactor welded", ChannelId.ERR_CONTACTOR_WELD), // - ERR_BACKEND_DISCONNECTED(0x80, // - "Backend disconnected", ChannelId.ERR_BACKEND_DISCONNECTED), // - ERR_ACTUATOR_LOCKING_FAILED(0x100, // - "Plug locking failed", ChannelId.ERR_ACTUATOR_LOCKING_FAILED), // - ERR_ACTUATOR_LOCKING_WITHOUT_PLUG_FAILED(0x200, // - "Locking without plug error", ChannelId.ERR_ACTUATOR_LOCKING_WITHOUT_PLUG_FAILED), // - ERR_ACTUATOR_STUCK(0x400, // - "Actuator stuck cannot unlock", ChannelId.ERR_ACTUATOR_STUCK), // - ERR_ACTUATOR_DETECTION_FAILED(0x800, // - "Actuator detection failed", ChannelId.ERR_ACTUATOR_DETECTION_FAILED), // - ERR_FW_UPDATE_RUNNING(0x1000, // - "FW Update in progress", ChannelId.ERR_FW_UPDATE_RUNNING), // - ERR_TILT(0x2000, // - "The charge point is tilted", ChannelId.ERR_TILT), // - ERR_WRONG_CP_PR_WIRING(0x4000, // - "CP/PR wiring issue", ChannelId.ERR_WRONG_CP_PR_WIRING), // - ERR_TYPE2_OVERLOAD_THR_2(0x8000, // - "Car current overload, charging stopped", ChannelId.ERR_TYPE2_OVERLOAD_THR_2), // - ERR_ACTUATOR_UNLOCKED_WHILE_CHARGING(0x10000, // - "Actuator unlocked while charging", ChannelId.ERR_ACTUATOR_UNLOCKED_WHILE_CHARGING), // - ERR_TILT_PREVENT_CHARGING_UNTIL_REBOOT(0x20000, // - "The charge point was tilted and it is not allowed to charge until the charge point is rebooted", - ChannelId.ERR_TILT_PREVENT_CHARGING_UNTIL_REBOOT), // - ERR_PIC24(0x40000, // - "PIC24 error", ChannelId.ERR_PIC24), // - ERR_USB_STICK_HANDLING(0x80000, // - "USB stick handling in progress", ChannelId.ERR_USB_STICK_HANDLING), // - ERR_INCORRECT_PHASE_INSTALLATION(0x100000, // - "Incorrect phase rotation direction detected", ChannelId.ERR_INCORRECT_PHASE_INSTALLATION), // - ERR_NO_POWER(0x200000, // - "No power on mains detected", ChannelId.ERR_NO_POWER) // - ; - - private final int value; - private final String name; - private final ChannelId channel; - - private MennekesErrorStates(int value, String name, ChannelId channel) { - this.value = value; - this.name = name; - this.channel = channel; - } - - public ChannelId getChannel() { - return this.channel; - } - - @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.ocpp.server/src/io/openems/edge/evcs/ocpp/server/EvcsOcppServer.java b/io.openems.edge.evcs.ocpp.server/src/io/openems/edge/evcs/ocpp/server/EvcsOcppServer.java index cabfb8d0540..043edb7f164 100644 --- a/io.openems.edge.evcs.ocpp.server/src/io/openems/edge/evcs/ocpp/server/EvcsOcppServer.java +++ b/io.openems.edge.evcs.ocpp.server/src/io/openems/edge/evcs/ocpp/server/EvcsOcppServer.java @@ -76,10 +76,9 @@ public class EvcsOcppServer extends AbstractOpenemsComponent implements OpenemsC */ @Reference(policy = ReferencePolicy.DYNAMIC, policyOption = ReferencePolicyOption.GREEDY, cardinality = ReferenceCardinality.MULTIPLE) protected void addEvcs(Evcs evcs) { - if (!(evcs instanceof AbstractManagedOcppEvcsComponent) || evcs == null) { + if (!(evcs instanceof AbstractManagedOcppEvcsComponent ocppEvcs) || evcs == null) { return; } - var ocppEvcs = (AbstractManagedOcppEvcsComponent) evcs; var presentEvcss = this.ocppEvcss.get(ocppEvcs.getConfiguredOcppId()); if (presentEvcss == null) { @@ -106,10 +105,9 @@ protected void addEvcs(Evcs evcs) { * @param evcs Evcs that should be removed */ protected void removeEvcs(Evcs evcs) { - if (!(evcs instanceof AbstractManagedOcppEvcsComponent) || evcs == null) { + if (!(evcs instanceof AbstractManagedOcppEvcsComponent ocppEvcs) || evcs == null) { return; } - var ocppEvcs = (AbstractManagedOcppEvcsComponent) evcs; var evcss = this.activeEvcsSessions.get(ocppEvcs.getSessionId()); if (evcss != null) { if (evcss.size() < 2) { diff --git a/io.openems.edge.fenecon.mini/src/io/openems/edge/fenecon/mini/ess/statemachine/StateMachine.java b/io.openems.edge.fenecon.mini/src/io/openems/edge/fenecon/mini/ess/statemachine/StateMachine.java index 4eb5fea90f6..9ddb8911efc 100644 --- a/io.openems.edge.fenecon.mini/src/io/openems/edge/fenecon/mini/ess/statemachine/StateMachine.java +++ b/io.openems.edge.fenecon.mini/src/io/openems/edge/fenecon/mini/ess/statemachine/StateMachine.java @@ -59,36 +59,22 @@ public StateMachine(State initialState) { @Override public StateHandler getStateHandler(State state) { - switch (state) { - case UNDEFINED: - return new UndefinedHandler(); - - case GO_READONLY_MODE: - return new GoReadonlyModeHandler(); - case ACTIVATE_ECONOMIC_MODE_1: - return new ActivateEconomicMode1Handler(); - case ACTIVATE_ECONOMIC_MODE_2: - return new ActivateEconomicMode2Handler(); - case ACTIVATE_ECONOMIC_MODE_3: - return new ActivateEconomicMode3Handler(); - case ACTIVATE_ECONOMIC_MODE_4: - return new ActivateEconomicMode4Handler(); - case READONLY_MODE: - return new ReadonlyModeHandler(); - - case GO_WRITE_MODE: - return new GoWriteModeHandler(); - case ACTIVATE_DEBUG_MODE_1: - return new ActivateDebugMode1Handler(); - case ACTIVATE_DEBUG_MODE_2: - return new ActivateDebugMode2Handler(); - case ACTIVATE_DEBUG_MODE_3: - return new ActivateDebugMode3Handler(); - case ACTIVATE_DEBUG_MODE_4: - return new ActivateDebugMode4Handler(); - case WRITE_MODE: - return new WriteModeHandler(); - } - throw new IllegalArgumentException("Unknown State [" + state + "]"); + return switch (state) { + case UNDEFINED -> new UndefinedHandler(); + + case GO_READONLY_MODE -> new GoReadonlyModeHandler(); + case ACTIVATE_ECONOMIC_MODE_1 -> new ActivateEconomicMode1Handler(); + case ACTIVATE_ECONOMIC_MODE_2 -> new ActivateEconomicMode2Handler(); + case ACTIVATE_ECONOMIC_MODE_3 -> new ActivateEconomicMode3Handler(); + case ACTIVATE_ECONOMIC_MODE_4 -> new ActivateEconomicMode4Handler(); + case READONLY_MODE -> new ReadonlyModeHandler(); + + case GO_WRITE_MODE -> new GoWriteModeHandler(); + case ACTIVATE_DEBUG_MODE_1 -> new ActivateDebugMode1Handler(); + case ACTIVATE_DEBUG_MODE_2 -> new ActivateDebugMode2Handler(); + case ACTIVATE_DEBUG_MODE_3 -> new ActivateDebugMode3Handler(); + case ACTIVATE_DEBUG_MODE_4 -> new ActivateDebugMode4Handler(); + case WRITE_MODE -> new WriteModeHandler(); + }; } } diff --git a/io.openems.edge.goodwe/src/io/openems/edge/goodwe/batteryinverter/GoodWeBatteryInverterImpl.java b/io.openems.edge.goodwe/src/io/openems/edge/goodwe/batteryinverter/GoodWeBatteryInverterImpl.java index 49e26e25259..fbe163b38b5 100644 --- a/io.openems.edge.goodwe/src/io/openems/edge/goodwe/batteryinverter/GoodWeBatteryInverterImpl.java +++ b/io.openems.edge.goodwe/src/io/openems/edge/goodwe/batteryinverter/GoodWeBatteryInverterImpl.java @@ -1,5 +1,6 @@ package io.openems.edge.goodwe.batteryinverter; +import static io.openems.common.utils.FunctionUtils.doNothing; import static io.openems.edge.common.channel.ChannelUtils.setWriteValueIfNotRead; import java.util.Objects; @@ -59,6 +60,7 @@ import io.openems.edge.goodwe.common.enums.ControlMode; import io.openems.edge.goodwe.common.enums.EnableCurve; import io.openems.edge.goodwe.common.enums.EnableDisable; +import io.openems.edge.goodwe.common.enums.FeedInPowerSettings.FixedPowerFactor; import io.openems.edge.timedata.api.Timedata; @Designate(ocd = Config.class, factory = true) @@ -253,93 +255,73 @@ private void applyConfigIfNotSet(Config config, boolean onConfigUpdate) throws O // Feed-in limitation setWriteValueIfNotRead(this.channel(GoodWe.ChannelId.FEED_POWER_PARA_SET), config.feedPowerPara()); - // Set to feed in power settings to default - setWriteValueIfNotRead(this.channel(GoodWe.ChannelId.QU_CURVE), EnableCurve.DISABLE); - setWriteValueIfNotRead(this.channel(GoodWe.ChannelId.ENABLE_CURVE_PU), EnableCurve.DISABLE); - - if (onConfigUpdate) { - // Mppt Shadow enable / disable - setWriteValueIfNotRead(this.channel(GoodWe.ChannelId.MPPT_FOR_SHADOW_ENABLE), false); - - // Feed-in settings - var setFeedInPowerSettings = config.setfeedInPowerSettings(); - switch (setFeedInPowerSettings) { - case UNDEFINED: - break; - case QU_ENABLE_CURVE: - setWriteValueIfNotRead(this.channel(GoodWe.ChannelId.LOCK_IN_POWER_QU), 200); - setWriteValueIfNotRead(this.channel(GoodWe.ChannelId.LOCK_OUT_POWER_QU), 50); - setWriteValueIfNotRead(this.channel(GoodWe.ChannelId.V1_VOLTAGE), 214); - setWriteValueIfNotRead(this.channel(GoodWe.ChannelId.V1_VALUE), 436); - setWriteValueIfNotRead(this.channel(GoodWe.ChannelId.V2_VOLTAGE), 223); - setWriteValueIfNotRead(this.channel(GoodWe.ChannelId.V2_VALUE), 0); - setWriteValueIfNotRead(this.channel(GoodWe.ChannelId.V3_VOLTAGE), 237); - setWriteValueIfNotRead(this.channel(GoodWe.ChannelId.V3_VALUE), 0); - setWriteValueIfNotRead(this.channel(GoodWe.ChannelId.V4_VOLTAGE), 247); - setWriteValueIfNotRead(this.channel(GoodWe.ChannelId.V4_VALUE), -526); - break; - case PU_ENABLE_CURVE: - setWriteValueIfNotRead(this.channel(GoodWe.ChannelId.A_POINT_POWER), 2000); - setWriteValueIfNotRead(this.channel(GoodWe.ChannelId.A_POINT_COS_PHI), 0); - setWriteValueIfNotRead(this.channel(GoodWe.ChannelId.B_POINT_POWER), 2000); - setWriteValueIfNotRead(this.channel(GoodWe.ChannelId.B_POINT_COS_PHI), 0); - setWriteValueIfNotRead(this.channel(GoodWe.ChannelId.C_POINT_POWER), 2000); - setWriteValueIfNotRead(this.channel(GoodWe.ChannelId.C_POINT_COS_PHI), 0); - break; - case LAGGING_0_80: - case LAGGING_0_81: - case LAGGING_0_82: - case LAGGING_0_83: - case LAGGING_0_84: - case LAGGING_0_85: - case LAGGING_0_86: - case LAGGING_0_87: - case LAGGING_0_88: - case LAGGING_0_89: - case LAGGING_0_90: - case LAGGING_0_91: - case LAGGING_0_92: - case LAGGING_0_93: - case LAGGING_0_94: - case LAGGING_0_95: - case LAGGING_0_96: - case LAGGING_0_97: - case LAGGING_0_98: - case LAGGING_0_99: - case LEADING_0_80: - case LEADING_0_81: - case LEADING_0_82: - case LEADING_0_83: - case LEADING_0_84: - case LEADING_0_85: - case LEADING_0_86: - case LEADING_0_87: - case LEADING_0_88: - case LEADING_0_89: - case LEADING_0_90: - case LEADING_0_91: - case LEADING_0_92: - case LEADING_0_93: - case LEADING_0_94: - case LEADING_0_95: - case LEADING_0_96: - case LEADING_0_97: - case LEADING_0_98: - case LEADING_0_99: - case LEADING_1: - if (setFeedInPowerSettings.fixedPowerFactor == null) { - throw new IllegalArgumentException( - "Feed-In-Power-Setting [" + setFeedInPowerSettings + "] has no fixed power factor"); - } - setWriteValueIfNotRead(this.channel(GoodWe.ChannelId.FIXED_POWER_FACTOR), - config.setfeedInPowerSettings().fixedPowerFactor); - break; - } + // Set feed in power settings + var setFeedInPowerSettings = config.setfeedInPowerSettings(); + var quEnableDisable = EnableCurve.DISABLE; + var puEnableDisable = EnableCurve.DISABLE; + var cosPhiPEnableDisable = EnableCurve.DISABLE; + var pfEnableDisable = EnableCurve.DISABLE; + var fixedPowerFactor = FixedPowerFactor.LEADING_1_OR_NONE; + + switch (setFeedInPowerSettings) { + + case UNDEFINED -> doNothing(); + case QU_ENABLE_CURVE -> { + quEnableDisable = EnableCurve.ENABLE; + // values according to vde-ar-n-4105 + setWriteValueIfNotRead(this.channel(GoodWe.ChannelId.LOCK_IN_POWER_QU), 200); + setWriteValueIfNotRead(this.channel(GoodWe.ChannelId.LOCK_OUT_POWER_QU), 50); + setWriteValueIfNotRead(this.channel(GoodWe.ChannelId.V1_VOLTAGE), 214); // ratio U/Un: 0.93 + setWriteValueIfNotRead(this.channel(GoodWe.ChannelId.V1_VALUE), 1000); // (var % rated VA) + setWriteValueIfNotRead(this.channel(GoodWe.ChannelId.V2_VOLTAGE), 223); // ratio U/Un: 0.97 + setWriteValueIfNotRead(this.channel(GoodWe.ChannelId.V2_VALUE), 0); // (var % rated VA) + setWriteValueIfNotRead(this.channel(GoodWe.ChannelId.V3_VOLTAGE), 237);// ratio U/Un: 1,03 + setWriteValueIfNotRead(this.channel(GoodWe.ChannelId.V3_VALUE), 0); // (var % rated VA) + setWriteValueIfNotRead(this.channel(GoodWe.ChannelId.V4_VOLTAGE), 247); // ratio U/Un: 1,07 + setWriteValueIfNotRead(this.channel(GoodWe.ChannelId.V4_VALUE), -1000); + } + case PU_ENABLE_CURVE -> { + // Not part of the 4105 for GERMANY + puEnableDisable = EnableCurve.ENABLE; + } + case LAGGING_0_80, LAGGING_0_81, LAGGING_0_82, LAGGING_0_83, LAGGING_0_84, LAGGING_0_85, LAGGING_0_86, + LAGGING_0_87, LAGGING_0_88, LAGGING_0_89, LAGGING_0_90, LAGGING_0_91, LAGGING_0_92, LAGGING_0_93, + LAGGING_0_94, LAGGING_0_95, LAGGING_0_96, LAGGING_0_97, LAGGING_0_98, LAGGING_0_99, LEADING_0_80, + LEADING_0_81, LEADING_0_82, LEADING_0_83, LEADING_0_84, LEADING_0_85, LEADING_0_86, LEADING_0_87, + LEADING_0_88, LEADING_0_89, LEADING_0_90, LEADING_0_91, LEADING_0_92, LEADING_0_93, LEADING_0_94, + LEADING_0_95, LEADING_0_96, LEADING_0_97, LEADING_0_98, LEADING_0_99, LEADING_1 -> { + + fixedPowerFactor = setFeedInPowerSettings.fixedPowerFactor; } + case PF_ENABLE_CURVE -> { + pfEnableDisable = EnableCurve.ENABLE; + // TODO: Details settings + } + case COS_PHI_P_CURVE -> { + cosPhiPEnableDisable = EnableCurve.ENABLE; + setWriteValueIfNotRead(this.channel(GoodWe.ChannelId.A_POINT_POWER), 100); // range -1000,1000: 10% + setWriteValueIfNotRead(this.channel(GoodWe.ChannelId.A_POINT_COS_PHI), 100); // -100,100: factor 1 + setWriteValueIfNotRead(this.channel(GoodWe.ChannelId.B_POINT_POWER), 500); // -1000,1000: 50% + setWriteValueIfNotRead(this.channel(GoodWe.ChannelId.B_POINT_COS_PHI), 100); // -100,100: factor 1 + setWriteValueIfNotRead(this.channel(GoodWe.ChannelId.C_POINT_POWER), 1000); // -1000,1000: 100% + setWriteValueIfNotRead(this.channel(GoodWe.ChannelId.C_POINT_COS_PHI), 90); // -100,100: factor 0,9 + } + } + setWriteValueIfNotRead(this.channel(GoodWe.ChannelId.ENABLE_QU_CURVE), quEnableDisable); + setWriteValueIfNotRead(this.channel(GoodWe.ChannelId.ENABLE_CURVE_COS_PHI_P), cosPhiPEnableDisable); + setWriteValueIfNotRead(this.channel(GoodWe.ChannelId.ENABLE_PU_CURVE), puEnableDisable); + setWriteValueIfNotRead(this.channel(GoodWe.ChannelId.ENABLE_PF_CURVE), pfEnableDisable); + setWriteValueIfNotRead(this.channel(GoodWe.ChannelId.FIXED_POWER_FACTOR), fixedPowerFactor); // Multi-functional Block for Ripple Control Receiver and NA protection on / off setWriteValueIfNotRead(this.channel(GoodWe.ChannelId.DRED_REMOTE_SHUTDOWN_RCR_FUNCTIONS_ENABLE), config.rcrEnable().booleanValue || config.naProtectionEnable().booleanValue); + + // Try only once + if (onConfigUpdate) { // + // Mppt Shadow enable / disable + setWriteValueIfNotRead(this.channel(GoodWe.ChannelId.MPPT_FOR_SHADOW_ENABLE), false); + } } /** @@ -594,7 +576,7 @@ public void run(Battery battery, int setActivePower, int setReactivePower) throw this.applyConfigIfNotSet(this.config, false); // Calculate ActivePower, Energy and Max-AC-Power. - this.updatePowerAndEnergyChannels(); + this.updatePowerAndEnergyChannels(battery.getSoc().get(), battery.getCurrent().get()); this.calculateMaxAcPower(this.getMaxApparentPower().orElse(0)); this.latestBatteryData = new BatteryData(battery.getChargeMaxCurrent().get(), battery.getVoltage().get()); diff --git a/io.openems.edge.goodwe/src/io/openems/edge/goodwe/common/AbstractGoodWe.java b/io.openems.edge.goodwe/src/io/openems/edge/goodwe/common/AbstractGoodWe.java index ee3a44735af..16146aac409 100644 --- a/io.openems.edge.goodwe/src/io/openems/edge/goodwe/common/AbstractGoodWe.java +++ b/io.openems.edge.goodwe/src/io/openems/edge/goodwe/common/AbstractGoodWe.java @@ -56,6 +56,7 @@ import io.openems.edge.goodwe.charger.GoodWeCharger; import io.openems.edge.goodwe.charger.twostring.GoodWeChargerTwoString; import io.openems.edge.goodwe.common.enums.BatteryMode; +import io.openems.edge.goodwe.common.enums.EmsPowerMode; import io.openems.edge.goodwe.common.enums.GoodWeType; import io.openems.edge.timedata.api.TimedataProvider; import io.openems.edge.timedata.api.utils.CalculateEnergyFromPower; @@ -650,10 +651,10 @@ protected final ModbusProtocol defineModbusProtocol() { SCALE_FACTOR_MINUS_2), // m(GoodWe.ChannelId.GRID_PROTECT, new UnsignedWordElement(45431))), // - // Cos Phi Curve new FC3ReadRegistersTask(45432, Priority.LOW, // - m(GoodWe.ChannelId.POWER_SLOPE_ENABLE, new UnsignedWordElement(45432)), // - m(GoodWe.ChannelId.ENABLE_CURVE_PU, new UnsignedWordElement(45433)), // + // Cos Phi Curve + m(GoodWe.ChannelId.ENABLE_POWER_SLOPE_COS_PHI_P, new UnsignedWordElement(45432)), // + m(GoodWe.ChannelId.ENABLE_CURVE_COS_PHI_P, new UnsignedWordElement(45433)), // m(GoodWe.ChannelId.A_POINT_POWER, new SignedWordElement(45434)), // m(GoodWe.ChannelId.A_POINT_COS_PHI, new SignedWordElement(45435), SCALE_FACTOR_MINUS_2), // m(GoodWe.ChannelId.B_POINT_POWER, new SignedWordElement(45436)), // @@ -663,12 +664,10 @@ protected final ModbusProtocol defineModbusProtocol() { m(GoodWe.ChannelId.LOCK_IN_VOLTAGE, new UnsignedWordElement(45440), SCALE_FACTOR_MINUS_1), // m(GoodWe.ChannelId.LOCK_OUT_VOLTAGE, new UnsignedWordElement(45441), SCALE_FACTOR_MINUS_1), // m(GoodWe.ChannelId.LOCK_OUT_POWER, new SignedWordElement(45442)), // + // Power and frequency curve (PF) + m(GoodWe.ChannelId.ENABLE_PF_CURVE, new UnsignedWordElement(45443))), // - // Power and frequency curve - m(new BitsWordElement(45443, this)// - .bit(0, GoodWe.ChannelId.POWER_FREQUENCY_ENABLED)// - .bit(1, GoodWe.ChannelId.POWER_FREQUENCY_RESPONSE_MODE)// - ), // + new FC3ReadRegistersTask(45444, Priority.LOW, // m(GoodWe.ChannelId.FFROZEN_DCH, new UnsignedWordElement(45444), SCALE_FACTOR_MINUS_2), // m(GoodWe.ChannelId.FFROZEN_CH, new UnsignedWordElement(45445), SCALE_FACTOR_MINUS_2), // m(GoodWe.ChannelId.FSTOP_DCH, new UnsignedWordElement(45446), SCALE_FACTOR_MINUS_2), // @@ -687,7 +686,7 @@ protected final ModbusProtocol defineModbusProtocol() { // QU Curve new FC3ReadRegistersTask(45456, Priority.LOW, // - m(GoodWe.ChannelId.QU_CURVE, new UnsignedWordElement(45456)), // + m(GoodWe.ChannelId.ENABLE_QU_CURVE, new UnsignedWordElement(45456)), // m(GoodWe.ChannelId.LOCK_IN_POWER_QU, new SignedWordElement(45457)), // m(GoodWe.ChannelId.LOCK_OUT_POWER_QU, new SignedWordElement(45458)), // m(GoodWe.ChannelId.V1_VOLTAGE, new UnsignedWordElement(45459), SCALE_FACTOR_MINUS_1), // ), // @@ -704,7 +703,7 @@ protected final ModbusProtocol defineModbusProtocol() { // PU Curve new FC3ReadRegistersTask(45472, Priority.LOW, // - m(GoodWe.ChannelId.PU_CURVE, new UnsignedWordElement(45472)), // + m(GoodWe.ChannelId.ENABLE_PU_CURVE, new UnsignedWordElement(45472)), // m(GoodWe.ChannelId.POWER_CHANGE_RATE, new UnsignedWordElement(45473)), // m(GoodWe.ChannelId.V1_VOLTAGE_PU, new UnsignedWordElement(45474), SCALE_FACTOR_MINUS_1), // m(GoodWe.ChannelId.V1_VALUE_PU, new SignedWordElement(45475), SCALE_FACTOR_MINUS_1), // @@ -714,8 +713,8 @@ protected final ModbusProtocol defineModbusProtocol() { m(GoodWe.ChannelId.V3_VALUE_PU, new SignedWordElement(45479), SCALE_FACTOR_MINUS_1), // m(GoodWe.ChannelId.V4_VOLTAGE_PU, new UnsignedWordElement(45480), SCALE_FACTOR_MINUS_1), // m(GoodWe.ChannelId.V4_VALUE_PU, new SignedWordElement(45481), SCALE_FACTOR_MINUS_1), // - // 80=Pf 0.8, 20= -0.8Pf - m(GoodWe.ChannelId.FIXED_POWER_FACTOR, new UnsignedWordElement(45482), SCALE_FACTOR_MINUS_2), // + // Fix Pf (80=Pf 0.8, 20= -0.8Pf) + m(GoodWe.ChannelId.FIXED_POWER_FACTOR, new UnsignedWordElement(45482)), // // Set the percentage of rated power of the inverter m(GoodWe.ChannelId.FIXED_REACTIVE_POWER, new SignedWordElement(45483), SCALE_FACTOR_MINUS_1), // m(GoodWe.ChannelId.FIXED_ACTIVE_POWER, new UnsignedWordElement(45484), SCALE_FACTOR_MINUS_1)), // @@ -964,28 +963,31 @@ protected final ModbusProtocol defineModbusProtocol() { m(GoodWe.ChannelId.POWER_RATE_LIMIT_REDUCTION, new UnsignedWordElement(45430), SCALE_FACTOR_MINUS_2), // m(GoodWe.ChannelId.GRID_PROTECT, new UnsignedWordElement(45431)), // - m(GoodWe.ChannelId.POWER_SLOPE_ENABLE, new UnsignedWordElement(45432))), // + m(GoodWe.ChannelId.ENABLE_POWER_SLOPE_COS_PHI_P, new UnsignedWordElement(45432))), // - // Cos Phi Curve new FC16WriteRegistersTask(45433, // - m(GoodWe.ChannelId.ENABLE_CURVE_PU, new UnsignedWordElement(45433)), // + // Cos Phi Curve + m(GoodWe.ChannelId.ENABLE_CURVE_COS_PHI_P, new UnsignedWordElement(45433)), // m(GoodWe.ChannelId.A_POINT_POWER, new SignedWordElement(45434)), // - m(GoodWe.ChannelId.A_POINT_COS_PHI, new SignedWordElement(45435), SCALE_FACTOR_MINUS_2), // + m(GoodWe.ChannelId.A_POINT_COS_PHI, new SignedWordElement(45435)), // m(GoodWe.ChannelId.B_POINT_POWER, new SignedWordElement(45436)), // - m(GoodWe.ChannelId.B_POINT_COS_PHI, new SignedWordElement(45437), SCALE_FACTOR_MINUS_2), // + m(GoodWe.ChannelId.B_POINT_COS_PHI, new SignedWordElement(45437)), // m(GoodWe.ChannelId.C_POINT_POWER, new SignedWordElement(45438)), // - m(GoodWe.ChannelId.C_POINT_COS_PHI, new SignedWordElement(45439), SCALE_FACTOR_MINUS_2), // + m(GoodWe.ChannelId.C_POINT_COS_PHI, new SignedWordElement(45439)) // + ), + + new FC16WriteRegistersTask(45440, // + // [600, 3000] m(GoodWe.ChannelId.LOCK_IN_VOLTAGE, new UnsignedWordElement(45440), SCALE_FACTOR_MINUS_1), // + // [600, 3000] m(GoodWe.ChannelId.LOCK_OUT_VOLTAGE, new UnsignedWordElement(45441), SCALE_FACTOR_MINUS_1), // - m(GoodWe.ChannelId.LOCK_OUT_POWER, new SignedWordElement(45442))), // + m(GoodWe.ChannelId.LOCK_OUT_POWER, new SignedWordElement(45442)), // - // Power and frequency curve - // m(new BitsWordElement(45443, this)// - // .bit(0, GoodWe.ChannelId.STATE_70)// - // .bit(1, GoodWe.ChannelId.STATE_71)), // + // Power and frequency curve (PF) + m(GoodWe.ChannelId.ENABLE_PF_CURVE, new UnsignedWordElement(45443)), // + // GW is not supporting Coils (POWER_FREQUENCY_RESPONSE_MODE will be set by + // default to slope (bit1: response mode, 1: fstop, 0: slope)) - // Power and frequency curve - new FC16WriteRegistersTask(45444, // m(GoodWe.ChannelId.FFROZEN_DCH, new UnsignedWordElement(45444), SCALE_FACTOR_MINUS_2), // m(GoodWe.ChannelId.FFROZEN_CH, new UnsignedWordElement(45445), SCALE_FACTOR_MINUS_2), // m(GoodWe.ChannelId.FSTOP_DCH, new UnsignedWordElement(45446), SCALE_FACTOR_MINUS_2), // @@ -1002,7 +1004,7 @@ protected final ModbusProtocol defineModbusProtocol() { m(GoodWe.ChannelId.CFP_OF_RECOVER_POWER_PERCENT, new UnsignedWordElement(45455)), // // QU Curve - m(GoodWe.ChannelId.QU_CURVE, new UnsignedWordElement(45456)), // + m(GoodWe.ChannelId.ENABLE_QU_CURVE, new UnsignedWordElement(45456)), // m(GoodWe.ChannelId.LOCK_IN_POWER_QU, new SignedWordElement(45457)), // m(GoodWe.ChannelId.LOCK_OUT_POWER_QU, new SignedWordElement(45458)), // m(GoodWe.ChannelId.V1_VOLTAGE, new UnsignedWordElement(45459), SCALE_FACTOR_MINUS_1), // ), // @@ -1019,7 +1021,7 @@ protected final ModbusProtocol defineModbusProtocol() { // PU Curve new FC16WriteRegistersTask(45472, // - m(GoodWe.ChannelId.PU_CURVE, new UnsignedWordElement(45472)), // + m(GoodWe.ChannelId.ENABLE_PU_CURVE, new UnsignedWordElement(45472)), // m(GoodWe.ChannelId.POWER_CHANGE_RATE, new UnsignedWordElement(45473), SCALE_FACTOR_MINUS_2), // m(GoodWe.ChannelId.V1_VOLTAGE_PU, new UnsignedWordElement(45474), SCALE_FACTOR_MINUS_1), // m(GoodWe.ChannelId.V1_VALUE_PU, new SignedWordElement(45475)), // @@ -1977,7 +1979,7 @@ protected final Integer calculatePvProduction() { return productionPower; } - protected void updatePowerAndEnergyChannels() { + protected void updatePowerAndEnergyChannels(Integer soc, Integer batteryCurrent) { final var productionPower = this.calculatePvProduction(); final Channel pBattery1Channel = this.channel(GoodWe.ChannelId.P_BATTERY1); var dcDischargePower = pBattery1Channel.value().get(); @@ -1991,6 +1993,10 @@ protected void updatePowerAndEnergyChannels() { state -> this.channel(GoodWe.ChannelId.IGNORE_IMPOSSIBLE_P_BATTERY_VALUE).setNextValue(state), dcDischargePowerChannel.value().asOptional()); + dcDischargePower = ignoreImpossibleMinPower(dcDischargePower, soc, batteryCurrent, + ((EnumReadChannel) this.channel(GoodWe.ChannelId.EMS_POWER_MODE)).getNextValue().asEnum(), + ((IntegerReadChannel) this.channel(GoodWe.ChannelId.EMS_POWER_SET)).getNextValue().get()); + var acActivePower = TypeUtils.sum(productionPower, dcDischargePower); /* @@ -2060,6 +2066,9 @@ protected void updatePowerAndEnergyChannels() { protected static Integer postprocessPBattery1(Integer pBattery, Integer dcVoltage, Integer maxDcCurrent, Consumer setState, Optional prevPBattery) { + /* + * Values above maximum charge/discharge power + */ var stateIgnoreImpossiblePBatteryValue = false; if (pBattery != null && dcVoltage != null && maxDcCurrent != null) { @@ -2072,10 +2081,43 @@ protected static Integer postprocessPBattery1(Integer pBattery, Integer dcVoltag .orElse(fitWithin(maxDcCurrent * dcVoltage * -1, maxDcCurrent * dcVoltage, pBattery)); } } + setState.accept(stateIgnoreImpossiblePBatteryValue); return pBattery; } + /** + * Ignore impossible minimum power. + * + *

+ * Even if there is no real power charged to the battery, the GoodWe Channel + * could remain on minimum power values. These values are ignored. + * + * @param goodweDcPower GoodWe DC battery power in W + * @param soc State of Charge + * @param cBattery Battery current in A + * @param powerMode EMS power mode + * @param powerSet EMS power set + * @return possible battery power + */ + protected static Integer ignoreImpossibleMinPower(Integer goodweDcPower, Integer soc, Integer cBattery, + EmsPowerMode powerMode, Integer powerSet) { + if (cBattery == null || soc == null || goodweDcPower == null || cBattery != 0 || powerMode == null + || powerSet == null) { + return goodweDcPower; + } + + final var batFullOrEmpty = soc >= 100 || soc <= 0; + final var emsTargetOfZero = (powerMode == EmsPowerMode.CHARGE_BAT || powerMode == EmsPowerMode.DISCHARGE_BAT) + && powerSet == 0; + + if (batFullOrEmpty || emsTargetOfZero) { + return Math.abs(goodweDcPower) < 50 /* W */ ? 0 : goodweDcPower; + } + + return goodweDcPower; + } + /** * Calculate and store Max-AC-Export and -Import channels. * diff --git a/io.openems.edge.goodwe/src/io/openems/edge/goodwe/common/ApplyPowerHandler.java b/io.openems.edge.goodwe/src/io/openems/edge/goodwe/common/ApplyPowerHandler.java index fc446b1febd..8fe1f0330e9 100644 --- a/io.openems.edge.goodwe/src/io/openems/edge/goodwe/common/ApplyPowerHandler.java +++ b/io.openems.edge.goodwe/src/io/openems/edge/goodwe/common/ApplyPowerHandler.java @@ -55,32 +55,21 @@ public synchronized void apply(AbstractGoodWe goodWe, int setActivePower, Contro emsPowerModeChannel.setNextWriteValue(apply.emsPowerMode); } - private static class Result { - - protected EmsPowerMode emsPowerMode; - protected int emsPowerSet; - - public Result(EmsPowerMode emsPowerMode, int emsPowerSet) { - this.emsPowerMode = emsPowerMode; - this.emsPowerSet = emsPowerSet; - } - + private static record Result(EmsPowerMode emsPowerMode, int emsPowerSet) { } private static ApplyPowerHandler.Result calculate(AbstractGoodWe goodWe, int activePowerSetPoint, int pvProduction, ControlMode controlMode, int gridActivePower, int essActivePower, int maxAcImport, int maxAcExport) throws OpenemsNamedException { - switch (controlMode) { - case INTERNAL: - return handleInternalMode(); - case SMART: - return handleSmartMode(goodWe, activePowerSetPoint, pvProduction, gridActivePower, essActivePower, - maxAcImport, maxAcExport); - case REMOTE: - return handleRemoteMode(activePowerSetPoint, pvProduction); - default: - return handleInternalMode(); - } + return switch (controlMode) { + case INTERNAL // + -> handleInternalMode(); + case SMART // + -> handleSmartMode(goodWe, activePowerSetPoint, pvProduction, gridActivePower, essActivePower, maxAcImport, + maxAcExport); + case REMOTE // + -> handleRemoteMode(activePowerSetPoint, pvProduction); + }; } private static Result handleInternalMode() { @@ -158,35 +147,26 @@ private void checkControlModeRequiresSmartMeter(AbstractGoodWe goodWe, ControlMo EnumReadChannel meterCommunicateStatusChannel = goodWe.channel(GoodWe.ChannelId.METER_COMMUNICATE_STATUS); MeterCommunicateStatus meterCommunicateStatus = meterCommunicateStatusChannel.value().asEnum(); - var enableWarning = false; - switch (meterCommunicateStatus) { - case UNDEFINED: + var enableWarning = switch (meterCommunicateStatus) { + case UNDEFINED -> // // We don't know if GoodWe Smart Meter is connected. Either not read yet (on // startup) or DSP version too low. - enableWarning = false; - break; + false; - case OK: + case OK -> // GoodWe Smart Meter is connected. - enableWarning = false; - break; + false; - case NG: - // GoodWe Smart Meter is NOT connected. - switch (controlMode) { - case REMOTE: + case NG // + -> switch (controlMode) { + case REMOTE -> // REMOTE mode is ok without GoodWe Smart Meter - enableWarning = false; - break; - - case INTERNAL: - case SMART: + false; + case INTERNAL, SMART -> // INTERNAL and SMART mode require a GoodWe Smart Meter - enableWarning = true; - break; - } - break; - } + true; + }; + }; goodWe.channel(GoodWe.ChannelId.NO_SMART_METER_DETECTED).setNextValue(enableWarning); } diff --git a/io.openems.edge.goodwe/src/io/openems/edge/goodwe/common/GoodWe.java b/io.openems.edge.goodwe/src/io/openems/edge/goodwe/common/GoodWe.java index cf148a50f69..612ef8f15ce 100644 --- a/io.openems.edge.goodwe/src/io/openems/edge/goodwe/common/GoodWe.java +++ b/io.openems.edge.goodwe/src/io/openems/edge/goodwe/common/GoodWe.java @@ -988,29 +988,29 @@ public static enum ChannelId implements io.openems.edge.common.channel.ChannelId .accessMode(AccessMode.READ_WRITE)), // GRID_PROTECT(Doc.of(GridProtect.values()) // .accessMode(AccessMode.READ_WRITE)), // - POWER_SLOPE_ENABLE(Doc.of(OpenemsType.INTEGER) // - .accessMode(AccessMode.READ_WRITE)), // // CosPhi curve - ENABLE_CURVE_PU(Doc.of(EnableCurve.values()) // + ENABLE_CURVE_COS_PHI_P(Doc.of(EnableCurve.values()) // + .accessMode(AccessMode.READ_WRITE)), // + ENABLE_POWER_SLOPE_COS_PHI_P(Doc.of(EnableCurve.values()) // .accessMode(AccessMode.READ_WRITE)), // A_POINT_POWER(Doc.of(OpenemsType.INTEGER) // .unit(Unit.WATT) // .accessMode(AccessMode.READ_WRITE)), // A_POINT_COS_PHI(Doc.of(OpenemsType.INTEGER) // - .unit(Unit.PERCENT) // + .unit(Unit.THOUSANDTH) // .accessMode(AccessMode.READ_WRITE)), // B_POINT_POWER(Doc.of(OpenemsType.INTEGER) // .unit(Unit.WATT) // .accessMode(AccessMode.READ_WRITE)), // B_POINT_COS_PHI(Doc.of(OpenemsType.INTEGER) // - .unit(Unit.PERCENT) // + .unit(Unit.THOUSANDTH) // .accessMode(AccessMode.READ_WRITE)), // C_POINT_POWER(Doc.of(OpenemsType.INTEGER) // .unit(Unit.WATT) // .accessMode(AccessMode.READ_WRITE)), // C_POINT_COS_PHI(Doc.of(OpenemsType.INTEGER) // - .unit(Unit.PERCENT) // + .unit(Unit.THOUSANDTH) // .accessMode(AccessMode.READ_WRITE)), // LOCK_IN_VOLTAGE(Doc.of(OpenemsType.INTEGER) // .unit(Unit.VOLT) // @@ -1022,11 +1022,15 @@ public static enum ChannelId implements io.openems.edge.common.channel.ChannelId .unit(Unit.WATT) // .accessMode(AccessMode.READ_WRITE)), // - // Power and frequency curve - POWER_FREQUENCY_ENABLED(Doc.of(OpenemsType.BOOLEAN) // - .text("Power and Frequency Curve Enabled")), // + // Power and frequency curve = PF + ENABLE_PF_CURVE(Doc.of(EnableCurve.values()) // + .text("Power and Frequency Curve Enabled") // + .accessMode(AccessMode.READ_WRITE)), // + // Written together with ENABLE_PF_CURVE as GoodWe is not supporting Coils, + // relevant is anyways 0=Slope. POWER_FREQUENCY_RESPONSE_MODE(Doc.of(OpenemsType.BOOLEAN) // - .text("Power and Frequency Curve: 0=Slope, 1=Fstop")), // + .text("Power and Frequency Curve: 0=Slope, 1=Fstop") // + .accessMode(AccessMode.READ_ONLY)), // FFROZEN_DCH(Doc.of(OpenemsType.INTEGER) // .unit(Unit.HERTZ) // @@ -1065,37 +1069,37 @@ public static enum ChannelId implements io.openems.edge.common.channel.ChannelId .accessMode(AccessMode.READ_WRITE)), // // QU curve - QU_CURVE(Doc.of(EnableCurve.values()) // + ENABLE_QU_CURVE(Doc.of(EnableCurve.values()) // .accessMode(AccessMode.READ_WRITE)), // LOCK_IN_POWER_QU(Doc.of(OpenemsType.INTEGER) // - .unit(Unit.WATT) // + .unit(Unit.THOUSANDTH) // .accessMode(AccessMode.READ_WRITE)), // LOCK_OUT_POWER_QU(Doc.of(OpenemsType.INTEGER) // - .unit(Unit.WATT) // + .unit(Unit.THOUSANDTH) // .accessMode(AccessMode.READ_WRITE)), // V1_VOLTAGE(Doc.of(OpenemsType.INTEGER) // .unit(Unit.VOLT) // .accessMode(AccessMode.READ_WRITE)), // V1_VALUE(Doc.of(OpenemsType.INTEGER) // - .unit(Unit.WATT) // + .unit(Unit.THOUSANDTH) // .accessMode(AccessMode.READ_WRITE)), // V2_VOLTAGE(Doc.of(OpenemsType.INTEGER) // .unit(Unit.VOLT) // .accessMode(AccessMode.READ_WRITE)), // V2_VALUE(Doc.of(OpenemsType.INTEGER) // - .unit(Unit.WATT) // + .unit(Unit.THOUSANDTH) // .accessMode(AccessMode.READ_WRITE)), // V3_VOLTAGE(Doc.of(OpenemsType.INTEGER) // .unit(Unit.VOLT) // .accessMode(AccessMode.READ_WRITE)), // V3_VALUE(Doc.of(OpenemsType.INTEGER) // - .unit(Unit.WATT) // + .unit(Unit.THOUSANDTH) // .accessMode(AccessMode.READ_WRITE)), // V4_VOLTAGE(Doc.of(OpenemsType.INTEGER) // .unit(Unit.VOLT) // .accessMode(AccessMode.READ_WRITE)), // V4_VALUE(Doc.of(OpenemsType.INTEGER) // - .unit(Unit.WATT) // + .unit(Unit.THOUSANDTH) // .accessMode(AccessMode.READ_WRITE)), // K_VALUE(Doc.of(OpenemsType.INTEGER) // .accessMode(AccessMode.READ_WRITE)), // @@ -1105,7 +1109,7 @@ public static enum ChannelId implements io.openems.edge.common.channel.ChannelId .accessMode(AccessMode.READ_WRITE)), // // PU curve - PU_CURVE(Doc.of(OpenemsType.INTEGER) // + ENABLE_PU_CURVE(Doc.of(EnableCurve.values()) // .accessMode(AccessMode.READ_WRITE)), // POWER_CHANGE_RATE(Doc.of(OpenemsType.INTEGER) // .accessMode(AccessMode.READ_WRITE)), // @@ -1113,22 +1117,28 @@ public static enum ChannelId implements io.openems.edge.common.channel.ChannelId .unit(Unit.VOLT) // .accessMode(AccessMode.READ_WRITE)), // V1_VALUE_PU(Doc.of(OpenemsType.INTEGER) // + .unit(Unit.THOUSANDTH) // .accessMode(AccessMode.READ_WRITE)), // V2_VOLTAGE_PU(Doc.of(OpenemsType.INTEGER) // .unit(Unit.VOLT) // .accessMode(AccessMode.READ_WRITE)), // V2_VALUE_PU(Doc.of(OpenemsType.INTEGER) // + .unit(Unit.THOUSANDTH) // .accessMode(AccessMode.READ_WRITE)), // V3_VOLTAGE_PU(Doc.of(OpenemsType.INTEGER) // .unit(Unit.VOLT) // .accessMode(AccessMode.READ_WRITE)), // V3_VALUE_PU(Doc.of(OpenemsType.INTEGER) // + .unit(Unit.THOUSANDTH) // .accessMode(AccessMode.READ_WRITE)), // V4_VOLTAGE_PU(Doc.of(OpenemsType.INTEGER) // .unit(Unit.VOLT) // .accessMode(AccessMode.READ_WRITE)), // V4_VALUE_PU(Doc.of(OpenemsType.INTEGER) // + .unit(Unit.THOUSANDTH) // .accessMode(AccessMode.READ_WRITE)), // + + // Fixed Power Factor FIXED_POWER_FACTOR(Doc.of(FixedPowerFactor.values()) // .accessMode(AccessMode.READ_WRITE)), // FIXED_REACTIVE_POWER(Doc.of(OpenemsType.INTEGER) // @@ -1320,7 +1330,7 @@ public static enum ChannelId implements io.openems.edge.common.channel.ChannelId * individually. */ DRED_REMOTE_SHUTDOWN_RCR_FUNCTIONS_ENABLE(Doc.of(OpenemsType.BOOLEAN) // - .accessMode(AccessMode.READ_WRITE)), // + .accessMode(AccessMode.READ_WRITE)), // DEBUG_EMS_POWER_MODE(Doc.of(EmsPowerMode.values())), // DEBUG_EMS_POWER_SET(Doc.of(OpenemsType.INTEGER)), // diff --git a/io.openems.edge.goodwe/src/io/openems/edge/goodwe/common/enums/EnableCurve.java b/io.openems.edge.goodwe/src/io/openems/edge/goodwe/common/enums/EnableCurve.java index 08c36b8b09d..41d3e71634d 100644 --- a/io.openems.edge.goodwe/src/io/openems/edge/goodwe/common/enums/EnableCurve.java +++ b/io.openems.edge.goodwe/src/io/openems/edge/goodwe/common/enums/EnableCurve.java @@ -5,8 +5,8 @@ public enum EnableCurve implements OptionsEnum { UNDEFINED(-1, "Undefined"), // - DISABLE(0, "Feed Power Disable"), // - ENABLE(1, "Feed Power Enable");// + DISABLE(0, "Disable Curve"), // + ENABLE(1, "Enable Curve"); // private final int value; private final String option; diff --git a/io.openems.edge.goodwe/src/io/openems/edge/goodwe/common/enums/FeedInPowerSettings.java b/io.openems.edge.goodwe/src/io/openems/edge/goodwe/common/enums/FeedInPowerSettings.java index 20173e352fb..7d150d6dd35 100644 --- a/io.openems.edge.goodwe/src/io/openems/edge/goodwe/common/enums/FeedInPowerSettings.java +++ b/io.openems.edge.goodwe/src/io/openems/edge/goodwe/common/enums/FeedInPowerSettings.java @@ -6,6 +6,8 @@ public enum FeedInPowerSettings { UNDEFINED(null), // QU_ENABLE_CURVE(null), // PU_ENABLE_CURVE(null), // + PF_ENABLE_CURVE(null), // + COS_PHI_P_CURVE(null), // LAGGING_0_99(FixedPowerFactor.LAGGING_0_99), // LAGGING_0_98(FixedPowerFactor.LAGGING_0_98), // @@ -48,10 +50,9 @@ public enum FeedInPowerSettings { LEADING_0_97(FixedPowerFactor.LEADING_0_97), // LEADING_0_98(FixedPowerFactor.LEADING_0_98), // LEADING_0_99(FixedPowerFactor.LEADING_0_99), // - LEADING_1(FixedPowerFactor.LEADING_1); + LEADING_1(FixedPowerFactor.LEADING_1_OR_NONE); public static enum FixedPowerFactor implements OptionsEnum { - UNDEFINED(-1, "Undefined"), // LAGGING_0_99(1, "0.99 lagging"), // LAGGING_0_98(2, "0.98 lagging"), // LAGGING_0_97(3, "0.97 lagging"), // @@ -92,7 +93,7 @@ public static enum FixedPowerFactor implements OptionsEnum { LEADING_0_97(97, "0.97 leading"), // LEADING_0_98(98, "0.98 leading"), // LEADING_0_99(99, "0.99 leading"), // - LEADING_1(100, "1 leading"); + LEADING_1_OR_NONE(100, "1 leading or none");// 100 also corresponds to "no" fixed power factor private final int value; private final String option; @@ -114,7 +115,7 @@ public String getName() { @Override public OptionsEnum getUndefined() { - return UNDEFINED; + return LEADING_1_OR_NONE; } } diff --git a/io.openems.edge.goodwe/src/io/openems/edge/goodwe/ess/GoodWeEssImpl.java b/io.openems.edge.goodwe/src/io/openems/edge/goodwe/ess/GoodWeEssImpl.java index 056126d62ec..d76c5eafbc1 100644 --- a/io.openems.edge.goodwe/src/io/openems/edge/goodwe/ess/GoodWeEssImpl.java +++ b/io.openems.edge.goodwe/src/io/openems/edge/goodwe/ess/GoodWeEssImpl.java @@ -144,7 +144,7 @@ public void handleEvent(Event event) { switch (event.getTopic()) { case EdgeEventConstants.TOPIC_CYCLE_BEFORE_PROCESS_IMAGE: - this.updatePowerAndEnergyChannels(); + this.updatePowerAndEnergyChannels(this.getSoc().get(), null); break; case EdgeEventConstants.TOPIC_CYCLE_AFTER_PROCESS_IMAGE: this.allowedChargeDischargeHandler.accept(this.componentManager); diff --git a/io.openems.edge.goodwe/src/io/openems/edge/goodwe/gridmeter/GoodWeGridMeterImpl.java b/io.openems.edge.goodwe/src/io/openems/edge/goodwe/gridmeter/GoodWeGridMeterImpl.java index d6574501518..8245c516ce9 100644 --- a/io.openems.edge.goodwe/src/io/openems/edge/goodwe/gridmeter/GoodWeGridMeterImpl.java +++ b/io.openems.edge.goodwe/src/io/openems/edge/goodwe/gridmeter/GoodWeGridMeterImpl.java @@ -339,17 +339,12 @@ protected void convertMeterConnectStatus(Integer value) { * @return connection information of the given phase */ protected static Integer getPhaseConnectionValue(Phase phase, int value) { - switch (phase) { - case L1: - return value & 0xF; - case L2: - return value >> 4 & 0xF; - case L3: - return value >> 8 & 0xF; - case ALL: - default: - return null; - } + return switch (phase) { + case L1 -> value & 0xF; + case L2 -> value >> 4 & 0xF; + case L3 -> value >> 8 & 0xF; + case ALL -> null; + }; } /** @@ -428,6 +423,9 @@ public ModbusSlaveTable getModbusSlaveTable(AccessMode accessMode) { protected static ElementToChannelConverter createAdjustCurrentSign( Supplier> getActivePowerNextValue) { return new ElementToChannelConverter(value -> { + if (value == null) { + return value; + } var activePower = getActivePowerNextValue.get().orElse(0); Integer intValue = TypeUtils.getAsType(INTEGER, value); return Math.abs(intValue) * Integer.signum(activePower); diff --git a/io.openems.edge.goodwe/src/io/openems/edge/goodwe/gridmeter/IgnoreZeroConverter.java b/io.openems.edge.goodwe/src/io/openems/edge/goodwe/gridmeter/IgnoreZeroConverter.java index 6539a6ea96f..c44b7f538b0 100644 --- a/io.openems.edge.goodwe/src/io/openems/edge/goodwe/gridmeter/IgnoreZeroConverter.java +++ b/io.openems.edge.goodwe/src/io/openems/edge/goodwe/gridmeter/IgnoreZeroConverter.java @@ -34,10 +34,10 @@ private IgnoreZeroConverter(GoodWeGridMeter parent) { if (value == null) { return null; } - if (value instanceof Integer && (Integer) value != 0) { + if (value instanceof Integer i && i != 0) { return value; } - if (value instanceof Long && (Long) value != 0L) { + if (value instanceof Long l && l != 0L) { return value; } var hasNoMeter = parent.getHasNoMeter(); diff --git a/io.openems.edge.goodwe/test/io/openems/edge/goodwe/batteryinverter/GoodWeBatteryInverterImplTest.java b/io.openems.edge.goodwe/test/io/openems/edge/goodwe/batteryinverter/GoodWeBatteryInverterImplTest.java index 2681a485c74..08b6fb6c85b 100644 --- a/io.openems.edge.goodwe/test/io/openems/edge/goodwe/batteryinverter/GoodWeBatteryInverterImplTest.java +++ b/io.openems.edge.goodwe/test/io/openems/edge/goodwe/batteryinverter/GoodWeBatteryInverterImplTest.java @@ -1,5 +1,6 @@ package io.openems.edge.goodwe.batteryinverter; +import static io.openems.common.test.TestUtils.createDummyClock; import static io.openems.edge.battery.api.Battery.ChannelId.CHARGE_MAX_CURRENT; import static io.openems.edge.batteryinverter.api.SymmetricBatteryInverter.ChannelId.ACTIVE_POWER; import static io.openems.edge.batteryinverter.api.SymmetricBatteryInverter.ChannelId.MAX_APPARENT_POWER; @@ -51,7 +52,6 @@ import io.openems.edge.common.test.ComponentTest; import io.openems.edge.common.test.DummyComponentManager; import io.openems.edge.common.test.DummyConfigurationAdmin; -import io.openems.edge.common.test.TestUtils; import io.openems.edge.ess.api.SymmetricEss; import io.openems.edge.ess.test.DummyPower; import io.openems.edge.goodwe.charger.singlestring.GoodWeChargerPv1; @@ -60,8 +60,10 @@ import io.openems.edge.goodwe.common.GoodWe; import io.openems.edge.goodwe.common.enums.ControlMode; import io.openems.edge.goodwe.common.enums.EmsPowerMode; +import io.openems.edge.goodwe.common.enums.EnableCurve; import io.openems.edge.goodwe.common.enums.EnableDisable; import io.openems.edge.goodwe.common.enums.FeedInPowerSettings; +import io.openems.edge.goodwe.common.enums.FeedInPowerSettings.FixedPowerFactor; import io.openems.edge.goodwe.common.enums.GoodWeType; import io.openems.edge.goodwe.common.enums.MeterCommunicateStatus; import io.openems.edge.goodwe.common.enums.PvMode; @@ -750,7 +752,7 @@ public void testReadFromModbus() throws Exception { new ComponentTest(sut) // .addReference("cm", new DummyConfigurationAdmin()) // .addReference("componentManager", - new DummyComponentManager(TestUtils.createDummyClock())) + new DummyComponentManager(createDummyClock())) .addReference("setModbus", new DummyModbusBridge("modbus2") // .withRegisters(35011, // Deprecated GoodWe type register new int[] { 0x4757, 0x3135, 0x4b2d, 0x4554, 0x3230 }) @@ -799,4 +801,51 @@ public void testReadFromModbus() throws Exception { .deactivate(); } + @Test + public void testPowerModeFromModbus() throws Exception { + var sut = new GoodWeBatteryInverterImpl(); + new ComponentTest(sut) // + .addReference("cm", new DummyConfigurationAdmin()) // + .addReference("componentManager", + new DummyComponentManager(createDummyClock())) + .addReference("setModbus", new DummyModbusBridge("modbus2") // + // Not part of the test + .withRegisters(35011, // Deprecated GoodWe type register + new int[] { 0x4757, 0x3135, 0x4b2d, 0x4554, 0x3230 }) + .withRegisters(35001, // Block including GoodWe Serial Number + new int[] { 0x3a98, 0x0001, 0x3730, 0x3135, 0x4b45, 0x5542, 0x3234, 0x3730, 0x3031, + 0x3734 }) + .withRegisters(35180, // Battery values of GoodWe + new int[] { 0x056e, 0x0000, 0xffff, 0xfffb, 0x0002 }) + .withRegisters(35016, // GoodWe Software Versions + new int[] { 0, 0, 0x07df, 0x0006, 0x0185 }) + .withRegisters(35111, // PV data including GridMode + new int[] { 0x8FC, 0, 0, 0, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0, 0x0200, 0x8EF, 0x0054, + 0x1389, 0xFFFF, 0xF869, 0x08E3, 0x0055, 0x138B, 0xFFFF, 0xF870, 0x08EC, 0x0056, + 0x138B, 0xFFFF, 0xF86b, 0x0001 /* GridMode */ }) + + // Power Mode + .withRegisters(45472, // + new int[] { 0x000, 0x0c8, 0x816, 0, 0x898, 0x3e8, 0x9c4, 0x3e8, 0xa5a, 0x0c8, 0x061, 0, + 0x3e8 })) + .activate(MyConfig.create() // + .setId("batteryInverter0") // + .setModbusId("modbus2") // + .setMpptForShadowEnable(EnableDisable.DISABLE) // + .setModbusUnitId(DEFAULT_UNIT_ID) // + .setSafetyCountry(SafetyCountry.GERMANY) // + .setMpptForShadowEnable(EnableDisable.ENABLE) // + .setBackupEnable(EnableDisable.ENABLE) // + .setFeedPowerEnable(EnableDisable.ENABLE) // + .setFeedPowerPara(3000) // + .setFeedInPowerSettings(FeedInPowerSettings.PU_ENABLE_CURVE) // + .setControlMode(ControlMode.SMART) // + .setStartStop(StartStopConfig.START) // + .build()) // + + .next(new TestCase() // + .output(GoodWe.ChannelId.ENABLE_PU_CURVE, EnableCurve.ENABLE) // WriteValue + .output(GoodWe.ChannelId.FIXED_POWER_FACTOR, FixedPowerFactor.LEADING_1_OR_NONE) // + ); + } } diff --git a/io.openems.edge.goodwe/test/io/openems/edge/goodwe/common/TestStatic.java b/io.openems.edge.goodwe/test/io/openems/edge/goodwe/common/TestStatic.java index 31c8dea5b60..f33b9a1b688 100644 --- a/io.openems.edge.goodwe/test/io/openems/edge/goodwe/common/TestStatic.java +++ b/io.openems.edge.goodwe/test/io/openems/edge/goodwe/common/TestStatic.java @@ -5,6 +5,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import java.util.Optional; @@ -12,6 +13,7 @@ import org.junit.Test; +import io.openems.edge.goodwe.common.enums.EmsPowerMode; import io.openems.edge.goodwe.common.enums.GoodWeType; public class TestStatic { @@ -219,4 +221,40 @@ public void testPostprocessPBattery1() { state -> stateResult.set(state), prevPBattery)); // assertTrue(stateResult.get()); } + + @Test + public void testignoreImpossibleMinimumPower() { + + var dcPower = 200_000; // W + var powerMode = EmsPowerMode.AUTO; + var powerSet = 0; + + assertEquals(dcPower, (int) AbstractGoodWe.ignoreImpossibleMinPower(dcPower, 50 /* SoC */, + 25 /* batteryCurrent */, powerMode, powerSet)); + + dcPower = 10; + assertEquals(dcPower, (int) AbstractGoodWe.ignoreImpossibleMinPower(dcPower, 50, 25, powerMode, powerSet)); + + dcPower = 10; + assertEquals(dcPower, (int) AbstractGoodWe.ignoreImpossibleMinPower(dcPower, 0, 2, powerMode, powerSet)); + assertEquals(dcPower, (int) AbstractGoodWe.ignoreImpossibleMinPower(dcPower, 2, 0, powerMode, powerSet)); + assertEquals(dcPower, + (int) AbstractGoodWe.ignoreImpossibleMinPower(dcPower, 95, 0, EmsPowerMode.CHARGE_BAT, 1000)); + + assertEquals(dcPower, (int) AbstractGoodWe.ignoreImpossibleMinPower(dcPower, null, 0, powerMode, powerSet)); + assertEquals(dcPower, (int) AbstractGoodWe.ignoreImpossibleMinPower(dcPower, 0, null, powerMode, powerSet)); + assertEquals(dcPower, (int) AbstractGoodWe.ignoreImpossibleMinPower(dcPower, 0, 0, null, powerSet)); + assertEquals(dcPower, (int) AbstractGoodWe.ignoreImpossibleMinPower(dcPower, 0, 0, powerMode, null)); + assertNull(AbstractGoodWe.ignoreImpossibleMinPower(null, null, null, null, null)); + + /* + * Ignore impossible value + */ + assertEquals(0, (int) AbstractGoodWe.ignoreImpossibleMinPower(dcPower, 0, 0, powerMode, powerSet)); + assertEquals(0, (int) AbstractGoodWe.ignoreImpossibleMinPower(dcPower, 100, 0, powerMode, powerSet)); + assertEquals(0, + (int) AbstractGoodWe.ignoreImpossibleMinPower(dcPower, 95, 0, EmsPowerMode.CHARGE_BAT, powerSet)); + assertEquals(0, + (int) AbstractGoodWe.ignoreImpossibleMinPower(dcPower, 95, 0, EmsPowerMode.DISCHARGE_BAT, powerSet)); + } } diff --git a/io.openems.edge.goodwe/test/io/openems/edge/goodwe/gridmeter/GoodWeGridMeterImplTest.java b/io.openems.edge.goodwe/test/io/openems/edge/goodwe/gridmeter/GoodWeGridMeterImplTest.java index c32d8e8b7f8..fe5dccd5425 100644 --- a/io.openems.edge.goodwe/test/io/openems/edge/goodwe/gridmeter/GoodWeGridMeterImplTest.java +++ b/io.openems.edge.goodwe/test/io/openems/edge/goodwe/gridmeter/GoodWeGridMeterImplTest.java @@ -148,6 +148,11 @@ public void testAdjustCurrentSign() { // negative to positive assertEquals(16, e2cConverter.elementToChannel(-16)); } + { + var e2cConverter = GoodWeGridMeterImpl.createAdjustCurrentSign(() -> new Value(null, 5000)); + // null stays null + assertEquals(null, e2cConverter.elementToChannel(null)); + } } @Test diff --git a/io.openems.edge.io.api/bnd.bnd b/io.openems.edge.io.api/bnd.bnd index e6f2e03ce02..aa7c0dd5fa0 100644 --- a/io.openems.edge.io.api/bnd.bnd +++ b/io.openems.edge.io.api/bnd.bnd @@ -6,7 +6,7 @@ Bundle-Version: 1.0.0.${tstamp} -buildpath: \ ${buildpath},\ io.openems.common,\ - io.openems.edge.common + io.openems.edge.common,\ -testpath: \ ${testpath} diff --git a/io.openems.edge.io.api/src/io/openems/edge/io/test/DummyInputOutput.java b/io.openems.edge.io.api/src/io/openems/edge/io/test/DummyInputOutput.java index 92e6b4a26c1..9e633ff4d8c 100644 --- a/io.openems.edge.io.api/src/io/openems/edge/io/test/DummyInputOutput.java +++ b/io.openems.edge.io.api/src/io/openems/edge/io/test/DummyInputOutput.java @@ -1,8 +1,10 @@ package io.openems.edge.io.test; +import static io.openems.common.channel.AccessMode.READ_WRITE; +import static io.openems.edge.common.test.TestUtils.withValue; + import java.util.stream.Stream; -import io.openems.common.channel.AccessMode; import io.openems.common.types.OpenemsType; import io.openems.edge.common.channel.BooleanReadChannel; import io.openems.edge.common.channel.BooleanWriteChannel; @@ -21,25 +23,25 @@ public class DummyInputOutput extends AbstractDummyOpenemsComponent channelId.doc().getAccessMode() == AccessMode.READ_WRITE) // + .filter(channelId -> channelId.doc().getAccessMode() == READ_WRITE) // .map(this::channel) // .toArray(BooleanWriteChannel[]::new); } @@ -83,4 +85,114 @@ public BooleanReadChannel[] digitalInputChannels() { return this.digitalOutputChannels; } + /** + * Set {@link Thermometer.ChannelId#INPUT_OUTPUT0}. + * + * @param value the value + * @return myself + */ + public final DummyInputOutput withInputOutput0(boolean value) { + withValue(this, DummyInputOutput.ChannelId.INPUT_OUTPUT0, value); + return this.self(); + } + + /** + * Set {@link Thermometer.ChannelId#INPUT_OUTPUT1}. + * + * @param value the value + * @return myself + */ + public final DummyInputOutput withInputOutput1(boolean value) { + withValue(this, DummyInputOutput.ChannelId.INPUT_OUTPUT1, value); + return this.self(); + } + + /** + * Set {@link Thermometer.ChannelId#INPUT_OUTPUT2}. + * + * @param value the value + * @return myself + */ + public final DummyInputOutput withInputOutput2(boolean value) { + withValue(this, DummyInputOutput.ChannelId.INPUT_OUTPUT2, value); + return this.self(); + } + + /** + * Set {@link Thermometer.ChannelId#INPUT_OUTPUT3}. + * + * @param value the value + * @return myself + */ + public final DummyInputOutput withInputOutput3(boolean value) { + withValue(this, DummyInputOutput.ChannelId.INPUT_OUTPUT3, value); + return this.self(); + } + + /** + * Set {@link Thermometer.ChannelId#INPUT_OUTPUT4}. + * + * @param value the value + * @return myself + */ + public final DummyInputOutput withInputOutput4(boolean value) { + withValue(this, DummyInputOutput.ChannelId.INPUT_OUTPUT4, value); + return this.self(); + } + + /** + * Set {@link Thermometer.ChannelId#INPUT_OUTPUT5}. + * + * @param value the value + * @return myself + */ + public final DummyInputOutput withInputOutput5(boolean value) { + withValue(this, DummyInputOutput.ChannelId.INPUT_OUTPUT5, value); + return this.self(); + } + + /** + * Set {@link Thermometer.ChannelId#INPUT_OUTPUT6}. + * + * @param value the value + * @return myself + */ + public final DummyInputOutput withInputOutput6(boolean value) { + withValue(this, DummyInputOutput.ChannelId.INPUT_OUTPUT6, value); + return this.self(); + } + + /** + * Set {@link Thermometer.ChannelId#INPUT_OUTPUT7}. + * + * @param value the value + * @return myself + */ + public final DummyInputOutput withInputOutput7(boolean value) { + withValue(this, DummyInputOutput.ChannelId.INPUT_OUTPUT7, value); + return this.self(); + } + + /** + * Set {@link Thermometer.ChannelId#INPUT_OUTPUT8}. + * + * @param value the value + * @return myself + */ + public final DummyInputOutput withInputOutput8(boolean value) { + withValue(this, DummyInputOutput.ChannelId.INPUT_OUTPUT8, value); + return this.self(); + } + + /** + * Set {@link Thermometer.ChannelId#INPUT_OUTPUT9}. + * + * @param value the value + * @return myself + */ + public final DummyInputOutput withInputOutput9(boolean value) { + withValue(this, DummyInputOutput.ChannelId.INPUT_OUTPUT9, value); + return this.self(); + } + } diff --git a/io.openems.edge.io.offgridswitch/src/io/openems/edge/iooffgridswitch/IoOffGridSwitchImpl.java b/io.openems.edge.io.offgridswitch/src/io/openems/edge/iooffgridswitch/IoOffGridSwitchImpl.java index 5ada4158ed6..f46880e569b 100644 --- a/io.openems.edge.io.offgridswitch/src/io/openems/edge/iooffgridswitch/IoOffGridSwitchImpl.java +++ b/io.openems.edge.io.offgridswitch/src/io/openems/edge/iooffgridswitch/IoOffGridSwitchImpl.java @@ -144,29 +144,18 @@ private void setOutput(ChannelAddress channelAddress, Contactor operation, Relay BooleanWriteChannel channel = this.componentManager.getChannel(channelAddress); // Get Target Value - Boolean targetValue = null; - switch (operation) { - case OPEN: - switch (relay) { - case NORMALLY_CLOSED: - targetValue = true; - break; - case NORMALLY_OPEN: - targetValue = false; - break; - } - break; - case CLOSE: - switch (relay) { - case NORMALLY_CLOSED: - targetValue = false; - break; - case NORMALLY_OPEN: - targetValue = true; - break; - } - break; - } + var targetValue = switch (operation) { + case OPEN // + -> switch (relay) { + case NORMALLY_CLOSED -> true; + case NORMALLY_OPEN -> false; + }; + case CLOSE // + -> switch (relay) { + case NORMALLY_CLOSED -> false; + case NORMALLY_OPEN -> true; + }; + }; if (Objects.equal(channel.value().get(), targetValue)) { // it is already in the desired state diff --git a/io.openems.edge.io.shelly/src/io/openems/edge/io/shelly/common/Utils.java b/io.openems.edge.io.shelly/src/io/openems/edge/io/shelly/common/Utils.java index ca4ac6ff5b4..d5d0edfabeb 100644 --- a/io.openems.edge.io.shelly/src/io/openems/edge/io/shelly/common/Utils.java +++ b/io.openems.edge.io.shelly/src/io/openems/edge/io/shelly/common/Utils.java @@ -1,7 +1,16 @@ package io.openems.edge.io.shelly.common; +import static java.util.Arrays.stream; +import static java.util.stream.Collectors.joining; + +import java.util.Objects; +import java.util.Optional; +import java.util.concurrent.CompletableFuture; + +import io.openems.edge.bridge.http.api.BridgeHttp; import io.openems.edge.common.channel.BooleanWriteChannel; import io.openems.edge.common.channel.Channel; +import io.openems.edge.common.channel.WriteChannel; import io.openems.edge.common.component.OpenemsComponent; public class Utils { @@ -13,17 +22,20 @@ private Utils() { * Generates a standard Debug-Log string for Shellys with one relay and power * meter. * - * @param relayChannel the Relay-Channel + * @param relayChannels the Relay-Channel * @param activePowerChannel the ActivePower-Channel * @return suitable for {@link OpenemsComponent#debugLog()} */ - public static String generateDebugLog(Channel relayChannel, Channel activePowerChannel) { + public static String generateDebugLog(Channel[] relayChannels, Channel activePowerChannel) { var b = new StringBuilder(); - relayChannel.value().asOptional().ifPresentOrElse(// - v -> b.append(v ? "On" : "Off"), // - () -> b.append("Unknown")); - b.append("|"); - b.append(activePowerChannel.value().asString()); + for (int i = 0; i < relayChannels.length; i++) { + var relayChannel = relayChannels[i]; + relayChannel.value().asOptional().ifPresentOrElse(v -> b.append(v ? "x" : "-"), () -> b.append("?")); + if (i < relayChannels.length - 1) { + b.append("|"); + } + } + b.append("|").append(activePowerChannel.value().asString()); return b.toString(); } @@ -35,21 +47,58 @@ public static String generateDebugLog(Channel relayChannel, Channel c.value().asOptional().map(v -> v // + ? "x" // + : "-") // + .orElse("?")) // + .collect(joining(" ")); + } + + /** + * Executes a write command to a specified relay channel by constructing and + * sending an HTTP request based on the channel's current and intended state. + * This method compares the current state with the desired state, and only + * proceeds with the HTTP request if they differ, ensuring no unnecessary + * commands are sent. The method returns a CompletableFuture that completes when + * the HTTP request is finished. It completes normally if the HTTP request + * succeeds, and exceptionally if the request fails due to errors. + * + * @param relayChannel the channel for the relay, specifying the current and + * desired states + * @param baseUrl the base URL for constructing the final endpoint URL + * @param httpBridge the HTTP bridge to send the request + * @param index the index of the DigitalChannel to write to (used for the + * URL) + * @return CompletableFuture{@code } that completes when the HTTP + * operation completes. Completes exceptionally if there is an error in + * the HTTP request. + */ + public static CompletableFuture executeWrite(WriteChannel relayChannel, String baseUrl, + BridgeHttp httpBridge, Integer index) { + CompletableFuture future = new CompletableFuture<>(); + Boolean readValue = relayChannel.value().get(); + Optional writeValue = relayChannel.getNextWriteValueAndReset(); + + if (writeValue.isEmpty()) { + future.complete(null); // No action needed + return future; + } + if (Objects.equals(readValue, writeValue.get())) { + future.complete(null); // No change in state + return future; + } + + final String url = baseUrl + "/rpc/Switch.Set?id=" + index + "&on=" + (writeValue.get() ? "true" : "false"); + httpBridge.get(url).whenComplete((response, exception) -> { + if (exception != null) { + future.completeExceptionally(exception); } else { - b.append("Unknown"); + future.complete(null); } - if (i < digitalOutputChannels.length) { - b.append("|"); - } - i++; - } - return b.toString(); + }); + + return future; } -} +} \ No newline at end of file diff --git a/io.openems.edge.io.shelly/src/io/openems/edge/io/shelly/shelly25/IoShelly25Impl.java b/io.openems.edge.io.shelly/src/io/openems/edge/io/shelly/shelly25/IoShelly25Impl.java index 3040a02fbbc..ef0297dac35 100644 --- a/io.openems.edge.io.shelly/src/io/openems/edge/io/shelly/shelly25/IoShelly25Impl.java +++ b/io.openems.edge.io.shelly/src/io/openems/edge/io/shelly/shelly25/IoShelly25Impl.java @@ -137,14 +137,19 @@ private void processHttpResult(HttpResponse result, HttpError error var relay1State = new RelayState(null, null, null); var relay2State = new RelayState(null, null, null); - try { - final var relays = getAsJsonArray(result.data(), "relays"); - relay1State = RelayState.from(getAsJsonObject(relays.get(0))); - relay2State = RelayState.from(getAsJsonObject(relays.get(1))); - - } catch (OpenemsNamedException | IndexOutOfBoundsException e) { - this.logDebug(this.log, e.getMessage()); - slaveCommunicationFailed = true; + if (error != null) { + this.logDebug(this.log, error.getMessage()); + + } else { + try { + final var relays = getAsJsonArray(result.data(), "relays"); + relay1State = RelayState.from(getAsJsonObject(relays.get(0))); + relay2State = RelayState.from(getAsJsonObject(relays.get(1))); + + } catch (OpenemsNamedException | IndexOutOfBoundsException e) { + this.logDebug(this.log, e.getMessage()); + slaveCommunicationFailed = true; + } } this._setSlaveCommunicationFailed(slaveCommunicationFailed); @@ -182,4 +187,4 @@ private void executeWrite(BooleanWriteChannel channel, int index) { } }); } -} +} \ No newline at end of file diff --git a/io.openems.edge.io.shelly/src/io/openems/edge/io/shelly/shelly3em/IoShelly3EmImpl.java b/io.openems.edge.io.shelly/src/io/openems/edge/io/shelly/shelly3em/IoShelly3EmImpl.java index d33add0361a..19a5447471c 100644 --- a/io.openems.edge.io.shelly/src/io/openems/edge/io/shelly/shelly3em/IoShelly3EmImpl.java +++ b/io.openems.edge.io.shelly/src/io/openems/edge/io/shelly/shelly3em/IoShelly3EmImpl.java @@ -4,11 +4,10 @@ import static io.openems.common.utils.JsonUtils.getAsFloat; import static io.openems.common.utils.JsonUtils.getAsJsonArray; import static io.openems.common.utils.JsonUtils.getAsJsonObject; +import static io.openems.edge.io.shelly.common.Utils.executeWrite; import static io.openems.edge.io.shelly.common.Utils.generateDebugLog; import static java.lang.Math.round; -import java.util.Objects; - import org.osgi.service.component.ComponentContext; import org.osgi.service.component.annotations.Activate; import org.osgi.service.component.annotations.Component; @@ -83,6 +82,8 @@ public IoShelly3EmImpl() { this.digitalOutputChannels = new BooleanWriteChannel[] { this.channel(IoShelly3Em.ChannelId.RELAY) }; ElectricityMeter.calculateSumActivePowerFromPhases(this); + ElectricityMeter.calculateSumCurrentFromPhases(this); + ElectricityMeter.calculateAverageVoltageFromPhases(this); } @Activate @@ -111,7 +112,7 @@ public BooleanWriteChannel[] digitalOutputChannels() { @Override public String debugLog() { - return generateDebugLog(this.getRelayChannel(), this.getActivePowerChannel()); + return generateDebugLog(this.digitalOutputChannels, this.getActivePowerChannel()); } @Override @@ -124,7 +125,7 @@ public void handleEvent(Event event) { case EdgeEventConstants.TOPIC_CYCLE_AFTER_PROCESS_IMAGE // -> this.calculateEnergy(); case EdgeEventConstants.TOPIC_CYCLE_EXECUTE_WRITE // - -> this.executeWrite(); + -> executeWrite(this.getRelayChannel(), this.baseUrl, this.httpBridge, 0); } } @@ -219,32 +220,6 @@ private void processHttpResult(HttpResponse result, Throwable error this._setCurrentL3(currentL3); } - /** - * Execute on Cycle Event "Execute Write". - */ - private void executeWrite() { - var channel = this.getRelayChannel(); - var index = 0; - var readValue = channel.value().get(); - var writeValue = channel.getNextWriteValueAndReset(); - if (writeValue.isEmpty()) { - return; - } - if (Objects.equals(readValue, writeValue.get())) { - return; - } - final var url = this.baseUrl + "/relay/" + index + "?turn=" + (writeValue.get() ? "on" : "off"); - - this.httpBridge.get(url).whenComplete((t, e) -> { - this._setSlaveCommunicationFailed(e != null); - if (e == null) { - this.logInfo(this.log, "Executed write successfully for URL: " + url); - } else { - this.logError(this.log, "Failed to execute write for URL: " + url + "; Error: " + e.getMessage()); - } - }); - } - /** * Calculate the Energy values from ActivePower. */ diff --git a/io.openems.edge.io.shelly/src/io/openems/edge/io/shelly/shellyplug/IoShellyPlugImpl.java b/io.openems.edge.io.shelly/src/io/openems/edge/io/shelly/shellyplug/IoShellyPlugImpl.java index 0e196afdfc6..24c6efa60d0 100644 --- a/io.openems.edge.io.shelly/src/io/openems/edge/io/shelly/shellyplug/IoShellyPlugImpl.java +++ b/io.openems.edge.io.shelly/src/io/openems/edge/io/shelly/shellyplug/IoShellyPlugImpl.java @@ -1,6 +1,12 @@ package io.openems.edge.io.shelly.shellyplug; +import static io.openems.common.utils.JsonUtils.getAsBoolean; +import static io.openems.common.utils.JsonUtils.getAsFloat; +import static io.openems.common.utils.JsonUtils.getAsJsonArray; +import static io.openems.common.utils.JsonUtils.getAsJsonObject; +import static io.openems.common.utils.JsonUtils.getAsLong; import static io.openems.edge.io.shelly.common.Utils.generateDebugLog; +import static java.lang.Math.round; import java.util.Objects; @@ -21,7 +27,6 @@ import io.openems.common.exceptions.OpenemsError.OpenemsNamedException; import io.openems.common.types.MeterType; -import io.openems.common.utils.JsonUtils; import io.openems.edge.bridge.http.api.BridgeHttp; import io.openems.edge.bridge.http.api.BridgeHttpFactory; import io.openems.edge.bridge.http.api.HttpResponse; @@ -102,7 +107,7 @@ public BooleanWriteChannel[] digitalOutputChannels() { @Override public String debugLog() { - return generateDebugLog(this.getRelayChannel(), this.getActivePowerChannel()); + return generateDebugLog(this.digitalOutputChannels, this.getActivePowerChannel()); } @Override @@ -128,17 +133,18 @@ private void processHttpResult(HttpResponse result, Throwable error return; } try { - final var relays = JsonUtils.getAsJsonArray(result.data(), "relays"); - final var relay1 = JsonUtils.getAsJsonObject(relays.get(0)); - final var relayIson = JsonUtils.getAsBoolean(relay1, "ison"); - final var meters = JsonUtils.getAsJsonArray(result.data(), "meters"); - final var meter1 = JsonUtils.getAsJsonObject(meters.get(0)); - final var power = Math.round(JsonUtils.getAsFloat(meter1, "power")); - final var energy = JsonUtils.getAsLong(meter1, "total") /* Unit: Wm */ / 60 /* Wh */; + var relays = getAsJsonArray(result.data(), "relays"); + var relay1 = getAsJsonObject(relays.get(0)); + var relayIson = getAsBoolean(relay1, "ison"); + var meters = getAsJsonArray(result.data(), "meters"); + var meter1 = getAsJsonObject(meters.get(0)); + var power = round(getAsFloat(meter1, "power")); + var energy = getAsLong(meter1, "total")/* Unit: Wm */ / 60 /* Wh */; this._setRelay(relayIson); this._setActivePower(power); this._setActiveProductionEnergy(energy); + } catch (OpenemsNamedException e) { this._setRelay(null); this._setActivePower(null); diff --git a/io.openems.edge.io.shelly/src/io/openems/edge/io/shelly/shellyplus1pm/IoShellyPlus1PmImpl.java b/io.openems.edge.io.shelly/src/io/openems/edge/io/shelly/shellyplus1pm/IoShellyPlus1PmImpl.java index 2de16729597..2c7ba81f6d9 100644 --- a/io.openems.edge.io.shelly/src/io/openems/edge/io/shelly/shellyplus1pm/IoShellyPlus1PmImpl.java +++ b/io.openems.edge.io.shelly/src/io/openems/edge/io/shelly/shellyplus1pm/IoShellyPlus1PmImpl.java @@ -123,7 +123,7 @@ public BooleanWriteChannel[] digitalOutputChannels() { @Override public String debugLog() { - return generateDebugLog(this.getRelayChannel(), this.getActivePowerChannel()); + return generateDebugLog(this.digitalOutputChannels, this.getActivePowerChannel()); } @Override @@ -238,4 +238,4 @@ public Timedata getTimedata() { return this.timedata; } -} +} \ No newline at end of file diff --git a/io.openems.edge.io.shelly/src/io/openems/edge/io/shelly/shellyplusplugs/Config.java b/io.openems.edge.io.shelly/src/io/openems/edge/io/shelly/shellyplusplugs/Config.java index 333aa093ac8..8dd6be7fcbd 100644 --- a/io.openems.edge.io.shelly/src/io/openems/edge/io/shelly/shellyplusplugs/Config.java +++ b/io.openems.edge.io.shelly/src/io/openems/edge/io/shelly/shellyplusplugs/Config.java @@ -19,7 +19,7 @@ @AttributeDefinition(name = "Is enabled?", description = "Is this Component enabled?") boolean enabled() default true; - + @AttributeDefinition(name = "Phase", description = "Which Phase is this Shelly Plug connected to?") SinglePhase phase() default SinglePhase.L1; diff --git a/io.openems.edge.io.shelly/src/io/openems/edge/io/shelly/shellyplusplugs/IoShellyPlusPlugsImpl.java b/io.openems.edge.io.shelly/src/io/openems/edge/io/shelly/shellyplusplugs/IoShellyPlusPlugsImpl.java index 4308fed821a..1828438a49a 100644 --- a/io.openems.edge.io.shelly/src/io/openems/edge/io/shelly/shellyplusplugs/IoShellyPlusPlugsImpl.java +++ b/io.openems.edge.io.shelly/src/io/openems/edge/io/shelly/shellyplusplugs/IoShellyPlusPlugsImpl.java @@ -3,11 +3,10 @@ import static io.openems.common.utils.JsonUtils.getAsBoolean; import static io.openems.common.utils.JsonUtils.getAsFloat; import static io.openems.common.utils.JsonUtils.getAsJsonObject; +import static io.openems.edge.io.shelly.common.Utils.executeWrite; import static io.openems.edge.io.shelly.common.Utils.generateDebugLog; import static java.lang.Math.round; -import java.util.Objects; - import org.osgi.service.component.ComponentContext; import org.osgi.service.component.annotations.Activate; import org.osgi.service.component.annotations.Component; @@ -29,7 +28,6 @@ import io.openems.common.types.MeterType; import io.openems.edge.bridge.http.api.BridgeHttp; import io.openems.edge.bridge.http.api.BridgeHttpFactory; -import io.openems.edge.bridge.http.api.HttpError; import io.openems.edge.bridge.http.api.HttpResponse; import io.openems.edge.common.channel.BooleanWriteChannel; import io.openems.edge.common.component.AbstractOpenemsComponent; @@ -123,7 +121,7 @@ public BooleanWriteChannel[] digitalOutputChannels() { @Override public String debugLog() { - return generateDebugLog(this.getRelayChannel(), this.getActivePowerChannel()); + return generateDebugLog(this.digitalOutputChannels, this.getActivePowerChannel()); } @Override @@ -136,11 +134,11 @@ public void handleEvent(Event event) { case EdgeEventConstants.TOPIC_CYCLE_AFTER_PROCESS_IMAGE // -> this.calculateEnergy(); case EdgeEventConstants.TOPIC_CYCLE_EXECUTE_WRITE // - -> this.executeWrite(); + -> executeWrite(this.getRelayChannel(), this.baseUrl, this.httpBridge, 0); } } - private void processHttpResult(HttpResponse result, HttpError error) { + private void processHttpResult(HttpResponse result, Throwable error) { this._setSlaveCommunicationFailed(result == null); Boolean relayStatus = null; @@ -177,32 +175,6 @@ private void processHttpResult(HttpResponse result, HttpError error this.channel(IoShellyPlusPlugs.ChannelId.HAS_UPDATE).setNextValue(updatesAvailable); } - /** - * Execute on Cycle Event "Execute Write". - */ - private void executeWrite() { - var channel = this.getRelayChannel(); - var readValue = channel.value().get(); - var writeValue = channel.getNextWriteValueAndReset(); - if (writeValue.isEmpty()) { - return; - } - if (Objects.equals(readValue, writeValue.get())) { - return; - } - var index = 0; - final var url = this.baseUrl + "/relay/" + index + "?turn=" + (writeValue.get() ? "on" : "off"); - - this.httpBridge.get(url).whenComplete((t, e) -> { - this._setSlaveCommunicationFailed(e != null); - if (e == null) { - this.logDebug(this.log, "Executed write successfully for URL: " + url); - } else { - this.logError(this.log, "Failed to execute write for URL: " + url + "; Error: " + e.getMessage()); - } - }); - } - /** * Calculate the Energy values from ActivePower. */ @@ -236,4 +208,4 @@ public Timedata getTimedata() { return this.timedata; } -} +} \ No newline at end of file diff --git a/io.openems.edge.io.shelly/src/io/openems/edge/io/shelly/shellypro3/Config.java b/io.openems.edge.io.shelly/src/io/openems/edge/io/shelly/shellypro3/Config.java index 92064d4d596..a8a268c2551 100644 --- a/io.openems.edge.io.shelly/src/io/openems/edge/io/shelly/shellypro3/Config.java +++ b/io.openems.edge.io.shelly/src/io/openems/edge/io/shelly/shellypro3/Config.java @@ -19,6 +19,6 @@ @AttributeDefinition(name = "IP-Address", description = "The IP address of the Shelly device.") String ip(); - - String webconsole_configurationFactory_nameHint() default "IO Shelly Pro 3 [{id}]"; + + String webconsole_configurationFactory_nameHint() default "IO Shelly Pro 3 [{id}]"; } diff --git a/io.openems.edge.io.shelly/src/io/openems/edge/io/shelly/shellypro3/IoShellyPro3Impl.java b/io.openems.edge.io.shelly/src/io/openems/edge/io/shelly/shellypro3/IoShellyPro3Impl.java index 888ceb58da3..5de68423610 100644 --- a/io.openems.edge.io.shelly/src/io/openems/edge/io/shelly/shellypro3/IoShellyPro3Impl.java +++ b/io.openems.edge.io.shelly/src/io/openems/edge/io/shelly/shellypro3/IoShellyPro3Impl.java @@ -4,8 +4,6 @@ import static io.openems.common.utils.JsonUtils.getAsJsonObject; import static io.openems.edge.io.shelly.common.Utils.generateDebugLog; -import java.util.Objects; - import org.osgi.service.component.ComponentContext; import org.osgi.service.component.annotations.Activate; import org.osgi.service.component.annotations.Component; @@ -30,6 +28,7 @@ import io.openems.edge.common.component.OpenemsComponent; import io.openems.edge.common.event.EdgeEventConstants; import io.openems.edge.io.api.DigitalOutput; +import io.openems.edge.io.shelly.common.Utils; @Designate(ocd = Config.class, factory = true) @Component(// @@ -106,7 +105,7 @@ public void handleEvent(Event event) { switch (event.getTopic()) { case EdgeEventConstants.TOPIC_CYCLE_EXECUTE_WRITE // - -> this.eventExecuteWrite(); + -> this.executeWrite(); } } @@ -137,31 +136,10 @@ private void processHttpResult(HttpResponse result, HttpError error } } - /** - * Execute on Cycle Event "Execute Write". - */ - private void eventExecuteWrite() { + private void executeWrite() { for (int i = 0; i < this.digitalOutputChannels.length; i++) { - this.executeWrite(this.digitalOutputChannels[i], i); - } - } - - private void executeWrite(BooleanWriteChannel channel, int index) { - var readValue = channel.value().get(); - var writeValue = channel.getNextWriteValueAndReset(); - if (writeValue.isEmpty()) { - return; - } - if (Objects.equals(readValue, writeValue.get())) { - return; + Utils.executeWrite(this.digitalOutputChannels[i], this.baseUrl, this.httpBridge, i); } - final String url = this.baseUrl + "/relay/" + index + "?turn=" + (writeValue.get() ? "on" : "off"); - this.httpBridge.get(url).whenComplete((t, e) -> { - if (e != null) { - this.logError(this.log, "HTTP request failed: " + e.getMessage()); - this._setSlaveCommunicationFailed(true); - } - }); } -} +} \ No newline at end of file diff --git a/io.openems.edge.io.shelly/src/io/openems/edge/io/shelly/shellypro3em/Config.java b/io.openems.edge.io.shelly/src/io/openems/edge/io/shelly/shellypro3em/Config.java index 57dfdf4412d..0f8469ad98f 100644 --- a/io.openems.edge.io.shelly/src/io/openems/edge/io/shelly/shellypro3em/Config.java +++ b/io.openems.edge.io.shelly/src/io/openems/edge/io/shelly/shellypro3em/Config.java @@ -5,26 +5,25 @@ import io.openems.common.types.MeterType; -@ObjectClassDefinition( - name = "IO Shelly Pro 3EM", // +@ObjectClassDefinition(name = "IO Shelly Pro 3EM", // description = "Implements the Shelly Pro 3EM Energy Meter.") @interface Config { @AttributeDefinition(name = "Component-ID", description = "Unique ID of this Component") - String id() default "meter0"; + String id() default "meter0"; @AttributeDefinition(name = "Alias", description = "Human-readable name of this Component; defaults to Component-ID") - String alias() default ""; + String alias() default ""; @AttributeDefinition(name = "Is enabled?", description = "Is this Component enabled?") - boolean enabled() default true; + boolean enabled() default true; - @AttributeDefinition(name = "Meter-Type", description = "Grid, Production (=default), Consumption") - MeterType type() default MeterType.GRID; + @AttributeDefinition(name = "Meter-Type", description = "Grid, Production (=default), Consumption") + MeterType type() default MeterType.GRID; @AttributeDefinition(name = "IP-Address", description = "The IP address of the Shelly device.") String ip(); - String webconsole_configurationFactory_nameHint() default "IO Shelly Pro 3EM [{id}]"; + String webconsole_configurationFactory_nameHint() default "IO Shelly Pro 3EM [{id}]"; } \ No newline at end of file diff --git a/io.openems.edge.io.shelly/src/io/openems/edge/io/shelly/shellypro3em/IoShellyPro3EmImpl.java b/io.openems.edge.io.shelly/src/io/openems/edge/io/shelly/shellypro3em/IoShellyPro3EmImpl.java index e0a59bc939b..d6f2957eb5a 100644 --- a/io.openems.edge.io.shelly/src/io/openems/edge/io/shelly/shellypro3em/IoShellyPro3EmImpl.java +++ b/io.openems.edge.io.shelly/src/io/openems/edge/io/shelly/shellypro3em/IoShellyPro3EmImpl.java @@ -76,6 +76,8 @@ public IoShellyPro3EmImpl() { ); ElectricityMeter.calculateSumActivePowerFromPhases(this); + ElectricityMeter.calculateSumCurrentFromPhases(this); + ElectricityMeter.calculateAverageVoltageFromPhases(this); } @Activate diff --git a/io.openems.edge.io.shelly/test/io/openems/edge/io/shelly/shelly25/IoShelly25ImplTest.java b/io.openems.edge.io.shelly/test/io/openems/edge/io/shelly/shelly25/IoShelly25ImplTest.java index 679d091a7de..42f6e4b355a 100644 --- a/io.openems.edge.io.shelly/test/io/openems/edge/io/shelly/shelly25/IoShelly25ImplTest.java +++ b/io.openems.edge.io.shelly/test/io/openems/edge/io/shelly/shelly25/IoShelly25ImplTest.java @@ -1,22 +1,75 @@ package io.openems.edge.io.shelly.shelly25; -import static io.openems.edge.bridge.http.dummy.DummyBridgeHttpFactory.ofDummyBridge; +import static org.junit.Assert.assertEquals; import org.junit.Test; +import io.openems.edge.bridge.http.api.HttpError; +import io.openems.edge.bridge.http.api.HttpResponse; +import io.openems.edge.bridge.http.dummy.DummyBridgeHttpBundle; +import io.openems.edge.common.test.AbstractComponentTest.TestCase; import io.openems.edge.common.test.ComponentTest; public class IoShelly25ImplTest { @Test public void test() throws Exception { - new ComponentTest(new IoShelly25Impl()) // - .addReference("httpBridgeFactory", ofDummyBridge()) // + final var sut = new IoShelly25Impl(); + final var httpTestBundle = new DummyBridgeHttpBundle(); + new ComponentTest(sut) // + .addReference("httpBridgeFactory", httpTestBundle.factory()) // .activate(MyConfig.create() // .setId("io0") // .setIp("127.0.0.1") // .build()) // - ; - } + // Test case for a successful JSON response + .next(new TestCase("Successful read response") // + .onBeforeProcessImage(() -> { + httpTestBundle.forceNextSuccessfulResult(HttpResponse.ok(""" + { + "relays": [ + { + "ison": true, + "overtemperature": false, + "overpower": false + }, + { + "ison": false, + "overtemperature": true, + "overpower": true + } + ] + } + """)); + httpTestBundle.triggerNextCycle(); + }) // + .onAfterProcessImage(() -> assertEquals("x -", sut.debugLog())) // + + .output(IoShelly25.ChannelId.RELAY_1, null) // expecting WriteValue + .output(IoShelly25.ChannelId.RELAY_1_OVERPOWER, false) // + .output(IoShelly25.ChannelId.RELAY_1_OVERTEMP, false) // + .output(IoShelly25.ChannelId.RELAY_2, null) // expecting WriteValue + .output(IoShelly25.ChannelId.RELAY_2_OVERPOWER, true) // + .output(IoShelly25.ChannelId.RELAY_2_OVERTEMP, true) // + .output(IoShelly25.ChannelId.SLAVE_COMMUNICATION_FAILED, false)) // + + // Test case for an invalid JSON response + .next(new TestCase("Invalid read response") // + .onBeforeProcessImage(() -> { // + httpTestBundle.forceNextFailedResult(HttpError.ResponseError.notFound()); + httpTestBundle.triggerNextCycle(); + }) // + .onAfterProcessImage(() -> assertEquals("? ?", sut.debugLog())) // + + .output(IoShelly25.ChannelId.RELAY_1, null) // expecting WriteValue + .output(IoShelly25.ChannelId.RELAY_1_OVERPOWER, null) // + .output(IoShelly25.ChannelId.RELAY_1_OVERTEMP, null) // + .output(IoShelly25.ChannelId.RELAY_2, null) // expecting WriteValue + .output(IoShelly25.ChannelId.RELAY_2_OVERPOWER, null) // + .output(IoShelly25.ChannelId.RELAY_2_OVERTEMP, null) // + .output(IoShelly25.ChannelId.SLAVE_COMMUNICATION_FAILED, true)) // + + .deactivate();// + } } \ No newline at end of file diff --git a/io.openems.edge.io.shelly/test/io/openems/edge/io/shelly/shelly3em/IoShelly3EmImplTest.java b/io.openems.edge.io.shelly/test/io/openems/edge/io/shelly/shelly3em/IoShelly3EmImplTest.java index e51922918ef..6d3671cf46c 100644 --- a/io.openems.edge.io.shelly/test/io/openems/edge/io/shelly/shelly3em/IoShelly3EmImplTest.java +++ b/io.openems.edge.io.shelly/test/io/openems/edge/io/shelly/shelly3em/IoShelly3EmImplTest.java @@ -1,24 +1,145 @@ package io.openems.edge.io.shelly.shelly3em; import static io.openems.common.types.MeterType.CONSUMPTION_METERED; -import static io.openems.edge.bridge.http.dummy.DummyBridgeHttpFactory.ofDummyBridge; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; import org.junit.Test; +import io.openems.edge.bridge.http.api.HttpError; +import io.openems.edge.bridge.http.api.HttpResponse; +import io.openems.edge.bridge.http.dummy.DummyBridgeHttpBundle; +import io.openems.edge.common.test.AbstractComponentTest.TestCase; import io.openems.edge.common.test.ComponentTest; +import io.openems.edge.meter.api.ElectricityMeter; public class IoShelly3EmImplTest { @Test public void test() throws Exception { - new ComponentTest(new IoShelly3EmImpl()) // - .addReference("httpBridgeFactory", ofDummyBridge()) // + final var sut = new IoShelly3EmImpl(); + final var httpTestBundle = new DummyBridgeHttpBundle(); + new ComponentTest(sut) // + .addReference("httpBridgeFactory", httpTestBundle.factory()) // .activate(MyConfig.create() // .setId("io0") // .setIp("127.0.0.1") // .setType(CONSUMPTION_METERED) // .build()) // - ; - } + .next(new TestCase("Successful read response") // + .onBeforeProcessImage(() -> { + httpTestBundle.forceNextSuccessfulResult(HttpResponse.ok(""" + { + "relays": [ + { + "ison": true, + "overpower": false + } + ], + "emeters": [ + { + "power": 8.52, + "current": 1, + "voltage": 230, + "is_valid": true + }, + { + "power": 31.39, + "current": 2, + "voltage": 231, + "is_valid": true + }, + { + "power": 58.75, + "current": 3, + "voltage": 232, + "is_valid": false + } + ], + "total_power": 35.88, + "emeter_n": { + "current": 0, + "ixsum": 0.7, + "mismatch": false, + "is_valid": false + }, + "update": { + "status": "idle", + "has_update": false + } + } + """)); + httpTestBundle.triggerNextCycle(); + }) // + .onAfterProcessImage(() -> assertEquals("x|99 W", sut.debugLog())) // + + .output(ElectricityMeter.ChannelId.ACTIVE_POWER, 99) // + .output(ElectricityMeter.ChannelId.ACTIVE_POWER_L1, 9) // + .output(ElectricityMeter.ChannelId.ACTIVE_POWER_L2, 31) // + .output(ElectricityMeter.ChannelId.ACTIVE_POWER_L3, 59) // + .output(ElectricityMeter.ChannelId.VOLTAGE, 231000) // + .output(ElectricityMeter.ChannelId.VOLTAGE_L1, 230000) // + .output(ElectricityMeter.ChannelId.VOLTAGE_L2, 231000) // + .output(ElectricityMeter.ChannelId.VOLTAGE_L3, 232000) // + .output(ElectricityMeter.ChannelId.CURRENT, 6000) // + .output(ElectricityMeter.ChannelId.CURRENT_L1, 1000) // + .output(ElectricityMeter.ChannelId.CURRENT_L2, 2000) // + .output(ElectricityMeter.ChannelId.CURRENT_L3, 3000) // + .output(ElectricityMeter.ChannelId.ACTIVE_CONSUMPTION_ENERGY, null) // + .output(ElectricityMeter.ChannelId.ACTIVE_PRODUCTION_ENERGY, null) // + .output(IoShelly3Em.ChannelId.RELAY_OVERPOWER_EXCEPTION, false) // + .output(IoShelly3Em.ChannelId.HAS_UPDATE, false) // + .output(IoShelly3Em.ChannelId.EMETER1_EXCEPTION, false) // + .output(IoShelly3Em.ChannelId.EMETER2_EXCEPTION, false) // + .output(IoShelly3Em.ChannelId.EMETER3_EXCEPTION, true) // + .output(IoShelly3Em.ChannelId.SLAVE_COMMUNICATION_FAILED, false)) // + + .next(new TestCase("Invalid read response") // + .onBeforeProcessImage(() -> { + httpTestBundle.forceNextFailedResult(HttpError.ResponseError.notFound()); + httpTestBundle.triggerNextCycle(); + }) // + .onAfterProcessImage(() -> assertEquals("?|UNDEFINED", sut.debugLog())) + + .output(ElectricityMeter.ChannelId.ACTIVE_POWER, null) // + .output(ElectricityMeter.ChannelId.ACTIVE_POWER_L1, null) // + .output(ElectricityMeter.ChannelId.ACTIVE_POWER_L2, null) // + .output(ElectricityMeter.ChannelId.ACTIVE_POWER_L3, null) // + .output(ElectricityMeter.ChannelId.VOLTAGE, null) // + .output(ElectricityMeter.ChannelId.VOLTAGE_L1, null) // + .output(ElectricityMeter.ChannelId.VOLTAGE_L2, null) // + .output(ElectricityMeter.ChannelId.VOLTAGE_L3, null) // + .output(ElectricityMeter.ChannelId.CURRENT, null) // + .output(ElectricityMeter.ChannelId.CURRENT_L1, null) // + .output(ElectricityMeter.ChannelId.CURRENT_L2, null) // + .output(ElectricityMeter.ChannelId.CURRENT_L3, null) // + .output(ElectricityMeter.ChannelId.ACTIVE_CONSUMPTION_ENERGY, null) // + .output(ElectricityMeter.ChannelId.ACTIVE_PRODUCTION_ENERGY, null) // + .output(IoShelly3Em.ChannelId.RELAY_OVERPOWER_EXCEPTION, false) // + .output(IoShelly3Em.ChannelId.HAS_UPDATE, false) // + .output(IoShelly3Em.ChannelId.EMETER1_EXCEPTION, false) // + .output(IoShelly3Em.ChannelId.EMETER2_EXCEPTION, false) // + .output(IoShelly3Em.ChannelId.EMETER3_EXCEPTION, true) // + .output(IoShelly3Em.ChannelId.SLAVE_COMMUNICATION_FAILED, true)) // + + // Test case for writing to relay + .next(new TestCase("Write") // + .onBeforeControllersCallbacks(() -> { + sut.setRelay(true); + }) // + .also(testCase -> { + final var relayTurnedOn = httpTestBundle + .expect("http://127.0.0.1/rpc/Switch.Set?id=0&on=true").toBeCalled(); + + testCase.onBeforeControllersCallbacks(() -> { + httpTestBundle.triggerNextCycle(); + }); + testCase.onAfterWriteCallbacks(() -> { + assertTrue("Failed to turn on relay", relayTurnedOn.get()); + }); + })) // + + .deactivate(); + } } diff --git a/io.openems.edge.io.shelly/test/io/openems/edge/io/shelly/shellyplug/IoShellyPlugImplTest.java b/io.openems.edge.io.shelly/test/io/openems/edge/io/shelly/shellyplug/IoShellyPlugImplTest.java index 60d97be0f50..6255b5fb688 100644 --- a/io.openems.edge.io.shelly/test/io/openems/edge/io/shelly/shellyplug/IoShellyPlugImplTest.java +++ b/io.openems.edge.io.shelly/test/io/openems/edge/io/shelly/shellyplug/IoShellyPlugImplTest.java @@ -1,25 +1,112 @@ package io.openems.edge.io.shelly.shellyplug; import static io.openems.common.types.MeterType.PRODUCTION; -import static io.openems.edge.bridge.http.dummy.DummyBridgeHttpFactory.ofDummyBridge; +import static io.openems.edge.meter.api.SinglePhase.L1; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; import org.junit.Test; +import io.openems.edge.bridge.http.api.HttpError; +import io.openems.edge.bridge.http.api.HttpResponse; +import io.openems.edge.bridge.http.dummy.DummyBridgeHttpBundle; +import io.openems.edge.common.test.AbstractComponentTest.TestCase; import io.openems.edge.common.test.ComponentTest; -import io.openems.edge.meter.api.SinglePhase; +import io.openems.edge.meter.api.ElectricityMeter; public class IoShellyPlugImplTest { @Test public void test() throws Exception { - new ComponentTest(new IoShellyPlugImpl()) // - .addReference("httpBridgeFactory", ofDummyBridge()) // + final var sut = new IoShellyPlugImpl(); + final var httpTestBundle = new DummyBridgeHttpBundle(); + new ComponentTest(sut) // + .addReference("httpBridgeFactory", httpTestBundle.factory()) // .activate(MyConfig.create() // .setId("io0") // - .setPhase(SinglePhase.L1) // + .setPhase(L1) // .setIp("127.0.0.1") // .setType(PRODUCTION) // .build()) // - ; + + .next(new TestCase("Successful read response") // + .onBeforeProcessImage(() -> { + httpTestBundle.forceNextSuccessfulResult(HttpResponse.ok(""" + { + "relays": [ + { + "ison": true + } + ], + "meters": [ + { + "power": 789.1, + "total": 72000 + } + ] + } + """)); + httpTestBundle.triggerNextCycle(); + }) // + .onAfterProcessImage(() -> assertEquals("x|789 W", sut.debugLog())) + + .output(ElectricityMeter.ChannelId.ACTIVE_POWER, 789) // + .output(ElectricityMeter.ChannelId.ACTIVE_POWER_L1, 789) // + .output(ElectricityMeter.ChannelId.ACTIVE_POWER_L2, null) // + .output(ElectricityMeter.ChannelId.ACTIVE_POWER_L3, null) // + .output(ElectricityMeter.ChannelId.VOLTAGE, null) // + .output(ElectricityMeter.ChannelId.VOLTAGE_L1, null) // + .output(ElectricityMeter.ChannelId.VOLTAGE_L2, null) // + .output(ElectricityMeter.ChannelId.VOLTAGE_L3, null) // + .output(ElectricityMeter.ChannelId.CURRENT, null) // + .output(ElectricityMeter.ChannelId.CURRENT_L1, null) // + .output(ElectricityMeter.ChannelId.CURRENT_L2, null) // + .output(ElectricityMeter.ChannelId.CURRENT_L3, null) // + .output(ElectricityMeter.ChannelId.ACTIVE_CONSUMPTION_ENERGY, null) // + .output(ElectricityMeter.ChannelId.ACTIVE_PRODUCTION_ENERGY, 1200L) // + .output(IoShellyPlug.ChannelId.RELAY, null) // + .output(IoShellyPlug.ChannelId.SLAVE_COMMUNICATION_FAILED, false)) // + + .next(new TestCase("Invalid read response") // + .onBeforeProcessImage(() -> { + httpTestBundle.forceNextFailedResult(HttpError.ResponseError.notFound()); + httpTestBundle.triggerNextCycle(); + }) // + .onAfterProcessImage(() -> assertEquals("?|UNDEFINED", sut.debugLog())) + + .output(ElectricityMeter.ChannelId.ACTIVE_POWER, null) // + .output(ElectricityMeter.ChannelId.ACTIVE_POWER_L1, null) // + .output(ElectricityMeter.ChannelId.ACTIVE_POWER_L2, null) // + .output(ElectricityMeter.ChannelId.ACTIVE_POWER_L3, null) // + .output(ElectricityMeter.ChannelId.VOLTAGE, null) // + .output(ElectricityMeter.ChannelId.VOLTAGE_L1, null) // + .output(ElectricityMeter.ChannelId.VOLTAGE_L2, null) // + .output(ElectricityMeter.ChannelId.VOLTAGE_L3, null) // + .output(ElectricityMeter.ChannelId.CURRENT, null) // + .output(ElectricityMeter.ChannelId.CURRENT_L1, null) // + .output(ElectricityMeter.ChannelId.CURRENT_L2, null) // + .output(ElectricityMeter.ChannelId.CURRENT_L3, null) // + .output(ElectricityMeter.ChannelId.ACTIVE_CONSUMPTION_ENERGY, null) // + .output(ElectricityMeter.ChannelId.ACTIVE_PRODUCTION_ENERGY, 1200L) // + .output(IoShellyPlug.ChannelId.RELAY, null) // + .output(IoShellyPlug.ChannelId.SLAVE_COMMUNICATION_FAILED, true)) // + + // Test case for writing to relay + .next(new TestCase("Write") // + .onBeforeControllersCallbacks(() -> { + sut.setRelay(true); + }) // + .also(testCase -> { + final var relayTurnedOn = httpTestBundle.expect("http://127.0.0.1/relay/0?turn=on") + .toBeCalled(); + testCase.onBeforeControllersCallbacks(() -> { + httpTestBundle.triggerNextCycle(); + }); + testCase.onAfterWriteCallbacks(() -> { + assertTrue("Failed to turn on relay", relayTurnedOn.get()); + }); + })) // + + .deactivate();// } } diff --git a/io.openems.edge.io.shelly/test/io/openems/edge/io/shelly/shellyplus1pm/IoShellyPlus1PmImplTest.java b/io.openems.edge.io.shelly/test/io/openems/edge/io/shelly/shellyplus1pm/IoShellyPlus1PmImplTest.java index d2314907aea..7ccd5d5a10a 100644 --- a/io.openems.edge.io.shelly/test/io/openems/edge/io/shelly/shellyplus1pm/IoShellyPlus1PmImplTest.java +++ b/io.openems.edge.io.shelly/test/io/openems/edge/io/shelly/shellyplus1pm/IoShellyPlus1PmImplTest.java @@ -1,13 +1,6 @@ package io.openems.edge.io.shelly.shellyplus1pm; import static io.openems.common.types.MeterType.CONSUMPTION_METERED; -import static io.openems.edge.meter.api.ElectricityMeter.ChannelId.ACTIVE_CONSUMPTION_ENERGY; -import static io.openems.edge.meter.api.ElectricityMeter.ChannelId.ACTIVE_POWER; -import static io.openems.edge.meter.api.ElectricityMeter.ChannelId.ACTIVE_POWER_L1; -import static io.openems.edge.meter.api.ElectricityMeter.ChannelId.ACTIVE_POWER_L2; -import static io.openems.edge.meter.api.ElectricityMeter.ChannelId.ACTIVE_PRODUCTION_ENERGY; -import static io.openems.edge.meter.api.ElectricityMeter.ChannelId.CURRENT; -import static io.openems.edge.meter.api.ElectricityMeter.ChannelId.VOLTAGE; import static io.openems.edge.meter.api.SinglePhase.L1; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; @@ -19,15 +12,15 @@ import io.openems.edge.bridge.http.dummy.DummyBridgeHttpBundle; import io.openems.edge.common.test.AbstractComponentTest.TestCase; import io.openems.edge.common.test.ComponentTest; +import io.openems.edge.meter.api.ElectricityMeter; import io.openems.edge.timedata.test.DummyTimedata; public class IoShellyPlus1PmImplTest { @Test public void test() throws Exception { - final var httpTestBundle = new DummyBridgeHttpBundle(); final var sut = new IoShellyPlus1PmImpl(); - + final var httpTestBundle = new DummyBridgeHttpBundle(); new ComponentTest(sut) // .addReference("httpBridgeFactory", httpTestBundle.factory()) // .addReference("timedata", new DummyTimedata("timedata0")) // @@ -39,11 +32,10 @@ public void test() throws Exception { .build()) // .next(new TestCase("Successful read response") // - .onBeforeControllersCallbacks(() -> { + .onBeforeProcessImage(() -> { httpTestBundle.forceNextSuccessfulResult(HttpResponse.ok(""" { "ble":{ - }, "cloud":{ "connected":true @@ -91,7 +83,6 @@ public void test() throws Exception { "schedule_rev":0, "webhook_rev":0, "available_updates":{ - }, "reset_reason":3 }, @@ -109,29 +100,50 @@ public void test() throws Exception { """)); httpTestBundle.triggerNextCycle(); }) // - .output(ACTIVE_POWER, 123) // - .output(ACTIVE_POWER_L1, 123) // - .output(ACTIVE_POWER_L2, null) // - .output(CURRENT, 500) // - .output(VOLTAGE, 231300)) // + .onAfterProcessImage(() -> assertEquals("-|123 W", sut.debugLog())) + + .output(ElectricityMeter.ChannelId.ACTIVE_POWER, 123) // + .output(ElectricityMeter.ChannelId.ACTIVE_POWER_L1, 123) // + .output(ElectricityMeter.ChannelId.ACTIVE_POWER_L2, null) // + .output(ElectricityMeter.ChannelId.ACTIVE_POWER_L3, null) // + .output(ElectricityMeter.ChannelId.VOLTAGE, 231300) // + .output(ElectricityMeter.ChannelId.VOLTAGE_L1, 231300) // + .output(ElectricityMeter.ChannelId.VOLTAGE_L2, null) // + .output(ElectricityMeter.ChannelId.VOLTAGE_L3, null) // + .output(ElectricityMeter.ChannelId.CURRENT, 500) // + .output(ElectricityMeter.ChannelId.CURRENT_L1, 500) // + .output(ElectricityMeter.ChannelId.CURRENT_L2, null) // + .output(ElectricityMeter.ChannelId.CURRENT_L3, null) // + .output(ElectricityMeter.ChannelId.ACTIVE_CONSUMPTION_ENERGY, null) // + .output(ElectricityMeter.ChannelId.ACTIVE_PRODUCTION_ENERGY, null) // + .output(IoShellyPlus1Pm.ChannelId.RELAY, null) // + .output(IoShellyPlus1Pm.ChannelId.SLAVE_COMMUNICATION_FAILED, false)) // .next(new TestCase("Invalid read response") // - .onBeforeControllersCallbacks(() -> assertEquals("Off|123 W", sut.debugLog())) - .onBeforeControllersCallbacks(() -> { + .onBeforeProcessImage(() -> { httpTestBundle.forceNextFailedResult(HttpError.ResponseError.notFound()); httpTestBundle.triggerNextCycle(); }) // - .output(ACTIVE_POWER, null) // - .output(ACTIVE_POWER_L1, null) // - .output(ACTIVE_POWER_L2, null) // - .output(CURRENT, null) // - .output(VOLTAGE, null) // + .onAfterProcessImage(() -> assertEquals("?|UNDEFINED", sut.debugLog())) - .output(ACTIVE_PRODUCTION_ENERGY, 0L) // - .output(ACTIVE_CONSUMPTION_ENERGY, 0L)) // + .output(ElectricityMeter.ChannelId.ACTIVE_POWER, null) // + .output(ElectricityMeter.ChannelId.ACTIVE_POWER_L1, null) // + .output(ElectricityMeter.ChannelId.ACTIVE_POWER_L2, null) // + .output(ElectricityMeter.ChannelId.ACTIVE_POWER_L3, null) // + .output(ElectricityMeter.ChannelId.VOLTAGE, null) // + .output(ElectricityMeter.ChannelId.VOLTAGE_L1, null) // + .output(ElectricityMeter.ChannelId.VOLTAGE_L2, null) // + .output(ElectricityMeter.ChannelId.VOLTAGE_L3, null) // + .output(ElectricityMeter.ChannelId.CURRENT, null) // + .output(ElectricityMeter.ChannelId.CURRENT_L1, null) // + .output(ElectricityMeter.ChannelId.CURRENT_L2, null) // + .output(ElectricityMeter.ChannelId.CURRENT_L3, null) // + .output(ElectricityMeter.ChannelId.ACTIVE_CONSUMPTION_ENERGY, 0L) // + .output(ElectricityMeter.ChannelId.ACTIVE_PRODUCTION_ENERGY, 0L) // + .output(IoShellyPlus1Pm.ChannelId.RELAY, null) // + .output(IoShellyPlus1Pm.ChannelId.SLAVE_COMMUNICATION_FAILED, true)) // .next(new TestCase("Write") // - .onBeforeControllersCallbacks(() -> assertEquals("Unknown|UNDEFINED", sut.debugLog())) .onBeforeControllersCallbacks(() -> sut.setRelay(true)) // .also(testCase -> { final var relayTurnedOn = httpTestBundle.expect("http://127.0.0.1/relay/0?turn=on") @@ -145,4 +157,4 @@ public void test() throws Exception { .deactivate(); } -} +} \ No newline at end of file diff --git a/io.openems.edge.io.shelly/test/io/openems/edge/io/shelly/shellyplusplugs/IoShellyPlugImplTest.java b/io.openems.edge.io.shelly/test/io/openems/edge/io/shelly/shellyplusplugs/IoShellyPlugImplTest.java deleted file mode 100644 index 773e6df2661..00000000000 --- a/io.openems.edge.io.shelly/test/io/openems/edge/io/shelly/shellyplusplugs/IoShellyPlugImplTest.java +++ /dev/null @@ -1,98 +0,0 @@ -package io.openems.edge.io.shelly.shellyplusplugs; - -import static io.openems.common.types.MeterType.PRODUCTION; -import static io.openems.edge.meter.api.ElectricityMeter.ChannelId.ACTIVE_CONSUMPTION_ENERGY; -import static io.openems.edge.meter.api.ElectricityMeter.ChannelId.ACTIVE_POWER; -import static io.openems.edge.meter.api.ElectricityMeter.ChannelId.ACTIVE_POWER_L1; -import static io.openems.edge.meter.api.ElectricityMeter.ChannelId.ACTIVE_POWER_L2; -import static io.openems.edge.meter.api.ElectricityMeter.ChannelId.ACTIVE_PRODUCTION_ENERGY; -import static io.openems.edge.meter.api.ElectricityMeter.ChannelId.CURRENT; -import static io.openems.edge.meter.api.ElectricityMeter.ChannelId.VOLTAGE; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -import org.junit.Test; - -import io.openems.edge.bridge.http.api.HttpError; -import io.openems.edge.bridge.http.api.HttpResponse; -import io.openems.edge.bridge.http.dummy.DummyBridgeHttpBundle; -import io.openems.edge.common.test.AbstractComponentTest.TestCase; -import io.openems.edge.common.test.ComponentTest; -import io.openems.edge.meter.api.SinglePhase; -import io.openems.edge.timedata.test.DummyTimedata; - -public class IoShellyPlugImplTest { - - @Test - public void test() throws Exception { - final var httpTestBundle = new DummyBridgeHttpBundle(); - final var sut = new IoShellyPlusPlugsImpl(); - new ComponentTest(sut) // - .addReference("httpBridgeFactory", httpTestBundle.factory()) // - .addReference("timedata", new DummyTimedata("timedata0")) // - .activate(MyConfig.create() // - .setId("io0") // - .setPhase(SinglePhase.L1) // - .setIp("127.0.0.1") // - .setType(PRODUCTION) // - .build()) // - - .next(new TestCase("Successful read response") // - .onBeforeControllersCallbacks(() -> { - httpTestBundle.forceNextSuccessfulResult(HttpResponse.ok(""" - { - "sys": { - "available_updates": { - "foo": "bar" - } - }, - "switch:0": { - "current": 1.234, - "voltage": 231.5, - "output": false, - "apower": 789.1 - } - } - """)); - httpTestBundle.triggerNextCycle(); - }) // - .output(ACTIVE_POWER, 789) // - .output(ACTIVE_POWER_L1, 789) // - .output(ACTIVE_POWER_L2, null) // - .output(CURRENT, 1234) // - .output(VOLTAGE, 231500)) // - - .next(new TestCase("Invalid read response") // - .onBeforeControllersCallbacks(() -> assertEquals("Off|789 W", sut.debugLog())) - - .onBeforeControllersCallbacks(() -> { - httpTestBundle.forceNextFailedResult(HttpError.ResponseError.notFound()); - httpTestBundle.triggerNextCycle(); - }) // - .output(ACTIVE_POWER, null) // - .output(ACTIVE_POWER_L1, null) // - .output(ACTIVE_POWER_L2, null) // - .output(CURRENT, null) // - .output(VOLTAGE, null) // - - .output(ACTIVE_PRODUCTION_ENERGY, 0L) // - .output(ACTIVE_CONSUMPTION_ENERGY, 0L)) // - - .next(new TestCase("Write") // - .onBeforeControllersCallbacks(() -> assertEquals("Unknown|UNDEFINED", sut.debugLog())) - .onBeforeControllersCallbacks(() -> { - sut.setRelay(true); - }) // - .also(testCase -> { - final var relayTurnedOn = httpTestBundle.expect("http://127.0.0.1/relay/0?turn=on") - .toBeCalled(); - - testCase.onBeforeControllersCallbacks(() -> httpTestBundle.triggerNextCycle()); - testCase.onAfterWriteCallbacks( - () -> assertTrue("Failed to turn on relay", relayTurnedOn.get())); - })) // - - .deactivate(); - } - -} diff --git a/io.openems.edge.io.shelly/test/io/openems/edge/io/shelly/shellyplusplugs/IoShellyPlusPlugImplTest.java b/io.openems.edge.io.shelly/test/io/openems/edge/io/shelly/shellyplusplugs/IoShellyPlusPlugImplTest.java new file mode 100644 index 00000000000..144244905c6 --- /dev/null +++ b/io.openems.edge.io.shelly/test/io/openems/edge/io/shelly/shellyplusplugs/IoShellyPlusPlugImplTest.java @@ -0,0 +1,112 @@ +package io.openems.edge.io.shelly.shellyplusplugs; + +import static io.openems.common.types.MeterType.PRODUCTION; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +import io.openems.edge.bridge.http.api.HttpError; +import io.openems.edge.bridge.http.api.HttpResponse; +import io.openems.edge.bridge.http.dummy.DummyBridgeHttpBundle; +import io.openems.edge.common.test.AbstractComponentTest.TestCase; +import io.openems.edge.common.test.ComponentTest; +import io.openems.edge.meter.api.ElectricityMeter; +import io.openems.edge.meter.api.SinglePhase; +import io.openems.edge.timedata.test.DummyTimedata; + +public class IoShellyPlusPlugImplTest { + + @Test + public void test() throws Exception { + final var httpTestBundle = new DummyBridgeHttpBundle(); + final var sut = new IoShellyPlusPlugsImpl(); + new ComponentTest(sut) // + .addReference("httpBridgeFactory", httpTestBundle.factory()) // + .addReference("timedata", new DummyTimedata("timedata0")) // + .activate(MyConfig.create() // + .setId("io0") // + .setPhase(SinglePhase.L1) // + .setIp("127.0.0.1") // + .setType(PRODUCTION) // + .build()) // + + .next(new TestCase("Successful read response") // + .onBeforeProcessImage(() -> { + httpTestBundle.forceNextSuccessfulResult(HttpResponse.ok(""" + { + "sys": { + "available_updates": { + "foo": "bar" + } + }, + "switch:0": { + "current": 1.234, + "voltage": 231.5, + "output": false, + "apower": 789.1 + } + } + """)); + httpTestBundle.triggerNextCycle(); + }) // + .onAfterProcessImage(() -> assertEquals("-|789 W", sut.debugLog())) + + .output(ElectricityMeter.ChannelId.ACTIVE_POWER, 789) // + .output(ElectricityMeter.ChannelId.ACTIVE_POWER_L1, 789) // + .output(ElectricityMeter.ChannelId.ACTIVE_POWER_L2, null) // + .output(ElectricityMeter.ChannelId.ACTIVE_POWER_L3, null) // + .output(ElectricityMeter.ChannelId.VOLTAGE, 231500) // + .output(ElectricityMeter.ChannelId.VOLTAGE_L1, 231500) // + .output(ElectricityMeter.ChannelId.VOLTAGE_L2, null) // + .output(ElectricityMeter.ChannelId.VOLTAGE_L3, null) // + .output(ElectricityMeter.ChannelId.CURRENT, 1234) // + .output(ElectricityMeter.ChannelId.CURRENT_L1, 1234) // + .output(ElectricityMeter.ChannelId.CURRENT_L2, null) // + .output(ElectricityMeter.ChannelId.CURRENT_L3, null) // + .output(ElectricityMeter.ChannelId.ACTIVE_CONSUMPTION_ENERGY, null) // + .output(ElectricityMeter.ChannelId.ACTIVE_PRODUCTION_ENERGY, null) // + .output(IoShellyPlusPlugs.ChannelId.RELAY, null) // + .output(IoShellyPlusPlugs.ChannelId.SLAVE_COMMUNICATION_FAILED, false)) // + + .next(new TestCase("Invalid read response") // + .onBeforeProcessImage(() -> { + httpTestBundle.forceNextFailedResult(HttpError.ResponseError.notFound()); + httpTestBundle.triggerNextCycle(); + }) // + .onAfterProcessImage(() -> assertEquals("?|UNDEFINED", sut.debugLog())) + + .output(ElectricityMeter.ChannelId.ACTIVE_POWER, null) // + .output(ElectricityMeter.ChannelId.ACTIVE_POWER_L1, null) // + .output(ElectricityMeter.ChannelId.ACTIVE_POWER_L2, null) // + .output(ElectricityMeter.ChannelId.ACTIVE_POWER_L3, null) // + .output(ElectricityMeter.ChannelId.VOLTAGE, null) // + .output(ElectricityMeter.ChannelId.VOLTAGE_L1, null) // + .output(ElectricityMeter.ChannelId.VOLTAGE_L2, null) // + .output(ElectricityMeter.ChannelId.VOLTAGE_L3, null) // + .output(ElectricityMeter.ChannelId.CURRENT, null) // + .output(ElectricityMeter.ChannelId.CURRENT_L1, null) // + .output(ElectricityMeter.ChannelId.CURRENT_L2, null) // + .output(ElectricityMeter.ChannelId.CURRENT_L3, null) // + .output(ElectricityMeter.ChannelId.ACTIVE_CONSUMPTION_ENERGY, 0L) // + .output(ElectricityMeter.ChannelId.ACTIVE_PRODUCTION_ENERGY, 0L) // + .output(IoShellyPlusPlugs.ChannelId.RELAY, null) // + .output(IoShellyPlusPlugs.ChannelId.SLAVE_COMMUNICATION_FAILED, true)) // + + // Test case for writing to relay + .next(new TestCase("Write") // + .onBeforeControllersCallbacks(() -> { + sut.setRelay(true); + }) // + .also(testCase -> { + final var relayTurnedOn = httpTestBundle + .expect("http://127.0.0.1/rpc/Switch.Set?id=0&on=true").toBeCalled(); + + testCase.onBeforeControllersCallbacks(() -> httpTestBundle.triggerNextCycle()); + testCase.onAfterWriteCallbacks( + () -> assertTrue("Failed to turn on relay", relayTurnedOn.get())); + })) // + + .deactivate();// + } +} diff --git a/io.openems.edge.io.shelly/test/io/openems/edge/io/shelly/shellypro3/IoShellyPro3ImplTest.java b/io.openems.edge.io.shelly/test/io/openems/edge/io/shelly/shellypro3/IoShellyPro3ImplTest.java index c7213418efe..4da9baff117 100644 --- a/io.openems.edge.io.shelly/test/io/openems/edge/io/shelly/shellypro3/IoShellyPro3ImplTest.java +++ b/io.openems.edge.io.shelly/test/io/openems/edge/io/shelly/shellypro3/IoShellyPro3ImplTest.java @@ -1,21 +1,74 @@ package io.openems.edge.io.shelly.shellypro3; +import static org.junit.Assert.assertEquals; + import org.junit.Test; -import io.openems.edge.bridge.http.dummy.DummyBridgeHttpFactory; +import io.openems.edge.bridge.http.api.HttpError; +import io.openems.edge.bridge.http.api.HttpResponse; +import io.openems.edge.bridge.http.dummy.DummyBridgeHttpBundle; +import io.openems.edge.common.test.AbstractComponentTest.TestCase; import io.openems.edge.common.test.ComponentTest; public class IoShellyPro3ImplTest { @Test public void test() throws Exception { - new ComponentTest(new IoShellyPro3Impl()) // - .addReference("httpBridgeFactory", DummyBridgeHttpFactory.ofDummyBridge()) // + final var httpTestBundle = new DummyBridgeHttpBundle(); + final var sut = new IoShellyPro3Impl(); + new ComponentTest(sut) // + .addReference("httpBridgeFactory", httpTestBundle.factory()) // .activate(MyConfig.create() // .setId("io0") // .setIp("127.0.0.1") // .build()) // - ; - } -} \ No newline at end of file + // Test case for successful JSON responses for all relays + .next(new TestCase("Successful read response for all relays") // + .onBeforeProcessImage(() -> { + httpTestBundle.forceNextSuccessfulResult(HttpResponse.ok(""" + { + "id": 0, + "source": "HTTP", + "output": true + } + """)); + httpTestBundle.forceNextSuccessfulResult(HttpResponse.ok(""" + { + "id": 1, + "source": "HTTP", + "output": false + } + """)); + httpTestBundle.forceNextSuccessfulResult(HttpResponse.ok(""" + { + "id": 2, + "source": "HTTP", + "output": true + } + """)); + httpTestBundle.triggerNextCycle(); + }) // + .onAfterProcessImage(() -> assertEquals("x x -", sut.debugLog())) + + .output(IoShellyPro3.ChannelId.RELAY_1, null) // expecting WriteValue + .output(IoShellyPro3.ChannelId.RELAY_2, null) // expecting WriteValue + .output(IoShellyPro3.ChannelId.RELAY_3, null) // expecting WriteValue + .output(IoShellyPro3.ChannelId.SLAVE_COMMUNICATION_FAILED, false)) // + + // Test case for an invalid JSON response + .next(new TestCase("Invalid read response for all relays") // + .onBeforeProcessImage(() -> { + httpTestBundle.forceNextFailedResult(HttpError.ResponseError.notFound()); + httpTestBundle.triggerNextCycle(); + }) // + .onAfterProcessImage(() -> assertEquals("? ? ?", sut.debugLog())) + + .output(IoShellyPro3.ChannelId.RELAY_1, null) // + .output(IoShellyPro3.ChannelId.RELAY_2, null) // + .output(IoShellyPro3.ChannelId.RELAY_3, null) // + .output(IoShellyPro3.ChannelId.SLAVE_COMMUNICATION_FAILED, true)) // + + .deactivate(); // + } +} diff --git a/io.openems.edge.io.shelly/test/io/openems/edge/io/shelly/shellypro3em/IoShelly3EmImplTest.java b/io.openems.edge.io.shelly/test/io/openems/edge/io/shelly/shellypro3em/IoShelly3EmImplTest.java deleted file mode 100644 index c6f0e340da5..00000000000 --- a/io.openems.edge.io.shelly/test/io/openems/edge/io/shelly/shellypro3em/IoShelly3EmImplTest.java +++ /dev/null @@ -1,23 +0,0 @@ -package io.openems.edge.io.shelly.shellypro3em; - -import org.junit.Test; - -import io.openems.common.types.MeterType; -import io.openems.edge.bridge.http.dummy.DummyBridgeHttpFactory; -import io.openems.edge.common.test.ComponentTest; - -public class IoShelly3EmImplTest { - - @Test - public void test() throws Exception { - new ComponentTest(new IoShellyPro3EmImpl()) // - .addReference("httpBridgeFactory", DummyBridgeHttpFactory.ofDummyBridge()) // - .activate(MyConfig.create() // - .setId("io0") // - .setIp("127.0.0.1") // - .setType(MeterType.CONSUMPTION_METERED) // - .build()) // - ; - } - -} diff --git a/io.openems.edge.io.shelly/test/io/openems/edge/io/shelly/shellypro3em/IoShellyPro3EmImplTest.java b/io.openems.edge.io.shelly/test/io/openems/edge/io/shelly/shellypro3em/IoShellyPro3EmImplTest.java new file mode 100644 index 00000000000..a2ff6c34a54 --- /dev/null +++ b/io.openems.edge.io.shelly/test/io/openems/edge/io/shelly/shellypro3em/IoShellyPro3EmImplTest.java @@ -0,0 +1,112 @@ +package io.openems.edge.io.shelly.shellypro3em; + +import static io.openems.common.types.MeterType.GRID; +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +import io.openems.edge.bridge.http.api.HttpError; +import io.openems.edge.bridge.http.api.HttpResponse; +import io.openems.edge.bridge.http.dummy.DummyBridgeHttpBundle; +import io.openems.edge.common.test.AbstractComponentTest.TestCase; +import io.openems.edge.common.test.ComponentTest; +import io.openems.edge.meter.api.ElectricityMeter; +import io.openems.edge.timedata.test.DummyTimedata; + +public class IoShellyPro3EmImplTest { + + @Test + public void test() throws Exception { + final var sut = new IoShellyPro3EmImpl(); + final var httpTestBundle = new DummyBridgeHttpBundle(); + new ComponentTest(sut) // + .addReference("httpBridgeFactory", httpTestBundle.factory()) // + .addReference("timedata", new DummyTimedata("timedata0")) // + .activate(MyConfig.create() // + .setId("io0") // + .setIp("127.0.0.1") // + .setType(GRID) // + .build()) // + + .next(new TestCase("Successful read response") // + .onBeforeProcessImage(() -> { + httpTestBundle.forceNextSuccessfulResult(HttpResponse.ok(""" + { + "id": 0, + "a_current": 0.593, + "a_voltage": 230.5, + "a_act_power": -75.4, + "a_aprt_power": 136.9, + "a_pf": 0.68, + "a_freq": 50, + "b_current": 11.608, + "b_voltage": 228.5, + "b_act_power": 2655.2, + "b_aprt_power": 2656.6, + "b_pf": 1, + "b_freq": 50, + "c_current": 0.058, + "c_voltage": 232.1, + "c_act_power": 2.1, + "c_aprt_power": 13.5, + "c_pf": 0.54, + "c_freq": 50, + "n_current": null, + "total_current": 12.259, + "total_act_power": 2581.781, + "total_aprt_power": 2806.935, + "user_calibrated_phase": [] + } + """)); + httpTestBundle.triggerNextCycle(); + }) // + .onAfterProcessImage(() -> assertEquals("L:2582 W", sut.debugLog())) + + .output(ElectricityMeter.ChannelId.ACTIVE_POWER, 2582) // + .output(ElectricityMeter.ChannelId.ACTIVE_POWER_L1, -75) // + .output(ElectricityMeter.ChannelId.ACTIVE_POWER_L2, 2655) // + .output(ElectricityMeter.ChannelId.ACTIVE_POWER_L3, 2) // + .output(ElectricityMeter.ChannelId.VOLTAGE, 230367) // + .output(ElectricityMeter.ChannelId.VOLTAGE_L1, 230500) // + .output(ElectricityMeter.ChannelId.VOLTAGE_L2, 228500) // + .output(ElectricityMeter.ChannelId.VOLTAGE_L3, 232100) // + .output(ElectricityMeter.ChannelId.CURRENT, 12259) // + .output(ElectricityMeter.ChannelId.CURRENT_L1, 593) // + .output(ElectricityMeter.ChannelId.CURRENT_L2, 11608) // + .output(ElectricityMeter.ChannelId.CURRENT_L3, 58) // + .output(ElectricityMeter.ChannelId.ACTIVE_CONSUMPTION_ENERGY, null) // + .output(ElectricityMeter.ChannelId.ACTIVE_PRODUCTION_ENERGY, null) // + .output(IoShellyPro3Em.ChannelId.NO_LOAD, false) // + .output(IoShellyPro3Em.ChannelId.PHASE_SEQUENCE_ERROR, false) // + .output(IoShellyPro3Em.ChannelId.POWER_METER_FAILURE, false) // + .output(IoShellyPro3Em.ChannelId.SLAVE_COMMUNICATION_FAILED, false)) // + + .next(new TestCase("Invalid read response") // + .onBeforeProcessImage(() -> { + httpTestBundle.forceNextFailedResult(HttpError.ResponseError.notFound()); + httpTestBundle.triggerNextCycle(); + }) // + .onAfterProcessImage(() -> assertEquals("L:UNDEFINED", sut.debugLog())) + + .output(ElectricityMeter.ChannelId.ACTIVE_POWER, null) // + .output(ElectricityMeter.ChannelId.ACTIVE_POWER_L1, null) // + .output(ElectricityMeter.ChannelId.ACTIVE_POWER_L2, null) // + .output(ElectricityMeter.ChannelId.ACTIVE_POWER_L3, null) // + .output(ElectricityMeter.ChannelId.VOLTAGE, null) // + .output(ElectricityMeter.ChannelId.VOLTAGE_L1, null) // + .output(ElectricityMeter.ChannelId.VOLTAGE_L2, null) // + .output(ElectricityMeter.ChannelId.VOLTAGE_L3, null) // + .output(ElectricityMeter.ChannelId.CURRENT, null) // + .output(ElectricityMeter.ChannelId.CURRENT_L1, null) // + .output(ElectricityMeter.ChannelId.CURRENT_L2, null) // + .output(ElectricityMeter.ChannelId.CURRENT_L3, null) // + .output(ElectricityMeter.ChannelId.ACTIVE_CONSUMPTION_ENERGY, 0L) // + .output(ElectricityMeter.ChannelId.ACTIVE_PRODUCTION_ENERGY, 0L) // + .output(IoShellyPro3Em.ChannelId.NO_LOAD, false) // + .output(IoShellyPro3Em.ChannelId.PHASE_SEQUENCE_ERROR, false) // + .output(IoShellyPro3Em.ChannelId.POWER_METER_FAILURE, false) // + .output(IoShellyPro3Em.ChannelId.SLAVE_COMMUNICATION_FAILED, true)) // + + .deactivate(); + } +} diff --git a/io.openems.edge.io.siemenslogo/.classpath b/io.openems.edge.io.siemenslogo/.classpath new file mode 100644 index 00000000000..b4cffd0fe60 --- /dev/null +++ b/io.openems.edge.io.siemenslogo/.classpath @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/io.openems.edge.io.siemenslogo/.gitignore b/io.openems.edge.io.siemenslogo/.gitignore new file mode 100644 index 00000000000..c2b941a96de --- /dev/null +++ b/io.openems.edge.io.siemenslogo/.gitignore @@ -0,0 +1,2 @@ +/bin_test/ +/generated/ diff --git a/io.openems.edge.io.siemenslogo/.project b/io.openems.edge.io.siemenslogo/.project new file mode 100644 index 00000000000..075d5c883e7 --- /dev/null +++ b/io.openems.edge.io.siemenslogo/.project @@ -0,0 +1,23 @@ + + + io.openems.edge.io.siemenslogo + + + + + + org.eclipse.jdt.core.javabuilder + + + + + bndtools.core.bndbuilder + + + + + + org.eclipse.jdt.core.javanature + bndtools.core.bndnature + + diff --git a/io.openems.edge.io.siemenslogo/.settings/org.eclipse.core.resources.prefs b/io.openems.edge.io.siemenslogo/.settings/org.eclipse.core.resources.prefs new file mode 100644 index 00000000000..99f26c0203a --- /dev/null +++ b/io.openems.edge.io.siemenslogo/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +encoding/=UTF-8 diff --git a/io.openems.edge.io.siemenslogo/bnd.bnd b/io.openems.edge.io.siemenslogo/bnd.bnd new file mode 100644 index 00000000000..9b8a05149c3 --- /dev/null +++ b/io.openems.edge.io.siemenslogo/bnd.bnd @@ -0,0 +1,19 @@ +Bundle-Name: OpenEMS Edge IO Siemens LOGO! +Bundle-Description: Siemens LOGO! 8 as network relais. Connected via Modbus. Relays starting \ + at VM 101, Bit 0 on SPS. +Bundle-Vendor: OpenEMS Association e.V. +Bundle-License: https://opensource.org/licenses/EPL-2.0 +Bundle-Version: 1.0.0.${tstamp} + +-buildpath: \ + ${buildpath},\ + com.ghgande.j2mod,\ + io.openems.common,\ + io.openems.edge.bridge.modbus,\ + io.openems.edge.common,\ + io.openems.edge.io.api,\ + slf4j.api,\ + +-testpath: \ + ${testpath} + \ No newline at end of file diff --git a/io.openems.edge.io.siemenslogo/readme.adoc b/io.openems.edge.io.siemenslogo/readme.adoc new file mode 100644 index 00000000000..c2ae5678a51 --- /dev/null +++ b/io.openems.edge.io.siemenslogo/readme.adoc @@ -0,0 +1,7 @@ += Siemens LOGO! + +First you have to configure a modbus server in LogoSoft which either accepts all connection sources or you limit this to your EMS-system. Like all other modbus devices you have to configure a modbus-ID (255 is default in LogoSoft!) and a start address, e.g. 100 or use the default address 0. + +If you don´t do any changes the addresses are configured as coils. In Logo! a virtual address (V) is written 0.0 which is the virtual address 0, Bit 0. For the connected device the coil-addresses start with 800 (first bit/coil), 801 is the second coil and so on + +https://github.com/OpenEMS/openems/tree/develop/io.openems.edge.io.siemenslogo[Source Code icon:github[]] \ No newline at end of file diff --git a/io.openems.edge.io.siemenslogo/src/io/openems/edge/io/siemenslogo/Config.java b/io.openems.edge.io.siemenslogo/src/io/openems/edge/io/siemenslogo/Config.java new file mode 100644 index 00000000000..5acb3061327 --- /dev/null +++ b/io.openems.edge.io.siemenslogo/src/io/openems/edge/io/siemenslogo/Config.java @@ -0,0 +1,36 @@ +package io.openems.edge.io.siemenslogo; + +import org.osgi.service.metatype.annotations.AttributeDefinition; +import org.osgi.service.metatype.annotations.ObjectClassDefinition; + +@ObjectClassDefinition(// + name = "Siemens LOGO!", // + description = "Siemens LOGO! 8 digital Input/Output") +@interface Config { + + @AttributeDefinition(name = "Component-ID", description = "Unique ID of this Component") + String id() default "io0"; + + @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 write address offset", description = "Address offset in LOGO! for writing outputs / relays. This is where the virtual addresses start, e.g. 808 for virtual address 101.0 in Logo!") + int modbusOffsetWriteAddress() default 800; + + @AttributeDefinition(name = "Modbus read address offset", description = "Address offset in LOGO! for reading inputs (DI1-4). This is where the virtual addresses start, e.g. 808 for virtual address 110.0 in Logo!") + int modbusOffsetReadAddress() default 880; + + @AttributeDefinition(name = "Modbus Unit-ID", description = "The Unit-ID of the Modbus device.") + int modbusUnitId() default 1; + + @AttributeDefinition(name = "Modbus target filter", description = "This is auto-generated by 'Modbus-ID'.") + String Modbus_target() default "(enabled=true)"; + + String webconsole_configurationFactory_nameHint() default "Siemens LOGO! [{id}]"; +} \ No newline at end of file diff --git a/io.openems.edge.io.siemenslogo/src/io/openems/edge/io/siemenslogo/SiemensLogoRelay.java b/io.openems.edge.io.siemenslogo/src/io/openems/edge/io/siemenslogo/SiemensLogoRelay.java new file mode 100644 index 00000000000..a4653889ba5 --- /dev/null +++ b/io.openems.edge.io.siemenslogo/src/io/openems/edge/io/siemenslogo/SiemensLogoRelay.java @@ -0,0 +1,275 @@ +package io.openems.edge.io.siemenslogo; + +import static io.openems.common.channel.AccessMode.READ_ONLY; +import static io.openems.common.channel.AccessMode.READ_WRITE; +import static io.openems.common.channel.PersistencePriority.HIGH; +import static io.openems.common.channel.PersistencePriority.MEDIUM; +import static io.openems.common.types.OpenemsType.BOOLEAN; + +import io.openems.edge.common.channel.BooleanDoc; +import io.openems.edge.common.channel.Doc; +import io.openems.edge.common.component.OpenemsComponent; +import io.openems.edge.common.modbusslave.ModbusSlave; +import io.openems.edge.io.api.DigitalOutput; + +public interface SiemensLogoRelay extends DigitalOutput, OpenemsComponent, ModbusSlave { + + public enum ChannelId implements io.openems.edge.common.channel.ChannelId { + /** + * Input 1. + * + *

    + *
  • Interface: SiemensLogoRelayInput + *
  • Type: Boolean + *
  • Range: On/Off + *
+ */ + INPUT_1(new BooleanDoc() // + .accessMode(READ_ONLY) // + .persistencePriority(HIGH)), + /** + * Input 2. + * + *
    + *
  • Interface: SiemensLogoRelayInput + *
  • Type: Boolean + *
  • Range: On/Off + *
+ */ + INPUT_2(new BooleanDoc() // + .accessMode(READ_ONLY) // + .persistencePriority(HIGH)), + /** + * Input 3. + * + *
    + *
  • Interface: SiemensLogoRelayInput + *
  • Type: Boolean + *
  • Range: On/Off + *
+ */ + INPUT_3(new BooleanDoc() // + .accessMode(READ_ONLY) // + .persistencePriority(HIGH)), + /** + * Input 4. + * + *
    + *
  • Interface: SiemensLogoRelayInput + *
  • Type: Boolean + *
  • Range: On/Off + *
+ */ + INPUT_4(new BooleanDoc() // + .accessMode(READ_ONLY) // + .persistencePriority(HIGH)), + /** + * Holds writes to Relay Output 1 for debugging. + * + *
    + *
  • Interface: SiemensLogoRelayOutput + *
  • Type: Boolean + *
  • Range: On/Off + *
+ */ + DEBUG_RELAY_1(Doc.of(BOOLEAN)), // + /** + * Relay 1. + * + *
    + *
  • Interface: SiemensLogoRelayOutput + *
  • Type: Boolean + *
  • Range: On/Off + *
+ */ + RELAY_1(new BooleanDoc() // + .accessMode(READ_WRITE) // + .persistencePriority(MEDIUM) // + .onChannelSetNextWriteMirrorToDebugChannel(ChannelId.DEBUG_RELAY_1)), + /** + * Holds writes to Relay Output 2 for debugging. + * + *
    + *
  • Interface: SiemensLogoRelayOutput + *
  • Type: Boolean + *
  • Range: On/Off + *
+ */ + DEBUG_RELAY_2(Doc.of(BOOLEAN) // + .persistencePriority(MEDIUM)), // + /** + * Relay 2. + * + *
    + *
  • Interface: SiemensLogoRelayOutput + *
  • Type: Boolean + *
  • Range: On/Off + *
+ */ + RELAY_2(new BooleanDoc() // + .accessMode(READ_WRITE) // + .persistencePriority(MEDIUM) // + .onChannelSetNextWriteMirrorToDebugChannel(ChannelId.DEBUG_RELAY_2)), + + /** + * Holds writes to Relay Output 3 for debugging. + * + *
    + *
  • Interface: SiemensLogoRelayOutput + *
  • Type: Boolean + *
  • Range: On/Off + *
+ */ + DEBUG_RELAY_3(Doc.of(BOOLEAN) // + .persistencePriority(MEDIUM)), // + /** + * Relay 3. + * + *
    + *
  • Interface: SiemensLogoRelayOutput + *
  • Type: Boolean + *
  • Range: On/Off + *
+ */ + RELAY_3(new BooleanDoc() // + .accessMode(READ_WRITE) // + .persistencePriority(MEDIUM) // + .onChannelSetNextWriteMirrorToDebugChannel(ChannelId.DEBUG_RELAY_3)), + + /** + * Holds writes to Relay Output 4 for debugging. + * + *
    + *
  • Interface: SiemensLogoRelayOutput + *
  • Type: Boolean + *
  • Range: On/Off + *
+ */ + DEBUG_RELAY_4(Doc.of(BOOLEAN) // + .persistencePriority(MEDIUM)), // + /** + * Relay 4. + * + *
    + *
  • Interface: SiemensLogoRelayOutput + *
  • Type: Boolean + *
  • Range: On/Off + *
+ */ + RELAY_4(new BooleanDoc() // + .accessMode(READ_WRITE) // + .persistencePriority(MEDIUM) // + .onChannelSetNextWriteMirrorToDebugChannel(ChannelId.DEBUG_RELAY_4)), + + /** + * Holds writes to Relay Output 5 for debugging. + * + *
    + *
  • Interface: SiemensLogoRelayOutput + *
  • Type: Boolean + *
  • Range: On/Off + *
+ */ + DEBUG_RELAY_5(Doc.of(BOOLEAN) // + .persistencePriority(MEDIUM)), // + /** + * Relay 5. + * + *
    + *
  • Interface: SiemensLogoRelayOutput + *
  • Type: Boolean + *
  • Range: On/Off + *
+ */ + RELAY_5(new BooleanDoc() // + .accessMode(READ_WRITE) // + .persistencePriority(MEDIUM) // + .onChannelSetNextWriteMirrorToDebugChannel(ChannelId.DEBUG_RELAY_5)), + + /** + * Holds writes to Relay Output 6 for debugging. + * + *
    + *
  • Interface: SiemensLogoRelayOutput + *
  • Type: Boolean + *
  • Range: On/Off + *
+ */ + DEBUG_RELAY_6(Doc.of(BOOLEAN) // + .persistencePriority(MEDIUM)), // + /** + * Relay 6. + * + *
    + *
  • Interface: SiemensLogoRelayOutput + *
  • Type: Boolean + *
  • Range: On/Off + *
+ */ + RELAY_6(new BooleanDoc() // + .accessMode(READ_WRITE) // + .persistencePriority(MEDIUM) // + .onChannelSetNextWriteMirrorToDebugChannel(ChannelId.DEBUG_RELAY_6)), + + /** + * Holds writes to Relay Output 7 for debugging. + * + *
    + *
  • Interface: SiemensLogoRelayOutput + *
  • Type: Boolean + *
  • Range: On/Off + *
+ */ + DEBUG_RELAY_7(Doc.of(BOOLEAN) // + .persistencePriority(MEDIUM)), // + /** + * Relay 7. + * + *
    + *
  • Interface: SiemensLogoRelayOutput + *
  • Type: Boolean + *
  • Range: On/Off + *
+ */ + RELAY_7(new BooleanDoc() // + .accessMode(READ_WRITE) // + .persistencePriority(MEDIUM) // + .onChannelSetNextWriteMirrorToDebugChannel(ChannelId.DEBUG_RELAY_7)), + + /** + * Holds writes to Relay Output 8 for debugging. + * + *
    + *
  • Interface: SiemensLogoRelayOutput + *
  • Type: Boolean + *
  • Range: On/Off + *
+ */ + DEBUG_RELAY_8(Doc.of(BOOLEAN) // + .persistencePriority(MEDIUM)), // + /** + * Relay 8. + * + *
    + *
  • Interface: SiemensLogoRelayOutput + *
  • Type: Boolean + *
  • Range: On/Off + *
+ */ + RELAY_8(new BooleanDoc() // + .accessMode(READ_WRITE) // + .persistencePriority(MEDIUM) // + .onChannelSetNextWriteMirrorToDebugChannel(ChannelId.DEBUG_RELAY_8)); + + private final Doc doc; + + private ChannelId(Doc doc) { + this.doc = doc; + } + + @Override + public Doc doc() { + return this.doc; + } + } +} diff --git a/io.openems.edge.io.siemenslogo/src/io/openems/edge/io/siemenslogo/SiemensLogoRelayImpl.java b/io.openems.edge.io.siemenslogo/src/io/openems/edge/io/siemenslogo/SiemensLogoRelayImpl.java new file mode 100644 index 00000000000..e7308dbdfb3 --- /dev/null +++ b/io.openems.edge.io.siemenslogo/src/io/openems/edge/io/siemenslogo/SiemensLogoRelayImpl.java @@ -0,0 +1,184 @@ +package io.openems.edge.io.siemenslogo; + +import static io.openems.common.channel.AccessMode.READ_ONLY; +import static io.openems.common.channel.AccessMode.READ_WRITE; +import static java.util.Arrays.stream; +import static java.util.stream.Collectors.joining; + +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.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 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.ModbusComponent; +import io.openems.edge.bridge.modbus.api.ModbusProtocol; +import io.openems.edge.bridge.modbus.api.element.CoilElement; +import io.openems.edge.bridge.modbus.api.task.FC1ReadCoilsTask; +import io.openems.edge.bridge.modbus.api.task.FC5WriteCoilTask; +import io.openems.edge.common.channel.BooleanReadChannel; +import io.openems.edge.common.channel.BooleanWriteChannel; +import io.openems.edge.common.component.OpenemsComponent; +import io.openems.edge.common.modbusslave.ModbusSlave; +import io.openems.edge.common.modbusslave.ModbusSlaveNatureTable; +import io.openems.edge.common.modbusslave.ModbusSlaveTable; +import io.openems.edge.common.modbusslave.ModbusType; +import io.openems.edge.common.taskmanager.Priority; +import io.openems.edge.io.api.DigitalInput; +import io.openems.edge.io.api.DigitalOutput; + +@Designate(ocd = Config.class, factory = true) +@Component(// + name = "IO.Siemens.LOGO", // + immediate = true, // + configurationPolicy = ConfigurationPolicy.REQUIRE // +) +public class SiemensLogoRelayImpl extends AbstractOpenemsModbusComponent + implements SiemensLogoRelay, DigitalOutput, DigitalInput, ModbusComponent, OpenemsComponent, ModbusSlave { + + private final BooleanWriteChannel[] digitalOutputChannels; + private final BooleanReadChannel[] digitalInputChannels; + + private int writeOffset = 0; + private int readOffset = 0; + + @Reference + private ConfigurationAdmin cm; + + @Reference(policy = ReferencePolicy.STATIC, policyOption = ReferencePolicyOption.GREEDY, cardinality = ReferenceCardinality.MANDATORY) + protected void setModbus(BridgeModbus modbus) { + super.setModbus(modbus); + } + + public SiemensLogoRelayImpl() { + super(// + OpenemsComponent.ChannelId.values(), // + ModbusComponent.ChannelId.values(), // + DigitalOutput.ChannelId.values(), // + DigitalInput.ChannelId.values(), // + SiemensLogoRelay.ChannelId.values() // + ); + this.digitalOutputChannels = stream(SiemensLogoRelay.ChannelId.values()) // + .filter(channelId -> channelId.doc().getAccessMode() == READ_WRITE) // + .map(channelId -> this.channel(channelId)) // + .toArray(BooleanWriteChannel[]::new); + this.digitalInputChannels = stream(SiemensLogoRelay.ChannelId.values()) // + .filter(channelId -> channelId.doc().getAccessMode() == READ_ONLY) // + .map(channelId -> this.channel(channelId)) // + .toArray(BooleanReadChannel[]::new); + } + + @Activate + private void activate(ComponentContext context, Config config) throws OpenemsException { + this.writeOffset = config.modbusOffsetWriteAddress(); + this.readOffset = config.modbusOffsetReadAddress(); + super.activate(context, config.id(), config.alias(), config.enabled(), config.modbusUnitId(), this.cm, "Modbus", + config.modbus_id()); + } + + @Deactivate + protected void deactivate() { + super.deactivate(); + } + + @Override + public BooleanWriteChannel[] digitalOutputChannels() { + return this.digitalOutputChannels; + } + + @Override + public BooleanReadChannel[] digitalInputChannels() { + return this.digitalInputChannels; + } + + @Override + protected ModbusProtocol defineModbusProtocol() { + return new ModbusProtocol(this, // + // Read Inputs + new FC1ReadCoilsTask(this.readOffset, Priority.HIGH, // + m(SiemensLogoRelay.ChannelId.INPUT_1, new CoilElement(0 + this.readOffset)), // + m(SiemensLogoRelay.ChannelId.INPUT_2, new CoilElement(1 + this.readOffset)), // + m(SiemensLogoRelay.ChannelId.INPUT_3, new CoilElement(2 + this.readOffset)), // + m(SiemensLogoRelay.ChannelId.INPUT_4, new CoilElement(3 + this.readOffset)) // + ), + + /* + * For Read: Read Coils + */ + new FC1ReadCoilsTask(this.writeOffset, Priority.LOW, // + m(SiemensLogoRelay.ChannelId.RELAY_1, new CoilElement(0 + this.writeOffset)), // + m(SiemensLogoRelay.ChannelId.RELAY_2, new CoilElement(1 + this.writeOffset)), // + m(SiemensLogoRelay.ChannelId.RELAY_3, new CoilElement(2 + this.writeOffset)), // + m(SiemensLogoRelay.ChannelId.RELAY_4, new CoilElement(3 + this.writeOffset)), // + m(SiemensLogoRelay.ChannelId.RELAY_5, new CoilElement(4 + this.writeOffset)), // + m(SiemensLogoRelay.ChannelId.RELAY_6, new CoilElement(5 + this.writeOffset)), // + m(SiemensLogoRelay.ChannelId.RELAY_7, new CoilElement(6 + this.writeOffset)), // + m(SiemensLogoRelay.ChannelId.RELAY_8, new CoilElement(7 + this.writeOffset)) // + ), + /* + * For Write: Write Single Coil + */ + new FC5WriteCoilTask(0 + this.writeOffset, + m(SiemensLogoRelay.ChannelId.RELAY_1, new CoilElement(0 + this.writeOffset))), // + new FC5WriteCoilTask(1 + this.writeOffset, + m(SiemensLogoRelay.ChannelId.RELAY_2, new CoilElement(1 + this.writeOffset))), // + new FC5WriteCoilTask(2 + this.writeOffset, + m(SiemensLogoRelay.ChannelId.RELAY_3, new CoilElement(2 + this.writeOffset))), // + new FC5WriteCoilTask(3 + this.writeOffset, + m(SiemensLogoRelay.ChannelId.RELAY_4, new CoilElement(3 + this.writeOffset))), // + new FC5WriteCoilTask(4 + this.writeOffset, + m(SiemensLogoRelay.ChannelId.RELAY_5, new CoilElement(4 + this.writeOffset))), // + new FC5WriteCoilTask(5 + this.writeOffset, + m(SiemensLogoRelay.ChannelId.RELAY_6, new CoilElement(5 + this.writeOffset))), // + new FC5WriteCoilTask(6 + this.writeOffset, + m(SiemensLogoRelay.ChannelId.RELAY_7, new CoilElement(6 + this.writeOffset))), // + new FC5WriteCoilTask(7 + this.writeOffset, + m(SiemensLogoRelay.ChannelId.RELAY_8, new CoilElement(7 + this.writeOffset))) // + ); + } + + @Override + public ModbusSlaveTable getModbusSlaveTable(AccessMode accessMode) { + return new ModbusSlaveTable(OpenemsComponent.getModbusSlaveNatureTable(accessMode), // + ModbusSlaveNatureTable.of(SiemensLogoRelay.class, accessMode, 100)// + .channel(0 + this.writeOffset, SiemensLogoRelay.ChannelId.RELAY_1, ModbusType.UINT16) // + .channel(1 + this.writeOffset, SiemensLogoRelay.ChannelId.RELAY_2, ModbusType.UINT16) // + .channel(2 + this.writeOffset, SiemensLogoRelay.ChannelId.RELAY_3, ModbusType.UINT16) // + .channel(3 + this.writeOffset, SiemensLogoRelay.ChannelId.RELAY_4, ModbusType.UINT16) // + .channel(4 + this.writeOffset, SiemensLogoRelay.ChannelId.RELAY_5, ModbusType.UINT16) // + .channel(5 + this.writeOffset, SiemensLogoRelay.ChannelId.RELAY_6, ModbusType.UINT16) // + .channel(6 + this.writeOffset, SiemensLogoRelay.ChannelId.RELAY_7, ModbusType.UINT16) // + .channel(7 + this.writeOffset, SiemensLogoRelay.ChannelId.RELAY_8, ModbusType.UINT16) // + + .channel(8 + this.readOffset, SiemensLogoRelay.ChannelId.INPUT_1, ModbusType.UINT16) // + .channel(9 + this.readOffset, SiemensLogoRelay.ChannelId.INPUT_2, ModbusType.UINT16) // + .channel(10 + this.readOffset, SiemensLogoRelay.ChannelId.INPUT_3, ModbusType.UINT16) // + .channel(11 + this.readOffset, SiemensLogoRelay.ChannelId.INPUT_4, ModbusType.UINT16) // + + .build()// + ); + } + + @Override + public String debugLog() { + var outputLog = stream(this.digitalOutputChannels) // + .map(c -> c.value().asOptional()) // + .map(t -> t.isPresent() ? (t.get() ? "X" : "-") : "?") // + .collect(joining("")); + var inputLog = stream(this.digitalInputChannels) // + .map(c -> c.value().asOptional()) // + .map(t -> t.isPresent() ? (t.get() ? "I" : "O") : "?") // + .collect(joining("")); + return "Output:" + outputLog + "|Input:" + inputLog; + } +} diff --git a/io.openems.edge.io.siemenslogo/test/.gitignore b/io.openems.edge.io.siemenslogo/test/.gitignore new file mode 100644 index 00000000000..e69de29bb2d diff --git a/io.openems.edge.io.siemenslogo/test/io/openems/edge/io/siemenslogo/MyConfig.java b/io.openems.edge.io.siemenslogo/test/io/openems/edge/io/siemenslogo/MyConfig.java new file mode 100644 index 00000000000..f80ac31e01e --- /dev/null +++ b/io.openems.edge.io.siemenslogo/test/io/openems/edge/io/siemenslogo/MyConfig.java @@ -0,0 +1,117 @@ +package io.openems.edge.io.siemenslogo; + +import static io.openems.common.utils.ConfigUtils.generateReferenceTargetFilter; + +import io.openems.common.test.AbstractComponentConfig; + +@SuppressWarnings("all") +public class MyConfig extends AbstractComponentConfig implements Config { + + protected static class Builder { + private String id; + private String alias = ""; // Default to empty string + private boolean enabled = true; // Default to true + private String modbusId; + private int modbusUnitId; + private int modbusOffsetWriteAddress; + private int modbusOffsetReadAddress; + + private Builder() { + } + + public Builder setId(String id) { + this.id = id; + return this; + } + + public Builder setAlias(String alias) { + this.alias = alias; + return this; + } + + public Builder setEnabled(boolean enabled) { + this.enabled = enabled; + return this; + } + + public Builder setModbusId(String modbusId) { + this.modbusId = modbusId; + return this; + } + + public Builder setModbusUnitId(int modbusUnitId) { + this.modbusUnitId = modbusUnitId; + return this; + } + + public Builder setModbusOffsetWriteAddress(int modbusOffsetWriteAddress) { + this.modbusOffsetWriteAddress = modbusOffsetWriteAddress; + return this; + } + + public Builder setModbusOffsetReadAddress(int modbusOffsetReadAddress) { + this.modbusOffsetReadAddress = modbusOffsetReadAddress; + 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 String id() { + return this.builder.id; + } + + @Override + public String alias() { + return this.builder.alias; + } + + @Override + public boolean enabled() { + return this.builder.enabled; + } + + @Override + public String modbus_id() { + return this.builder.modbusId; + } + + @Override + public int modbusUnitId() { + return this.builder.modbusUnitId; + } + + @Override + public int modbusOffsetWriteAddress() { + return this.builder.modbusOffsetWriteAddress; + } + + @Override + public int modbusOffsetReadAddress() { + return this.builder.modbusOffsetReadAddress; + } + + @Override + public String Modbus_target() { + return generateReferenceTargetFilter(this.id(), this.modbus_id()); + } +} diff --git a/io.openems.edge.io.siemenslogo/test/io/openems/edge/io/siemenslogo/SiemensLogoRelayImplTest.java b/io.openems.edge.io.siemenslogo/test/io/openems/edge/io/siemenslogo/SiemensLogoRelayImplTest.java new file mode 100644 index 00000000000..48a51617328 --- /dev/null +++ b/io.openems.edge.io.siemenslogo/test/io/openems/edge/io/siemenslogo/SiemensLogoRelayImplTest.java @@ -0,0 +1,36 @@ +package io.openems.edge.io.siemenslogo; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +import io.openems.common.channel.AccessMode; +import io.openems.edge.bridge.modbus.test.DummyModbusBridge; +import io.openems.edge.common.test.AbstractComponentTest.TestCase; +import io.openems.edge.common.test.ComponentTest; +import io.openems.edge.common.test.DummyConfigurationAdmin; + +public class SiemensLogoRelayImplTest { + + @Test + public void test() throws Exception { + var sut = new SiemensLogoRelayImpl(); + new ComponentTest(new SiemensLogoRelayImpl()) // + .addReference("cm", new DummyConfigurationAdmin()) // + .addReference("setModbus", new DummyModbusBridge("modbus0")) // + .activate(MyConfig.create() // + .setId("io0") // + .setModbusId("modbus0") // + .build()) // + .next(new TestCase()) // + .deactivate(); + assertEquals("Output:????????|Input:????????????", sut.debugLog()); + + var mst = sut.getModbusSlaveTable(AccessMode.READ_WRITE); + assertEquals(180, mst.getLength()); + + assertEquals(8, sut.digitalOutputChannels().length); + assertEquals(12, sut.digitalInputChannels().length); + } + +} diff --git a/io.openems.edge.io.wago/src/io/openems/edge/wago/IoWagoImpl.java b/io.openems.edge.io.wago/src/io/openems/edge/wago/IoWagoImpl.java index fae2ebd405d..5bb4e89a85b 100644 --- a/io.openems.edge.io.wago/src/io/openems/edge/wago/IoWagoImpl.java +++ b/io.openems.edge.io.wago/src/io/openems/edge/wago/IoWagoImpl.java @@ -304,8 +304,8 @@ public String debugLog() { @Override public BooleanReadChannel[] digitalInputChannels() { - List channels = new ArrayList<>(); - for (FieldbusModule module : this.modules) { + var channels = new ArrayList(); + for (var module : this.modules) { Collections.addAll(channels, module.getChannels()); } var result = new BooleanReadChannel[channels.size()]; @@ -317,11 +317,11 @@ public BooleanReadChannel[] digitalInputChannels() { @Override public BooleanWriteChannel[] digitalOutputChannels() { - List channels = new ArrayList<>(); - for (FieldbusModule module : this.modules) { - for (BooleanReadChannel channel : module.getChannels()) { - if (channel instanceof BooleanWriteChannel) { - channels.add((BooleanWriteChannel) channel); + var channels = new ArrayList(); + for (var module : this.modules) { + for (var channel : module.getChannels()) { + if (channel instanceof BooleanWriteChannel bwc) { + channels.add(bwc); } } } diff --git a/io.openems.edge.io.weidmueller/src/io/openems/edge/io/weidmueller/IoWeidmuellerUr20.java b/io.openems.edge.io.weidmueller/src/io/openems/edge/io/weidmueller/IoWeidmuellerUr20.java index 05ed735239d..d4e9044d18d 100644 --- a/io.openems.edge.io.weidmueller/src/io/openems/edge/io/weidmueller/IoWeidmuellerUr20.java +++ b/io.openems.edge.io.weidmueller/src/io/openems/edge/io/weidmueller/IoWeidmuellerUr20.java @@ -20,4 +20,4 @@ public Doc doc() { } } -} +} \ No newline at end of file diff --git a/io.openems.edge.io.weidmueller/src/io/openems/edge/io/weidmueller/IoWeidmuellerUr20Impl.java b/io.openems.edge.io.weidmueller/src/io/openems/edge/io/weidmueller/IoWeidmuellerUr20Impl.java index 1ac395603ea..159528ebcf8 100644 --- a/io.openems.edge.io.weidmueller/src/io/openems/edge/io/weidmueller/IoWeidmuellerUr20Impl.java +++ b/io.openems.edge.io.weidmueller/src/io/openems/edge/io/weidmueller/IoWeidmuellerUr20Impl.java @@ -152,6 +152,18 @@ private void activate(ComponentContext context, Config config) throws OpenemsExc tasks = myTasks.toArray(Task[]::new); break; } + + case UR20_16DI_P: { + var element = new BitsWordElement(inputRegisterOffset, this); + for (var i = 0; i < 16; i++) { + var channelId = FieldbusChannelId.forDigitalInput(moduleCount, i + 1); + var channel = (BooleanReadChannel) this.addChannel(channelId); + this.modules.get(module).add(channel); + element.bit(i, channelId); + } + tasks = new Task[] { new FC3ReadRegistersTask(element.startAddress, Priority.HIGH, element) }; + break; + } } if (tasks == null || tasks.length == 0) { @@ -237,4 +249,4 @@ private CompletableFuture> readCurrentModuleList(int numberOfEntries) .thenApply(rsr -> ((ReadElementsResult) rsr).values()); } -} +} \ No newline at end of file diff --git a/io.openems.edge.io.weidmueller/src/io/openems/edge/io/weidmueller/URemoteModule.java b/io.openems.edge.io.weidmueller/src/io/openems/edge/io/weidmueller/URemoteModule.java index cddc3bc8d71..7f4ea68c666 100644 --- a/io.openems.edge.io.weidmueller/src/io/openems/edge/io/weidmueller/URemoteModule.java +++ b/io.openems.edge.io.weidmueller/src/io/openems/edge/io/weidmueller/URemoteModule.java @@ -12,7 +12,7 @@ public enum URemoteModule { // UR20_8DI_P_2W(0x00131FC1), // // UR20_8DI_P_3W(0x000A1FC1), // // UR20_8DI_P_3W_HD(0x00031FC1), // - // UR20_16DI_P(0x00049FC2), // + UR20_16DI_P(0x00049FC2, 2, 0), // // UR20_16DI_P_PLC_INT(0x00059FC2), // // UR20_2DI_P_TS(0x0F014700), // // UR20_4DI_P_TS(0x0F024700), // diff --git a/io.openems.edge.io.weidmueller/test/io/openems/edge/io/weidmueller/IoWeidmuellerUr20ImplTest.java b/io.openems.edge.io.weidmueller/test/io/openems/edge/io/weidmueller/IoWeidmuellerUr20ImplTest.java index eadbf247bb5..19e62d5be1c 100644 --- a/io.openems.edge.io.weidmueller/test/io/openems/edge/io/weidmueller/IoWeidmuellerUr20ImplTest.java +++ b/io.openems.edge.io.weidmueller/test/io/openems/edge/io/weidmueller/IoWeidmuellerUr20ImplTest.java @@ -21,4 +21,4 @@ public void test() throws Exception { .next(new TestCase()); } -} +} \ No newline at end of file diff --git a/io.openems.edge.kaco.blueplanet.hybrid10/src/io/openems/edge/kaco/blueplanet/hybrid10/core/KacoBlueplanetHybrid10CoreImpl.java b/io.openems.edge.kaco.blueplanet.hybrid10/src/io/openems/edge/kaco/blueplanet/hybrid10/core/KacoBlueplanetHybrid10CoreImpl.java index 6317332ec38..eda9ad22a28 100644 --- a/io.openems.edge.kaco.blueplanet.hybrid10/src/io/openems/edge/kaco/blueplanet/hybrid10/core/KacoBlueplanetHybrid10CoreImpl.java +++ b/io.openems.edge.kaco.blueplanet.hybrid10/src/io/openems/edge/kaco/blueplanet/hybrid10/core/KacoBlueplanetHybrid10CoreImpl.java @@ -312,15 +312,10 @@ private void initClient(Config config, InetAddress inverterAddress) throws Excep Float comVersion = TypeUtils.getAsType(OpenemsType.FLOAT, this._bpData.systemInfo.getComVersion()); this.stableVersion = StableVersion.getCurrentStableVersion(comVersion); - switch (this.stableVersion) { - case VERSION_7_OR_OLDER: - availInitResponse = this.initVersion7(); - break; - case UNDEFINED: - case VERSION_8: - availInitResponse = this.initVersion8(); - break; - } + availInitResponse = switch (this.stableVersion) { + case VERSION_7_OR_OLDER -> this.initVersion7(); + case UNDEFINED, VERSION_8 -> this.initVersion8(); + }; if (!availInitResponse) { Thread.sleep(1000); // try again after 1 second diff --git a/io.openems.edge.katek.edcom/src/com/ed/data/DemoData.java b/io.openems.edge.katek.edcom/src/com/ed/data/DemoData.java index 8b564c3601b..bc8e85247d8 100644 --- a/io.openems.edge.katek.edcom/src/com/ed/data/DemoData.java +++ b/io.openems.edge.katek.edcom/src/com/ed/data/DemoData.java @@ -86,21 +86,12 @@ public DemoData() throws Exception { * @return AC RMS Voltage [V] (~ 20ms, grid synchronized measurement) */ public float getAcVoltage(int phaseIx) throws RuntimeException { - float f; - switch (phaseIx) { - default: - throw new RuntimeException("bad index"); - case 0: - f = uL1.getFloat(0); - break; - case 1: - f = uL2.getFloat(0); - break; - case 2: - f = uL3.getFloat(0); - break; - } - return f; + return switch (phaseIx) { + default -> throw new RuntimeException("bad index"); + case 0 -> uL1.getFloat(0); + case 1 -> uL2.getFloat(0); + case 2 -> uL3.getFloat(0); + }; } /** @@ -110,18 +101,11 @@ public float getAcVoltage(int phaseIx) throws RuntimeException { * @return PV Voltage [V] */ public float getPvVoltage(int pvIx) throws RuntimeException { - float f; - switch (pvIx) { - default: - throw new RuntimeException("wrong index"); - case 0: - f = uSg1.getFloat(0); - break; - case 1: - f = uSg2.getFloat(0); - break; - } - return f; + return switch (pvIx) { + default -> throw new RuntimeException("wrong index"); + case 0 -> uSg1.getFloat(0); + case 1 -> uSg2.getFloat(0); + }; } /** diff --git a/io.openems.edge.katek.edcom/src/com/ed/data/EnergyMeter.java b/io.openems.edge.katek.edcom/src/com/ed/data/EnergyMeter.java index 331614a4850..a6f00d3c625 100644 --- a/io.openems.edge.katek.edcom/src/com/ed/data/EnergyMeter.java +++ b/io.openems.edge.katek.edcom/src/com/ed/data/EnergyMeter.java @@ -61,24 +61,15 @@ public EnergyMeter() throws Exception { * @throws Exception wrong parameters or no inverter data available */ public float getEInverterFeedIn(int timePeriod) throws Exception { - float r = 0.0f; if (e_inverter_feed_in.refreshTime() == 0) { throw new RuntimeException("no data"); } - switch (timePeriod) { - default: - throw new RuntimeException("wrong parameters"); - case EnergyMeter.DAY: - r = qXToFloat(e_inverter_feed_in.getLong(timePeriod), 16, 240000.0f); - break; - case EnergyMeter.MONTH: - r = qXToFloat(e_inverter_feed_in.getLong(timePeriod), 16, 7200000.0f); - break; - case EnergyMeter.YEAR: - r = qXToFloat(e_inverter_feed_in.getLong(timePeriod), 32, 87600000.0f); - break; - } - return r; + return switch (timePeriod) { + default -> throw new RuntimeException("wrong parameters"); + case EnergyMeter.DAY -> qXToFloat(e_inverter_feed_in.getLong(timePeriod), 16, 240000.0f); + case EnergyMeter.MONTH -> qXToFloat(e_inverter_feed_in.getLong(timePeriod), 16, 7200000.0f); + case EnergyMeter.YEAR -> qXToFloat(e_inverter_feed_in.getLong(timePeriod), 32, 87600000.0f); + }; } /** @@ -90,24 +81,15 @@ public float getEInverterFeedIn(int timePeriod) throws Exception { * @throws Exception wrong parameters or no inverter data available */ public float getEInverterCons(int timePeriod) throws Exception { - float r = 0.0f; if (e_inverter_cons.refreshTime() == 0) { throw new RuntimeException("no data"); } - switch (timePeriod) { - default: - throw new RuntimeException("wrong parameters"); - case EnergyMeter.DAY: - r = qXToFloat(e_inverter_cons.getLong(timePeriod), 16, 240000.0f); - break; - case EnergyMeter.MONTH: - r = qXToFloat(e_inverter_cons.getLong(timePeriod), 16, 7200000.0f); - break; - case EnergyMeter.YEAR: - r = qXToFloat(e_inverter_cons.getLong(timePeriod), 32, 87600000.0f); - break; - } - return r; + return switch (timePeriod) { + default -> throw new RuntimeException("wrong parameters"); + case EnergyMeter.DAY -> qXToFloat(e_inverter_cons.getLong(timePeriod), 16, 240000.0f); + case EnergyMeter.MONTH -> qXToFloat(e_inverter_cons.getLong(timePeriod), 16, 7200000.0f); + case EnergyMeter.YEAR -> qXToFloat(e_inverter_cons.getLong(timePeriod), 32, 87600000.0f); + }; } /** @@ -119,24 +101,15 @@ public float getEInverterCons(int timePeriod) throws Exception { * @throws Exception wrong parameters or no inverter data available */ public float getEGridFeedIn(int timePeriod) throws Exception { - float r = 0.0f; if (e_grid_feed_in.refreshTime() == 0) { throw new RuntimeException("no data"); } - switch (timePeriod) { - default: - throw new RuntimeException("wrong parameters"); - case EnergyMeter.DAY: - r = qXToFloat(e_grid_feed_in.getLong(timePeriod), 16, 2400000.0f); - break; - case EnergyMeter.MONTH: - r = qXToFloat(e_grid_feed_in.getLong(timePeriod), 16, 72000000.0f); - break; - case EnergyMeter.YEAR: - r = qXToFloat(e_grid_feed_in.getLong(timePeriod), 32, 876000000.0f); - break; - } - return r; + return switch (timePeriod) { + default -> throw new RuntimeException("wrong parameters"); + case EnergyMeter.DAY -> qXToFloat(e_grid_feed_in.getLong(timePeriod), 16, 2400000.0f); + case EnergyMeter.MONTH -> qXToFloat(e_grid_feed_in.getLong(timePeriod), 16, 72000000.0f); + case EnergyMeter.YEAR -> qXToFloat(e_grid_feed_in.getLong(timePeriod), 32, 876000000.0f); + }; } /** @@ -148,24 +121,15 @@ public float getEGridFeedIn(int timePeriod) throws Exception { * @throws Exception wrong parameters or no inverter data available */ public float getEConsFromGrid(int timePeriod) throws Exception { - float r = 0.0f; if (e_consumption_from_grid.refreshTime() == 0) { throw new RuntimeException("no data"); } - switch (timePeriod) { - default: - throw new RuntimeException("wrong parameters"); - case EnergyMeter.DAY: - r = qXToFloat(e_consumption_from_grid.getLong(timePeriod), 16, 2400000.0f); - break; - case EnergyMeter.MONTH: - r = qXToFloat(e_consumption_from_grid.getLong(timePeriod), 16, 72000000.0f); - break; - case EnergyMeter.YEAR: - r = qXToFloat(e_consumption_from_grid.getLong(timePeriod), 32, 876000000.0f); - break; - } - return r; + return switch (timePeriod) { + default -> throw new RuntimeException("wrong parameters"); + case EnergyMeter.DAY -> qXToFloat(e_consumption_from_grid.getLong(timePeriod), 16, 2400000.0f); + case EnergyMeter.MONTH -> qXToFloat(e_consumption_from_grid.getLong(timePeriod), 16, 72000000.0f); + case EnergyMeter.YEAR -> qXToFloat(e_consumption_from_grid.getLong(timePeriod), 32, 876000000.0f); + }; } /** @@ -177,24 +141,15 @@ public float getEConsFromGrid(int timePeriod) throws Exception { * @throws Exception wrong parameters or no inverter data available */ public float getESelfConsumption(int timePeriod) throws Exception { - float r = 0.0f; if (e_self_consumption.refreshTime() == 0) { throw new RuntimeException("no data"); } - switch (timePeriod) { - default: - throw new RuntimeException("wrong parameters"); - case EnergyMeter.DAY: - r = qXToFloat(e_self_consumption.getLong(timePeriod), 16, 240000.0f); - break; - case EnergyMeter.MONTH: - r = qXToFloat(e_self_consumption.getLong(timePeriod), 16, 7200000.0f); - break; - case EnergyMeter.YEAR: - r = qXToFloat(e_self_consumption.getLong(timePeriod), 32, 87600000.0f); - break; - } - return r; + return switch (timePeriod) { + default -> throw new RuntimeException("wrong parameters"); + case EnergyMeter.DAY -> qXToFloat(e_self_consumption.getLong(timePeriod), 16, 240000.0f); + case EnergyMeter.MONTH -> qXToFloat(e_self_consumption.getLong(timePeriod), 16, 7200000.0f); + case EnergyMeter.YEAR -> qXToFloat(e_self_consumption.getLong(timePeriod), 32, 87600000.0f); + }; } /** @@ -206,29 +161,19 @@ public float getESelfConsumption(int timePeriod) throws Exception { * @throws Exception wrong parameters or no inverter data available */ public float getAhBattery(int timePeriod) throws Exception { - float r = 0.0f; if (ah_battery.refreshTime() == 0) { throw new RuntimeException("no data"); } - switch (timePeriod) { - default: - throw new RuntimeException("wrong parameters"); - case EnergyMeter.DAY: - r = qXToFloat(ah_battery.getLong(timePeriod), 16, 600.0f); - break; - case EnergyMeter.MONTH: - r = qXToFloat(ah_battery.getLong(timePeriod), 16, 18000.0f); - break; - case EnergyMeter.YEAR: - r = qXToFloat(ah_battery.getLong(timePeriod), 32, 219000.0f); - break; - } - return r; + return switch (timePeriod) { + default -> throw new RuntimeException("wrong parameters"); + case EnergyMeter.DAY -> qXToFloat(ah_battery.getLong(timePeriod), 16, 600.0f); + case EnergyMeter.MONTH -> qXToFloat(ah_battery.getLong(timePeriod), 16, 18000.0f); + case EnergyMeter.YEAR -> qXToFloat(ah_battery.getLong(timePeriod), 32, 219000.0f); + }; } protected static float qXToFloat(long qx, int fractBitsCnt, float fMax) { - float f = (float) (((double) fMax * qx) / (float) ((long) 1 << fractBitsCnt)); - return f; + return (float) (((double) fMax * qx) / (float) ((long) 1 << fractBitsCnt)); } @Override diff --git a/io.openems.edge.katek.edcom/src/com/ed/data/InverterData.java b/io.openems.edge.katek.edcom/src/com/ed/data/InverterData.java index 036a8813064..aaf62f50461 100644 --- a/io.openems.edge.katek.edcom/src/com/ed/data/InverterData.java +++ b/io.openems.edge.katek.edcom/src/com/ed/data/InverterData.java @@ -103,21 +103,12 @@ public InverterData() throws Exception { * @return AC RMS Voltage [V] (~ 20ms, grid synchronized measurement) */ public float getAcVoltage(int phaseIx) throws RuntimeException { - float f; - switch (phaseIx) { - default: - throw new RuntimeException("bad index"); - case 0: - f = uL1.getFloat(0); - break; - case 1: - f = uL2.getFloat(0); - break; - case 2: - f = uL3.getFloat(0); - break; - } - return f; + return switch (phaseIx) { + default -> throw new RuntimeException("bad index"); + case 0 -> uL1.getFloat(0); + case 1 -> uL2.getFloat(0); + case 2 -> uL3.getFloat(0); + }; } /** @@ -128,21 +119,12 @@ public float getAcVoltage(int phaseIx) throws RuntimeException { * consumption */ public float getAcPower(int phaseIx) throws RuntimeException { - float f; - switch (phaseIx) { - default: - throw new RuntimeException("bad index"); - case 0: - f = pL1.getFloat(0); - break; - case 1: - f = pL2.getFloat(0); - break; - case 2: - f = pL3.getFloat(0); - break; - } - return f; + return switch (phaseIx) { + default -> throw new RuntimeException("bad index"); + case 0 -> pL1.getFloat(0); + case 1 -> pL2.getFloat(0); + case 2 -> pL3.getFloat(0); + }; } /** @@ -164,18 +146,11 @@ public float getReactivPower(int phaseIx) throws RuntimeException { * @return PV Voltage [V] */ public float getPvVoltage(int pvIx) throws RuntimeException { - float f; - switch (pvIx) { - default: - throw new RuntimeException("wrong index"); - case 0: - f = uSg1.getFloat(0); - break; - case 1: - f = uSg2.getFloat(0); - break; - } - return f; + return switch (pvIx) { + default -> throw new RuntimeException("wrong index"); + case 0 -> uSg1.getFloat(0); + case 1 -> uSg2.getFloat(0); + }; } /** diff --git a/io.openems.edge.katek.edcom/src/com/ed/data/history/ADataItem.java b/io.openems.edge.katek.edcom/src/com/ed/data/history/ADataItem.java index ddba22d73e6..fd4b3bbc94d 100644 --- a/io.openems.edge.katek.edcom/src/com/ed/data/history/ADataItem.java +++ b/io.openems.edge.katek.edcom/src/com/ed/data/history/ADataItem.java @@ -181,8 +181,8 @@ boolean isCS() throws Exception { @Override public boolean equals(Object o) { boolean b = false; - if (o instanceof ADataItem) { - b = Arrays.equals(((ADataItem) o).bytes, this.bytes); + if (o instanceof ADataItem adi) { + b = Arrays.equals(adi.bytes, this.bytes); } return b; } diff --git a/io.openems.edge.katek.edcom/src/com/ed/edcom/Client.java b/io.openems.edge.katek.edcom/src/com/ed/edcom/Client.java index 3e39681b187..c3c7c9c97e4 100644 --- a/io.openems.edge.katek.edcom/src/com/ed/edcom/Client.java +++ b/io.openems.edge.katek.edcom/src/com/ed/edcom/Client.java @@ -940,21 +940,21 @@ private int createMessage() { } } } - switch (tel_type) { + tel_len = switch (tel_type) { default: - case 0: // dsp data request + case 0: { // dsp data request out_buf[2] = (byte) 0x34; - tel_len = putIds(out_buf); - break; - case 1: // dsp parameters senden + yield putIds(out_buf); + } + case 1: { // dsp parameters senden out_buf[2] = (byte) 0x33; - tel_len = putParams(out_buf); - break; - case 2: // pic dara request + yield putParams(out_buf); + } + case 2: { // pic dara request out_buf[2] = (byte) 0x30; - tel_len = putPicMsg(out_buf); - break; + yield putPicMsg(out_buf); } + }; lastMsgType = tel_type; } if (tel_len < 10) { diff --git a/io.openems.edge.katek.edcom/src/com/ed/edcom/DspVar.java b/io.openems.edge.katek.edcom/src/com/ed/edcom/DspVar.java index f2b51e9f712..fb7646c889a 100644 --- a/io.openems.edge.katek.edcom/src/com/ed/edcom/DspVar.java +++ b/io.openems.edge.katek.edcom/src/com/ed/edcom/DspVar.java @@ -317,49 +317,48 @@ public synchronized void setValue(Object in, int n) { return; } setModifiedNow(); - if (in instanceof Float) { - bufWrite.putFloat(n * 4, ((Float) in).floatValue()); + if (in instanceof Float f) { + bufWrite.putFloat(n * 4, f.floatValue()); } - if (in instanceof Long) { + if (in instanceof Long l) { switch (type) { case TYPE_UINT32: case TYPE_INT32: - bufWrite.putInt(n * 4, ((Long) in).intValue()); + bufWrite.putInt(n * 4, l.intValue()); break; case TYPE_UINT16: case TYPE_INT16: - bufWrite.putShort(n * 2, ((Long) in).shortValue()); + bufWrite.putShort(n * 2, l.shortValue()); break; case TYPE_UINT8: case TYPE_INT8: - bufWrite.put(n, ((Long) in).byteValue()); + bufWrite.put(n, l.byteValue()); break; } } - if (in instanceof Integer) { + if (in instanceof Integer i) { switch (type) { case TYPE_UINT32: case TYPE_INT32: - bufWrite.putInt(n * 4, ((Integer) in).intValue()); + bufWrite.putInt(n * 4, i.intValue()); break; case TYPE_UINT16: case TYPE_INT16: - bufWrite.putShort(n * 2, ((Integer) in).shortValue()); + bufWrite.putShort(n * 2, i.shortValue()); break; case TYPE_UINT8: case TYPE_INT8: - bufWrite.put(n, ((Integer) in).byteValue()); + bufWrite.put(n, i.byteValue()); break; } } - if (in instanceof ByteBuffer) { - ByteBuffer bf = (ByteBuffer) in; + if (in instanceof ByteBuffer bf) { for (int i = 0; i < data_set.length && i < bf.capacity(); i++) { data_set[i] = bf.get(i); } } - if (in instanceof String) { - str = (String) in; + if (in instanceof String ins) { + str = ins; str = str.replace("[", ""); str = str.replace("]", ""); str = str.replace(" ", ""); @@ -458,28 +457,15 @@ synchronized float getFloat(byte b[], int ix) throws IndexOutOfBoundsException { } private static int getVarLen(int vType, int vArrayLen) throws RuntimeException { - int vLen = 0; if (vArrayLen == 0) { vArrayLen = 1; } - switch (vType) { - default: - throw new RuntimeException("wrong variable type"); - case TYPE_FLOAT: - case TYPE_UINT32: - case TYPE_INT32: - vLen = 4 * vArrayLen; - break; - case TYPE_UINT16: - case TYPE_INT16: - vLen = 2 * vArrayLen; - break; - case TYPE_UINT8: - case TYPE_INT8: - vLen = vArrayLen; - break; - } - return vLen; + return switch (vType) { + default -> throw new RuntimeException("wrong variable type"); + case TYPE_FLOAT, TYPE_UINT32, TYPE_INT32 -> 4 * vArrayLen; + case TYPE_UINT16, TYPE_INT16 -> 2 * vArrayLen; + case TYPE_UINT8, TYPE_INT8 -> vArrayLen; + }; } } //CHECKSTYLE:ON diff --git a/io.openems.edge.meter.api/src/io/openems/edge/meter/api/ElectricityMeter.java b/io.openems.edge.meter.api/src/io/openems/edge/meter/api/ElectricityMeter.java index af1c088c8ec..5229e4f8c2d 100644 --- a/io.openems.edge.meter.api/src/io/openems/edge/meter/api/ElectricityMeter.java +++ b/io.openems.edge.meter.api/src/io/openems/edge/meter/api/ElectricityMeter.java @@ -21,7 +21,7 @@ /** * Represents an electricity Meter. - * + * *

* Meaning of positive and negative values for Power and Current depends on the * {@link MeterType} (via {@link #getMeterType()}): @@ -52,7 +52,7 @@ *

  • negative: (undefined) * * - * + * *

    * If values for all phases are equal (i.e. the measured device is 'symmetric'), * consider using the helper methods: @@ -60,12 +60,14 @@ *

  • {@link #calculateSumActivePowerFromPhases(ElectricityMeter)} *
  • {@link #calculateSumReactivePowerFromPhases(ElectricityMeter)} *
  • {@link #calculatePhasesFromActivePower(ElectricityMeter)} + *
  • {@link #calculatePhasesFromVoltage(ElectricityMeter)} *
  • {@link #calculatePhasesFromReactivePower(ElectricityMeter)} + *
  • {@link #calculateCurrentsFromActivePowerAndVoltage(ElectricityMeter)} *
  • {@link #calculateSumActiveProductionEnergyFromPhases(ElectricityMeter)} *
  • {@link #calculateAverageVoltageFromPhases(ElectricityMeter)} *
  • {@link #calculateSumCurrentFromPhases(ElectricityMeter)} * - * + * *

    * If only ever L1, L2 or L3 can be set, implement the {@link SinglePhaseMeter} * Nature additionally and consider using its helper methods. @@ -409,10 +411,10 @@ public Doc doc() { /** * Is this device actively managed by OpenEMS?. - * + * *

    * If this is a normal electricity meter, return false. - * + * *

    * If this is an actively managed device like a heat-pump or electric vehicle * charging station, return true. The value will then get ignored for @@ -478,7 +480,7 @@ public static ModbusSlaveNatureTable getModbusSlaveNatureTable(AccessMode access /** * Used for Modbus/TCP Api Controller. Provides a Modbus table for the Channels * of this Component - without individual phases. - * + * *

    * This method provides a way to stay compatible with previous SymmetricMeter * implementations that did not support AsymmetricMeter. Do not use for new @@ -1569,7 +1571,7 @@ public static void calculateSumActiveProductionEnergyFromPhases(ElectricityMeter /** * Initializes Channel listeners for a Symmetric {@link ElectricityMeter}. - * + * *

    * Calculate the {@link ChannelId#ACTIVE_POWER_L1}, * {@link ChannelId#ACTIVE_POWER_L2} and @@ -1589,7 +1591,68 @@ public static void calculatePhasesFromActivePower(ElectricityMeter meter) { /** * Initializes Channel listeners for a Symmetric {@link ElectricityMeter}. + * + *

    + * Calculate the {@link ChannelId#VOLTAGE_L1}, {@link ChannelId#VOLTAGE_L2} and + * {@link ChannelId#VOLTAGE_L3}-Channels as a copy of the + * {@link ChannelId#VOLTAGE}-Channel. + * + * @param meter the {@link ElectricityMeter} + */ + public static void calculatePhasesFromVoltage(ElectricityMeter meter) { + meter.getVoltageChannel().onSetNextValue(value -> { + meter.getVoltageL1Channel().setNextValue(value.get()); + meter.getVoltageL2Channel().setNextValue(value.get()); + meter.getVoltageL3Channel().setNextValue(value.get()); + }); + } + + /** + * Initializes Channel listeners for a Symmetric {@link ElectricityMeter}. + * + *

    + * Calculates + *

      + *
    • {@link ChannelId#CURRENT_L1} based on {@link ChannelId#ACTIVE_POWER_L1} + * and {@link ChannelId#VOLTAGE_L1}. + *
    • {@link ChannelId#CURRENT_L2} based on {@link ChannelId#ACTIVE_POWER_L2} + * and {@link ChannelId#VOLTAGE_L2}. + *
    • {@link ChannelId#CURRENT_L3} based on {@link ChannelId#ACTIVE_POWER_L3} + * and {@link ChannelId#VOLTAGE_L3}. + *
    + * + * @param meter the {@link ElectricityMeter} + */ + public static void calculateCurrentsFromActivePowerAndVoltage(ElectricityMeter meter) { + meter.getActivePowerL1Channel().onSetNextValue(value -> { + meter._setCurrentL1(currentFromActivePowerAndVoltage(value.get(), meter.getVoltageL1().get())); + }); + meter.getActivePowerL2Channel().onSetNextValue(value -> { + meter._setCurrentL2(currentFromActivePowerAndVoltage(value.get(), meter.getVoltageL2().get())); + }); + meter.getActivePowerL3Channel().onSetNextValue(value -> { + meter._setCurrentL3(currentFromActivePowerAndVoltage(value.get(), meter.getVoltageL3().get())); + }); + } + + /** + * Calculates Current (in [mA]) from ActivePower (in [W]) and Voltage (in [mV]). * + * @param power the power + * @param voltage the voltage + * @return the current or null if power or voltage or null + */ + private static Integer currentFromActivePowerAndVoltage(Integer power, Integer voltage) { + if (power == null || voltage == null) { + return null; + } + // somewhat complicated computation, but prevents integer overflows + return (power * 1000 /* [mW] */) / (voltage / 1000 /* [V] */); + } + + /** + * Initializes Channel listeners for a Symmetric {@link ElectricityMeter}. + * *

    * Calculate the {@link ChannelId#REACTIVE_POWER_L1}, * {@link ChannelId#REACTIVE_POWER_L2} and diff --git a/io.openems.edge.meter.api/src/io/openems/edge/meter/api/SinglePhaseMeter.java b/io.openems.edge.meter.api/src/io/openems/edge/meter/api/SinglePhaseMeter.java index 206766eaa16..bfc63d03bf0 100644 --- a/io.openems.edge.meter.api/src/io/openems/edge/meter/api/SinglePhaseMeter.java +++ b/io.openems.edge.meter.api/src/io/openems/edge/meter/api/SinglePhaseMeter.java @@ -39,7 +39,7 @@ public Doc doc() { /** * Initializes Channel listeners for a {@link SinglePhaseMeter}. - * + * *

    * Sets the correct value for {@link ChannelId#ACTIVE_POWER_L1}, * {@link ChannelId#ACTIVE_POWER_L2} or {@link ChannelId#ACTIVE_POWER_L3} from @@ -54,12 +54,12 @@ public static void calculateSinglePhaseFromActivePower(SinglePhaseMeter meter) { /** * Initializes Channel listeners for a {@link SinglePhaseMeter}. - * + * *

    * Use this method if it is not known at compile time, that the * {@link ElectricityMeter} is a {@link SinglePhaseMeter}, i.e. it is not * implementing {@link SinglePhaseMeter}. - * + * *

    * Sets the correct value for {@link ChannelId#ACTIVE_POWER_L1}, * {@link ChannelId#ACTIVE_POWER_L2} or {@link ChannelId#ACTIVE_POWER_L3} from @@ -82,7 +82,7 @@ public static void calculateSinglePhaseFromActi /** * Initializes Channel listeners for a {@link SinglePhaseMeter}. - * + * *

    * Sets the correct value for {@link ChannelId#REACTIVE_POWER_L1}, * {@link ChannelId#REACTIVE_POWER_L2} or {@link ChannelId#REACTIVE_POWER_L3} @@ -97,12 +97,12 @@ public static void calculateSinglePhaseFromReactivePower(SinglePhaseMeter meter) /** * Initializes Channel listeners for a {@link SinglePhaseMeter}. - * + * *

    * Use this method if it is not known at compile time, that the * {@link ElectricityMeter} is a {@link SinglePhaseMeter}, i.e. it is not * implementing {@link SinglePhaseMeter}. - * + * *

    * Sets the correct value for {@link ChannelId#REACTIVE_POWER_L1}, * {@link ChannelId#REACTIVE_POWER_L2} or {@link ChannelId#REACTIVE_POWER_L3} @@ -125,7 +125,7 @@ public static void calculateSinglePhaseFromReac /** * Initializes Channel listeners for a {@link SinglePhaseMeter}. - * + * *

    * Sets the correct value for {@link ChannelId#CURRENT_L1}, * {@link ChannelId#CURRENT_L2} or {@link ChannelId#CURRENT_L3} from @@ -140,12 +140,12 @@ public static void calculateSinglePhaseFromCurrent(SinglePhaseMeter meter) { /** * Initializes Channel listeners for a {@link SinglePhaseMeter}. - * + * *

    * Use this method if it is not known at compile time, that the * {@link ElectricityMeter} is a {@link SinglePhaseMeter}, i.e. it is not * implementing {@link SinglePhaseMeter}. - * + * *

    * Sets the correct value for {@link ChannelId#CURRENT_L1}, * {@link ChannelId#CURRENT_L2} or {@link ChannelId#CURRENT_L3} from @@ -167,7 +167,7 @@ public static void calculateSinglePhaseFromCurr /** * Initializes Channel listeners for a {@link SinglePhaseMeter}. - * + * *

    * Sets the correct value for {@link ChannelId#VOLTAGE_L1}, * {@link ChannelId#VOLTAGE_L2} or {@link ChannelId#VOLTAGE_L3} from @@ -182,12 +182,12 @@ public static void calculateSinglePhaseFromVoltage(SinglePhaseMeter meter) { /** * Initializes Channel listeners for a {@link SinglePhaseMeter}. - * + * *

    * Use this method if it is not known at compile time, that the * {@link ElectricityMeter} is a {@link SinglePhaseMeter}, i.e. it is not * implementing {@link SinglePhaseMeter}. - * + * *

    * Sets the correct value for {@link ChannelId#VOLTAGE_L1}, * {@link ChannelId#VOLTAGE_L2} or {@link ChannelId#VOLTAGE_L3} from diff --git a/io.openems.edge.meter.api/test/io/openems/edge/meter/api/ElectricityMeterTest.java b/io.openems.edge.meter.api/test/io/openems/edge/meter/api/ElectricityMeterTest.java index c5d56e17c90..31f3c29a7bd 100644 --- a/io.openems.edge.meter.api/test/io/openems/edge/meter/api/ElectricityMeterTest.java +++ b/io.openems.edge.meter.api/test/io/openems/edge/meter/api/ElectricityMeterTest.java @@ -1,22 +1,22 @@ package io.openems.edge.meter.api; +import static io.openems.edge.common.test.TestUtils.activateNextProcessImage; +import static io.openems.edge.meter.api.ElectricityMeter.calculateCurrentsFromActivePowerAndVoltage; import static org.junit.Assert.assertEquals; import org.junit.Test; -import io.openems.edge.common.test.TestUtils; import io.openems.edge.meter.test.DummyElectricityMeter; public class ElectricityMeterTest { @Test public void testCalculateSumActivePowerFromPhases() { - var sut = new DummyElectricityMeter("meter0"); // - // Without calculateSumActivePowerFromPhases - sut.withActivePowerL1(1000); - sut.withActivePowerL2(200); - sut.withActivePowerL3(30); + var sut = new DummyElectricityMeter("meter0") // + .withActivePowerL1(1000) // + .withActivePowerL2(200) // + .withActivePowerL3(30); assertEquals(null, sut.getActivePower().get()); assertEquals(1000, sut.getActivePowerL1().get().intValue()); assertEquals(200, sut.getActivePowerL2().get().intValue()); @@ -24,21 +24,22 @@ public void testCalculateSumActivePowerFromPhases() { // Activate ElectricityMeter.calculateSumActivePowerFromPhases(sut); - sut.withActivePowerL1(2000); - sut.withActivePowerL2(300); - sut.withActivePowerL3(40); - TestUtils.activateNextProcessImage(sut); + sut // + .withActivePowerL1(2000) // + .withActivePowerL2(300) // + .withActivePowerL3(40); + + activateNextProcessImage(sut); assertEquals(2340, sut.getActivePower().get().intValue()); } @Test public void testCalculateSumReactivePowerFromPhases() { - var sut = new DummyElectricityMeter("meter0"); // - // Without calculateSumReactivePowerFromPhases - sut.withReactivePowerL1(1000); - sut.withReactivePowerL2(200); - sut.withReactivePowerL3(30); + var sut = new DummyElectricityMeter("meter0") // + .withReactivePowerL1(1000) // + .withReactivePowerL2(200) // + .withReactivePowerL3(30); assertEquals(null, sut.getReactivePower().get()); assertEquals(1000, sut.getReactivePowerL1().get().intValue()); assertEquals(200, sut.getReactivePowerL2().get().intValue()); @@ -46,21 +47,22 @@ public void testCalculateSumReactivePowerFromPhases() { // Activate ElectricityMeter.calculateSumReactivePowerFromPhases(sut); - sut.withReactivePowerL1(2000); - sut.withReactivePowerL2(300); - sut.withReactivePowerL3(40); - TestUtils.activateNextProcessImage(sut); + sut // + .withReactivePowerL1(2000) // + .withReactivePowerL2(300) // + .withReactivePowerL3(40); + + activateNextProcessImage(sut); assertEquals(2340, sut.getReactivePower().get().intValue()); } @Test public void testCalculateSumCurrentFromPhases() { - var sut = new DummyElectricityMeter("meter0"); // - // Without calculateSumCurrentFromPhasess - sut.withCurrentL1(1000); - sut.withCurrentL2(200); - sut.withCurrentL3(30); + var sut = new DummyElectricityMeter("meter0") // + .withCurrentL1(1000) // + .withCurrentL2(200) // + .withCurrentL3(30); assertEquals(null, sut.getCurrent().get()); assertEquals(1000, sut.getCurrentL1().get().intValue()); assertEquals(200, sut.getCurrentL2().get().intValue()); @@ -68,21 +70,22 @@ public void testCalculateSumCurrentFromPhases() { // Activate ElectricityMeter.calculateSumCurrentFromPhases(sut); - sut.withCurrentL1(2000); - sut.withCurrentL2(300); - sut.withCurrentL3(40); - TestUtils.activateNextProcessImage(sut); + sut // + .withCurrentL1(2000) // + .withCurrentL2(300) // + .withCurrentL3(40); + + activateNextProcessImage(sut); assertEquals(2340, sut.getCurrent().get().intValue()); } @Test public void testCalculateAverageVoltageFromPhases() { - var sut = new DummyElectricityMeter("meter0"); // - // Without calculateAverageVoltageFromPhases - sut.withVoltageL1(1000); - sut.withVoltageL2(200); - sut.withVoltageL3(30); + var sut = new DummyElectricityMeter("meter0") // + .withVoltageL1(1000) // + .withVoltageL2(200) // + .withVoltageL3(30); assertEquals(null, sut.getVoltage().get()); assertEquals(1000, sut.getVoltageL1().get().intValue()); assertEquals(200, sut.getVoltageL2().get().intValue()); @@ -90,21 +93,22 @@ public void testCalculateAverageVoltageFromPhases() { // Activate ElectricityMeter.calculateAverageVoltageFromPhases(sut); - sut.withVoltageL1(2000); - sut.withVoltageL2(300); - sut.withVoltageL3(40); - TestUtils.activateNextProcessImage(sut); + sut // + .withVoltageL1(2000) // + .withVoltageL2(300) // + .withVoltageL3(40); + + activateNextProcessImage(sut); assertEquals(780, sut.getVoltage().get().intValue()); } @Test public void testCalculateSumActiveProductionEnergyFromPhases() { - var sut = new DummyElectricityMeter("meter0"); // - // Without calculateSumActiveProductionEnergyFromPhases - sut.withActiveProductionEnergyL1(1000); - sut.withActiveProductionEnergyL2(200); - sut.withActiveProductionEnergyL3(30); + var sut = new DummyElectricityMeter("meter0") // + .withActiveProductionEnergyL1(1000) // + .withActiveProductionEnergyL2(200) // + .withActiveProductionEnergyL3(30); assertEquals(null, sut.getActiveProductionEnergy().get()); assertEquals(1000, sut.getActiveProductionEnergyL1().get().intValue()); assertEquals(200, sut.getActiveProductionEnergyL2().get().intValue()); @@ -112,19 +116,20 @@ public void testCalculateSumActiveProductionEnergyFromPhases() { // Activate ElectricityMeter.calculateSumActiveProductionEnergyFromPhases(sut); - sut.withActiveProductionEnergyL1(2000); - sut.withActiveProductionEnergyL2(300); - sut.withActiveProductionEnergyL3(40); - TestUtils.activateNextProcessImage(sut); + sut // + .withActiveProductionEnergyL1(2000) // + .withActiveProductionEnergyL2(300) // + .withActiveProductionEnergyL3(40); + + activateNextProcessImage(sut); assertEquals(2340, sut.getActiveProductionEnergy().get().intValue()); } @Test public void testCalculatePhasesFromActivePower() { - var sut = new DummyElectricityMeter("meter0"); // - // Without calculatePhasesFromActivePower - sut.withActivePower(3000); + var sut = new DummyElectricityMeter("meter0") // + .withActivePower(3000); assertEquals(3000, sut.getActivePower().get().intValue()); assertEquals(null, sut.getActivePowerL1().get()); assertEquals(null, sut.getActivePowerL2().get()); @@ -133,7 +138,8 @@ public void testCalculatePhasesFromActivePower() { // Activate ElectricityMeter.calculatePhasesFromActivePower(sut); sut.withActivePower(3000); - TestUtils.activateNextProcessImage(sut); + activateNextProcessImage(sut); + assertEquals(1000, sut.getActivePowerL1().get().intValue()); assertEquals(1000, sut.getActivePowerL2().get().intValue()); assertEquals(1000, sut.getActivePowerL3().get().intValue()); @@ -141,10 +147,9 @@ public void testCalculatePhasesFromActivePower() { @Test public void testCalculatePhasesFromReactivePower() { - var sut = new DummyElectricityMeter("meter0"); // - // Without calculatePhasesFromReactivePower - sut.withReactivePower(3000); + var sut = new DummyElectricityMeter("meter0") // + .withReactivePower(3000); assertEquals(3000, sut.getReactivePower().get().intValue()); assertEquals(null, sut.getReactivePowerL1().get()); assertEquals(null, sut.getReactivePowerL2().get()); @@ -153,10 +158,77 @@ public void testCalculatePhasesFromReactivePower() { // Activate ElectricityMeter.calculatePhasesFromReactivePower(sut); sut.withReactivePower(3000); - TestUtils.activateNextProcessImage(sut); + + activateNextProcessImage(sut); assertEquals(1000, sut.getReactivePowerL1().get().intValue()); assertEquals(1000, sut.getReactivePowerL2().get().intValue()); assertEquals(1000, sut.getReactivePowerL3().get().intValue()); } + @Test + public void testCalculatePhasesFromVoltage() { + var sut = new DummyElectricityMeter("meter0") // + .withVoltage(231_000); + assertEquals(null, sut.getVoltageL1().get()); + assertEquals(null, sut.getVoltageL2().get()); + assertEquals(null, sut.getVoltageL3().get()); + + ElectricityMeter.calculatePhasesFromVoltage(sut); + sut.withVoltage(231_000); + + activateNextProcessImage(sut); + assertEquals(231_000, sut.getVoltageL1().get().intValue()); + assertEquals(231_000, sut.getVoltageL2().get().intValue()); + assertEquals(231_000, sut.getVoltageL3().get().intValue()); + + } + + @Test + public void testCalculateCurrentsFromActivePowerAndVoltage() { + var sut = prepareTestCalculateCurrentsStep1(233_000); + prepareTestCalculateCurrentsStep2(sut, 233_000); + + assertEquals(4329, sut.getCurrentL1().get().intValue()); + assertEquals(8620, sut.getCurrentL2().get().intValue()); + assertEquals(12875, sut.getCurrentL3().get().intValue()); + } + + @Test + public void testCalculateCurrentsFromActivePowerAndNullVoltage() { + var sut = prepareTestCalculateCurrentsStep1(null); + prepareTestCalculateCurrentsStep2(sut, null); + + assertEquals(4329, sut.getCurrentL1().get().intValue()); + assertEquals(8620, sut.getCurrentL2().get().intValue()); + assertEquals(null, sut.getCurrentL3().get()); + } + + private static DummyElectricityMeter prepareTestCalculateCurrentsStep1(Integer voltageL3) { + var sut = new DummyElectricityMeter("meter0") // + .withActivePowerL1(1000) // + .withActivePowerL2(2000) // + .withActivePowerL3(3000) // + .withVoltageL1(231_000) // + .withVoltageL2(232_000) // + .withVoltageL3(voltageL3); // + + assertEquals(null, sut.getCurrentL1().get()); + assertEquals(null, sut.getCurrentL2().get()); + assertEquals(null, sut.getCurrentL3().get()); + return sut; + } + + private static void prepareTestCalculateCurrentsStep2(DummyElectricityMeter sut, Integer voltageL3) { + calculateCurrentsFromActivePowerAndVoltage(sut); + sut // + .withActivePowerL1(1000) // + .withActivePowerL2(2000) // + .withActivePowerL3(3000) // + .withVoltageL1(231_000) // + .withVoltageL2(232_000) // + .withVoltageL3(voltageL3); + + activateNextProcessImage(sut); + } + } diff --git a/io.openems.edge.meter.carlo.gavazzi.em300/test/io/openems/edge/meter/carlo/gavazzi/em300/MeterCarloGavazziEm300ImplTest.java b/io.openems.edge.meter.carlo.gavazzi.em300/test/io/openems/edge/meter/carlo/gavazzi/em300/MeterCarloGavazziEm300ImplTest.java index a802bbe67c0..4cdb50a76d2 100644 --- a/io.openems.edge.meter.carlo.gavazzi.em300/test/io/openems/edge/meter/carlo/gavazzi/em300/MeterCarloGavazziEm300ImplTest.java +++ b/io.openems.edge.meter.carlo.gavazzi.em300/test/io/openems/edge/meter/carlo/gavazzi/em300/MeterCarloGavazziEm300ImplTest.java @@ -1,5 +1,6 @@ package io.openems.edge.meter.carlo.gavazzi.em300; +import static io.openems.common.test.TestUtils.createDummyClock; import static io.openems.common.types.MeterType.GRID; import org.junit.Test; @@ -9,7 +10,6 @@ import io.openems.edge.common.test.ComponentTest; import io.openems.edge.common.test.DummyComponentManager; import io.openems.edge.common.test.DummyConfigurationAdmin; -import io.openems.edge.common.test.TestUtils; import io.openems.edge.meter.api.ElectricityMeter; public class MeterCarloGavazziEm300ImplTest { @@ -34,7 +34,7 @@ public void testReadFromModbus() throws Exception { var sut = new MeterCarloGavazziEm300Impl(); new ComponentTest(sut) // .addReference("cm", new DummyConfigurationAdmin()) // - .addComponent(new DummyComponentManager(TestUtils.createDummyClock())) + .addComponent(new DummyComponentManager(createDummyClock())) .addReference("setModbus", new DummyModbusBridge("modbus2") // .withInputRegisters(300001 - this.offset, // new int[] { 0x08c3, 0x0000, // diff --git a/io.openems.edge.meter.carlo.gavazzi.em300/test/io/openems/edge/meter/carlo/gavazzi/em300/MyConfig.java b/io.openems.edge.meter.carlo.gavazzi.em300/test/io/openems/edge/meter/carlo/gavazzi/em300/MyConfig.java index c3cdb032436..c3f7691f7e9 100644 --- a/io.openems.edge.meter.carlo.gavazzi.em300/test/io/openems/edge/meter/carlo/gavazzi/em300/MyConfig.java +++ b/io.openems.edge.meter.carlo.gavazzi.em300/test/io/openems/edge/meter/carlo/gavazzi/em300/MyConfig.java @@ -31,7 +31,7 @@ public Builder setType(MeterType type) { this.type = type; return this; } - + public Builder setModbusUnitId(int unitId) { this.modbusUnitId = unitId; return this; diff --git a/io.openems.edge.meter.virtual/src/io/openems/edge/meter/virtual/subtract/SubtractChannelManager.java b/io.openems.edge.meter.virtual/src/io/openems/edge/meter/virtual/subtract/SubtractChannelManager.java index 2752b4e8cd9..c2939c012b0 100644 --- a/io.openems.edge.meter.virtual/src/io/openems/edge/meter/virtual/subtract/SubtractChannelManager.java +++ b/io.openems.edge.meter.virtual/src/io/openems/edge/meter/virtual/subtract/SubtractChannelManager.java @@ -1,5 +1,7 @@ package io.openems.edge.meter.virtual.subtract; +import static io.openems.common.utils.FunctionUtils.doNothing; + import java.util.List; import java.util.function.Consumer; @@ -60,28 +62,30 @@ private void activateSubtractInteger(OpenemsComponent minuend /* nullable */, Li // Subtrahends Integer subtrahendsSum = null; for (OpenemsComponent subtrahend : subtrahends) { - if (subtrahend instanceof ElectricityMeter meter) { + switch (subtrahend) { + case ElectricityMeter meter -> { IntegerReadChannel channel = meter.channel(meterChannelId); subtrahendsSum = TypeUtils.sum(subtrahendsSum, channel.getNextValue().get()); - } else if (subtrahend instanceof SymmetricEss) { - IntegerReadChannel channel = ((SymmetricEss) subtrahend).channel(essChannelId); + } + case SymmetricEss ess -> { + IntegerReadChannel channel = ess.channel(essChannelId); subtrahendsSum = TypeUtils.sum(subtrahendsSum, channel.getNextValue().get()); } + default -> doNothing(); + } } - final Integer minuendValue; - if (minuend == null) { - minuendValue = 0; - } else if (minuend instanceof ElectricityMeter meter) { + final Integer minuendValue = switch (minuend) { + case ElectricityMeter meter -> { IntegerReadChannel channel = meter.channel(meterChannelId); - minuendValue = channel.getNextValue().get(); - } else if (minuend instanceof SymmetricEss) { - IntegerReadChannel channel = ((SymmetricEss) minuend).channel(essChannelId); - minuendValue = channel.getNextValue().get(); - } else { - // should not happen - minuendValue = null; + yield channel.getNextValue().get(); + } + case SymmetricEss ess -> { + IntegerReadChannel channel = ess.channel(essChannelId); + yield channel.getNextValue().get(); } + case null, default -> 0; + }; final Integer result; // Minuend @@ -96,20 +100,22 @@ private void activateSubtractInteger(OpenemsComponent minuend /* nullable */, Li }; // Minuend - if (minuend == null) { - // no listener for minuend - } else if (minuend instanceof ElectricityMeter) { - this.addOnSetNextValueListener(minuend, meterChannelId, callback); - } else if (minuend instanceof SymmetricEss) { - this.addOnSetNextValueListener(minuend, essChannelId, callback); + switch (minuend) { + case ElectricityMeter meter // + -> this.addOnSetNextValueListener(minuend, meterChannelId, callback); + case SymmetricEss ess // + -> this.addOnSetNextValueListener(minuend, essChannelId, callback); + case null, default -> doNothing(); } // Subtrahends for (OpenemsComponent subtrahend : subtrahends) { - if (subtrahend instanceof ElectricityMeter) { - this.addOnSetNextValueListener(subtrahend, meterChannelId, callback); - } else if (subtrahend instanceof SymmetricEss) { - this.addOnSetNextValueListener(subtrahend, essChannelId, callback); + switch (subtrahend) { + case ElectricityMeter meter // + -> this.addOnSetNextValueListener(subtrahend, meterChannelId, callback); + case SymmetricEss ess // + -> this.addOnSetNextValueListener(subtrahend, essChannelId, callback); + default -> doNothing(); } } } @@ -117,28 +123,32 @@ private void activateSubtractInteger(OpenemsComponent minuend /* nullable */, Li private void activateSubtractLong(OpenemsComponent minuend /* nullable */, List subtrahends, ElectricityMeter.ChannelId meterChannelId, SymmetricEss.ChannelId essChannelId) { final Consumer> callback = (ignore) -> { - Long result = null; - // Minuend - if (minuend == null) { - result = 0L; - } else if (minuend instanceof ElectricityMeter meter) { + Long result = switch (minuend) { + case ElectricityMeter meter -> { LongReadChannel channel = meter.channel(meterChannelId); - result = channel.getNextValue().get(); - } else if (minuend instanceof SymmetricEss) { - LongReadChannel channel = ((SymmetricEss) minuend).channel(essChannelId); - result = channel.getNextValue().get(); + yield channel.getNextValue().get(); + } + case SymmetricEss ess -> { + LongReadChannel channel = ess.channel(essChannelId); + yield channel.getNextValue().get(); } + case null, default -> 0L; + }; // Subtrahends for (OpenemsComponent subtrahend : subtrahends) { - if (subtrahend instanceof ElectricityMeter meter) { + switch (subtrahend) { + case ElectricityMeter meter -> { LongReadChannel channel = meter.channel(meterChannelId); result = TypeUtils.subtract(result, channel.getNextValue().get()); - } else if (subtrahend instanceof SymmetricEss) { - LongReadChannel channel = ((SymmetricEss) subtrahend).channel(essChannelId); + } + case SymmetricEss ess -> { + LongReadChannel channel = ess.channel(essChannelId); result = TypeUtils.subtract(result, channel.getNextValue().get()); } + default -> doNothing(); + } } LongReadChannel channel = this.parent.channel(meterChannelId); @@ -146,20 +156,22 @@ private void activateSubtractLong(OpenemsComponent minuend /* nullable */, List< }; // Minuend - if (minuend == null) { - // no listener for minuend - } else if (minuend instanceof ElectricityMeter) { - this.addOnSetNextValueListener(minuend, meterChannelId, callback); - } else if (minuend instanceof SymmetricEss) { - this.addOnSetNextValueListener(minuend, essChannelId, callback); + switch (minuend) { + case ElectricityMeter meter // + -> this.addOnSetNextValueListener(minuend, meterChannelId, callback); + case SymmetricEss ess // + -> this.addOnSetNextValueListener(minuend, essChannelId, callback); + case null, default -> doNothing(); } // Subtrahends for (OpenemsComponent subtrahend : subtrahends) { - if (subtrahend instanceof ElectricityMeter) { - this.addOnSetNextValueListener(subtrahend, meterChannelId, callback); - } else if (subtrahend instanceof SymmetricEss) { - this.addOnSetNextValueListener(subtrahend, essChannelId, callback); + switch (subtrahend) { + case ElectricityMeter meter // + -> this.addOnSetNextValueListener(subtrahend, meterChannelId, callback); + case SymmetricEss ess // + -> this.addOnSetNextValueListener(subtrahend, essChannelId, callback); + default -> doNothing(); } } } diff --git a/io.openems.edge.onewire.thermometer/src/io/openems/edge/onewire/thermometer/OneWireThermometer.java b/io.openems.edge.onewire.thermometer/src/io/openems/edge/onewire/thermometer/OneWireThermometer.java index 3b23f9ace6d..b324aee4b3b 100644 --- a/io.openems.edge.onewire.thermometer/src/io/openems/edge/onewire/thermometer/OneWireThermometer.java +++ b/io.openems.edge.onewire.thermometer/src/io/openems/edge/onewire/thermometer/OneWireThermometer.java @@ -1,5 +1,7 @@ package io.openems.edge.onewire.thermometer; +import static io.openems.common.channel.Debounce.TRUE_VALUES_IN_A_ROW_TO_SET_TRUE; + import io.openems.common.channel.Level; import io.openems.edge.common.channel.Doc; import io.openems.edge.common.component.OpenemsComponent; @@ -8,7 +10,8 @@ public interface OneWireThermometer extends Thermometer, OpenemsComponent { public enum ChannelId implements io.openems.edge.common.channel.ChannelId { - COMMUNICATION_FAILED(Doc.of(Level.FAULT)); + COMMUNICATION_FAILED(Doc.of(Level.FAULT) // + .debounce(5, TRUE_VALUES_IN_A_ROW_TO_SET_TRUE)); private final Doc doc; diff --git a/io.openems.edge.onewire.thermometer/src/io/openems/edge/onewire/thermometer/OneWireThermometerImpl.java b/io.openems.edge.onewire.thermometer/src/io/openems/edge/onewire/thermometer/OneWireThermometerImpl.java index 2f941cc0d7e..2a6886e790d 100644 --- a/io.openems.edge.onewire.thermometer/src/io/openems/edge/onewire/thermometer/OneWireThermometerImpl.java +++ b/io.openems.edge.onewire.thermometer/src/io/openems/edge/onewire/thermometer/OneWireThermometerImpl.java @@ -18,7 +18,6 @@ import com.dalsemi.onewire.OneWireException; import com.dalsemi.onewire.adapter.DSPortAdapter; -import com.dalsemi.onewire.container.OneWireContainer; import com.dalsemi.onewire.container.TemperatureContainer; import io.openems.common.exceptions.OpenemsException; @@ -104,10 +103,9 @@ private TemperatureContainer getDeviceContainer(DSPortAdapter adapter) throws Op return this._container; } var owc = adapter.getDeviceContainer(this.config.address()); - if (!(owc instanceof OneWireContainer)) { + if (!(owc instanceof TemperatureContainer container)) { throw new OpenemsException("This is not a OneWire Temperature Container"); } - var container = (TemperatureContainer) owc; this._container = container; return this._container; } diff --git a/io.openems.edge.predictor.api/test/io/openems/edge/predictor/api/test/DummyPredictorManagerTest.java b/io.openems.edge.predictor.api/test/io/openems/edge/predictor/api/test/DummyPredictorManagerTest.java index 8dc48474b55..7dfd0039849 100644 --- a/io.openems.edge.predictor.api/test/io/openems/edge/predictor/api/test/DummyPredictorManagerTest.java +++ b/io.openems.edge.predictor.api/test/io/openems/edge/predictor/api/test/DummyPredictorManagerTest.java @@ -1,6 +1,6 @@ package io.openems.edge.predictor.api.test; -import static io.openems.edge.common.test.TestUtils.createDummyClock; +import static io.openems.common.test.TestUtils.createDummyClock; import static io.openems.edge.predictor.api.prediction.Prediction.EMPTY_PREDICTION; import static org.junit.Assert.assertEquals; diff --git a/io.openems.edge.predictor.api/test/io/openems/edge/predictor/api/test/DummyPredictorTest.java b/io.openems.edge.predictor.api/test/io/openems/edge/predictor/api/test/DummyPredictorTest.java index f7593b5359c..c7f317dd22b 100644 --- a/io.openems.edge.predictor.api/test/io/openems/edge/predictor/api/test/DummyPredictorTest.java +++ b/io.openems.edge.predictor.api/test/io/openems/edge/predictor/api/test/DummyPredictorTest.java @@ -1,6 +1,6 @@ package io.openems.edge.predictor.api.test; -import static io.openems.edge.common.test.TestUtils.createDummyClock; +import static io.openems.common.test.TestUtils.createDummyClock; import static io.openems.edge.predictor.api.test.DummyPredictorManagerTest.SUM_PRODUCTION_ACTIVE_POWER; import static java.time.temporal.ChronoUnit.MINUTES; import static org.junit.Assert.assertEquals; diff --git a/io.openems.edge.predictor.lstm/src/io/openems/edge/predictor/lstm/preprocessing/DataModification.java b/io.openems.edge.predictor.lstm/src/io/openems/edge/predictor/lstm/preprocessing/DataModification.java index 47d107b9843..8e9324e6922 100644 --- a/io.openems.edge.predictor.lstm/src/io/openems/edge/predictor/lstm/preprocessing/DataModification.java +++ b/io.openems.edge.predictor.lstm/src/io/openems/edge/predictor/lstm/preprocessing/DataModification.java @@ -227,13 +227,13 @@ public static double standardize(double inputData, double mean, double standerdD * @param hyperParameters instance of {@link HyperParameters} * @return The reverse standardized value in the original data's scale. */ - public static double reverseStandrize(double zvalue, double mean, double standardDeviation, + public static double reverseStandardize(double zvalue, double mean, double standardDeviation, HyperParameters hyperParameters) { double reverseStand = 0; double meanTarget = hyperParameters.getMean(); double standardDeviationTarget = hyperParameters.getStandardDeviation(); - reverseStand = ((zvalue - meanTarget) * (standardDeviation / standardDeviationTarget) + mean); + reverseStand = (zvalue - meanTarget) * (standardDeviation / standardDeviationTarget) + mean; return reverseStand; } @@ -252,11 +252,11 @@ public static double reverseStandrize(double zvalue, double mean, double standar * and standard deviation. * @return A new list containing the reverse standardized values. */ - public static double[] reverseStandrize(ArrayList data, ArrayList mean, + public static double[] reverseStandardize(ArrayList data, ArrayList mean, ArrayList standDeviation, HyperParameters hyperParameters) { var revNorm = new double[data.size()]; for (int i = 0; i < data.size(); i++) { - revNorm[i] = (reverseStandrize(data.get(i), mean.get(i), standDeviation.get(i), hyperParameters)); + revNorm[i] = reverseStandardize(data.get(i), mean.get(i), standDeviation.get(i), hyperParameters); } return revNorm; } @@ -276,11 +276,11 @@ public static double[] reverseStandrize(ArrayList data, ArrayList data, double mean, double standDeviation, + public static double[] reverseStandardize(ArrayList data, double mean, double standDeviation, HyperParameters hyperParameters) { var revNorm = new double[data.size()]; for (int i = 0; i < data.size(); i++) { - revNorm[i] = (reverseStandrize(data.get(i), mean, standDeviation, hyperParameters)); + revNorm[i] = reverseStandardize(data.get(i), mean, standDeviation, hyperParameters); } return revNorm; } @@ -324,11 +324,11 @@ public static double[] reverseStandrize(ArrayList data, double mean, dou * and standard deviation. * @return A new list containing the reverse standardized values. */ - public static double[] reverseStandrize(double[] data, double mean, double standDeviation, + public static double[] reverseStandardize(double[] data, double mean, double standDeviation, HyperParameters hyperParameters) { var revNorm = new double[data.length]; for (int i = 0; i < data.length; i++) { - revNorm[i] = (reverseStandrize(data[i], mean, standDeviation, hyperParameters)); + revNorm[i] = reverseStandardize(data[i], mean, standDeviation, hyperParameters); } return revNorm; } @@ -354,7 +354,7 @@ public static ArrayList>> groupDataByHourAndMinute(A groupByHour.hour(); for (int i = 0; i < groupByHour.getGroupedDataByHour().size(); i++) { - GroupBy groupByMinute = new GroupBy(groupByHour.getGroupedDataByHour().get(i), + var groupByMinute = new GroupBy(groupByHour.getGroupedDataByHour().get(i), groupByHour.getGroupedDateByHour().get(i)); groupByMinute.minute(); diff --git a/io.openems.edge.predictor.lstm/src/io/openems/edge/predictor/lstm/preprocessingpipeline/ConstantScalingPipe.java b/io.openems.edge.predictor.lstm/src/io/openems/edge/predictor/lstm/preprocessingpipeline/ConstantScalingPipe.java index 49e6b6147a4..a2386fab884 100644 --- a/io.openems.edge.predictor.lstm/src/io/openems/edge/predictor/lstm/preprocessingpipeline/ConstantScalingPipe.java +++ b/io.openems.edge.predictor.lstm/src/io/openems/edge/predictor/lstm/preprocessingpipeline/ConstantScalingPipe.java @@ -12,7 +12,7 @@ public ConstantScalingPipe(double factor) { @Override public Object execute(Object input) { - return (input instanceof double[] in) // + return input instanceof double[] in // ? constantScaling(in, this.scalingFactor) // : new IllegalArgumentException("Input must be an instance of double[]"); } diff --git a/io.openems.edge.predictor.lstm/src/io/openems/edge/predictor/lstm/preprocessingpipeline/DifferencingPipe.java b/io.openems.edge.predictor.lstm/src/io/openems/edge/predictor/lstm/preprocessingpipeline/DifferencingPipe.java index eda1d0963cf..b4c68ab8100 100644 --- a/io.openems.edge.predictor.lstm/src/io/openems/edge/predictor/lstm/preprocessingpipeline/DifferencingPipe.java +++ b/io.openems.edge.predictor.lstm/src/io/openems/edge/predictor/lstm/preprocessingpipeline/DifferencingPipe.java @@ -6,7 +6,7 @@ public class DifferencingPipe implements Stage { @Override public Object execute(Object input) { - return (input instanceof double[] in) // + return input instanceof double[] in // ? Differencing.firstOrderDifferencing(in) // : new IllegalArgumentException("Input must be an instance of double[]"); } diff --git a/io.openems.edge.predictor.lstm/src/io/openems/edge/predictor/lstm/preprocessingpipeline/FilterOutliersPipe.java b/io.openems.edge.predictor.lstm/src/io/openems/edge/predictor/lstm/preprocessingpipeline/FilterOutliersPipe.java index e6ec17f578a..c0b40da77fa 100644 --- a/io.openems.edge.predictor.lstm/src/io/openems/edge/predictor/lstm/preprocessingpipeline/FilterOutliersPipe.java +++ b/io.openems.edge.predictor.lstm/src/io/openems/edge/predictor/lstm/preprocessingpipeline/FilterOutliersPipe.java @@ -6,7 +6,7 @@ public class FilterOutliersPipe implements Stage { @Override public Object execute(Object input) { - return (input instanceof double[] in) // + return input instanceof double[] in // ? FilterOutliers.filterOutlier(in) // : new IllegalArgumentException("Input must be an instance of double[]"); } diff --git a/io.openems.edge.predictor.lstm/src/io/openems/edge/predictor/lstm/preprocessingpipeline/MovingAveragePipe.java b/io.openems.edge.predictor.lstm/src/io/openems/edge/predictor/lstm/preprocessingpipeline/MovingAveragePipe.java index 4ac0ba16f18..b37f9976a4d 100644 --- a/io.openems.edge.predictor.lstm/src/io/openems/edge/predictor/lstm/preprocessingpipeline/MovingAveragePipe.java +++ b/io.openems.edge.predictor.lstm/src/io/openems/edge/predictor/lstm/preprocessingpipeline/MovingAveragePipe.java @@ -6,7 +6,7 @@ public class MovingAveragePipe implements Stage { @Override public Object execute(Object input) { - return (input instanceof double[] in) // + return input instanceof double[] in // ? MovingAverage.movingAverage(in) // : new IllegalArgumentException("Input must be an instance of double[]"); } diff --git a/io.openems.edge.predictor.lstm/src/io/openems/edge/predictor/lstm/preprocessingpipeline/NormalizePipe.java b/io.openems.edge.predictor.lstm/src/io/openems/edge/predictor/lstm/preprocessingpipeline/NormalizePipe.java index 6ee14e728bd..78c19f83c1b 100644 --- a/io.openems.edge.predictor.lstm/src/io/openems/edge/predictor/lstm/preprocessingpipeline/NormalizePipe.java +++ b/io.openems.edge.predictor.lstm/src/io/openems/edge/predictor/lstm/preprocessingpipeline/NormalizePipe.java @@ -16,25 +16,26 @@ public NormalizePipe(HyperParameters hyper) { @Override public Object execute(Object input) { try { - if (input instanceof double[][][] inputArray) { - + return switch (input) { + case double[][][] inputArray -> { double[][] trainData = inputArray[0]; double[] targetData = inputArray[1][0]; double[][] normalizedTrainData = normalizeData(trainData, this.hyperParameters); double[] normalizedTargetData = normalizeData(trainData, targetData, this.hyperParameters); - return new double[][][] { normalizedTrainData, { normalizedTargetData } }; + yield new double[][][] { normalizedTrainData, { normalizedTargetData } }; + } - } else if (input instanceof double[][] inputArray) { - return normalizeData(inputArray, this.hyperParameters); + case double[][] inputArray // + -> normalizeData(inputArray, this.hyperParameters); - } else if (input instanceof double[] inputArray) { - return standardize(inputArray, this.hyperParameters); + case double[] inputArray // + -> standardize(inputArray, this.hyperParameters); - } else { - throw new IllegalArgumentException("Illegal Argument encountered during normalization"); - } + default // + -> throw new IllegalArgumentException("Illegal Argument encountered during normalization"); + }; } catch (Exception e) { throw new RuntimeException("Illegal Argument encountered during normalization"); } diff --git a/io.openems.edge.predictor.lstm/src/io/openems/edge/predictor/lstm/preprocessingpipeline/RemoveNegativesPipe.java b/io.openems.edge.predictor.lstm/src/io/openems/edge/predictor/lstm/preprocessingpipeline/RemoveNegativesPipe.java index 10f9d492f27..1498a30765d 100644 --- a/io.openems.edge.predictor.lstm/src/io/openems/edge/predictor/lstm/preprocessingpipeline/RemoveNegativesPipe.java +++ b/io.openems.edge.predictor.lstm/src/io/openems/edge/predictor/lstm/preprocessingpipeline/RemoveNegativesPipe.java @@ -6,7 +6,7 @@ public class RemoveNegativesPipe implements Stage { @Override public Object execute(Object input) { - return (input instanceof double[] in) // + return input instanceof double[] in // ? removeNegatives(in) // : new IllegalArgumentException("Input must be an instance of double[]"); } diff --git a/io.openems.edge.predictor.lstm/src/io/openems/edge/predictor/lstm/preprocessingpipeline/ReverseNormalizationPipe.java b/io.openems.edge.predictor.lstm/src/io/openems/edge/predictor/lstm/preprocessingpipeline/ReverseNormalizationPipe.java index 210774461c1..48f2c7895aa 100644 --- a/io.openems.edge.predictor.lstm/src/io/openems/edge/predictor/lstm/preprocessingpipeline/ReverseNormalizationPipe.java +++ b/io.openems.edge.predictor.lstm/src/io/openems/edge/predictor/lstm/preprocessingpipeline/ReverseNormalizationPipe.java @@ -1,7 +1,8 @@ package io.openems.edge.predictor.lstm.preprocessingpipeline; +import static io.openems.edge.predictor.lstm.preprocessing.DataModification.reverseStandardize; + import io.openems.edge.predictor.lstm.common.HyperParameters; -import io.openems.edge.predictor.lstm.preprocessing.DataModification; public class ReverseNormalizationPipe implements Stage { private Object mean; @@ -17,28 +18,31 @@ public ReverseNormalizationPipe(Object average, Object std, HyperParameters hyp) @Override public Object execute(Object input) { try { - if (input instanceof double[] inputArray) { + return switch (input) { + case double[] inputArray -> { if (this.mean instanceof double[] meanArray // && this.stdDeviation instanceof double[] sdArray) { - return DataModification.reverseStandrize(inputArray, meanArray, sdArray, this.hyperParameters); + yield reverseStandardize(inputArray, meanArray, sdArray, this.hyperParameters); } else if (this.mean instanceof Double meanValue // && this.stdDeviation instanceof Double sdValue) { - return DataModification.reverseStandrize(inputArray, meanValue, sdValue, this.hyperParameters); + yield reverseStandardize(inputArray, meanValue, sdValue, this.hyperParameters); } else { throw new IllegalArgumentException("Input must be an instance of double[]"); } + } - } else if (input instanceof Double inputArray) { + case Double inputArray -> { double mean = (double) this.mean; double std = (double) this.stdDeviation; - return DataModification.reverseStandrize(inputArray, mean, std, this.hyperParameters); - - } else { - throw new IllegalArgumentException("Input must be an instance of double[]"); + yield reverseStandardize(inputArray, mean, std, this.hyperParameters); } + default // + -> throw new IllegalArgumentException("Input must be an instance of double[]"); + }; + } catch (Exception e) { throw new RuntimeException("Error processing input data", e); } diff --git a/io.openems.edge.predictor.lstm/src/io/openems/edge/predictor/lstm/preprocessingpipeline/ReverseScalingPipe.java b/io.openems.edge.predictor.lstm/src/io/openems/edge/predictor/lstm/preprocessingpipeline/ReverseScalingPipe.java index 065562807c8..380aa6884e4 100644 --- a/io.openems.edge.predictor.lstm/src/io/openems/edge/predictor/lstm/preprocessingpipeline/ReverseScalingPipe.java +++ b/io.openems.edge.predictor.lstm/src/io/openems/edge/predictor/lstm/preprocessingpipeline/ReverseScalingPipe.java @@ -13,7 +13,7 @@ public ReverseScalingPipe(HyperParameters hyperParameters) { @Override public Object execute(Object input) { - return (input instanceof double[] inputArray) // + return input instanceof double[] inputArray // ? scaleBack(inputArray, this.hype.getScalingMin(), this.hype.getScalingMax()) // : new IllegalArgumentException("Input must be an instance of double[]"); } diff --git a/io.openems.edge.predictor.lstm/src/io/openems/edge/predictor/lstm/preprocessingpipeline/ScalingPipe.java b/io.openems.edge.predictor.lstm/src/io/openems/edge/predictor/lstm/preprocessingpipeline/ScalingPipe.java index 7f958983bc1..9dac330ae18 100644 --- a/io.openems.edge.predictor.lstm/src/io/openems/edge/predictor/lstm/preprocessingpipeline/ScalingPipe.java +++ b/io.openems.edge.predictor.lstm/src/io/openems/edge/predictor/lstm/preprocessingpipeline/ScalingPipe.java @@ -17,15 +17,14 @@ public ScalingPipe(HyperParameters hyperParameters) { @Override public Object execute(Object value) { - if (value instanceof double[][] v) { - return this.scaleSecondCase(v); - - } else if (value instanceof double[] v) { - return (this.scaleFirstCase(v)); - - } else { - throw new IllegalArgumentException("Input must be an instance of double[]"); - } + return switch (value) { + case double[][] v // + -> this.scaleSecondCase(v); + case double[] v // + -> this.scaleFirstCase(v); + default // + -> throw new IllegalArgumentException("Input must be an instance of double[]"); + }; } /** diff --git a/io.openems.edge.predictor.persistencemodel/test/io/openems/edge/predictor/persistencemodel/PredictorPersistenceModelImplTest.java b/io.openems.edge.predictor.persistencemodel/test/io/openems/edge/predictor/persistencemodel/PredictorPersistenceModelImplTest.java index 665664e9f7d..0090e9e4a33 100644 --- a/io.openems.edge.predictor.persistencemodel/test/io/openems/edge/predictor/persistencemodel/PredictorPersistenceModelImplTest.java +++ b/io.openems.edge.predictor.persistencemodel/test/io/openems/edge/predictor/persistencemodel/PredictorPersistenceModelImplTest.java @@ -1,6 +1,6 @@ package io.openems.edge.predictor.persistencemodel; -import static io.openems.edge.common.test.TestUtils.createDummyClock; +import static io.openems.common.test.TestUtils.createDummyClock; import static io.openems.edge.predictor.api.prediction.LogVerbosity.NONE; import static io.openems.edge.predictor.api.prediction.Prediction.EMPTY_PREDICTION; import static java.time.temporal.ChronoUnit.HOURS; diff --git a/io.openems.edge.scheduler.allalphabetically/src/io/openems/edge/scheduler/allalphabetically/SchedulerAllAlphabeticallyImpl.java b/io.openems.edge.scheduler.allalphabetically/src/io/openems/edge/scheduler/allalphabetically/SchedulerAllAlphabeticallyImpl.java index aaa2f05c9ae..bc7b98d9b6f 100644 --- a/io.openems.edge.scheduler.allalphabetically/src/io/openems/edge/scheduler/allalphabetically/SchedulerAllAlphabeticallyImpl.java +++ b/io.openems.edge.scheduler.allalphabetically/src/io/openems/edge/scheduler/allalphabetically/SchedulerAllAlphabeticallyImpl.java @@ -59,8 +59,8 @@ public LinkedHashSet getControllers() { var result = new LinkedHashSet(); // add sorted controllers - for (String id : this.config.controllers_ids()) { - if (id.equals("")) { + for (var id : this.config.controllers_ids()) { + if (id.isBlank()) { continue; } result.add(id); @@ -68,7 +68,7 @@ public LinkedHashSet getControllers() { // add remaining controllers this.componentManager.getEnabledComponents().stream() // - .filter(c -> c instanceof Controller) // + .filter(Controller.class::isInstance) // .sorted(Comparator.comparing(OpenemsComponent::id)) // .forEach(c -> result.add(c.id())); diff --git a/io.openems.edge.scheduler.daily/test/io/openems/edge/scheduler/daily/SchedulerDailyImplTest.java b/io.openems.edge.scheduler.daily/test/io/openems/edge/scheduler/daily/SchedulerDailyImplTest.java index f992c074e95..54bbbfef1a2 100644 --- a/io.openems.edge.scheduler.daily/test/io/openems/edge/scheduler/daily/SchedulerDailyImplTest.java +++ b/io.openems.edge.scheduler.daily/test/io/openems/edge/scheduler/daily/SchedulerDailyImplTest.java @@ -1,8 +1,8 @@ package io.openems.edge.scheduler.daily; +import static io.openems.common.test.TestUtils.createDummyClock; import static io.openems.common.utils.JsonUtils.buildJsonArray; import static io.openems.common.utils.JsonUtils.buildJsonObject; -import static io.openems.edge.common.test.TestUtils.createDummyClock; import static java.time.temporal.ChronoUnit.HOURS; import static org.junit.Assert.assertEquals; diff --git a/io.openems.edge.thermometer.api/src/io/openems/edge/thermometer/test/AbstractDummyThermometer.java b/io.openems.edge.thermometer.api/src/io/openems/edge/thermometer/test/AbstractDummyThermometer.java new file mode 100644 index 00000000000..f72645d5271 --- /dev/null +++ b/io.openems.edge.thermometer.api/src/io/openems/edge/thermometer/test/AbstractDummyThermometer.java @@ -0,0 +1,26 @@ +package io.openems.edge.thermometer.test; + +import static io.openems.edge.common.test.TestUtils.withValue; + +import io.openems.edge.common.test.AbstractDummyOpenemsComponent; +import io.openems.edge.thermometer.api.Thermometer; + +public abstract class AbstractDummyThermometer> + extends AbstractDummyOpenemsComponent implements Thermometer { + + protected AbstractDummyThermometer(String id, io.openems.edge.common.channel.ChannelId[] firstInitialChannelIds, + io.openems.edge.common.channel.ChannelId[]... furtherInitialChannelIds) { + super(id, firstInitialChannelIds, furtherInitialChannelIds); + } + + /** + * Set {@link Thermometer.ChannelId#TEMPERATURE}. + * + * @param value the value + * @return myself + */ + public final SELF withTemperature(int value) { + withValue(this, Thermometer.ChannelId.TEMPERATURE, value); + return this.self(); + } +} diff --git a/io.openems.edge.thermometer.api/src/io/openems/edge/thermometer/test/DummyThermometer.java b/io.openems.edge.thermometer.api/src/io/openems/edge/thermometer/test/DummyThermometer.java new file mode 100644 index 00000000000..712183bc675 --- /dev/null +++ b/io.openems.edge.thermometer.api/src/io/openems/edge/thermometer/test/DummyThermometer.java @@ -0,0 +1,23 @@ +package io.openems.edge.thermometer.test; + +import io.openems.edge.common.component.OpenemsComponent; +import io.openems.edge.thermometer.api.Thermometer; + +/** + * Provides a simple, simulated {@link Thermometer} component that can be used + * together with the OpenEMS Component test framework. + */ +public class DummyThermometer extends AbstractDummyThermometer + implements Thermometer, OpenemsComponent { + + public DummyThermometer(String id) { + super(id, // + OpenemsComponent.ChannelId.values(), // + Thermometer.ChannelId.values()); + } + + @Override + protected final DummyThermometer self() { + return this; + } +} diff --git a/io.openems.edge.thermometer.api/src/io/openems/edge/thermometer/test/package-info.java b/io.openems.edge.thermometer.api/src/io/openems/edge/thermometer/test/package-info.java new file mode 100644 index 00000000000..7406f956cc7 --- /dev/null +++ b/io.openems.edge.thermometer.api/src/io/openems/edge/thermometer/test/package-info.java @@ -0,0 +1,3 @@ +@org.osgi.annotation.versioning.Version("1.0.0") +@org.osgi.annotation.bundle.Export +package io.openems.edge.thermometer.test; diff --git a/io.openems.edge.timeofusetariff.api/test/io/openems/edge/timeofusetariff/api/utils/ExchangeRateApiTest.java b/io.openems.edge.timeofusetariff.api/test/io/openems/edge/timeofusetariff/api/utils/ExchangeRateApiTest.java index 7d0ee419286..8c167f54485 100644 --- a/io.openems.edge.timeofusetariff.api/test/io/openems/edge/timeofusetariff/api/utils/ExchangeRateApiTest.java +++ b/io.openems.edge.timeofusetariff.api/test/io/openems/edge/timeofusetariff/api/utils/ExchangeRateApiTest.java @@ -62,7 +62,8 @@ public class ExchangeRateApiTest { // Remove '@Ignore' tag to test this API call. @Ignore @Test - public void testGetExchangeRate() throws IOException, OpenemsNamedException, ParserConfigurationException, SAXException { + public void testGetExchangeRate() + throws IOException, OpenemsNamedException, ParserConfigurationException, SAXException { var rate = getExchangeRate("EUR", Currency.SEK); System.out.println(rate); } diff --git a/io.openems.edge.timeofusetariff.entsoe/test/io/openems/edge/timeofusetariff/entsoe/ParserTest.java b/io.openems.edge.timeofusetariff.entsoe/test/io/openems/edge/timeofusetariff/entsoe/ParserTest.java index c7268b00ed5..d570f9ee9f9 100644 --- a/io.openems.edge.timeofusetariff.entsoe/test/io/openems/edge/timeofusetariff/entsoe/ParserTest.java +++ b/io.openems.edge.timeofusetariff.entsoe/test/io/openems/edge/timeofusetariff/entsoe/ParserTest.java @@ -1,5 +1,6 @@ package io.openems.edge.timeofusetariff.entsoe; +import static io.openems.common.test.TestUtils.createDummyClock; import static io.openems.edge.timeofusetariff.entsoe.Utils.getDuration; import static io.openems.edge.timeofusetariff.entsoe.Utils.parseCurrency; import static io.openems.edge.timeofusetariff.entsoe.Utils.parsePrices; @@ -13,7 +14,6 @@ import com.google.common.collect.ImmutableTable; import io.openems.edge.common.currency.Currency; -import io.openems.edge.common.test.TestUtils; public class ParserTest { @@ -838,7 +838,7 @@ public void testParseCurrency() throws Exception { @Test public void testPreferredResolutionExists() { - var clock = TestUtils.createDummyClock(); + final var clock = createDummyClock(); // Create sample data var table = ImmutableTable.builder() .put(Duration.ofMinutes(15), ZonedDateTime.now(clock), 100.0) diff --git a/io.openems.edge.timeofusetariff.groupe/src/io/openems/edge/timeofusetariff/groupe/TimeOfUseTariffGroupeImpl.java b/io.openems.edge.timeofusetariff.groupe/src/io/openems/edge/timeofusetariff/groupe/TimeOfUseTariffGroupeImpl.java index 3a644d09fd9..77f7f344dc7 100644 --- a/io.openems.edge.timeofusetariff.groupe/src/io/openems/edge/timeofusetariff/groupe/TimeOfUseTariffGroupeImpl.java +++ b/io.openems.edge.timeofusetariff.groupe/src/io/openems/edge/timeofusetariff/groupe/TimeOfUseTariffGroupeImpl.java @@ -166,10 +166,10 @@ private void handleEndpointResponse(HttpResponse response) throws Openem } private void handleEndpointError(HttpError error) { - var httpStatusCode = INTERNAL_ERROR; - if (error instanceof HttpError.ResponseError re) { - httpStatusCode = re.status.code(); - } + var httpStatusCode = switch (error) { + case HttpError.ResponseError re -> re.status.code(); + default -> INTERNAL_ERROR; + }; this.channel(TimeOfUseTariffGroupe.ChannelId.HTTP_STATUS_CODE).setNextValue(httpStatusCode); this.log.error(error.getMessage(), error); diff --git a/io.openems.edge.timeofusetariff.groupe/test/io/openems/edge/timeofusetariff/groupe/TimeOfUseTariffGroupeImplTest.java b/io.openems.edge.timeofusetariff.groupe/test/io/openems/edge/timeofusetariff/groupe/TimeOfUseTariffGroupeImplTest.java index ebd8707bfb8..e0e116e20df 100644 --- a/io.openems.edge.timeofusetariff.groupe/test/io/openems/edge/timeofusetariff/groupe/TimeOfUseTariffGroupeImplTest.java +++ b/io.openems.edge.timeofusetariff.groupe/test/io/openems/edge/timeofusetariff/groupe/TimeOfUseTariffGroupeImplTest.java @@ -1,7 +1,7 @@ package io.openems.edge.timeofusetariff.groupe; +import static io.openems.common.test.TestUtils.createDummyClock; import static io.openems.edge.common.currency.Currency.CHF; -import static io.openems.edge.common.test.TestUtils.createDummyClock; import static io.openems.edge.timeofusetariff.groupe.TimeOfUseTariffGroupeImpl.parsePrices; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; diff --git a/io.openems.edge.timeofusetariff.hassfurt/src/io/openems/edge/timeofusetariff/hassfurt/Config.java b/io.openems.edge.timeofusetariff.hassfurt/src/io/openems/edge/timeofusetariff/hassfurt/Config.java index 1875b929bd1..79612fa199e 100644 --- a/io.openems.edge.timeofusetariff.hassfurt/src/io/openems/edge/timeofusetariff/hassfurt/Config.java +++ b/io.openems.edge.timeofusetariff.hassfurt/src/io/openems/edge/timeofusetariff/hassfurt/Config.java @@ -16,7 +16,7 @@ @AttributeDefinition(name = "Is enabled?", description = "Is this Component enabled?") boolean enabled() default true; - + @AttributeDefinition(name = "Tariff Type", description = "Tariff type that the customer has subscribed to") TariffType tariffType() default TariffType.STROM_FLEX; diff --git a/io.openems.edge.timeofusetariff.hassfurt/src/io/openems/edge/timeofusetariff/hassfurt/TariffType.java b/io.openems.edge.timeofusetariff.hassfurt/src/io/openems/edge/timeofusetariff/hassfurt/TariffType.java index 77a9e13618a..92ca11309ba 100644 --- a/io.openems.edge.timeofusetariff.hassfurt/src/io/openems/edge/timeofusetariff/hassfurt/TariffType.java +++ b/io.openems.edge.timeofusetariff.hassfurt/src/io/openems/edge/timeofusetariff/hassfurt/TariffType.java @@ -5,7 +5,7 @@ public enum TariffType { * haStrom Flex. */ STROM_FLEX, // - + /** * haStrom Flex Pro. */ diff --git a/io.openems.edge.timeofusetariff.hassfurt/src/io/openems/edge/timeofusetariff/hassfurt/TimeOfUseTariffHassfurtImpl.java b/io.openems.edge.timeofusetariff.hassfurt/src/io/openems/edge/timeofusetariff/hassfurt/TimeOfUseTariffHassfurtImpl.java index 322f2081ff4..0090a0a324c 100644 --- a/io.openems.edge.timeofusetariff.hassfurt/src/io/openems/edge/timeofusetariff/hassfurt/TimeOfUseTariffHassfurtImpl.java +++ b/io.openems.edge.timeofusetariff.hassfurt/src/io/openems/edge/timeofusetariff/hassfurt/TimeOfUseTariffHassfurtImpl.java @@ -184,10 +184,10 @@ private void handleEndpointResponse(HttpResponse response) throws Openem } private void handleEndpointError(HttpError error) { - var httpStatusCode = INTERNAL_ERROR; - if (error instanceof HttpError.ResponseError re) { - httpStatusCode = re.status.code(); - } + var httpStatusCode = switch (error) { + case HttpError.ResponseError re -> re.status.code(); + default -> INTERNAL_ERROR; + }; this.channel(TimeOfUseTariffHassfurt.ChannelId.HTTP_STATUS_CODE).setNextValue(httpStatusCode); this.log.error(error.getMessage(), error); diff --git a/io.openems.edge.timeofusetariff.hassfurt/test/io/openems/edge/timeofusetariff/hassfurt/TimeOfUseTariffHassfurtImplTest.java b/io.openems.edge.timeofusetariff.hassfurt/test/io/openems/edge/timeofusetariff/hassfurt/TimeOfUseTariffHassfurtImplTest.java index 041b9e6ae0e..52797a738b5 100644 --- a/io.openems.edge.timeofusetariff.hassfurt/test/io/openems/edge/timeofusetariff/hassfurt/TimeOfUseTariffHassfurtImplTest.java +++ b/io.openems.edge.timeofusetariff.hassfurt/test/io/openems/edge/timeofusetariff/hassfurt/TimeOfUseTariffHassfurtImplTest.java @@ -1,6 +1,6 @@ package io.openems.edge.timeofusetariff.hassfurt; -import static io.openems.edge.common.test.TestUtils.createDummyClock; +import static io.openems.common.test.TestUtils.createDummyClock; import static io.openems.edge.timeofusetariff.hassfurt.TimeOfUseTariffHassfurtImpl.parsePrices; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; diff --git a/io.openems.edge.timeofusetariff.rabotcharge/src/io/openems/edge/timeofusetariff/rabotcharge/TimeOfUseTariffRabotChargeImpl.java b/io.openems.edge.timeofusetariff.rabotcharge/src/io/openems/edge/timeofusetariff/rabotcharge/TimeOfUseTariffRabotChargeImpl.java index 37afa08b64d..7ef68ad176a 100644 --- a/io.openems.edge.timeofusetariff.rabotcharge/src/io/openems/edge/timeofusetariff/rabotcharge/TimeOfUseTariffRabotChargeImpl.java +++ b/io.openems.edge.timeofusetariff.rabotcharge/src/io/openems/edge/timeofusetariff/rabotcharge/TimeOfUseTariffRabotChargeImpl.java @@ -1,10 +1,12 @@ package io.openems.edge.timeofusetariff.rabotcharge; +import static io.openems.common.types.HttpStatus.UNAUTHORIZED; import static io.openems.common.utils.JsonUtils.getAsDouble; import static io.openems.common.utils.JsonUtils.getAsJsonArray; import static io.openems.common.utils.JsonUtils.getAsString; import static io.openems.common.utils.JsonUtils.parseToJsonObject; import static io.openems.edge.timeofusetariff.api.utils.TimeOfUseTariffUtils.generateDebugLog; +import static java.time.temporal.ChronoUnit.SECONDS; import java.time.Clock; import java.time.Duration; @@ -150,8 +152,11 @@ private CompletableFuture refreshToken() { tokenFuture.complete(token); }, error -> { this.log.error("Unable to get token", error); - this._setHttpStatusCode( - error instanceof HttpError.ResponseError r ? r.status.code() : INTERNAL_ERROR); + this._setHttpStatusCode(// + switch (error) { + case HttpError.ResponseError re -> re.status.code(); + default -> INTERNAL_ERROR; + }); this._setStatusAuthenticationFailed(true); }); @@ -176,8 +181,11 @@ private void scheduleRequest() { }).whenComplete((priceComponent, error) -> { if (priceComponent == null) { this.log.error("Unable to get price components", error); - this._setHttpStatusCode( - error instanceof HttpError.ResponseError r ? r.status.code() : INTERNAL_ERROR); + this._setHttpStatusCode(// + switch (error) { + case HttpError.ResponseError re -> re.status.code(); + default -> INTERNAL_ERROR; + }); return; } this._setHttpStatusCode(HttpStatus.OK.code()); @@ -210,23 +218,24 @@ public Delay onFirstRunDelay() { @Override public Delay onSuccessRunDelay(HttpResponse result) { return DelayTimeProviderChain.fixedAtEveryFull(this.clock, DurationUnit.ofDays(1)) // - .plusRandomDelay(60, ChronoUnit.SECONDS) // + .plusRandomDelay(60, SECONDS) // .getDelay(); } @Override public Delay onErrorRunDelay(HttpError error) { - if (error instanceof HttpError.ResponseError r && r.status.equals(HttpStatus.UNAUTHORIZED)) { + return switch (error) { + case HttpError.ResponseError r when r.status.equals(UNAUTHORIZED) -> { // reschedule after authenticated TimeOfUseTariffRabotChargeImpl.this.scheduleRequest(); - return Delay.infinite(); + yield Delay.infinite(); } - - return DelayTimeProviderChain.fixedDelay(Duration.ofHours(1))// - .plusRandomDelay(60, ChronoUnit.SECONDS) // - .getDelay(); + default // + -> DelayTimeProviderChain.fixedDelay(Duration.ofHours(1))// + .plusRandomDelay(60, SECONDS) // + .getDelay(); + }; } - } private Endpoint createRabotChargeEndpoint(String accessToken) { @@ -257,15 +266,14 @@ private void handleEndpointResponse(HttpResponse response, PriceComponen } private void handleEndpointError(HttpError error) { - var httpStatusCode = INTERNAL_ERROR; - if (error instanceof HttpError.ResponseError re) { - httpStatusCode = re.status.code(); - - this._setStatusAuthenticationFailed(httpStatusCode == HttpStatus.UNAUTHORIZED.code()); - this._setStatusBadRequest(httpStatusCode == HttpStatus.BAD_REQUEST.code()); - } - - this.channel(TimeOfUseTariffRabotCharge.ChannelId.HTTP_STATUS_CODE).setNextValue(httpStatusCode); + var httpStatusCode = switch (error) { + case HttpError.ResponseError re -> re.status.code(); + default -> INTERNAL_ERROR; + }; + + this._setHttpStatusCode(httpStatusCode); + this._setStatusAuthenticationFailed(httpStatusCode == UNAUTHORIZED.code()); + this._setStatusBadRequest(httpStatusCode == HttpStatus.BAD_REQUEST.code()); this.log.error(error.getMessage(), error); } diff --git a/io.openems.edge.timeofusetariff.rabotcharge/test/io/openems/edge/timeofusetariff/rabotcharge/TimeOfUseTariffRabotChargeImplTest.java b/io.openems.edge.timeofusetariff.rabotcharge/test/io/openems/edge/timeofusetariff/rabotcharge/TimeOfUseTariffRabotChargeImplTest.java index adc60697492..df7f605f959 100644 --- a/io.openems.edge.timeofusetariff.rabotcharge/test/io/openems/edge/timeofusetariff/rabotcharge/TimeOfUseTariffRabotChargeImplTest.java +++ b/io.openems.edge.timeofusetariff.rabotcharge/test/io/openems/edge/timeofusetariff/rabotcharge/TimeOfUseTariffRabotChargeImplTest.java @@ -1,6 +1,13 @@ package io.openems.edge.timeofusetariff.rabotcharge; -import static io.openems.edge.common.test.TestUtils.createDummyClock; +import static io.openems.common.test.TestUtils.createDummyClock; +import static io.openems.edge.bridge.http.dummy.DummyBridgeHttpFactory.cycleSubscriber; +import static io.openems.edge.bridge.http.dummy.DummyBridgeHttpFactory.dummyBridgeHttpExecutor; +import static io.openems.edge.bridge.http.dummy.DummyBridgeHttpFactory.dummyEndpointFetcher; +import static io.openems.edge.bridge.http.dummy.DummyBridgeHttpFactory.ofBridgeImpl; +import static io.openems.edge.timeofusetariff.rabotcharge.TimeOfUseTariffRabotChargeImpl.RABOT_CHARGE_API_URL; +import static io.openems.edge.timeofusetariff.rabotcharge.TimeOfUseTariffRabotChargeImpl.RABOT_CHARGE_PRIZE_COMPONENT_URL; +import static io.openems.edge.timeofusetariff.rabotcharge.TimeOfUseTariffRabotChargeImpl.RABOT_CHARGE_TOKEN_URL; import static io.openems.edge.timeofusetariff.rabotcharge.TimeOfUseTariffRabotChargeImpl.parsePrices; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -15,7 +22,6 @@ import io.openems.common.utils.JsonUtils; import io.openems.edge.bridge.http.api.HttpError; import io.openems.edge.bridge.http.api.HttpResponse; -import io.openems.edge.bridge.http.dummy.DummyBridgeHttpFactory; import io.openems.edge.common.test.AbstractComponentTest.TestCase; import io.openems.edge.common.test.ComponentTest; import io.openems.edge.common.test.DummyComponentManager; @@ -95,21 +101,20 @@ public class TimeOfUseTariffRabotChargeImplTest { public void test() throws Exception { final var clock = createDummyClock(); - final var endpointFetcher = DummyBridgeHttpFactory.dummyEndpointFetcher(); + final var endpointFetcher = dummyEndpointFetcher(); endpointFetcher.addEndpointHandler(endpoint -> { - if (endpoint.url().equals(TimeOfUseTariffRabotChargeImpl.RABOT_CHARGE_TOKEN_URL.toEncodedString())) { + if (endpoint.url().equals(RABOT_CHARGE_TOKEN_URL.toEncodedString())) { return HttpResponse.ok(JsonUtils.buildJsonObject() // .addProperty("access_token", "FJAWognawn") // .build().toString()); } - if (endpoint.url().equals(TimeOfUseTariffRabotChargeImpl.RABOT_CHARGE_API_URL.toEncodedString())) { + if (endpoint.url().equals(RABOT_CHARGE_API_URL.toEncodedString())) { return HttpResponse.ok(DUMMY_PRICES); } - if (endpoint.url() - .startsWith(TimeOfUseTariffRabotChargeImpl.RABOT_CHARGE_PRIZE_COMPONENT_URL.toEncodedString())) { + if (endpoint.url().startsWith(RABOT_CHARGE_PRIZE_COMPONENT_URL.toEncodedString())) { return HttpResponse.ok(JsonUtils.buildJsonObject() // .addProperty("taxAndFeeKwHPrice", 3.44) // .addProperty("gridFeeKwHPrice", 7.89) // @@ -120,10 +125,10 @@ public void test() throws Exception { throw HttpError.ResponseError.notFound(); }); - final var executor = DummyBridgeHttpFactory.dummyBridgeHttpExecutor(); + final var executor = dummyBridgeHttpExecutor(); - final var factory = DummyBridgeHttpFactory.ofBridgeImpl(// - () -> DummyBridgeHttpFactory.cycleSubscriber(), // + final var factory = ofBridgeImpl(// + () -> cycleSubscriber(), // () -> endpointFetcher, // () -> executor // ); diff --git a/io.openems.edge.timeofusetariff.swisspower/src/io/openems/edge/timeofusetariff/swisspower/TimeOfUseTariffSwisspowerImpl.java b/io.openems.edge.timeofusetariff.swisspower/src/io/openems/edge/timeofusetariff/swisspower/TimeOfUseTariffSwisspowerImpl.java index 4fd7c4a7b82..edc0f145d8f 100644 --- a/io.openems.edge.timeofusetariff.swisspower/src/io/openems/edge/timeofusetariff/swisspower/TimeOfUseTariffSwisspowerImpl.java +++ b/io.openems.edge.timeofusetariff.swisspower/src/io/openems/edge/timeofusetariff/swisspower/TimeOfUseTariffSwisspowerImpl.java @@ -197,11 +197,13 @@ private void handleEndpointResponse(HttpResponse response) throws Openem } private void handleEndpointError(HttpError error) { - var httpStatusCode = (error instanceof HttpError.ResponseError re) ? re.status.code() : INTERNAL_ERROR; - var serverError = (httpStatusCode == SERVER_ERROR_CODE); - var badRequest = (httpStatusCode == BAD_REQUEST_ERROR_CODE); - var timeoutError = (error instanceof HttpError.UnknownError e - && e.getCause() instanceof SocketTimeoutException); + var httpStatusCode = switch (error) { + case HttpError.ResponseError re -> re.status.code(); + default -> INTERNAL_ERROR; + }; + var serverError = httpStatusCode == SERVER_ERROR_CODE; + var badRequest = httpStatusCode == BAD_REQUEST_ERROR_CODE; + var timeoutError = error instanceof HttpError.UnknownError e && e.getCause() instanceof SocketTimeoutException; this.setChannelValues(httpStatusCode, serverError, badRequest, timeoutError); this.log.error("HTTP Error [{}]: {}", httpStatusCode, error.getMessage()); diff --git a/io.openems.edge.timeofusetariff.swisspower/test/io/openems/edge/timeofusetariff/swisspower/TimeOfUseTariffSwisspowerImplTest.java b/io.openems.edge.timeofusetariff.swisspower/test/io/openems/edge/timeofusetariff/swisspower/TimeOfUseTariffSwisspowerImplTest.java index da9f93d852b..d859b6dd77b 100644 --- a/io.openems.edge.timeofusetariff.swisspower/test/io/openems/edge/timeofusetariff/swisspower/TimeOfUseTariffSwisspowerImplTest.java +++ b/io.openems.edge.timeofusetariff.swisspower/test/io/openems/edge/timeofusetariff/swisspower/TimeOfUseTariffSwisspowerImplTest.java @@ -1,7 +1,8 @@ package io.openems.edge.timeofusetariff.swisspower; +import static io.openems.common.test.TestUtils.createDummyClock; +import static io.openems.edge.bridge.http.dummy.DummyBridgeHttpFactory.ofDummyBridge; import static io.openems.edge.common.currency.Currency.EUR; -import static io.openems.edge.common.test.TestUtils.createDummyClock; import static io.openems.edge.timeofusetariff.swisspower.TimeOfUseTariffSwisspowerImpl.parsePrices; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -9,7 +10,6 @@ import org.junit.Test; import io.openems.common.exceptions.OpenemsError.OpenemsNamedException; -import io.openems.edge.bridge.http.dummy.DummyBridgeHttpFactory; import io.openems.edge.common.test.ComponentTest; import io.openems.edge.common.test.DummyComponentManager; import io.openems.edge.common.test.DummyMeta; @@ -200,7 +200,7 @@ public void test() throws Exception { var dummyMeta = new DummyMeta("foo0") // .withCurrency(EUR); new ComponentTest(swissPower) // - .addReference("httpBridgeFactory", DummyBridgeHttpFactory.ofDummyBridge()) // + .addReference("httpBridgeFactory", ofDummyBridge()) // .addReference("meta", dummyMeta) // .addReference("componentManager", new DummyComponentManager(clock)) // .activate(MyConfig.create() // diff --git a/io.openems.shared.influxdb/src/io/openems/shared/influxdb/proxy/FluxProxy.java b/io.openems.shared.influxdb/src/io/openems/shared/influxdb/proxy/FluxProxy.java index f0039e1ad1d..112d07be0bf 100644 --- a/io.openems.shared.influxdb/src/io/openems/shared/influxdb/proxy/FluxProxy.java +++ b/io.openems.shared.influxdb/src/io/openems/shared/influxdb/proxy/FluxProxy.java @@ -1,5 +1,7 @@ package io.openems.shared.influxdb.proxy; +import static io.openems.common.utils.CollectorUtils.toDoubleMap; + import java.time.ZonedDateTime; import java.time.temporal.ChronoUnit; import java.time.temporal.TemporalAdjusters; @@ -25,7 +27,6 @@ import io.openems.common.exceptions.OpenemsException; import io.openems.common.timedata.Resolution; import io.openems.common.types.ChannelAddress; -import io.openems.common.utils.CollectorUtils; import io.openems.shared.influxdb.InfluxConnector.InfluxConnection; /** @@ -327,14 +328,14 @@ private static SortedMap> timestamp = resolution.revertInfluxDbOffset(timestamp); var valueObj = record.getValue(); - final JsonElement value; - if (valueObj == null) { - value = JsonNull.INSTANCE; - } else if (valueObj instanceof Number) { - value = new JsonPrimitive((Number) valueObj); - } else { - value = new JsonPrimitive(valueObj.toString()); - } + var value = switch (valueObj) { + case null // + -> JsonNull.INSTANCE; + case Number n // + -> new JsonPrimitive(n); + default // + -> new JsonPrimitive(valueObj.toString()); + }; var channelAddresss = ChannelAddress.fromString(record.getField()); @@ -367,21 +368,21 @@ private static SortedMap convertHistoricEnergyResul for (FluxRecord record : fluxTable.getRecords()) { var valueObj = record.getValue(); - final JsonElement value; - if (valueObj == null) { - value = JsonNull.INSTANCE; - } else if (valueObj instanceof Number) { - var number = (Number) valueObj; + var value = switch (valueObj) { + case null // + -> JsonNull.INSTANCE; + case Number number -> { if (number.intValue() < 0) { // do not consider negative values LOG.warn("Got negative Energy value [" + number + "] for query: " + query); - value = JsonNull.INSTANCE; + yield JsonNull.INSTANCE; } else { - value = new JsonPrimitive(number); + yield new JsonPrimitive(number); } - } else { - value = new JsonPrimitive(valueObj.toString()); } + default // + -> new JsonPrimitive(valueObj.toString()); + }; var channelAddresss = ChannelAddress.fromString(record.getField()); @@ -421,15 +422,14 @@ private static SortedMap convertFirstValueBeforeQue for (FluxRecord record : fluxTable.getRecords()) { var valueObj = record.getValue(); - JsonElement value; - - if (valueObj == null) { - value = JsonNull.INSTANCE; - } else if (valueObj instanceof Number) { - value = new JsonPrimitive((Number) valueObj); - } else { - value = new JsonPrimitive(valueObj.toString()); - } + var value = switch (valueObj) { + case null // + -> JsonNull.INSTANCE; + case Number number // + -> new JsonPrimitive(number); + default // + -> new JsonPrimitive(valueObj.toString()); + }; var channelAddresss = ChannelAddress.fromString(record.getField()); latestValues.put(channelAddresss, value); @@ -447,7 +447,7 @@ private static Map> convertAvailableSinceQueryResult( } return queryResult.stream() // .flatMap(t -> t.getRecords().stream()) // - .collect(CollectorUtils.toDoubleMap(// + .collect(toDoubleMap(// record -> Integer.parseInt((String) record.getValueByKey(tag)), // record -> (String) record.getValueByKey(QueryProxy.CHANNEL_TAG), // record -> (Long) record.getValue()) // diff --git a/io.openems.shared.influxdb/src/io/openems/shared/influxdb/proxy/InfluxQlProxy.java b/io.openems.shared.influxdb/src/io/openems/shared/influxdb/proxy/InfluxQlProxy.java index bdd64fb4cb5..79ee9dc5bea 100644 --- a/io.openems.shared.influxdb/src/io/openems/shared/influxdb/proxy/InfluxQlProxy.java +++ b/io.openems.shared.influxdb/src/io/openems/shared/influxdb/proxy/InfluxQlProxy.java @@ -616,21 +616,16 @@ private static SortedMap> } private static JsonElement convertToJsonElement(Object valueObj) { - if (valueObj == null) { - return JsonNull.INSTANCE; - } - if (valueObj instanceof Number) { - return new JsonPrimitive((Number) valueObj); - } - - final String str; - if (valueObj instanceof String) { - str = (String) valueObj; - } else { - str = valueObj.toString(); - } - - return parseToJsonElement(str); + return switch (valueObj) { + case null // + -> JsonNull.INSTANCE; + case Number n // + -> new JsonPrimitive(n); + case String s // + -> parseToJsonElement(s); + default // + -> parseToJsonElement(valueObj.toString()); + }; } private static SortedMap convertHistoricEnergyResultSingleValueInDay(// @@ -677,20 +672,17 @@ private static SortedMap convertHistoricEnergyResul continue; } var valueObj = record.getValueByKey(column); - final JsonElement value; - if (valueObj == null) { - value = JsonNull.INSTANCE; - } else if (valueObj instanceof Number n) { - value = new JsonPrimitive(n); - } else { - final String str; - if (valueObj instanceof String) { - str = (String) valueObj; - } else { - str = valueObj.toString(); - } - value = parseToJsonElement(str); - } + var value = switch (valueObj) { + case null // + -> JsonNull.INSTANCE; + case Number n // + -> new JsonPrimitive(n); + case String str // + -> parseToJsonElement(str); + default // + -> parseToJsonElement(valueObj.toString()); + }; + try { m.accept(new Pair<>(ChannelAddress.fromString(column), value)); } catch (OpenemsNamedException e) { @@ -730,20 +722,17 @@ private static SortedMap convertHistoricEnergyResul continue; } var valueObj = record.getValueByKey(column); - JsonElement value; - if (valueObj == null) { - value = JsonNull.INSTANCE; - } else if (valueObj instanceof Number) { - value = assertPositive((Number) valueObj, influxEdgeId, channels); - } else { - final String str; - if (valueObj instanceof String) { - str = (String) valueObj; - } else { - str = valueObj.toString(); - } - value = parseToJsonElement(str); - } + var value = switch (valueObj) { + case null // + -> JsonNull.INSTANCE; + case Number n // + -> assertPositive(n, influxEdgeId, channels); + case String s // + -> parseToJsonElement(s); + default // + -> parseToJsonElement(valueObj.toString()); + }; + map.put(ChannelAddress.fromString(column), value); } } diff --git a/ui/.eslintrc.json b/ui/eslint.config.mjs similarity index 56% rename from ui/.eslintrc.json rename to ui/eslint.config.mjs index 94564f9bfc6..4f36917fdfb 100644 --- a/ui/.eslintrc.json +++ b/ui/eslint.config.mjs @@ -1,38 +1,59 @@ -{ - "root": true, - "ignorePatterns": [ - "projects/**/*" - ], - "overrides": [ - { - "files": [ - "*.ts" - ], - "env": { - "browser": true, - "node": true, - "jest": true - }, - "parserOptions": { - "project": [ - "tsconfig.json" - ], - "createDefaultProgram": true - }, - "plugins": [ - "import", - "unused-imports", - "@stylistic", - "check-file" - ], - "extends": [ - "eslint:recommended", - "plugin:@typescript-eslint/recommended", - "plugin:@angular-eslint/recommended", - "plugin:@angular-eslint/template/process-inline-templates", - "plugin:import/recommended" - ], - "rules": { +import unusedImports from "eslint-plugin-unused-imports"; +import stylistic from "@stylistic/eslint-plugin"; +import globals from "globals"; +import path from "node:path"; +import { fileURLToPath } from "node:url"; +import js from "@eslint/js"; +import { FlatCompat } from "@eslint/eslintrc"; +import importPlugin from "eslint-plugin-import"; +import checkFile from "eslint-plugin-check-file"; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); +const compat = new FlatCompat({ + baseDirectory: __dirname, + recommendedConfig: js.configs.recommended, + allConfig: js.configs.all +}); + +export default [{ + "ignores": ["projects/**/*"], +}, ...compat.extends( + "eslint:recommended", + "plugin:@typescript-eslint/recommended", + "plugin:@angular-eslint/recommended", + "plugin:@angular-eslint/template/process-inline-templates", + "plugin:import/recommended" +).map(config => ({ + ...config, + "files": ["**/*.ts"], +})), { + "files": ["**/*.ts"], + + "plugins": { + "unused-imports": unusedImports, + "@stylistic": stylistic, + "import": importPlugin, + "check-file": checkFile, + }, + + "languageOptions": { + "globals": { + ...globals.browser, + ...globals.node, + ...globals.jest, + }, + + "ecmaVersion": 5, + "sourceType": "commonjs", + + "parserOptions": { + "project": ["tsconfig.json"], + "createDefaultProgram": true, + }, + }, + + "rules": { "check-file/filename-naming-convention": [ "off", { @@ -101,7 +122,8 @@ "@typescript-eslint/no-unused-vars": [ "error", { - "args": "none" + "args": "none", + "ignoreRestSiblings": true } ], "@typescript-eslint/no-explicit-any": 0, @@ -126,33 +148,24 @@ "message": "Using 'xdescribe' is not allowed." } ] - }, - "overrides": [ - { - "files": [ - "*.component.ts", - "*.service.ts", - "*.module.ts" - ], - "rules": { - "check-file/filename-naming-convention": "off" - } - } - ], - "settings": { - "import/resolver": { - "typescript": {} - } - } }, - { - "files": [ - "*.html" - ], - "extends": [ - "plugin:@angular-eslint/template/recommended" - ], - "rules": {} + "settings": { + "import/resolver": { + "typescript": {} + } } - ] -} +}, { + "files": ["*.component.ts", "*.service.ts", "*.module.ts"], + "plugins": { + "check-file": checkFile, + }, + "rules": { + "check-file/filename-naming-convention": "off", + }, +}, ...compat.extends("plugin:@angular-eslint/template/recommended").map(config => ({ + ...config, + "files": ["**/*.html"], +})), { + "files": ["**/*.html"], + "rules": {}, +}]; diff --git a/ui/package-lock.json b/ui/package-lock.json index a48a50f5b8b..98259befaa0 100644 --- a/ui/package-lock.json +++ b/ui/package-lock.json @@ -1,12 +1,12 @@ { "name": "openems-ui", - "version": "2025.1.0", + "version": "2025.2.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "openems-ui", - "version": "2025.1.0", + "version": "2025.2.0", "license": "AGPL-3.0", "dependencies": { "@angular/animations": "19.0.5", @@ -17,8 +17,8 @@ "@angular/platform-browser-dynamic": "19.0.5", "@angular/router": "19.0.5", "@angular/service-worker": "19.0.5", - "@awesome-cordova-plugins/core": "^6.13.0", - "@awesome-cordova-plugins/file-opener": "^6.13.0", + "@awesome-cordova-plugins/core": "^6.14.0", + "@awesome-cordova-plugins/file-opener": "^6.14.0", "@capacitor-community/file-opener": "^6.0.1", "@capacitor/android": "^6.2.0", "@capacitor/app": "^6.0.2", @@ -51,9 +51,9 @@ "ngx-spinner": "^17.0.0", "roboto-fontface": "^0.10.0", "rxjs": "~7.8.1", - "swiper": "11.1.15", + "swiper": "11.2.1", "tslib": "^2.8.1", - "uuid": "^11.0.3", + "uuid": "^11.0.5", "zone.js": "~0.15.0" }, "devDependencies": { @@ -73,18 +73,18 @@ "@ionic/angular-toolkit": "^12.1.1", "@ionic/cli": "^7.2.0", "@schematics/angular": "^19.0.6", - "@stylistic/eslint-plugin": "^2.12.1", + "@stylistic/eslint-plugin": "^2.13.0", "@types/jasmine": "~5.1.5", "@types/jasminewd2": "~2.0.13", "@types/json-schema": "^7.0.15", "@types/node": "^20.12.6", - "@types/qs": "^6.9.17", + "@types/qs": "^6.9.18", "@types/range-parser": "^1.2.7", "@types/send": "^0.17.4", "@types/uuid": "^10.0.0", "@typescript-eslint/eslint-plugin": "^8.19.0", "@typescript-eslint/parser": "^8.19.0", - "@typescript-eslint/types": "^8.19.0", + "@typescript-eslint/types": "^8.20.0", "eslint": "^9.17.0", "eslint-import-resolver-typescript": "^3.7.0", "eslint-plugin-check-file": "^2.8.0", @@ -92,6 +92,7 @@ "eslint-plugin-jsdoc": "50.6.1", "eslint-plugin-prefer-arrow": "1.2.3", "eslint-plugin-unused-imports": "^4.1.4", + "globals": "^15.9.0", "jasmine-core": "~5.5.0", "jasmine-spec-reporter": "~7.0.0", "karma": "~6.4.4", @@ -135,19 +136,19 @@ } }, "node_modules/@angular-devkit/build-angular": { - "version": "19.0.6", - "resolved": "https://registry.npmjs.org/@angular-devkit/build-angular/-/build-angular-19.0.6.tgz", - "integrity": "sha512-dWTAsE6BSI8z0xglQdYBdqTBwg1Q+RWE3OrmlGs+520Dcoq/F0Z41Y1F3MiuHuQPdDAIQr88iB0APkIRW4clMg==", + "version": "19.1.5", + "resolved": "https://registry.npmjs.org/@angular-devkit/build-angular/-/build-angular-19.1.5.tgz", + "integrity": "sha512-ny7ktNOTxaEi6cS3V6XFP5bbJkgiMt3OUNUYLdfdbv4y6wolVlPVHKl+wb4xs6tgbnmx63+e6zGpoDMCRytgcg==", "dev": true, "license": "MIT", "dependencies": { "@ampproject/remapping": "2.3.0", - "@angular-devkit/architect": "0.1900.6", - "@angular-devkit/build-webpack": "0.1900.6", - "@angular-devkit/core": "19.0.6", - "@angular/build": "19.0.6", + "@angular-devkit/architect": "0.1901.5", + "@angular-devkit/build-webpack": "0.1901.5", + "@angular-devkit/core": "19.1.5", + "@angular/build": "19.1.5", "@babel/core": "7.26.0", - "@babel/generator": "7.26.2", + "@babel/generator": "7.26.3", "@babel/helper-annotate-as-pure": "7.25.9", "@babel/helper-split-export-declaration": "7.24.7", "@babel/plugin-transform-async-generator-functions": "7.25.9", @@ -156,21 +157,21 @@ "@babel/preset-env": "7.26.0", "@babel/runtime": "7.26.0", "@discoveryjs/json-ext": "0.6.3", - "@ngtools/webpack": "19.0.6", - "@vitejs/plugin-basic-ssl": "1.1.0", + "@ngtools/webpack": "19.1.5", + "@vitejs/plugin-basic-ssl": "1.2.0", "ansi-colors": "4.1.3", "autoprefixer": "10.4.20", "babel-loader": "9.2.1", "browserslist": "^4.21.5", "copy-webpack-plugin": "12.0.2", "css-loader": "7.1.2", - "esbuild-wasm": "0.24.0", - "fast-glob": "3.3.2", + "esbuild-wasm": "0.24.2", + "fast-glob": "3.3.3", "http-proxy-middleware": "3.0.3", "istanbul-lib-instrument": "6.0.3", "jsonc-parser": "3.3.1", "karma-source-map-support": "1.4.0", - "less": "4.2.0", + "less": "4.2.1", "less-loader": "12.2.0", "license-webpack-plugin": "4.0.2", "loader-utils": "3.3.1", @@ -178,22 +179,22 @@ "open": "10.1.0", "ora": "5.4.1", "picomatch": "4.0.2", - "piscina": "4.7.0", + "piscina": "4.8.0", "postcss": "8.4.49", "postcss-loader": "8.1.1", "resolve-url-loader": "5.0.0", "rxjs": "7.8.1", - "sass": "1.80.7", - "sass-loader": "16.0.3", + "sass": "1.83.1", + "sass-loader": "16.0.4", "semver": "7.6.3", "source-map-loader": "5.0.0", "source-map-support": "0.5.21", - "terser": "5.36.0", + "terser": "5.37.0", "tree-kill": "1.2.2", "tslib": "2.8.1", - "webpack": "5.96.1", + "webpack": "5.97.1", "webpack-dev-middleware": "7.4.2", - "webpack-dev-server": "5.1.0", + "webpack-dev-server": "5.2.0", "webpack-merge": "6.0.1", "webpack-subresource-integrity": "5.1.0" }, @@ -203,14 +204,14 @@ "yarn": ">= 1.13.0" }, "optionalDependencies": { - "esbuild": "0.24.0" + "esbuild": "0.24.2" }, "peerDependencies": { "@angular/compiler-cli": "^19.0.0", "@angular/localize": "^19.0.0", "@angular/platform-server": "^19.0.0", "@angular/service-worker": "^19.0.0", - "@angular/ssr": "^19.0.6", + "@angular/ssr": "^19.1.5", "@web/test-runner": "^0.19.0", "browser-sync": "^3.0.2", "jest": "^29.5.0", @@ -218,8 +219,8 @@ "karma": "^6.3.0", "ng-packagr": "^19.0.0", "protractor": "^7.0.0", - "tailwindcss": "^2.0.0 || ^3.0.0", - "typescript": ">=5.5 <5.7" + "tailwindcss": "^2.0.0 || ^3.0.0 || ^4.0.0", + "typescript": ">=5.5 <5.8" }, "peerDependenciesMeta": { "@angular/localize": { @@ -260,31 +261,28 @@ } } }, - "node_modules/@angular-devkit/build-webpack": { - "version": "0.1900.6", - "resolved": "https://registry.npmjs.org/@angular-devkit/build-webpack/-/build-webpack-0.1900.6.tgz", - "integrity": "sha512-WehtVrbBow4fc7hsaUKb+BZ6MDE5lO98/tgv7GR5PkRdGKnyLA0pW1AfPLJJQDgcaKjneramMhDFNc1eGSX0mQ==", + "node_modules/@angular-devkit/build-angular/node_modules/@angular-devkit/architect": { + "version": "0.1901.5", + "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1901.5.tgz", + "integrity": "sha512-zlRudZx34FkFZnSdaQCjxDleHwbQYNLdBFcLi+FBwt0UXqxmhbEIasK3l/3kCOC3QledrjUzVXgouji+OZ/WGQ==", "dev": true, "license": "MIT", "dependencies": { - "@angular-devkit/architect": "0.1900.6", + "@angular-devkit/core": "19.1.5", "rxjs": "7.8.1" }, "engines": { "node": "^18.19.1 || ^20.11.1 || >=22.0.0", "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", "yarn": ">= 1.13.0" - }, - "peerDependencies": { - "webpack": "^5.30.0", - "webpack-dev-server": "^5.0.2" } }, - "node_modules/@angular-devkit/core": { - "version": "19.0.6", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-19.0.6.tgz", - "integrity": "sha512-WUWJhzQDsovfMY6jtb9Ktz/5sJszsaErj+XV2aXab85f1OweI/Iv2urPZnJwUSilvVN5Ok/fy3IJ6SuihK4Ceg==", + "node_modules/@angular-devkit/build-angular/node_modules/@angular-devkit/core": { + "version": "19.1.5", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-19.1.5.tgz", + "integrity": "sha512-wGKV+i5mCM/Hd/3CsdrIYcVi5G2Wg/D5941bUDXivrbsqHfKVINxAkI3OI1eaD90VnAL8ICrQEoAhh6ni2Umkg==", "dev": true, + "license": "MIT", "dependencies": { "ajv": "8.17.1", "ajv-formats": "3.0.1", @@ -307,151 +305,38 @@ } } }, - "node_modules/@angular-devkit/schematics": { - "version": "19.0.6", - "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-19.0.6.tgz", - "integrity": "sha512-R9hlHfAh1HKoIWgnYJlOEKhUezhTNl0fpUmHxG2252JSY5FLRxmYArTtJYYmbNdBbsBLNg3UHyM/GBPvJSA3NQ==", - "dev": true, - "dependencies": { - "@angular-devkit/core": "19.0.6", - "jsonc-parser": "3.3.1", - "magic-string": "0.30.12", - "ora": "5.4.1", - "rxjs": "7.8.1" - }, - "engines": { - "node": "^18.19.1 || ^20.11.1 || >=22.0.0", - "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", - "yarn": ">= 1.13.0" - } - }, - "node_modules/@angular-eslint/builder": { - "version": "19.0.2", - "resolved": "https://registry.npmjs.org/@angular-eslint/builder/-/builder-19.0.2.tgz", - "integrity": "sha512-BdmMSndQt2fSBiTVniskUcUpQaeweUapbsL0IDfQ7a13vL0NVXpc3K89YXuVE/xsb08uHtqphuwxPAAj6kX3OA==", - "dev": true, - "dependencies": { - "@angular-devkit/architect": ">= 0.1900.0 < 0.2000.0", - "@angular-devkit/core": ">= 19.0.0 < 20.0.0" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", - "typescript": "*" - } - }, - "node_modules/@angular-eslint/bundled-angular-compiler": { - "version": "19.0.2", - "resolved": "https://registry.npmjs.org/@angular-eslint/bundled-angular-compiler/-/bundled-angular-compiler-19.0.2.tgz", - "integrity": "sha512-HPmp92r70SNO/0NdIaIhxrgVSpomqryuUk7jszvNRtu+OzYCJGcbLhQD38T3dbBWT/AV0QXzyzExn6/2ai9fEw==", - "dev": true - }, - "node_modules/@angular-eslint/eslint-plugin": { - "version": "19.0.2", - "resolved": "https://registry.npmjs.org/@angular-eslint/eslint-plugin/-/eslint-plugin-19.0.2.tgz", - "integrity": "sha512-DLuNVVGGFicSThOcMSJyNje+FZSPdG0B3lCBRiqcgKH/16kfM4pV8MobPM7RGK2NhaOmmZ4zzJNwpwWPSgi+Lw==", - "dev": true, - "dependencies": { - "@angular-eslint/bundled-angular-compiler": "19.0.2", - "@angular-eslint/utils": "19.0.2" - }, - "peerDependencies": { - "@typescript-eslint/utils": "^7.11.0 || ^8.0.0", - "eslint": "^8.57.0 || ^9.0.0", - "typescript": "*" - } - }, - "node_modules/@angular-eslint/eslint-plugin-template": { - "version": "19.0.2", - "resolved": "https://registry.npmjs.org/@angular-eslint/eslint-plugin-template/-/eslint-plugin-template-19.0.2.tgz", - "integrity": "sha512-f/OCF9ThnxQ8m0eNYPwnCrySQPhYfCOF6STL7F9LnS8Bs3ZeW3/oT1yLaMIZ1Eg0ogIkgxksMAJZjrJPUPBD1Q==", - "dev": true, - "dependencies": { - "@angular-eslint/bundled-angular-compiler": "19.0.2", - "@angular-eslint/utils": "19.0.2", - "aria-query": "5.3.2", - "axobject-query": "4.1.0" - }, - "peerDependencies": { - "@typescript-eslint/types": "^7.11.0 || ^8.0.0", - "@typescript-eslint/utils": "^7.11.0 || ^8.0.0", - "eslint": "^8.57.0 || ^9.0.0", - "typescript": "*" - } - }, - "node_modules/@angular-eslint/template-parser": { - "version": "19.0.2", - "resolved": "https://registry.npmjs.org/@angular-eslint/template-parser/-/template-parser-19.0.2.tgz", - "integrity": "sha512-z3rZd2sBfuYcFf9rGDsB2zz2fbGX8kkF+0ftg9eocyQmzWrlZHFmuw9ha7oP/Mz8gpblyCS/aa1U/Srs6gz0UQ==", - "dev": true, - "dependencies": { - "@angular-eslint/bundled-angular-compiler": "19.0.2", - "eslint-scope": "^8.0.2" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", - "typescript": "*" - } - }, - "node_modules/@angular-eslint/utils": { - "version": "19.0.2", - "resolved": "https://registry.npmjs.org/@angular-eslint/utils/-/utils-19.0.2.tgz", - "integrity": "sha512-HotBT8OKr7zCaX1S9k27JuhRiTVIbbYVl6whlb3uwdMIPIWY8iOcEh1tjI4qDPUafpLfR72Dhwi5bO1E17F3/Q==", - "dev": true, - "dependencies": { - "@angular-eslint/bundled-angular-compiler": "19.0.2" - }, - "peerDependencies": { - "@typescript-eslint/utils": "^7.11.0 || ^8.0.0", - "eslint": "^8.57.0 || ^9.0.0", - "typescript": "*" - } - }, - "node_modules/@angular/animations": { - "version": "19.0.5", - "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-19.0.5.tgz", - "integrity": "sha512-HCOF2CrhUvjoZWusd4nh32VOxpUrg6bV+3Z8Q36Ix3aZdni8v0qoP2rl5wGbotaPtYg5RtyDH60Z2AOPKqlrZg==", - "license": "MIT", - "dependencies": { - "tslib": "^2.3.0" - }, - "engines": { - "node": "^18.19.1 || ^20.11.1 || >=22.0.0" - }, - "peerDependencies": { - "@angular/core": "19.0.5" - } - }, - "node_modules/@angular/build": { - "version": "19.0.6", - "resolved": "https://registry.npmjs.org/@angular/build/-/build-19.0.6.tgz", - "integrity": "sha512-KEVNLgTZUF2dfpOYQn+yR2HONHUTxq/2rFVhiK9qAvrm/m+uKJNEXx7hGtbRyoqenZff4ScJq+7feITUldfX8g==", + "node_modules/@angular-devkit/build-angular/node_modules/@angular/build": { + "version": "19.1.5", + "resolved": "https://registry.npmjs.org/@angular/build/-/build-19.1.5.tgz", + "integrity": "sha512-byoHcv0/s6WGWap59s43N/eC+4NsviuTnGoj+iR0ayubk8snn6jdkZLbFDfnTuQlTiu4ok8/XcksjzeMkgGyyw==", "dev": true, "license": "MIT", "dependencies": { "@ampproject/remapping": "2.3.0", - "@angular-devkit/architect": "0.1900.6", + "@angular-devkit/architect": "0.1901.5", + "@angular-devkit/core": "19.1.5", "@babel/core": "7.26.0", "@babel/helper-annotate-as-pure": "7.25.9", "@babel/helper-split-export-declaration": "7.24.7", "@babel/plugin-syntax-import-attributes": "7.26.0", - "@inquirer/confirm": "5.0.2", - "@vitejs/plugin-basic-ssl": "1.1.0", - "beasties": "0.1.0", + "@inquirer/confirm": "5.1.1", + "@vitejs/plugin-basic-ssl": "1.2.0", + "beasties": "0.2.0", "browserslist": "^4.23.0", - "esbuild": "0.24.0", - "fast-glob": "3.3.2", - "https-proxy-agent": "7.0.5", + "esbuild": "0.24.2", + "fast-glob": "3.3.3", + "https-proxy-agent": "7.0.6", "istanbul-lib-instrument": "6.0.3", "listr2": "8.2.5", - "magic-string": "0.30.12", + "magic-string": "0.30.17", "mrmime": "2.0.0", "parse5-html-rewriting-stream": "7.0.0", "picomatch": "4.0.2", - "piscina": "4.7.0", - "rollup": "4.26.0", - "sass": "1.80.7", + "piscina": "4.8.0", + "rollup": "4.30.1", + "sass": "1.83.1", "semver": "7.6.3", - "vite": "5.4.11", + "vite": "6.0.11", "watchpack": "2.4.2" }, "engines": { @@ -460,7 +345,7 @@ "yarn": ">= 1.13.0" }, "optionalDependencies": { - "lmdb": "3.1.5" + "lmdb": "3.2.2" }, "peerDependencies": { "@angular/compiler": "^19.0.0", @@ -468,11 +353,12 @@ "@angular/localize": "^19.0.0", "@angular/platform-server": "^19.0.0", "@angular/service-worker": "^19.0.0", - "@angular/ssr": "^19.0.6", + "@angular/ssr": "^19.1.5", "less": "^4.2.0", + "ng-packagr": "^19.0.0", "postcss": "^8.4.0", - "tailwindcss": "^2.0.0 || ^3.0.0", - "typescript": ">=5.5 <5.7" + "tailwindcss": "^2.0.0 || ^3.0.0 || ^4.0.0", + "typescript": ">=5.5 <5.8" }, "peerDependenciesMeta": { "@angular/localize": { @@ -490,6 +376,9 @@ "less": { "optional": true }, + "ng-packagr": { + "optional": true + }, "postcss": { "optional": true }, @@ -498,555 +387,1045 @@ } } }, - "node_modules/@angular/build/node_modules/@inquirer/confirm": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-5.0.2.tgz", - "integrity": "sha512-KJLUHOaKnNCYzwVbryj3TNBxyZIrr56fR5N45v6K9IPrbT6B7DcudBMfylkV1A8PUdJE15mybkEQyp2/ZUpxUA==", + "node_modules/@angular-devkit/build-angular/node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.30.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.30.1.tgz", + "integrity": "sha512-pSWY+EVt3rJ9fQ3IqlrEUtXh3cGqGtPDH1FQlNZehO2yYxCHEX1SPsz1M//NXwYfbTlcKr9WObLnJX9FsS9K1Q==", + "cpu": [ + "arm" + ], "dev": true, "license": "MIT", - "dependencies": { - "@inquirer/core": "^10.1.0", - "@inquirer/type": "^3.0.1" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - } + "optional": true, + "os": [ + "android" + ] }, - "node_modules/@angular/build/node_modules/https-proxy-agent": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", - "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", + "node_modules/@angular-devkit/build-angular/node_modules/@rollup/rollup-android-arm64": { + "version": "4.30.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.30.1.tgz", + "integrity": "sha512-/NA2qXxE3D/BRjOJM8wQblmArQq1YoBVJjrjoTSBS09jgUisq7bqxNHJ8kjCHeV21W/9WDGwJEWSN0KQ2mtD/w==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", - "dependencies": { - "agent-base": "^7.0.2", - "debug": "4" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/@angular/cdk": { - "version": "19.0.3", - "resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-19.0.3.tgz", - "integrity": "sha512-sPdIKbSgNk4z02FqdTTMUS62aLVA2R/DsnOk3qdH+nEfeS4nNWQEzwrvMf6dDsTeLQ6YJLWXfZfemsGYpOoiWg==", - "peer": true, - "dependencies": { - "tslib": "^2.3.0" - }, - "optionalDependencies": { - "parse5": "^7.1.2" - }, - "peerDependencies": { - "@angular/common": "^19.0.0 || ^20.0.0", - "@angular/core": "^19.0.0 || ^20.0.0", - "rxjs": "^6.5.3 || ^7.4.0" - } + "optional": true, + "os": [ + "android" + ] }, - "node_modules/@angular/cli": { - "version": "19.0.6", - "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-19.0.6.tgz", - "integrity": "sha512-ZEHhgRRVIdn10dbsAjB8TE9Co32hfuL9/im5Jcfa1yrn6KJefmigz6KN8Xu7FXMH5FkdqfQ11QpLBxJSPb9aww==", + "node_modules/@angular-devkit/build-angular/node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.30.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.30.1.tgz", + "integrity": "sha512-r7FQIXD7gB0WJ5mokTUgUWPl0eYIH0wnxqeSAhuIwvnnpjdVB8cRRClyKLQr7lgzjctkbp5KmswWszlwYln03Q==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", - "dependencies": { - "@angular-devkit/architect": "0.1900.6", - "@angular-devkit/core": "19.0.6", - "@angular-devkit/schematics": "19.0.6", - "@inquirer/prompts": "7.1.0", - "@listr2/prompt-adapter-inquirer": "2.0.18", - "@schematics/angular": "19.0.6", - "@yarnpkg/lockfile": "1.1.0", - "ini": "5.0.0", - "jsonc-parser": "3.3.1", - "listr2": "8.2.5", - "npm-package-arg": "12.0.0", - "npm-pick-manifest": "10.0.0", - "pacote": "20.0.0", - "resolve": "1.22.8", - "semver": "7.6.3", - "symbol-observable": "4.0.0", - "yargs": "17.7.2" - }, - "bin": { - "ng": "bin/ng.js" - }, - "engines": { - "node": "^18.19.1 || ^20.11.1 || >=22.0.0", - "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", - "yarn": ">= 1.13.0" - } + "optional": true, + "os": [ + "darwin" + ] }, - "node_modules/@angular/common": { - "version": "19.0.5", - "resolved": "https://registry.npmjs.org/@angular/common/-/common-19.0.5.tgz", - "integrity": "sha512-fFK+euCj1AjBHBCpj9VnduMSeqoMRhZZHbhPYiND7tucRRJ8vwGU0sYK2KI/Ko+fsrNIXL/0O4F36jVPl09Smg==", - "dependencies": { - "tslib": "^2.3.0" - }, - "engines": { - "node": "^18.19.1 || ^20.11.1 || >=22.0.0" - }, - "peerDependencies": { - "@angular/core": "19.0.5", - "rxjs": "^6.5.3 || ^7.4.0" - } + "node_modules/@angular-devkit/build-angular/node_modules/@rollup/rollup-darwin-x64": { + "version": "4.30.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.30.1.tgz", + "integrity": "sha512-x78BavIwSH6sqfP2xeI1hd1GpHL8J4W2BXcVM/5KYKoAD3nNsfitQhvWSw+TFtQTLZ9OmlF+FEInEHyubut2OA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] }, - "node_modules/@angular/compiler": { - "version": "19.0.5", - "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-19.0.5.tgz", - "integrity": "sha512-S8ku5Ljp0kqX3shfmE9DVo09629jeYJSlBRGbj2Glb92dd+VQZPOz7KxqKRTwmAl7lQIV/+4Lr6G/GVTsoC4vg==", + "node_modules/@angular-devkit/build-angular/node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.30.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.30.1.tgz", + "integrity": "sha512-HYTlUAjbO1z8ywxsDFWADfTRfTIIy/oUlfIDmlHYmjUP2QRDTzBuWXc9O4CXM+bo9qfiCclmHk1x4ogBjOUpUQ==", + "cpu": [ + "arm64" + ], + "dev": true, "license": "MIT", - "dependencies": { - "tslib": "^2.3.0" - }, - "engines": { - "node": "^18.19.1 || ^20.11.1 || >=22.0.0" - }, - "peerDependencies": { - "@angular/core": "19.0.5" - }, - "peerDependenciesMeta": { - "@angular/core": { - "optional": true - } + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@angular-devkit/build-angular/node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.30.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.30.1.tgz", + "integrity": "sha512-1MEdGqogQLccphhX5myCJqeGNYTNcmTyaic9S7CG3JhwuIByJ7J05vGbZxsizQthP1xpVx7kd3o31eOogfEirw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@angular-devkit/build-angular/node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.30.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.30.1.tgz", + "integrity": "sha512-PaMRNBSqCx7K3Wc9QZkFx5+CX27WFpAMxJNiYGAXfmMIKC7jstlr32UhTgK6T07OtqR+wYlWm9IxzennjnvdJg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@angular-devkit/build-angular/node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.30.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.30.1.tgz", + "integrity": "sha512-B8Rcyj9AV7ZlEFqvB5BubG5iO6ANDsRKlhIxySXcF1axXYUyqwBok+XZPgIYGBgs7LDXfWfifxhw0Ik57T0Yug==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@angular-devkit/build-angular/node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.30.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.30.1.tgz", + "integrity": "sha512-hqVyueGxAj3cBKrAI4aFHLV+h0Lv5VgWZs9CUGqr1z0fZtlADVV1YPOij6AhcK5An33EXaxnDLmJdQikcn5NEw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@angular-devkit/build-angular/node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.30.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.30.1.tgz", + "integrity": "sha512-i4Ab2vnvS1AE1PyOIGp2kXni69gU2DAUVt6FSXeIqUCPIR3ZlheMW3oP2JkukDfu3PsexYRbOiJrY+yVNSk9oA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@angular-devkit/build-angular/node_modules/@rollup/rollup-linux-loongarch64-gnu": { + "version": "4.30.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.30.1.tgz", + "integrity": "sha512-fARcF5g296snX0oLGkVxPmysetwUk2zmHcca+e9ObOovBR++9ZPOhqFUM61UUZ2EYpXVPN1redgqVoBB34nTpQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@angular-devkit/build-angular/node_modules/@rollup/rollup-linux-powerpc64le-gnu": { + "version": "4.30.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.30.1.tgz", + "integrity": "sha512-GLrZraoO3wVT4uFXh67ElpwQY0DIygxdv0BNW9Hkm3X34wu+BkqrDrkcsIapAY+N2ATEbvak0XQ9gxZtCIA5Rw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@angular-devkit/build-angular/node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.30.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.30.1.tgz", + "integrity": "sha512-0WKLaAUUHKBtll0wvOmh6yh3S0wSU9+yas923JIChfxOaaBarmb/lBKPF0w/+jTVozFnOXJeRGZ8NvOxvk/jcw==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@angular-devkit/build-angular/node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.30.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.30.1.tgz", + "integrity": "sha512-GWFs97Ruxo5Bt+cvVTQkOJ6TIx0xJDD/bMAOXWJg8TCSTEK8RnFeOeiFTxKniTc4vMIaWvCplMAFBt9miGxgkA==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@angular-devkit/build-angular/node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.30.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.30.1.tgz", + "integrity": "sha512-UtgGb7QGgXDIO+tqqJ5oZRGHsDLO8SlpE4MhqpY9Llpzi5rJMvrK6ZGhsRCST2abZdBqIBeXW6WPD5fGK5SDwg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@angular-devkit/build-angular/node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.30.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.30.1.tgz", + "integrity": "sha512-V9U8Ey2UqmQsBT+xTOeMzPzwDzyXmnAoO4edZhL7INkwQcaW1Ckv3WJX3qrrp/VHaDkEWIBWhRwP47r8cdrOow==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@angular-devkit/build-angular/node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.30.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.30.1.tgz", + "integrity": "sha512-WabtHWiPaFF47W3PkHnjbmWawnX/aE57K47ZDT1BXTS5GgrBUEpvOzq0FI0V/UYzQJgdb8XlhVNH8/fwV8xDjw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@angular-devkit/build-angular/node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.30.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.30.1.tgz", + "integrity": "sha512-pxHAU+Zv39hLUTdQQHUVHf4P+0C47y/ZloorHpzs2SXMRqeAWmGghzAhfOlzFHHwjvgokdFAhC4V+6kC1lRRfw==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@angular-devkit/build-angular/node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.30.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.30.1.tgz", + "integrity": "sha512-D6qjsXGcvhTjv0kI4fU8tUuBDF/Ueee4SVX79VfNDXZa64TfCW1Slkb6Z7O1p7vflqZjcmOVdZlqf8gvJxc6og==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@angular-devkit/build-angular/node_modules/magic-string": { + "version": "0.30.17", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", + "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0" } }, - "node_modules/@angular/compiler-cli": { - "version": "19.0.5", - "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-19.0.5.tgz", - "integrity": "sha512-KSzuWCTZlvJsoAenxM9cjTOzNM8mrFxDBInj0KVPz7QU83amGS4rcv1pWO/QGYQcErfskcN84TAdMegaRWWCmA==", + "node_modules/@angular-devkit/build-angular/node_modules/rollup": { + "version": "4.30.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.30.1.tgz", + "integrity": "sha512-mlJ4glW020fPuLi7DkM/lN97mYEZGWeqBnrljzN0gs7GLctqX3lNWxKQ7Gl712UAX+6fog/L3jh4gb7R6aVi3w==", "dev": true, "license": "MIT", "dependencies": { - "@babel/core": "7.26.0", - "@jridgewell/sourcemap-codec": "^1.4.14", - "chokidar": "^4.0.0", - "convert-source-map": "^1.5.1", - "reflect-metadata": "^0.2.0", - "semver": "^7.0.0", - "tslib": "^2.3.0", - "yargs": "^17.2.1" + "@types/estree": "1.0.6" }, "bin": { - "ng-xi18n": "bundles/src/bin/ng_xi18n.js", - "ngc": "bundles/src/bin/ngc.js", - "ngcc": "bundles/ngcc/index.js" + "rollup": "dist/bin/rollup" }, "engines": { - "node": "^18.19.1 || ^20.11.1 || >=22.0.0" + "node": ">=18.0.0", + "npm": ">=8.0.0" }, - "peerDependencies": { - "@angular/compiler": "19.0.5", - "typescript": ">=5.5 <5.7" + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.30.1", + "@rollup/rollup-android-arm64": "4.30.1", + "@rollup/rollup-darwin-arm64": "4.30.1", + "@rollup/rollup-darwin-x64": "4.30.1", + "@rollup/rollup-freebsd-arm64": "4.30.1", + "@rollup/rollup-freebsd-x64": "4.30.1", + "@rollup/rollup-linux-arm-gnueabihf": "4.30.1", + "@rollup/rollup-linux-arm-musleabihf": "4.30.1", + "@rollup/rollup-linux-arm64-gnu": "4.30.1", + "@rollup/rollup-linux-arm64-musl": "4.30.1", + "@rollup/rollup-linux-loongarch64-gnu": "4.30.1", + "@rollup/rollup-linux-powerpc64le-gnu": "4.30.1", + "@rollup/rollup-linux-riscv64-gnu": "4.30.1", + "@rollup/rollup-linux-s390x-gnu": "4.30.1", + "@rollup/rollup-linux-x64-gnu": "4.30.1", + "@rollup/rollup-linux-x64-musl": "4.30.1", + "@rollup/rollup-win32-arm64-msvc": "4.30.1", + "@rollup/rollup-win32-ia32-msvc": "4.30.1", + "@rollup/rollup-win32-x64-msvc": "4.30.1", + "fsevents": "~2.3.2" } }, - "node_modules/@angular/core": { - "version": "19.0.5", - "resolved": "https://registry.npmjs.org/@angular/core/-/core-19.0.5.tgz", - "integrity": "sha512-Ywc6sPO6G/Y1stfk3y/MallV/h0yzQ0vdOHRWueLrk5kD1DTdbolV4X03Cs3PuVvravgcSVE3nnuuHFuH32emQ==", + "node_modules/@angular-devkit/build-webpack": { + "version": "0.1901.5", + "resolved": "https://registry.npmjs.org/@angular-devkit/build-webpack/-/build-webpack-0.1901.5.tgz", + "integrity": "sha512-UxEoF7F8L1GpH/N4me7VGe5ZPfxIiVHyhw5/ck3rcVbT6YD22/GYFGSJRGYP+D7LLTJ7OOQvfD6Bc/q62HhWvA==", + "dev": true, "license": "MIT", "dependencies": { - "tslib": "^2.3.0" + "@angular-devkit/architect": "0.1901.5", + "rxjs": "7.8.1" }, "engines": { - "node": "^18.19.1 || ^20.11.1 || >=22.0.0" + "node": "^18.19.1 || ^20.11.1 || >=22.0.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" }, "peerDependencies": { - "rxjs": "^6.5.3 || ^7.4.0", - "zone.js": "~0.15.0" + "webpack": "^5.30.0", + "webpack-dev-server": "^5.0.2" } }, - "node_modules/@angular/forms": { - "version": "19.0.5", - "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-19.0.5.tgz", - "integrity": "sha512-OhNFkfOoguqCDq07vNBV28FFrmTM8S11Z3Cd6PQZJJF9TgAtpV5KtF7A3eXBCN92W4pmqluomPjfK7YyImzIYQ==", + "node_modules/@angular-devkit/build-webpack/node_modules/@angular-devkit/architect": { + "version": "0.1901.5", + "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1901.5.tgz", + "integrity": "sha512-zlRudZx34FkFZnSdaQCjxDleHwbQYNLdBFcLi+FBwt0UXqxmhbEIasK3l/3kCOC3QledrjUzVXgouji+OZ/WGQ==", + "dev": true, "license": "MIT", "dependencies": { - "tslib": "^2.3.0" + "@angular-devkit/core": "19.1.5", + "rxjs": "7.8.1" }, "engines": { - "node": "^18.19.1 || ^20.11.1 || >=22.0.0" - }, - "peerDependencies": { - "@angular/common": "19.0.5", - "@angular/core": "19.0.5", - "@angular/platform-browser": "19.0.5", - "rxjs": "^6.5.3 || ^7.4.0" + "node": "^18.19.1 || ^20.11.1 || >=22.0.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" } }, - "node_modules/@angular/language-service": { - "version": "19.0.5", - "resolved": "https://registry.npmjs.org/@angular/language-service/-/language-service-19.0.5.tgz", - "integrity": "sha512-E4WFEsCzHuF3DYe4EfOCiMGW1zWmq3UYi5XXOBNLyzWDvwU5xTfdme6ECXGawHMc2kCaWMVNL4DzYpVsUgLG0w==", + "node_modules/@angular-devkit/build-webpack/node_modules/@angular-devkit/core": { + "version": "19.1.5", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-19.1.5.tgz", + "integrity": "sha512-wGKV+i5mCM/Hd/3CsdrIYcVi5G2Wg/D5941bUDXivrbsqHfKVINxAkI3OI1eaD90VnAL8ICrQEoAhh6ni2Umkg==", "dev": true, "license": "MIT", - "engines": { - "node": "^18.19.1 || ^20.11.1 || >=22.0.0" - } - }, - "node_modules/@angular/platform-browser": { - "version": "19.0.5", - "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-19.0.5.tgz", - "integrity": "sha512-41+Jo5DEil4Ifvv+UE/p1l9YJtYN+xfhx+/C9cahVgvV5D2q+givyK73d0Mnb6XOfe1q+hoV5lZ+XhQYp21//g==", - "license": "MIT", "dependencies": { - "tslib": "^2.3.0" + "ajv": "8.17.1", + "ajv-formats": "3.0.1", + "jsonc-parser": "3.3.1", + "picomatch": "4.0.2", + "rxjs": "7.8.1", + "source-map": "0.7.4" }, "engines": { - "node": "^18.19.1 || ^20.11.1 || >=22.0.0" + "node": "^18.19.1 || ^20.11.1 || >=22.0.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" }, "peerDependencies": { - "@angular/animations": "19.0.5", - "@angular/common": "19.0.5", - "@angular/core": "19.0.5" + "chokidar": "^4.0.0" }, "peerDependenciesMeta": { - "@angular/animations": { + "chokidar": { "optional": true } } }, - "node_modules/@angular/platform-browser-dynamic": { - "version": "19.0.5", - "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-19.0.5.tgz", - "integrity": "sha512-KKFdue/uJVxkWdrntRAXkz+ycp4nD3SuGOH5pPf2svCBxieuHuFlWDi+DYVuFSEpC/ICCmlhrtzIAm44A4qzzQ==", - "license": "MIT", - "dependencies": { - "tslib": "^2.3.0" - }, + "node_modules/@angular-devkit/core": { + "version": "19.0.6", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-19.0.6.tgz", + "integrity": "sha512-WUWJhzQDsovfMY6jtb9Ktz/5sJszsaErj+XV2aXab85f1OweI/Iv2urPZnJwUSilvVN5Ok/fy3IJ6SuihK4Ceg==", + "dev": true, + "dependencies": { + "ajv": "8.17.1", + "ajv-formats": "3.0.1", + "jsonc-parser": "3.3.1", + "picomatch": "4.0.2", + "rxjs": "7.8.1", + "source-map": "0.7.4" + }, "engines": { - "node": "^18.19.1 || ^20.11.1 || >=22.0.0" + "node": "^18.19.1 || ^20.11.1 || >=22.0.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" }, "peerDependencies": { - "@angular/common": "19.0.5", - "@angular/compiler": "19.0.5", - "@angular/core": "19.0.5", - "@angular/platform-browser": "19.0.5" + "chokidar": "^4.0.0" + }, + "peerDependenciesMeta": { + "chokidar": { + "optional": true + } } }, - "node_modules/@angular/router": { - "version": "19.0.5", - "resolved": "https://registry.npmjs.org/@angular/router/-/router-19.0.5.tgz", - "integrity": "sha512-6tNubVVj/rRyTg+OXjQxACfufvCLHAwDQtv9wqt6q/3OYSnysHTik3ho3FaFPwu7fXJ+6p9Rjzkh2VY9QMk4bw==", - "license": "MIT", + "node_modules/@angular-devkit/schematics": { + "version": "19.0.6", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-19.0.6.tgz", + "integrity": "sha512-R9hlHfAh1HKoIWgnYJlOEKhUezhTNl0fpUmHxG2252JSY5FLRxmYArTtJYYmbNdBbsBLNg3UHyM/GBPvJSA3NQ==", + "dev": true, "dependencies": { - "tslib": "^2.3.0" + "@angular-devkit/core": "19.0.6", + "jsonc-parser": "3.3.1", + "magic-string": "0.30.12", + "ora": "5.4.1", + "rxjs": "7.8.1" }, "engines": { - "node": "^18.19.1 || ^20.11.1 || >=22.0.0" - }, - "peerDependencies": { - "@angular/common": "19.0.5", - "@angular/core": "19.0.5", - "@angular/platform-browser": "19.0.5", - "rxjs": "^6.5.3 || ^7.4.0" + "node": "^18.19.1 || ^20.11.1 || >=22.0.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" } }, - "node_modules/@angular/service-worker": { - "version": "19.0.5", - "resolved": "https://registry.npmjs.org/@angular/service-worker/-/service-worker-19.0.5.tgz", - "integrity": "sha512-qU5lgx1WJ+feCOV/EhkN9m20xFdIslpEQcSZZC+VJnEwcG6VTbofg1dRaHWZ9HAjS1uP7bFoK0HUYu4el0bHGA==", - "license": "MIT", + "node_modules/@angular-eslint/builder": { + "version": "19.0.2", + "resolved": "https://registry.npmjs.org/@angular-eslint/builder/-/builder-19.0.2.tgz", + "integrity": "sha512-BdmMSndQt2fSBiTVniskUcUpQaeweUapbsL0IDfQ7a13vL0NVXpc3K89YXuVE/xsb08uHtqphuwxPAAj6kX3OA==", + "dev": true, "dependencies": { - "tslib": "^2.3.0" - }, - "bin": { - "ngsw-config": "ngsw-config.js" - }, - "engines": { - "node": "^18.19.1 || ^20.11.1 || >=22.0.0" + "@angular-devkit/architect": ">= 0.1900.0 < 0.2000.0", + "@angular-devkit/core": ">= 19.0.0 < 20.0.0" }, "peerDependencies": { - "@angular/common": "19.0.5", - "@angular/core": "19.0.5" + "eslint": "^8.57.0 || ^9.0.0", + "typescript": "*" } }, - "node_modules/@awesome-cordova-plugins/core": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/@awesome-cordova-plugins/core/-/core-6.13.0.tgz", - "integrity": "sha512-iqa5TU8HcFns/ND18KFrDVo4rGD4d4Gr5bgACFPwfztNCNmCRp+qkhv/xRBstqZ72qYH2oAJnEE1PTUY+IfX7Q==", + "node_modules/@angular-eslint/bundled-angular-compiler": { + "version": "19.0.2", + "resolved": "https://registry.npmjs.org/@angular-eslint/bundled-angular-compiler/-/bundled-angular-compiler-19.0.2.tgz", + "integrity": "sha512-HPmp92r70SNO/0NdIaIhxrgVSpomqryuUk7jszvNRtu+OzYCJGcbLhQD38T3dbBWT/AV0QXzyzExn6/2ai9fEw==", + "dev": true + }, + "node_modules/@angular-eslint/eslint-plugin": { + "version": "19.0.2", + "resolved": "https://registry.npmjs.org/@angular-eslint/eslint-plugin/-/eslint-plugin-19.0.2.tgz", + "integrity": "sha512-DLuNVVGGFicSThOcMSJyNje+FZSPdG0B3lCBRiqcgKH/16kfM4pV8MobPM7RGK2NhaOmmZ4zzJNwpwWPSgi+Lw==", + "dev": true, "dependencies": { - "@types/cordova": "latest" + "@angular-eslint/bundled-angular-compiler": "19.0.2", + "@angular-eslint/utils": "19.0.2" }, "peerDependencies": { - "rxjs": "^5.5.0 || ^6.5.0 || ^7.3.0" + "@typescript-eslint/utils": "^7.11.0 || ^8.0.0", + "eslint": "^8.57.0 || ^9.0.0", + "typescript": "*" } }, - "node_modules/@awesome-cordova-plugins/file-opener": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/@awesome-cordova-plugins/file-opener/-/file-opener-6.13.0.tgz", - "integrity": "sha512-0+caltmjJf3BuZiklqaSHsxviDiS4znnJj3RiBfoERfPCRa0HIyO8dywH2EhkOMhYQ5g8gBobTTOJQpV/yQhmw==", + "node_modules/@angular-eslint/eslint-plugin-template": { + "version": "19.0.2", + "resolved": "https://registry.npmjs.org/@angular-eslint/eslint-plugin-template/-/eslint-plugin-template-19.0.2.tgz", + "integrity": "sha512-f/OCF9ThnxQ8m0eNYPwnCrySQPhYfCOF6STL7F9LnS8Bs3ZeW3/oT1yLaMIZ1Eg0ogIkgxksMAJZjrJPUPBD1Q==", + "dev": true, "dependencies": { - "@types/cordova": "latest" + "@angular-eslint/bundled-angular-compiler": "19.0.2", + "@angular-eslint/utils": "19.0.2", + "aria-query": "5.3.2", + "axobject-query": "4.1.0" }, "peerDependencies": { - "@awesome-cordova-plugins/core": "^6.0.1", - "rxjs": "^5.5.0 || ^6.5.0 || ^7.3.0" + "@typescript-eslint/types": "^7.11.0 || ^8.0.0", + "@typescript-eslint/utils": "^7.11.0 || ^8.0.0", + "eslint": "^8.57.0 || ^9.0.0", + "typescript": "*" } }, - "node_modules/@babel/code-frame": { - "version": "7.26.2", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", - "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", + "node_modules/@angular-eslint/template-parser": { + "version": "19.0.2", + "resolved": "https://registry.npmjs.org/@angular-eslint/template-parser/-/template-parser-19.0.2.tgz", + "integrity": "sha512-z3rZd2sBfuYcFf9rGDsB2zz2fbGX8kkF+0ftg9eocyQmzWrlZHFmuw9ha7oP/Mz8gpblyCS/aa1U/Srs6gz0UQ==", "dev": true, "dependencies": { - "@babel/helper-validator-identifier": "^7.25.9", - "js-tokens": "^4.0.0", - "picocolors": "^1.0.0" + "@angular-eslint/bundled-angular-compiler": "19.0.2", + "eslint-scope": "^8.0.2" }, - "engines": { - "node": ">=6.9.0" + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": "*" } }, - "node_modules/@babel/compat-data": { - "version": "7.26.3", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.3.tgz", - "integrity": "sha512-nHIxvKPniQXpmQLb0vhY3VaFb3S0YrTAwpOWJZh1wn3oJPjJk9Asva204PsBdmAE8vpzfHudT8DB0scYvy9q0g==", + "node_modules/@angular-eslint/utils": { + "version": "19.0.2", + "resolved": "https://registry.npmjs.org/@angular-eslint/utils/-/utils-19.0.2.tgz", + "integrity": "sha512-HotBT8OKr7zCaX1S9k27JuhRiTVIbbYVl6whlb3uwdMIPIWY8iOcEh1tjI4qDPUafpLfR72Dhwi5bO1E17F3/Q==", "dev": true, - "engines": { - "node": ">=6.9.0" + "dependencies": { + "@angular-eslint/bundled-angular-compiler": "19.0.2" + }, + "peerDependencies": { + "@typescript-eslint/utils": "^7.11.0 || ^8.0.0", + "eslint": "^8.57.0 || ^9.0.0", + "typescript": "*" } }, - "node_modules/@babel/core": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.0.tgz", - "integrity": "sha512-i1SLeK+DzNnQ3LL/CswPCa/E5u4lh1k6IAEphON8F+cXt0t9euTshDru0q7/IqMa1PMPz5RnHuHscF8/ZJsStg==", - "dev": true, + "node_modules/@angular/animations": { + "version": "19.0.5", + "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-19.0.5.tgz", + "integrity": "sha512-HCOF2CrhUvjoZWusd4nh32VOxpUrg6bV+3Z8Q36Ix3aZdni8v0qoP2rl5wGbotaPtYg5RtyDH60Z2AOPKqlrZg==", + "license": "MIT", "dependencies": { - "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.26.0", - "@babel/generator": "^7.26.0", - "@babel/helper-compilation-targets": "^7.25.9", - "@babel/helper-module-transforms": "^7.26.0", - "@babel/helpers": "^7.26.0", - "@babel/parser": "^7.26.0", - "@babel/template": "^7.25.9", - "@babel/traverse": "^7.25.9", - "@babel/types": "^7.26.0", - "convert-source-map": "^2.0.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.3", - "semver": "^6.3.1" + "tslib": "^2.3.0" }, "engines": { - "node": ">=6.9.0" + "node": "^18.19.1 || ^20.11.1 || >=22.0.0" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" + "peerDependencies": { + "@angular/core": "19.0.5" } }, - "node_modules/@babel/core/node_modules/convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true - }, - "node_modules/@babel/core/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" + "node_modules/@angular/cdk": { + "version": "19.0.3", + "resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-19.0.3.tgz", + "integrity": "sha512-sPdIKbSgNk4z02FqdTTMUS62aLVA2R/DsnOk3qdH+nEfeS4nNWQEzwrvMf6dDsTeLQ6YJLWXfZfemsGYpOoiWg==", + "peer": true, + "dependencies": { + "tslib": "^2.3.0" + }, + "optionalDependencies": { + "parse5": "^7.1.2" + }, + "peerDependencies": { + "@angular/common": "^19.0.0 || ^20.0.0", + "@angular/core": "^19.0.0 || ^20.0.0", + "rxjs": "^6.5.3 || ^7.4.0" } }, - "node_modules/@babel/generator": { - "version": "7.26.2", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.2.tgz", - "integrity": "sha512-zevQbhbau95nkoxSq3f/DC/SC+EEOUZd3DYqfSkMhY2/wfSeaHV1Ew4vk8e+x8lja31IbyuUa2uQ3JONqKbysw==", + "node_modules/@angular/cli": { + "version": "19.0.6", + "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-19.0.6.tgz", + "integrity": "sha512-ZEHhgRRVIdn10dbsAjB8TE9Co32hfuL9/im5Jcfa1yrn6KJefmigz6KN8Xu7FXMH5FkdqfQ11QpLBxJSPb9aww==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/parser": "^7.26.2", - "@babel/types": "^7.26.0", - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25", - "jsesc": "^3.0.2" + "@angular-devkit/architect": "0.1900.6", + "@angular-devkit/core": "19.0.6", + "@angular-devkit/schematics": "19.0.6", + "@inquirer/prompts": "7.1.0", + "@listr2/prompt-adapter-inquirer": "2.0.18", + "@schematics/angular": "19.0.6", + "@yarnpkg/lockfile": "1.1.0", + "ini": "5.0.0", + "jsonc-parser": "3.3.1", + "listr2": "8.2.5", + "npm-package-arg": "12.0.0", + "npm-pick-manifest": "10.0.0", + "pacote": "20.0.0", + "resolve": "1.22.8", + "semver": "7.6.3", + "symbol-observable": "4.0.0", + "yargs": "17.7.2" + }, + "bin": { + "ng": "bin/ng.js" }, "engines": { - "node": ">=6.9.0" + "node": "^18.19.1 || ^20.11.1 || >=22.0.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" } }, - "node_modules/@babel/helper-annotate-as-pure": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.25.9.tgz", - "integrity": "sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g==", - "dev": true, + "node_modules/@angular/common": { + "version": "19.0.5", + "resolved": "https://registry.npmjs.org/@angular/common/-/common-19.0.5.tgz", + "integrity": "sha512-fFK+euCj1AjBHBCpj9VnduMSeqoMRhZZHbhPYiND7tucRRJ8vwGU0sYK2KI/Ko+fsrNIXL/0O4F36jVPl09Smg==", "dependencies": { - "@babel/types": "^7.25.9" + "tslib": "^2.3.0" }, "engines": { - "node": ">=6.9.0" + "node": "^18.19.1 || ^20.11.1 || >=22.0.0" + }, + "peerDependencies": { + "@angular/core": "19.0.5", + "rxjs": "^6.5.3 || ^7.4.0" } }, - "node_modules/@babel/helper-compilation-targets": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.9.tgz", - "integrity": "sha512-j9Db8Suy6yV/VHa4qzrj9yZfZxhLWQdVnRlXxmKLYlhWUVB1sB2G5sxuWYXk/whHD9iW76PmNzxZ4UCnTQTVEQ==", - "dev": true, + "node_modules/@angular/compiler": { + "version": "19.0.5", + "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-19.0.5.tgz", + "integrity": "sha512-S8ku5Ljp0kqX3shfmE9DVo09629jeYJSlBRGbj2Glb92dd+VQZPOz7KxqKRTwmAl7lQIV/+4Lr6G/GVTsoC4vg==", + "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.25.9", - "@babel/helper-validator-option": "^7.25.9", - "browserslist": "^4.24.0", - "lru-cache": "^5.1.1", - "semver": "^6.3.1" + "tslib": "^2.3.0" }, "engines": { - "node": ">=6.9.0" + "node": "^18.19.1 || ^20.11.1 || >=22.0.0" + }, + "peerDependencies": { + "@angular/core": "19.0.5" + }, + "peerDependenciesMeta": { + "@angular/core": { + "optional": true + } } }, - "node_modules/@babel/helper-compilation-targets/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "node_modules/@angular/compiler-cli": { + "version": "19.0.5", + "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-19.0.5.tgz", + "integrity": "sha512-KSzuWCTZlvJsoAenxM9cjTOzNM8mrFxDBInj0KVPz7QU83amGS4rcv1pWO/QGYQcErfskcN84TAdMegaRWWCmA==", "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "7.26.0", + "@jridgewell/sourcemap-codec": "^1.4.14", + "chokidar": "^4.0.0", + "convert-source-map": "^1.5.1", + "reflect-metadata": "^0.2.0", + "semver": "^7.0.0", + "tslib": "^2.3.0", + "yargs": "^17.2.1" + }, "bin": { - "semver": "bin/semver.js" + "ng-xi18n": "bundles/src/bin/ng_xi18n.js", + "ngc": "bundles/src/bin/ngc.js", + "ngcc": "bundles/ngcc/index.js" + }, + "engines": { + "node": "^18.19.1 || ^20.11.1 || >=22.0.0" + }, + "peerDependencies": { + "@angular/compiler": "19.0.5", + "typescript": ">=5.5 <5.7" } }, - "node_modules/@babel/helper-create-class-features-plugin": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.25.9.tgz", - "integrity": "sha512-UTZQMvt0d/rSz6KI+qdu7GQze5TIajwTS++GUozlw8VBJDEOAqSXwm1WvmYEZwqdqSGQshRocPDqrt4HBZB3fQ==", - "dev": true, + "node_modules/@angular/core": { + "version": "19.0.5", + "resolved": "https://registry.npmjs.org/@angular/core/-/core-19.0.5.tgz", + "integrity": "sha512-Ywc6sPO6G/Y1stfk3y/MallV/h0yzQ0vdOHRWueLrk5kD1DTdbolV4X03Cs3PuVvravgcSVE3nnuuHFuH32emQ==", + "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.25.9", - "@babel/helper-member-expression-to-functions": "^7.25.9", - "@babel/helper-optimise-call-expression": "^7.25.9", - "@babel/helper-replace-supers": "^7.25.9", - "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9", - "@babel/traverse": "^7.25.9", - "semver": "^6.3.1" + "tslib": "^2.3.0" }, "engines": { - "node": ">=6.9.0" + "node": "^18.19.1 || ^20.11.1 || >=22.0.0" }, "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-create-class-features-plugin/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" + "rxjs": "^6.5.3 || ^7.4.0", + "zone.js": "~0.15.0" } }, - "node_modules/@babel/helper-create-regexp-features-plugin": { - "version": "7.26.3", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.26.3.tgz", - "integrity": "sha512-G7ZRb40uUgdKOQqPLjfD12ZmGA54PzqDFUv2BKImnC9QIfGhIHKvVML0oN8IUiDq4iRqpq74ABpvOaerfWdong==", - "dev": true, + "node_modules/@angular/forms": { + "version": "19.0.5", + "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-19.0.5.tgz", + "integrity": "sha512-OhNFkfOoguqCDq07vNBV28FFrmTM8S11Z3Cd6PQZJJF9TgAtpV5KtF7A3eXBCN92W4pmqluomPjfK7YyImzIYQ==", + "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.25.9", - "regexpu-core": "^6.2.0", - "semver": "^6.3.1" + "tslib": "^2.3.0" }, "engines": { - "node": ">=6.9.0" + "node": "^18.19.1 || ^20.11.1 || >=22.0.0" }, "peerDependencies": { - "@babel/core": "^7.0.0" + "@angular/common": "19.0.5", + "@angular/core": "19.0.5", + "@angular/platform-browser": "19.0.5", + "rxjs": "^6.5.3 || ^7.4.0" } }, - "node_modules/@babel/helper-create-regexp-features-plugin/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "node_modules/@angular/language-service": { + "version": "19.0.5", + "resolved": "https://registry.npmjs.org/@angular/language-service/-/language-service-19.0.5.tgz", + "integrity": "sha512-E4WFEsCzHuF3DYe4EfOCiMGW1zWmq3UYi5XXOBNLyzWDvwU5xTfdme6ECXGawHMc2kCaWMVNL4DzYpVsUgLG0w==", "dev": true, - "bin": { - "semver": "bin/semver.js" + "license": "MIT", + "engines": { + "node": "^18.19.1 || ^20.11.1 || >=22.0.0" } }, - "node_modules/@babel/helper-define-polyfill-provider": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.3.tgz", - "integrity": "sha512-HK7Bi+Hj6H+VTHA3ZvBis7V/6hu9QuTrnMXNybfUf2iiuU/N97I8VjB+KbhFF8Rld/Lx5MzoCwPCpPjfK+n8Cg==", - "dev": true, + "node_modules/@angular/platform-browser": { + "version": "19.0.5", + "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-19.0.5.tgz", + "integrity": "sha512-41+Jo5DEil4Ifvv+UE/p1l9YJtYN+xfhx+/C9cahVgvV5D2q+givyK73d0Mnb6XOfe1q+hoV5lZ+XhQYp21//g==", + "license": "MIT", "dependencies": { - "@babel/helper-compilation-targets": "^7.22.6", - "@babel/helper-plugin-utils": "^7.22.5", - "debug": "^4.1.1", - "lodash.debounce": "^4.0.8", - "resolve": "^1.14.2" + "tslib": "^2.3.0" + }, + "engines": { + "node": "^18.19.1 || ^20.11.1 || >=22.0.0" }, "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + "@angular/animations": "19.0.5", + "@angular/common": "19.0.5", + "@angular/core": "19.0.5" + }, + "peerDependenciesMeta": { + "@angular/animations": { + "optional": true + } } }, - "node_modules/@babel/helper-member-expression-to-functions": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.25.9.tgz", - "integrity": "sha512-wbfdZ9w5vk0C0oyHqAJbc62+vet5prjj01jjJ8sKn3j9h3MQQlflEdXYvuqRWjHnM12coDEqiC1IRCi0U/EKwQ==", - "dev": true, + "node_modules/@angular/platform-browser-dynamic": { + "version": "19.0.5", + "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-19.0.5.tgz", + "integrity": "sha512-KKFdue/uJVxkWdrntRAXkz+ycp4nD3SuGOH5pPf2svCBxieuHuFlWDi+DYVuFSEpC/ICCmlhrtzIAm44A4qzzQ==", + "license": "MIT", "dependencies": { - "@babel/traverse": "^7.25.9", - "@babel/types": "^7.25.9" + "tslib": "^2.3.0" }, "engines": { - "node": ">=6.9.0" + "node": "^18.19.1 || ^20.11.1 || >=22.0.0" + }, + "peerDependencies": { + "@angular/common": "19.0.5", + "@angular/compiler": "19.0.5", + "@angular/core": "19.0.5", + "@angular/platform-browser": "19.0.5" } }, - "node_modules/@babel/helper-module-imports": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz", - "integrity": "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==", - "dev": true, + "node_modules/@angular/router": { + "version": "19.0.5", + "resolved": "https://registry.npmjs.org/@angular/router/-/router-19.0.5.tgz", + "integrity": "sha512-6tNubVVj/rRyTg+OXjQxACfufvCLHAwDQtv9wqt6q/3OYSnysHTik3ho3FaFPwu7fXJ+6p9Rjzkh2VY9QMk4bw==", + "license": "MIT", "dependencies": { - "@babel/traverse": "^7.25.9", - "@babel/types": "^7.25.9" + "tslib": "^2.3.0" }, "engines": { - "node": ">=6.9.0" + "node": "^18.19.1 || ^20.11.1 || >=22.0.0" + }, + "peerDependencies": { + "@angular/common": "19.0.5", + "@angular/core": "19.0.5", + "@angular/platform-browser": "19.0.5", + "rxjs": "^6.5.3 || ^7.4.0" } }, - "node_modules/@babel/helper-module-transforms": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz", - "integrity": "sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==", - "dev": true, + "node_modules/@angular/service-worker": { + "version": "19.0.5", + "resolved": "https://registry.npmjs.org/@angular/service-worker/-/service-worker-19.0.5.tgz", + "integrity": "sha512-qU5lgx1WJ+feCOV/EhkN9m20xFdIslpEQcSZZC+VJnEwcG6VTbofg1dRaHWZ9HAjS1uP7bFoK0HUYu4el0bHGA==", + "license": "MIT", "dependencies": { - "@babel/helper-module-imports": "^7.25.9", - "@babel/helper-validator-identifier": "^7.25.9", - "@babel/traverse": "^7.25.9" + "tslib": "^2.3.0" + }, + "bin": { + "ngsw-config": "ngsw-config.js" }, "engines": { - "node": ">=6.9.0" + "node": "^18.19.1 || ^20.11.1 || >=22.0.0" }, "peerDependencies": { - "@babel/core": "^7.0.0" + "@angular/common": "19.0.5", + "@angular/core": "19.0.5" } }, - "node_modules/@babel/helper-optimise-call-expression": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.25.9.tgz", - "integrity": "sha512-FIpuNaz5ow8VyrYcnXQTDRGvV6tTjkNtCK/RYNDXGSLlUD6cBuQTSw43CShGxjvfBTfcUA/r6UhUCbtYqkhcuQ==", - "dev": true, + "node_modules/@awesome-cordova-plugins/core": { + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/@awesome-cordova-plugins/core/-/core-6.14.0.tgz", + "integrity": "sha512-oJdmzR8DA/dyZnKlXBnjav0ZNTCacGMEWZOxnrnXqr3I7nVEK0Kr2EIJx7CtAIXxFCpEjQQTH7loFur86O3xpw==", "dependencies": { - "@babel/types": "^7.25.9" + "@types/cordova": "latest" }, - "engines": { - "node": ">=6.9.0" + "peerDependencies": { + "rxjs": "^5.5.0 || ^6.5.0 || ^7.3.0" } }, - "node_modules/@babel/helper-plugin-utils": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.25.9.tgz", - "integrity": "sha512-kSMlyUVdWe25rEsRGviIgOWnoT/nfABVWlqt9N19/dIPWViAOW2s9wznP5tURbs/IDuNk4gPy3YdYRgH3uxhBw==", + "node_modules/@awesome-cordova-plugins/file-opener": { + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/@awesome-cordova-plugins/file-opener/-/file-opener-6.14.0.tgz", + "integrity": "sha512-EN4SfDWs99zN12pbEMk+NjqDEUbZbOe3Eq9ItTJIT7cyIS2PF+w2qT2QmhnBZdmYOqecIngqmjj+3w+zQnEt+w==", + "dependencies": { + "@types/cordova": "latest" + }, + "peerDependencies": { + "@awesome-cordova-plugins/core": "^6.0.1", + "rxjs": "^5.5.0 || ^6.5.0 || ^7.3.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", + "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.25.9", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" + }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/helper-remap-async-to-generator": { - "version": "7.25.9", + "node_modules/@babel/compat-data": { + "version": "7.26.3", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.3.tgz", + "integrity": "sha512-nHIxvKPniQXpmQLb0vhY3VaFb3S0YrTAwpOWJZh1wn3oJPjJk9Asva204PsBdmAE8vpzfHudT8DB0scYvy9q0g==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.0.tgz", + "integrity": "sha512-i1SLeK+DzNnQ3LL/CswPCa/E5u4lh1k6IAEphON8F+cXt0t9euTshDru0q7/IqMa1PMPz5RnHuHscF8/ZJsStg==", + "dev": true, + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.26.0", + "@babel/generator": "^7.26.0", + "@babel/helper-compilation-targets": "^7.25.9", + "@babel/helper-module-transforms": "^7.26.0", + "@babel/helpers": "^7.26.0", + "@babel/parser": "^7.26.0", + "@babel/template": "^7.25.9", + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.26.0", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/core/node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true + }, + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/generator": { + "version": "7.26.3", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.3.tgz", + "integrity": "sha512-6FF/urZvD0sTeO7k6/B15pMLC4CHUv1426lzr3N01aHJTl046uCAh9LXW/fzeXXjPNCJ6iABW5XaWOsIZB93aQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.26.3", + "@babel/types": "^7.26.3", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-annotate-as-pure": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.25.9.tgz", + "integrity": "sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g==", + "dev": true, + "dependencies": { + "@babel/types": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.9.tgz", + "integrity": "sha512-j9Db8Suy6yV/VHa4qzrj9yZfZxhLWQdVnRlXxmKLYlhWUVB1sB2G5sxuWYXk/whHD9iW76PmNzxZ4UCnTQTVEQ==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.25.9", + "@babel/helper-validator-option": "^7.25.9", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-create-class-features-plugin": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.25.9.tgz", + "integrity": "sha512-UTZQMvt0d/rSz6KI+qdu7GQze5TIajwTS++GUozlw8VBJDEOAqSXwm1WvmYEZwqdqSGQshRocPDqrt4HBZB3fQ==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.25.9", + "@babel/helper-member-expression-to-functions": "^7.25.9", + "@babel/helper-optimise-call-expression": "^7.25.9", + "@babel/helper-replace-supers": "^7.25.9", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9", + "@babel/traverse": "^7.25.9", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-class-features-plugin/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-create-regexp-features-plugin": { + "version": "7.26.3", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.26.3.tgz", + "integrity": "sha512-G7ZRb40uUgdKOQqPLjfD12ZmGA54PzqDFUv2BKImnC9QIfGhIHKvVML0oN8IUiDq4iRqpq74ABpvOaerfWdong==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.25.9", + "regexpu-core": "^6.2.0", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-regexp-features-plugin/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-define-polyfill-provider": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.3.tgz", + "integrity": "sha512-HK7Bi+Hj6H+VTHA3ZvBis7V/6hu9QuTrnMXNybfUf2iiuU/N97I8VjB+KbhFF8Rld/Lx5MzoCwPCpPjfK+n8Cg==", + "dev": true, + "dependencies": { + "@babel/helper-compilation-targets": "^7.22.6", + "@babel/helper-plugin-utils": "^7.22.5", + "debug": "^4.1.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.14.2" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@babel/helper-member-expression-to-functions": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.25.9.tgz", + "integrity": "sha512-wbfdZ9w5vk0C0oyHqAJbc62+vet5prjj01jjJ8sKn3j9h3MQQlflEdXYvuqRWjHnM12coDEqiC1IRCi0U/EKwQ==", + "dev": true, + "dependencies": { + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz", + "integrity": "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==", + "dev": true, + "dependencies": { + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz", + "integrity": "sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==", + "dev": true, + "dependencies": { + "@babel/helper-module-imports": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9", + "@babel/traverse": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-optimise-call-expression": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.25.9.tgz", + "integrity": "sha512-FIpuNaz5ow8VyrYcnXQTDRGvV6tTjkNtCK/RYNDXGSLlUD6cBuQTSw43CShGxjvfBTfcUA/r6UhUCbtYqkhcuQ==", + "dev": true, + "dependencies": { + "@babel/types": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.25.9.tgz", + "integrity": "sha512-kSMlyUVdWe25rEsRGviIgOWnoT/nfABVWlqt9N19/dIPWViAOW2s9wznP5tURbs/IDuNk4gPy3YdYRgH3uxhBw==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-remap-async-to-generator": { + "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.25.9.tgz", "integrity": "sha512-IZtukuUeBbhgOcaW2s06OXTzVNJR0ybm4W5xC1opWFFJMZbwRj5LCk+ByYH7WdZPZTt8KnFwA8pvjN2yqcPlgw==", "dev": true, @@ -1442,6 +1821,16 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-transform-classes/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/@babel/plugin-transform-computed-properties": { "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.25.9.tgz", @@ -2277,20 +2666,14 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/traverse/node_modules/@babel/generator": { - "version": "7.26.3", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.3.tgz", - "integrity": "sha512-6FF/urZvD0sTeO7k6/B15pMLC4CHUv1426lzr3N01aHJTl046uCAh9LXW/fzeXXjPNCJ6iABW5XaWOsIZB93aQ==", + "node_modules/@babel/traverse/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", "dev": true, - "dependencies": { - "@babel/parser": "^7.26.3", - "@babel/types": "^7.26.3", - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25", - "jsesc": "^3.0.2" - }, + "license": "MIT", "engines": { - "node": ">=6.9.0" + "node": ">=4" } }, "node_modules/@babel/types": { @@ -2664,9 +3047,9 @@ } }, "node_modules/@esbuild/aix-ppc64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.24.0.tgz", - "integrity": "sha512-WtKdFM7ls47zkKHFVzMz8opM7LkcsIp9amDUBIAWirg70RM71WRSjdILPsY5Uv1D42ZpUfaPILDlfactHgsRkw==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.24.2.tgz", + "integrity": "sha512-thpVCb/rhxE/BnMLQ7GReQLLN8q9qbHmI55F4489/ByVg2aQaQ6kbcLb6FHkocZzQhxc4gx0sCk0tJkKBFzDhA==", "cpu": [ "ppc64" ], @@ -2681,9 +3064,9 @@ } }, "node_modules/@esbuild/android-arm": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.24.0.tgz", - "integrity": "sha512-arAtTPo76fJ/ICkXWetLCc9EwEHKaeya4vMrReVlEIUCAUncH7M4bhMQ+M9Vf+FFOZJdTNMXNBrWwW+OXWpSew==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.24.2.tgz", + "integrity": "sha512-tmwl4hJkCfNHwFB3nBa8z1Uy3ypZpxqxfTQOcHX+xRByyYgunVbZ9MzUUfb0RxaHIMnbHagwAxuTL+tnNM+1/Q==", "cpu": [ "arm" ], @@ -2698,9 +3081,9 @@ } }, "node_modules/@esbuild/android-arm64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.24.0.tgz", - "integrity": "sha512-Vsm497xFM7tTIPYK9bNTYJyF/lsP590Qc1WxJdlB6ljCbdZKU9SY8i7+Iin4kyhV/KV5J2rOKsBQbB77Ab7L/w==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.24.2.tgz", + "integrity": "sha512-cNLgeqCqV8WxfcTIOeL4OAtSmL8JjcN6m09XIgro1Wi7cF4t/THaWEa7eL5CMoMBdjoHOTh/vwTO/o2TRXIyzg==", "cpu": [ "arm64" ], @@ -2715,9 +3098,9 @@ } }, "node_modules/@esbuild/android-x64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.24.0.tgz", - "integrity": "sha512-t8GrvnFkiIY7pa7mMgJd7p8p8qqYIz1NYiAoKc75Zyv73L3DZW++oYMSHPRarcotTKuSs6m3hTOa5CKHaS02TQ==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.24.2.tgz", + "integrity": "sha512-B6Q0YQDqMx9D7rvIcsXfmJfvUYLoP722bgfBlO5cGvNVb5V/+Y7nhBE3mHV9OpxBf4eAS2S68KZztiPaWq4XYw==", "cpu": [ "x64" ], @@ -2732,9 +3115,9 @@ } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.24.0.tgz", - "integrity": "sha512-CKyDpRbK1hXwv79soeTJNHb5EiG6ct3efd/FTPdzOWdbZZfGhpbcqIpiD0+vwmpu0wTIL97ZRPZu8vUt46nBSw==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.24.2.tgz", + "integrity": "sha512-kj3AnYWc+CekmZnS5IPu9D+HWtUI49hbnyqk0FLEJDbzCIQt7hg7ucF1SQAilhtYpIujfaHr6O0UHlzzSPdOeA==", "cpu": [ "arm64" ], @@ -2749,9 +3132,9 @@ } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.24.0.tgz", - "integrity": "sha512-rgtz6flkVkh58od4PwTRqxbKH9cOjaXCMZgWD905JOzjFKW+7EiUObfd/Kav+A6Gyud6WZk9w+xu6QLytdi2OA==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.24.2.tgz", + "integrity": "sha512-WeSrmwwHaPkNR5H3yYfowhZcbriGqooyu3zI/3GGpF8AyUdsrrP0X6KumITGA9WOyiJavnGZUwPGvxvwfWPHIA==", "cpu": [ "x64" ], @@ -2766,9 +3149,9 @@ } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.24.0.tgz", - "integrity": "sha512-6Mtdq5nHggwfDNLAHkPlyLBpE5L6hwsuXZX8XNmHno9JuL2+bg2BX5tRkwjyfn6sKbxZTq68suOjgWqCicvPXA==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.24.2.tgz", + "integrity": "sha512-UN8HXjtJ0k/Mj6a9+5u6+2eZ2ERD7Edt1Q9IZiB5UZAIdPnVKDoG7mdTVGhHJIeEml60JteamR3qhsr1r8gXvg==", "cpu": [ "arm64" ], @@ -2783,9 +3166,9 @@ } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.24.0.tgz", - "integrity": "sha512-D3H+xh3/zphoX8ck4S2RxKR6gHlHDXXzOf6f/9dbFt/NRBDIE33+cVa49Kil4WUjxMGW0ZIYBYtaGCa2+OsQwQ==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.24.2.tgz", + "integrity": "sha512-TvW7wE/89PYW+IevEJXZ5sF6gJRDY/14hyIGFXdIucxCsbRmLUcjseQu1SyTko+2idmCw94TgyaEZi9HUSOe3Q==", "cpu": [ "x64" ], @@ -2800,9 +3183,9 @@ } }, "node_modules/@esbuild/linux-arm": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.24.0.tgz", - "integrity": "sha512-gJKIi2IjRo5G6Glxb8d3DzYXlxdEj2NlkixPsqePSZMhLudqPhtZ4BUrpIuTjJYXxvF9njql+vRjB2oaC9XpBw==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.24.2.tgz", + "integrity": "sha512-n0WRM/gWIdU29J57hJyUdIsk0WarGd6To0s+Y+LwvlC55wt+GT/OgkwoXCXvIue1i1sSNWblHEig00GBWiJgfA==", "cpu": [ "arm" ], @@ -2817,9 +3200,9 @@ } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.24.0.tgz", - "integrity": "sha512-TDijPXTOeE3eaMkRYpcy3LarIg13dS9wWHRdwYRnzlwlA370rNdZqbcp0WTyyV/k2zSxfko52+C7jU5F9Tfj1g==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.24.2.tgz", + "integrity": "sha512-7HnAD6074BW43YvvUmE/35Id9/NB7BeX5EoNkK9obndmZBUk8xmJJeU7DwmUeN7tkysslb2eSl6CTrYz6oEMQg==", "cpu": [ "arm64" ], @@ -2834,9 +3217,9 @@ } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.24.0.tgz", - "integrity": "sha512-K40ip1LAcA0byL05TbCQ4yJ4swvnbzHscRmUilrmP9Am7//0UjPreh4lpYzvThT2Quw66MhjG//20mrufm40mA==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.24.2.tgz", + "integrity": "sha512-sfv0tGPQhcZOgTKO3oBE9xpHuUqguHvSo4jl+wjnKwFpapx+vUDcawbwPNuBIAYdRAvIDBfZVvXprIj3HA+Ugw==", "cpu": [ "ia32" ], @@ -2851,9 +3234,9 @@ } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.24.0.tgz", - "integrity": "sha512-0mswrYP/9ai+CU0BzBfPMZ8RVm3RGAN/lmOMgW4aFUSOQBjA31UP8Mr6DDhWSuMwj7jaWOT0p0WoZ6jeHhrD7g==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.24.2.tgz", + "integrity": "sha512-CN9AZr8kEndGooS35ntToZLTQLHEjtVB5n7dl8ZcTZMonJ7CCfStrYhrzF97eAecqVbVJ7APOEe18RPI4KLhwQ==", "cpu": [ "loong64" ], @@ -2868,9 +3251,9 @@ } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.24.0.tgz", - "integrity": "sha512-hIKvXm0/3w/5+RDtCJeXqMZGkI2s4oMUGj3/jM0QzhgIASWrGO5/RlzAzm5nNh/awHE0A19h/CvHQe6FaBNrRA==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.24.2.tgz", + "integrity": "sha512-iMkk7qr/wl3exJATwkISxI7kTcmHKE+BlymIAbHO8xanq/TjHaaVThFF6ipWzPHryoFsesNQJPE/3wFJw4+huw==", "cpu": [ "mips64el" ], @@ -2885,9 +3268,9 @@ } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.24.0.tgz", - "integrity": "sha512-HcZh5BNq0aC52UoocJxaKORfFODWXZxtBaaZNuN3PUX3MoDsChsZqopzi5UupRhPHSEHotoiptqikjN/B77mYQ==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.24.2.tgz", + "integrity": "sha512-shsVrgCZ57Vr2L8mm39kO5PPIb+843FStGt7sGGoqiiWYconSxwTiuswC1VJZLCjNiMLAMh34jg4VSEQb+iEbw==", "cpu": [ "ppc64" ], @@ -2902,9 +3285,9 @@ } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.24.0.tgz", - "integrity": "sha512-bEh7dMn/h3QxeR2KTy1DUszQjUrIHPZKyO6aN1X4BCnhfYhuQqedHaa5MxSQA/06j3GpiIlFGSsy1c7Gf9padw==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.24.2.tgz", + "integrity": "sha512-4eSFWnU9Hhd68fW16GD0TINewo1L6dRrB+oLNNbYyMUAeOD2yCK5KXGK1GH4qD/kT+bTEXjsyTCiJGHPZ3eM9Q==", "cpu": [ "riscv64" ], @@ -2919,9 +3302,9 @@ } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.24.0.tgz", - "integrity": "sha512-ZcQ6+qRkw1UcZGPyrCiHHkmBaj9SiCD8Oqd556HldP+QlpUIe2Wgn3ehQGVoPOvZvtHm8HPx+bH20c9pvbkX3g==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.24.2.tgz", + "integrity": "sha512-S0Bh0A53b0YHL2XEXC20bHLuGMOhFDO6GN4b3YjRLK//Ep3ql3erpNcPlEFed93hsQAjAQDNsvcK+hV90FubSw==", "cpu": [ "s390x" ], @@ -2936,9 +3319,9 @@ } }, "node_modules/@esbuild/linux-x64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.24.0.tgz", - "integrity": "sha512-vbutsFqQ+foy3wSSbmjBXXIJ6PL3scghJoM8zCL142cGaZKAdCZHyf+Bpu/MmX9zT9Q0zFBVKb36Ma5Fzfa8xA==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.24.2.tgz", + "integrity": "sha512-8Qi4nQcCTbLnK9WoMjdC9NiTG6/E38RNICU6sUNqK0QFxCYgoARqVqxdFmWkdonVsvGqWhmm7MO0jyTqLqwj0Q==", "cpu": [ "x64" ], @@ -2952,10 +3335,27 @@ "node": ">=18" } }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.24.2.tgz", + "integrity": "sha512-wuLK/VztRRpMt9zyHSazyCVdCXlpHkKm34WUyinD2lzK07FAHTq0KQvZZlXikNWkDGoT6x3TD51jKQ7gMVpopw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.24.0.tgz", - "integrity": "sha512-hjQ0R/ulkO8fCYFsG0FZoH+pWgTTDreqpqY7UnQntnaKv95uP5iW3+dChxnx7C3trQQU40S+OgWhUVwCjVFLvg==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.24.2.tgz", + "integrity": "sha512-VefFaQUc4FMmJuAxmIHgUmfNiLXY438XrL4GDNV1Y1H/RW3qow68xTwjZKfj/+Plp9NANmzbH5R40Meudu8mmw==", "cpu": [ "x64" ], @@ -2970,9 +3370,9 @@ } }, "node_modules/@esbuild/openbsd-arm64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.24.0.tgz", - "integrity": "sha512-MD9uzzkPQbYehwcN583yx3Tu5M8EIoTD+tUgKF982WYL9Pf5rKy9ltgD0eUgs8pvKnmizxjXZyLt0z6DC3rRXg==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.24.2.tgz", + "integrity": "sha512-YQbi46SBct6iKnszhSvdluqDmxCJA+Pu280Av9WICNwQmMxV7nLRHZfjQzwbPs3jeWnuAhE9Jy0NrnJ12Oz+0A==", "cpu": [ "arm64" ], @@ -2987,9 +3387,9 @@ } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.24.0.tgz", - "integrity": "sha512-4ir0aY1NGUhIC1hdoCzr1+5b43mw99uNwVzhIq1OY3QcEwPDO3B7WNXBzaKY5Nsf1+N11i1eOfFcq+D/gOS15Q==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.24.2.tgz", + "integrity": "sha512-+iDS6zpNM6EnJyWv0bMGLWSWeXGN/HTaF/LXHXHwejGsVi+ooqDfMCCTerNFxEkM3wYVcExkeGXNqshc9iMaOA==", "cpu": [ "x64" ], @@ -3004,9 +3404,9 @@ } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.24.0.tgz", - "integrity": "sha512-jVzdzsbM5xrotH+W5f1s+JtUy1UWgjU0Cf4wMvffTB8m6wP5/kx0KiaLHlbJO+dMgtxKV8RQ/JvtlFcdZ1zCPA==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.24.2.tgz", + "integrity": "sha512-hTdsW27jcktEvpwNHJU4ZwWFGkz2zRJUz8pvddmXPtXDzVKTTINmlmga3ZzwcuMpUvLw7JkLy9QLKyGpD2Yxig==", "cpu": [ "x64" ], @@ -3021,9 +3421,9 @@ } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.24.0.tgz", - "integrity": "sha512-iKc8GAslzRpBytO2/aN3d2yb2z8XTVfNV0PjGlCxKo5SgWmNXx82I/Q3aG1tFfS+A2igVCY97TJ8tnYwpUWLCA==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.24.2.tgz", + "integrity": "sha512-LihEQ2BBKVFLOC9ZItT9iFprsE9tqjDjnbulhHoFxYQtQfai7qfluVODIYxt1PgdoyQkz23+01rzwNwYfutxUQ==", "cpu": [ "arm64" ], @@ -3038,9 +3438,9 @@ } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.24.0.tgz", - "integrity": "sha512-vQW36KZolfIudCcTnaTpmLQ24Ha1RjygBo39/aLkM2kmjkWmZGEJ5Gn9l5/7tzXA42QGIoWbICfg6KLLkIw6yw==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.24.2.tgz", + "integrity": "sha512-q+iGUwfs8tncmFC9pcnD5IvRHAzmbwQ3GPS5/ceCyHdjXubwQWI12MKWSNSMYLJMq23/IUCvJMS76PDqXe1fxA==", "cpu": [ "ia32" ], @@ -3055,9 +3455,9 @@ } }, "node_modules/@esbuild/win32-x64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.24.0.tgz", - "integrity": "sha512-7IAFPrjSQIJrGsK6flwg7NFmwBoSTyF3rl7If0hNUFQU4ilTsEPL6GuMuU9BfIWVVGuRnuIidkSMC+c0Otu8IA==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.24.2.tgz", + "integrity": "sha512-7VTgWzgMGvup6aSqDPLiW5zHaxYJGTO4OokMjIlrCtf+VpEL+cXKtCvg723iguPYI5oaUNdS+/V7OU2gvXVWEg==", "cpu": [ "x64" ], @@ -3357,13 +3757,14 @@ } }, "node_modules/@inquirer/confirm": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-5.1.0.tgz", - "integrity": "sha512-osaBbIMEqVFjTX5exoqPXs6PilWQdjaLhGtMDXMXg/yxkHXNq43GlxGyTA35lK2HpzUgDN+Cjh/2AmqCN0QJpw==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-5.1.1.tgz", + "integrity": "sha512-vVLSbGci+IKQvDOtzpPTCOiEJCNidHcAq9JYVoWTW0svb5FiwSLotkM+JXNXejfjnzVYV9n0DTBythl9+XgTxg==", "dev": true, + "license": "MIT", "dependencies": { - "@inquirer/core": "^10.1.1", - "@inquirer/type": "^3.0.1" + "@inquirer/core": "^10.1.2", + "@inquirer/type": "^3.0.2" }, "engines": { "node": ">=18" @@ -3373,18 +3774,18 @@ } }, "node_modules/@inquirer/core": { - "version": "10.1.1", - "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-10.1.1.tgz", - "integrity": "sha512-rmZVXy9iZvO3ZStEe/ayuuwIJ23LSF13aPMlLMTQARX6lGUBDHGV8UB5i9MRrfy0+mZwt5/9bdy8llszSD3NQA==", + "version": "10.1.5", + "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-10.1.5.tgz", + "integrity": "sha512-/vyCWhET0ktav/mUeBqJRYTwmjFPIKPRYb3COAw7qORULgipGSUO2vL32lQKki3UxDKJ8BvuEbokaoyCA6YlWw==", "dev": true, + "license": "MIT", "dependencies": { - "@inquirer/figures": "^1.0.8", - "@inquirer/type": "^3.0.1", + "@inquirer/figures": "^1.0.10", + "@inquirer/type": "^3.0.3", "ansi-escapes": "^4.3.2", "cli-width": "^4.1.0", "mute-stream": "^2.0.0", "signal-exit": "^4.1.0", - "strip-ansi": "^6.0.1", "wrap-ansi": "^6.2.0", "yoctocolors-cjs": "^2.1.2" }, @@ -3427,10 +3828,11 @@ } }, "node_modules/@inquirer/figures": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-1.0.8.tgz", - "integrity": "sha512-tKd+jsmhq21AP1LhexC0pPwsCxEhGgAkg28byjJAd+xhmIs8LUX8JbUc3vBf3PhLxWiB5EvyBE5X7JSPAqMAqg==", + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-1.0.10.tgz", + "integrity": "sha512-Ey6176gZmeqZuY/W/nZiUyvmb1/qInjcpiZjXWi6nON+nxJpD1bxtSoBxNliGISae32n6OwbY+TSXPZ1CfS4bw==", "dev": true, + "license": "MIT", "engines": { "node": ">=18" } @@ -3563,10 +3965,11 @@ } }, "node_modules/@inquirer/type": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-3.0.1.tgz", - "integrity": "sha512-+ksJMIy92sOAiAccGpcKZUc3bYO07cADnscIxHBknEm3uNts3movSmBofc1908BNy5edKscxYeAdaX1NXkHS6A==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-3.0.3.tgz", + "integrity": "sha512-I4VIHFxUuY1bshGbXZTxCmhwaaEst9s/lll3ekok+o1Z26/ZUKdx8y1b7lsoG6rtsBDwEGfiBJ2SfirjoISLpg==", "dev": true, + "license": "MIT", "engines": { "node": ">=18" }, @@ -4520,9 +4923,9 @@ } }, "node_modules/@lmdb/lmdb-darwin-arm64": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/@lmdb/lmdb-darwin-arm64/-/lmdb-darwin-arm64-3.1.5.tgz", - "integrity": "sha512-ue5PSOzHMCIYrfvPP/MRS6hsKKLzqqhcdAvJCO8uFlDdj598EhgnacuOTuqA6uBK5rgiZXfDWyb7DVZSiBKxBA==", + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/@lmdb/lmdb-darwin-arm64/-/lmdb-darwin-arm64-3.2.2.tgz", + "integrity": "sha512-WBSJT9Z7DTol5viq+DZD2TapeWOw7mlwXxiSBHgAzqVwsaVb0h/ekMD9iu/jDD8MUA20tO9N0WEdnT06fsUp+g==", "cpu": [ "arm64" ], @@ -4534,9 +4937,9 @@ ] }, "node_modules/@lmdb/lmdb-darwin-x64": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/@lmdb/lmdb-darwin-x64/-/lmdb-darwin-x64-3.1.5.tgz", - "integrity": "sha512-CGhsb0R5vE6mMNCoSfxHFD8QTvBHM51gs4DBeigTYHWnYv2V5YpJkC4rMo5qAAFifuUcc0+a8a3SIU0c9NrfNw==", + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/@lmdb/lmdb-darwin-x64/-/lmdb-darwin-x64-3.2.2.tgz", + "integrity": "sha512-4S13kUtR7c/j/MzkTIBJCXv52hQ41LG2ukeaqw4Eng9K0pNKLFjo1sDSz96/yKhwykxrWDb13ddJ/ZqD3rAhUA==", "cpu": [ "x64" ], @@ -4548,9 +4951,9 @@ ] }, "node_modules/@lmdb/lmdb-linux-arm": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/@lmdb/lmdb-linux-arm/-/lmdb-linux-arm-3.1.5.tgz", - "integrity": "sha512-3WeW328DN+xB5PZdhSWmqE+t3+44xWXEbqQ+caWJEZfOFdLp9yklBZEbVqVdqzznkoaXJYxTCp996KD6HmANeg==", + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/@lmdb/lmdb-linux-arm/-/lmdb-linux-arm-3.2.2.tgz", + "integrity": "sha512-uW31JmfuPAaLUYW7NsEU8gzwgDAzpGPwjvkxnKlcWd8iDutoPKDJi8Wk9lFmPEZRxVSB0j1/wDQ7N2qliR9UFA==", "cpu": [ "arm" ], @@ -4562,9 +4965,9 @@ ] }, "node_modules/@lmdb/lmdb-linux-arm64": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/@lmdb/lmdb-linux-arm64/-/lmdb-linux-arm64-3.1.5.tgz", - "integrity": "sha512-LAjaoOcBHGj6fiYB8ureiqPoph4eygbXu4vcOF+hsxiY74n8ilA7rJMmGUT0K0JOB5lmRQHSmor3mytRjS4qeQ==", + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/@lmdb/lmdb-linux-arm64/-/lmdb-linux-arm64-3.2.2.tgz", + "integrity": "sha512-4hdgZtWI1idQlWRp+eleWXD9KLvObgboRaVoBj2POdPEYvsKANllvMW0El8tEQwtw74yB9NT6P8ENBB5UJf5+g==", "cpu": [ "arm64" ], @@ -4576,9 +4979,9 @@ ] }, "node_modules/@lmdb/lmdb-linux-x64": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/@lmdb/lmdb-linux-x64/-/lmdb-linux-x64-3.1.5.tgz", - "integrity": "sha512-k/IklElP70qdCXOQixclSl2GPLFiopynGoKX1FqDd1/H0E3Fo1oPwjY2rEVu+0nS3AOw1sryStdXk8CW3cVIsw==", + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/@lmdb/lmdb-linux-x64/-/lmdb-linux-x64-3.2.2.tgz", + "integrity": "sha512-A0zjf4a2vM4B4GAx78ncuOTZ8Ka1DbTaG1Axf1e00Sa7f5coqlWiLg1PX7Gxvyibc2YqtqB+8tg1KKrE8guZVw==", "cpu": [ "x64" ], @@ -4590,9 +4993,9 @@ ] }, "node_modules/@lmdb/lmdb-win32-x64": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/@lmdb/lmdb-win32-x64/-/lmdb-win32-x64-3.1.5.tgz", - "integrity": "sha512-KYar6W8nraZfSJspcK7Kp7hdj238X/FNauYbZyrqPBrtsXI1hvI4/KcRcRGP50aQoV7fkKDyJERlrQGMGTZUsA==", + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/@lmdb/lmdb-win32-x64/-/lmdb-win32-x64-3.2.2.tgz", + "integrity": "sha512-Y0qoSCAja+xZE7QQ0LCHoYAuyI1n9ZqukQJa8lv9X3yCvWahFF7OYHAgVH1ejp43XWstj3U89/PAAzcowgF/uQ==", "cpu": [ "x64" ], @@ -4993,9 +5396,9 @@ } }, "node_modules/@ngtools/webpack": { - "version": "19.0.6", - "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-19.0.6.tgz", - "integrity": "sha512-eWrIb0tS1CK6+JvFS4GgTD4fN9TtmApKrlaj3pPQXKXKKd42361ec85fuQQXdb4G8eEEq0vyd/bn4NJllh/3vw==", + "version": "19.1.5", + "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-19.1.5.tgz", + "integrity": "sha512-oIpE5Ci/Gl2iZqa0Hs6IOxaXEDHkF/zisHcflzYGkMnYcSFj+wRgYEuBFaHLCwuxQf9OdGu31i05w849i6tY1Q==", "dev": true, "license": "MIT", "engines": { @@ -5005,7 +5408,7 @@ }, "peerDependencies": { "@angular/compiler-cli": "^19.0.0", - "typescript": ">=5.5 <5.7", + "typescript": ">=5.5 <5.8", "webpack": "^5.54.0" } }, @@ -5563,11 +5966,12 @@ } }, "node_modules/@parcel/watcher": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.0.tgz", - "integrity": "sha512-i0GV1yJnm2n3Yq1qw6QrUrd/LI9bE8WEBOTtOkpCXHHdyN3TAGgqAK/DAT05z4fq2x04cARXt2pDmjWjL92iTQ==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.1.tgz", + "integrity": "sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg==", "dev": true, "hasInstallScript": true, + "license": "MIT", "optional": true, "dependencies": { "detect-libc": "^1.0.3", @@ -5583,29 +5987,30 @@ "url": "https://opencollective.com/parcel" }, "optionalDependencies": { - "@parcel/watcher-android-arm64": "2.5.0", - "@parcel/watcher-darwin-arm64": "2.5.0", - "@parcel/watcher-darwin-x64": "2.5.0", - "@parcel/watcher-freebsd-x64": "2.5.0", - "@parcel/watcher-linux-arm-glibc": "2.5.0", - "@parcel/watcher-linux-arm-musl": "2.5.0", - "@parcel/watcher-linux-arm64-glibc": "2.5.0", - "@parcel/watcher-linux-arm64-musl": "2.5.0", - "@parcel/watcher-linux-x64-glibc": "2.5.0", - "@parcel/watcher-linux-x64-musl": "2.5.0", - "@parcel/watcher-win32-arm64": "2.5.0", - "@parcel/watcher-win32-ia32": "2.5.0", - "@parcel/watcher-win32-x64": "2.5.0" + "@parcel/watcher-android-arm64": "2.5.1", + "@parcel/watcher-darwin-arm64": "2.5.1", + "@parcel/watcher-darwin-x64": "2.5.1", + "@parcel/watcher-freebsd-x64": "2.5.1", + "@parcel/watcher-linux-arm-glibc": "2.5.1", + "@parcel/watcher-linux-arm-musl": "2.5.1", + "@parcel/watcher-linux-arm64-glibc": "2.5.1", + "@parcel/watcher-linux-arm64-musl": "2.5.1", + "@parcel/watcher-linux-x64-glibc": "2.5.1", + "@parcel/watcher-linux-x64-musl": "2.5.1", + "@parcel/watcher-win32-arm64": "2.5.1", + "@parcel/watcher-win32-ia32": "2.5.1", + "@parcel/watcher-win32-x64": "2.5.1" } }, "node_modules/@parcel/watcher-android-arm64": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.0.tgz", - "integrity": "sha512-qlX4eS28bUcQCdribHkg/herLe+0A9RyYC+mm2PXpncit8z5b3nSqGVzMNR3CmtAOgRutiZ02eIJJgP/b1iEFQ==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.1.tgz", + "integrity": "sha512-KF8+j9nNbUN8vzOFDpRMsaKBHZ/mcjEjMToVMJOhTozkDonQFFrRcfdLWn6yWKCmJKmdVxSgHiYvTCef4/qcBA==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "android" @@ -5619,13 +6024,14 @@ } }, "node_modules/@parcel/watcher-darwin-arm64": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.0.tgz", - "integrity": "sha512-hyZ3TANnzGfLpRA2s/4U1kbw2ZI4qGxaRJbBH2DCSREFfubMswheh8TeiC1sGZ3z2jUf3s37P0BBlrD3sjVTUw==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.1.tgz", + "integrity": "sha512-eAzPv5osDmZyBhou8PoF4i6RQXAfeKL9tjb3QzYuccXFMQU0ruIc/POh30ePnaOyD1UXdlKguHBmsTs53tVoPw==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "darwin" @@ -5639,13 +6045,14 @@ } }, "node_modules/@parcel/watcher-darwin-x64": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.0.tgz", - "integrity": "sha512-9rhlwd78saKf18fT869/poydQK8YqlU26TMiNg7AIu7eBp9adqbJZqmdFOsbZ5cnLp5XvRo9wcFmNHgHdWaGYA==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.1.tgz", + "integrity": "sha512-1ZXDthrnNmwv10A0/3AJNZ9JGlzrF82i3gNQcWOzd7nJ8aj+ILyW1MTxVk35Db0u91oD5Nlk9MBiujMlwmeXZg==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "darwin" @@ -5659,13 +6066,14 @@ } }, "node_modules/@parcel/watcher-freebsd-x64": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.0.tgz", - "integrity": "sha512-syvfhZzyM8kErg3VF0xpV8dixJ+RzbUaaGaeb7uDuz0D3FK97/mZ5AJQ3XNnDsXX7KkFNtyQyFrXZzQIcN49Tw==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.1.tgz", + "integrity": "sha512-SI4eljM7Flp9yPuKi8W0ird8TI/JK6CSxju3NojVI6BjHsTyK7zxA9urjVjEKJ5MBYC+bLmMcbAWlZ+rFkLpJQ==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "freebsd" @@ -5679,13 +6087,14 @@ } }, "node_modules/@parcel/watcher-linux-arm-glibc": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.0.tgz", - "integrity": "sha512-0VQY1K35DQET3dVYWpOaPFecqOT9dbuCfzjxoQyif1Wc574t3kOSkKevULddcR9znz1TcklCE7Ht6NIxjvTqLA==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.1.tgz", + "integrity": "sha512-RCdZlEyTs8geyBkkcnPWvtXLY44BCeZKmGYRtSgtwwnHR4dxfHRG3gR99XdMEdQ7KeiDdasJwwvNSF5jKtDwdA==", "cpu": [ "arm" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -5699,13 +6108,14 @@ } }, "node_modules/@parcel/watcher-linux-arm-musl": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.0.tgz", - "integrity": "sha512-6uHywSIzz8+vi2lAzFeltnYbdHsDm3iIB57d4g5oaB9vKwjb6N6dRIgZMujw4nm5r6v9/BQH0noq6DzHrqr2pA==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.1.tgz", + "integrity": "sha512-6E+m/Mm1t1yhB8X412stiKFG3XykmgdIOqhjWj+VL8oHkKABfu/gjFj8DvLrYVHSBNC+/u5PeNrujiSQ1zwd1Q==", "cpu": [ "arm" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -5719,13 +6129,14 @@ } }, "node_modules/@parcel/watcher-linux-arm64-glibc": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.0.tgz", - "integrity": "sha512-BfNjXwZKxBy4WibDb/LDCriWSKLz+jJRL3cM/DllnHH5QUyoiUNEp3GmL80ZqxeumoADfCCP19+qiYiC8gUBjA==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.1.tgz", + "integrity": "sha512-LrGp+f02yU3BN9A+DGuY3v3bmnFUggAITBGriZHUREfNEzZh/GO06FF5u2kx8x+GBEUYfyTGamol4j3m9ANe8w==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -5739,13 +6150,14 @@ } }, "node_modules/@parcel/watcher-linux-arm64-musl": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.0.tgz", - "integrity": "sha512-S1qARKOphxfiBEkwLUbHjCY9BWPdWnW9j7f7Hb2jPplu8UZ3nes7zpPOW9bkLbHRvWM0WDTsjdOTUgW0xLBN1Q==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.1.tgz", + "integrity": "sha512-cFOjABi92pMYRXS7AcQv9/M1YuKRw8SZniCDw0ssQb/noPkRzA+HBDkwmyOJYp5wXcsTrhxO0zq1U11cK9jsFg==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -5759,13 +6171,14 @@ } }, "node_modules/@parcel/watcher-linux-x64-glibc": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.0.tgz", - "integrity": "sha512-d9AOkusyXARkFD66S6zlGXyzx5RvY+chTP9Jp0ypSTC9d4lzyRs9ovGf/80VCxjKddcUvnsGwCHWuF2EoPgWjw==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.1.tgz", + "integrity": "sha512-GcESn8NZySmfwlTsIur+49yDqSny2IhPeZfXunQi48DMugKeZ7uy1FX83pO0X22sHntJ4Ub+9k34XQCX+oHt2A==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -5779,13 +6192,14 @@ } }, "node_modules/@parcel/watcher-linux-x64-musl": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.0.tgz", - "integrity": "sha512-iqOC+GoTDoFyk/VYSFHwjHhYrk8bljW6zOhPuhi5t9ulqiYq1togGJB5e3PwYVFFfeVgc6pbz3JdQyDoBszVaA==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.1.tgz", + "integrity": "sha512-n0E2EQbatQ3bXhcH2D1XIAANAcTZkQICBPVaxMeaCVBtOpBZpWJuf7LwyWPSBDITb7In8mqQgJ7gH8CILCURXg==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -5799,13 +6213,14 @@ } }, "node_modules/@parcel/watcher-win32-arm64": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.0.tgz", - "integrity": "sha512-twtft1d+JRNkM5YbmexfcH/N4znDtjgysFaV9zvZmmJezQsKpkfLYJ+JFV3uygugK6AtIM2oADPkB2AdhBrNig==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.1.tgz", + "integrity": "sha512-RFzklRvmc3PkjKjry3hLF9wD7ppR4AKcWNzH7kXR7GUe0Igb3Nz8fyPwtZCSquGrhU5HhUNDr/mKBqj7tqA2Vw==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "win32" @@ -5819,13 +6234,14 @@ } }, "node_modules/@parcel/watcher-win32-ia32": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.0.tgz", - "integrity": "sha512-+rgpsNRKwo8A53elqbbHXdOMtY/tAtTzManTWShB5Kk54N8Q9mzNWV7tV+IbGueCbcj826MfWGU3mprWtuf1TA==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.1.tgz", + "integrity": "sha512-c2KkcVN+NJmuA7CGlaGD1qJh1cLfDnQsHjE89E60vUEMlqduHGCdCLJCID5geFVM0dOtA3ZiIO8BoEQmzQVfpQ==", "cpu": [ "ia32" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "win32" @@ -5839,13 +6255,14 @@ } }, "node_modules/@parcel/watcher-win32-x64": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.0.tgz", - "integrity": "sha512-lPrxve92zEHdgeff3aiu4gDOIt4u7sJYha6wbdEZDCDUhtjTsOMiaJzG5lMY4GkWH8p0fMmO2Ppq5G5XXG+DQw==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.1.tgz", + "integrity": "sha512-9lHBdJITeNR++EvSQVUcaZoWupyHfXe1jZvGZ06O/5MflPcuPLtEphScIBL+AiCWBO46tDSHzWyD0uDmmZqsgA==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "win32" @@ -5891,9 +6308,9 @@ } }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.26.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.26.0.tgz", - "integrity": "sha512-gJNwtPDGEaOEgejbaseY6xMFu+CPltsc8/T+diUTTbOQLqD+bnrJq9ulH6WD69TqwqWmrfRAtUv30cCFZlbGTQ==", + "version": "4.34.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.34.0.tgz", + "integrity": "sha512-Eeao7ewDq79jVEsrtWIj5RNqB8p2knlm9fhR6uJ2gqP7UfbLrTrxevudVrEPDM7Wkpn/HpRC2QfazH7MXLz3vQ==", "cpu": [ "arm" ], @@ -5905,9 +6322,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.26.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.26.0.tgz", - "integrity": "sha512-YJa5Gy8mEZgz5JquFruhJODMq3lTHWLm1fOy+HIANquLzfIOzE9RA5ie3JjCdVb9r46qfAQY/l947V0zfGJ0OQ==", + "version": "4.34.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.34.0.tgz", + "integrity": "sha512-yVh0Kf1f0Fq4tWNf6mWcbQBCLDpDrDEl88lzPgKhrgTcDrTtlmun92ywEF9dCjmYO3EFiSuJeeo9cYRxl2FswA==", "cpu": [ "arm64" ], @@ -5919,9 +6336,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.26.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.26.0.tgz", - "integrity": "sha512-ErTASs8YKbqTBoPLp/kA1B1Um5YSom8QAc4rKhg7b9tyyVqDBlQxy7Bf2wW7yIlPGPg2UODDQcbkTlruPzDosw==", + "version": "4.34.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.34.0.tgz", + "integrity": "sha512-gCs0ErAZ9s0Osejpc3qahTsqIPUDjSKIyxK/0BGKvL+Tn0n3Kwvj8BrCv7Y5sR1Ypz1K2qz9Ny0VvkVyoXBVUQ==", "cpu": [ "arm64" ], @@ -5933,9 +6350,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.26.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.26.0.tgz", - "integrity": "sha512-wbgkYDHcdWW+NqP2mnf2NOuEbOLzDblalrOWcPyY6+BRbVhliavon15UploG7PpBRQ2bZJnbmh8o3yLoBvDIHA==", + "version": "4.34.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.34.0.tgz", + "integrity": "sha512-aIB5Anc8hngk15t3GUkiO4pv42ykXHfmpXGS+CzM9CTyiWyT8HIS5ygRAy7KcFb/wiw4Br+vh1byqcHRTfq2tQ==", "cpu": [ "x64" ], @@ -5947,9 +6364,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.26.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.26.0.tgz", - "integrity": "sha512-Y9vpjfp9CDkAG4q/uwuhZk96LP11fBz/bYdyg9oaHYhtGZp7NrbkQrj/66DYMMP2Yo/QPAsVHkV891KyO52fhg==", + "version": "4.34.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.34.0.tgz", + "integrity": "sha512-kpdsUdMlVJMRMaOf/tIvxk8TQdzHhY47imwmASOuMajg/GXpw8GKNd8LNwIHE5Yd1onehNpcUB9jHY6wgw9nHQ==", "cpu": [ "arm64" ], @@ -5961,9 +6378,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.26.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.26.0.tgz", - "integrity": "sha512-A/jvfCZ55EYPsqeaAt/yDAG4q5tt1ZboWMHEvKAH9Zl92DWvMIbnZe/f/eOXze65aJaaKbL+YeM0Hz4kLQvdwg==", + "version": "4.34.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.34.0.tgz", + "integrity": "sha512-D0RDyHygOBCQiqookcPevrvgEarN0CttBecG4chOeIYCNtlKHmf5oi5kAVpXV7qs0Xh/WO2RnxeicZPtT50V0g==", "cpu": [ "x64" ], @@ -5975,9 +6392,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.26.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.26.0.tgz", - "integrity": "sha512-paHF1bMXKDuizaMODm2bBTjRiHxESWiIyIdMugKeLnjuS1TCS54MF5+Y5Dx8Ui/1RBPVRE09i5OUlaLnv8OGnA==", + "version": "4.34.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.34.0.tgz", + "integrity": "sha512-mCIw8j5LPDXmCOW8mfMZwT6F/Kza03EnSr4wGYEswrEfjTfVsFOxvgYfuRMxTuUF/XmRb9WSMD5GhCWDe2iNrg==", "cpu": [ "arm" ], @@ -5989,9 +6406,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.26.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.26.0.tgz", - "integrity": "sha512-cwxiHZU1GAs+TMxvgPfUDtVZjdBdTsQwVnNlzRXC5QzIJ6nhfB4I1ahKoe9yPmoaA/Vhf7m9dB1chGPpDRdGXg==", + "version": "4.34.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.34.0.tgz", + "integrity": "sha512-AwwldAu4aCJPob7zmjuDUMvvuatgs8B/QiVB0KwkUarAcPB3W+ToOT+18TQwY4z09Al7G0BvCcmLRop5zBLTag==", "cpu": [ "arm" ], @@ -6003,9 +6420,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.26.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.26.0.tgz", - "integrity": "sha512-4daeEUQutGRCW/9zEo8JtdAgtJ1q2g5oHaoQaZbMSKaIWKDQwQ3Yx0/3jJNmpzrsScIPtx/V+1AfibLisb3AMQ==", + "version": "4.34.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.34.0.tgz", + "integrity": "sha512-e7kDUGVP+xw05pV65ZKb0zulRploU3gTu6qH1qL58PrULDGxULIS0OSDQJLH7WiFnpd3ZKUU4VM3u/Z7Zw+e7Q==", "cpu": [ "arm64" ], @@ -6017,9 +6434,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.26.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.26.0.tgz", - "integrity": "sha512-eGkX7zzkNxvvS05ROzJ/cO/AKqNvR/7t1jA3VZDi2vRniLKwAWxUr85fH3NsvtxU5vnUUKFHKh8flIBdlo2b3Q==", + "version": "4.34.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.34.0.tgz", + "integrity": "sha512-SXYJw3zpwHgaBqTXeAZ31qfW/v50wq4HhNVvKFhRr5MnptRX2Af4KebLWR1wpxGJtLgfS2hEPuALRIY3LPAAcA==", "cpu": [ "arm64" ], @@ -6030,10 +6447,24 @@ "linux" ] }, + "node_modules/@rollup/rollup-linux-loongarch64-gnu": { + "version": "4.34.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.34.0.tgz", + "integrity": "sha512-e5XiCinINCI4RdyU3sFyBH4zzz7LiQRvHqDtRe9Dt8o/8hTBaYpdPimayF00eY2qy5j4PaaWK0azRgUench6WQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.26.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.26.0.tgz", - "integrity": "sha512-Odp/lgHbW/mAqw/pU21goo5ruWsytP7/HCC/liOt0zcGG0llYWKrd10k9Fj0pdj3prQ63N5yQLCLiE7HTX+MYw==", + "version": "4.34.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.34.0.tgz", + "integrity": "sha512-3SWN3e0bAsm9ToprLFBSro8nJe6YN+5xmB11N4FfNf92wvLye/+Rh5JGQtKOpwLKt6e61R1RBc9g+luLJsc23A==", "cpu": [ "ppc64" ], @@ -6045,9 +6476,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.26.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.26.0.tgz", - "integrity": "sha512-MBR2ZhCTzUgVD0OJdTzNeF4+zsVogIR1U/FsyuFerwcqjZGvg2nYe24SAHp8O5sN8ZkRVbHwlYeHqcSQ8tcYew==", + "version": "4.34.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.34.0.tgz", + "integrity": "sha512-B1Oqt3GLh7qmhvfnc2WQla4NuHlcxAD5LyueUi5WtMc76ZWY+6qDtQYqnxARx9r+7mDGfamD+8kTJO0pKUJeJA==", "cpu": [ "riscv64" ], @@ -6059,9 +6490,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.26.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.26.0.tgz", - "integrity": "sha512-YYcg8MkbN17fMbRMZuxwmxWqsmQufh3ZJFxFGoHjrE7bv0X+T6l3glcdzd7IKLiwhT+PZOJCblpnNlz1/C3kGQ==", + "version": "4.34.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.34.0.tgz", + "integrity": "sha512-UfUCo0h/uj48Jq2lnhX0AOhZPSTAq3Eostas+XZ+GGk22pI+Op1Y6cxQ1JkUuKYu2iU+mXj1QjPrZm9nNWV9rg==", "cpu": [ "s390x" ], @@ -6073,9 +6504,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.26.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.26.0.tgz", - "integrity": "sha512-ZuwpfjCwjPkAOxpjAEjabg6LRSfL7cAJb6gSQGZYjGhadlzKKywDkCUnJ+KEfrNY1jH5EEoSIKLCb572jSiglA==", + "version": "4.34.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.34.0.tgz", + "integrity": "sha512-chZLTUIPbgcpm+Z7ALmomXW8Zh+wE2icrG+K6nt/HenPLmtwCajhQC5flNSk1Xy5EDMt/QAOz2MhzfOfJOLSiA==", "cpu": [ "x64" ], @@ -6087,9 +6518,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.26.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.26.0.tgz", - "integrity": "sha512-+HJD2lFS86qkeF8kNu0kALtifMpPCZU80HvwztIKnYwym3KnA1os6nsX4BGSTLtS2QVAGG1P3guRgsYyMA0Yhg==", + "version": "4.34.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.34.0.tgz", + "integrity": "sha512-jo0UolK70O28BifvEsFD/8r25shFezl0aUk2t0VJzREWHkq19e+pcLu4kX5HiVXNz5qqkD+aAq04Ct8rkxgbyQ==", "cpu": [ "x64" ], @@ -6101,9 +6532,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.26.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.26.0.tgz", - "integrity": "sha512-WUQzVFWPSw2uJzX4j6YEbMAiLbs0BUysgysh8s817doAYhR5ybqTI1wtKARQKo6cGop3pHnrUJPFCsXdoFaimQ==", + "version": "4.34.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.34.0.tgz", + "integrity": "sha512-Vmg0NhAap2S54JojJchiu5An54qa6t/oKT7LmDaWggpIcaiL8WcWHEN6OQrfTdL6mQ2GFyH7j2T5/3YPEDOOGA==", "cpu": [ "arm64" ], @@ -6115,9 +6546,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.26.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.26.0.tgz", - "integrity": "sha512-D4CxkazFKBfN1akAIY6ieyOqzoOoBV1OICxgUblWxff/pSjCA2khXlASUx7mK6W1oP4McqhgcCsu6QaLj3WMWg==", + "version": "4.34.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.34.0.tgz", + "integrity": "sha512-CV2aqhDDOsABKHKhNcs1SZFryffQf8vK2XrxP6lxC99ELZAdvsDgPklIBfd65R8R+qvOm1SmLaZ/Fdq961+m7A==", "cpu": [ "ia32" ], @@ -6129,9 +6560,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.26.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.26.0.tgz", - "integrity": "sha512-2x8MO1rm4PGEP0xWbubJW5RtbNLk3puzAMaLQd3B3JHVw4KcHlmXcO+Wewx9zCoo7EUFiMlu/aZbCJ7VjMzAag==", + "version": "4.34.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.34.0.tgz", + "integrity": "sha512-g2ASy1QwHP88y5KWvblUolJz9rN+i4ZOsYzkEwcNfaNooxNUXG+ON6F5xFo0NIItpHqxcdAyls05VXpBnludGw==", "cpu": [ "x64" ], @@ -6269,9 +6700,9 @@ } }, "node_modules/@stylistic/eslint-plugin": { - "version": "2.12.1", - "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin/-/eslint-plugin-2.12.1.tgz", - "integrity": "sha512-fubZKIHSPuo07FgRTn6S4Nl0uXPRPYVNpyZzIDGfp7Fny6JjNus6kReLD7NI380JXi4HtUTSOZ34LBuNPO1XLQ==", + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin/-/eslint-plugin-2.13.0.tgz", + "integrity": "sha512-RnO1SaiCFHn666wNz2QfZEFxvmiNRqhzaMXHXxXXKt+MEP7aajlPxUSMIQpKAaJfverpovEYqjBOXDq6dDcaOQ==", "dev": true, "dependencies": { "@typescript-eslint/utils": "^8.13.0", @@ -6510,9 +6941,9 @@ } }, "node_modules/@types/express-serve-static-core": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-5.0.3.tgz", - "integrity": "sha512-JEhMNwUJt7bw728CydvYzntD0XJeTmDnvwLlbfbAhE7Tbslm/ax6bdIiUwTgeVlZTsJQPwZwKpAkyDtIjsvx3g==", + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-5.0.6.tgz", + "integrity": "sha512-3xhRnjJPkULekpSzgtoNYYcTWgEZkp4myc+Saevii5JPnHNvHMRlBSHDbs7Bh1iPPoVTERHEZXyhyLbMEsExsA==", "dev": true, "license": "MIT", "dependencies": { @@ -6630,10 +7061,11 @@ "dev": true }, "node_modules/@types/qs": { - "version": "6.9.17", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.17.tgz", - "integrity": "sha512-rX4/bPcfmvxHDv0XjfJELTTr+iB+tn032nPILqHm5wbthUUUuVtNGGqzhya9XUxjTP8Fpr0qYgSZZKxGY++svQ==", - "dev": true + "version": "6.9.18", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.18.tgz", + "integrity": "sha512-kK7dgTYDyGqS+e2Q4aK9X3D7q234CIZ1Bv0q/7Z5IwRDoADNU81xXJK/YVyLbLTZCoIwUoDoffFeF+p/eIklAA==", + "dev": true, + "license": "MIT" }, "node_modules/@types/range-parser": { "version": "1.2.7", @@ -6703,9 +7135,9 @@ "dev": true }, "node_modules/@types/ws": { - "version": "8.5.13", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.13.tgz", - "integrity": "sha512-osM/gWBTPKgHV8XkTunnegTRIsvF6owmf5w+JtAfOw472dptdm0dlGv4xCt6GwQRcC2XVOvvRE/0bAoQcL2QkA==", + "version": "8.5.14", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.14.tgz", + "integrity": "sha512-bd/YFLW+URhBzMXurx7lWByOu+xzU9+kb3RboOteXYDfW+tr+JZa99OyNmPINEGB/ahzKrEuc8rcv4gnpJmxTw==", "dev": true, "license": "MIT", "dependencies": { @@ -6767,6 +7199,19 @@ "typescript": ">=4.8.4 <5.8.0" } }, + "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/types": { + "version": "8.19.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.19.0.tgz", + "integrity": "sha512-8XQ4Ss7G9WX8oaYvD4OOLCjIQYgRQxO+qCiR2V2s2GxI9AUpo7riNwo6jDhKtTcaJjT8PY54j2Yb33kWtSJsmA==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, "node_modules/@typescript-eslint/scope-manager": { "version": "8.19.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.19.0.tgz", @@ -6785,6 +7230,19 @@ "url": "https://opencollective.com/typescript-eslint" } }, + "node_modules/@typescript-eslint/scope-manager/node_modules/@typescript-eslint/types": { + "version": "8.19.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.19.0.tgz", + "integrity": "sha512-8XQ4Ss7G9WX8oaYvD4OOLCjIQYgRQxO+qCiR2V2s2GxI9AUpo7riNwo6jDhKtTcaJjT8PY54j2Yb33kWtSJsmA==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, "node_modules/@typescript-eslint/type-utils": { "version": "8.19.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.19.0.tgz", @@ -6810,9 +7268,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.19.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.19.0.tgz", - "integrity": "sha512-8XQ4Ss7G9WX8oaYvD4OOLCjIQYgRQxO+qCiR2V2s2GxI9AUpo7riNwo6jDhKtTcaJjT8PY54j2Yb33kWtSJsmA==", + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.20.0.tgz", + "integrity": "sha512-cqaMiY72CkP+2xZRrFt3ExRBu0WmVitN/rYPZErA80mHjHx/Svgp8yfbzkJmDoQ/whcytOPO9/IZXnOc+wigRA==", "dev": true, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -6849,6 +7307,19 @@ "typescript": ">=4.8.4 <5.8.0" } }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/@typescript-eslint/types": { + "version": "8.19.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.19.0.tgz", + "integrity": "sha512-8XQ4Ss7G9WX8oaYvD4OOLCjIQYgRQxO+qCiR2V2s2GxI9AUpo7riNwo6jDhKtTcaJjT8PY54j2Yb33kWtSJsmA==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, "node_modules/@typescript-eslint/utils": { "version": "8.19.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.19.0.tgz", @@ -6873,6 +7344,19 @@ "typescript": ">=4.8.4 <5.8.0" } }, + "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/types": { + "version": "8.19.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.19.0.tgz", + "integrity": "sha512-8XQ4Ss7G9WX8oaYvD4OOLCjIQYgRQxO+qCiR2V2s2GxI9AUpo7riNwo6jDhKtTcaJjT8PY54j2Yb33kWtSJsmA==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, "node_modules/@typescript-eslint/visitor-keys": { "version": "8.19.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.19.0.tgz", @@ -6891,17 +7375,30 @@ "url": "https://opencollective.com/typescript-eslint" } }, + "node_modules/@typescript-eslint/visitor-keys/node_modules/@typescript-eslint/types": { + "version": "8.19.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.19.0.tgz", + "integrity": "sha512-8XQ4Ss7G9WX8oaYvD4OOLCjIQYgRQxO+qCiR2V2s2GxI9AUpo7riNwo6jDhKtTcaJjT8PY54j2Yb33kWtSJsmA==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, "node_modules/@vitejs/plugin-basic-ssl": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-basic-ssl/-/plugin-basic-ssl-1.1.0.tgz", - "integrity": "sha512-wO4Dk/rm8u7RNhOf95ZzcEmC9rYOncYgvq4z3duaJrCgjN8BxAnDVyndanfcJZ0O6XZzHz6Q0hTimxTg8Y9g/A==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-basic-ssl/-/plugin-basic-ssl-1.2.0.tgz", + "integrity": "sha512-mkQnxTkcldAzIsomk1UuLfAu9n+kpQ3JbHcpCp7d2Oo6ITtji8pHS3QToOWjhPFvNQSnhlkAjmGbhv2QvwO/7Q==", "dev": true, "license": "MIT", "engines": { - "node": ">=14.6.0" + "node": ">=14.21.3" }, "peerDependencies": { - "vite": "^3.0.0 || ^4.0.0 || ^5.0.0" + "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0" } }, "node_modules/@webassemblyjs/ast": { @@ -7780,9 +8277,9 @@ "license": "MIT" }, "node_modules/beasties": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/beasties/-/beasties-0.1.0.tgz", - "integrity": "sha512-+Ssscd2gVG24qRNC+E2g88D+xsQW4xwakWtKAiGEQ3Pw54/FGdyo9RrfxhGhEv6ilFVbB7r3Lgx+QnAxnSpECw==", + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/beasties/-/beasties-0.2.0.tgz", + "integrity": "sha512-Ljqskqx/tbZagIglYoJIMzH5zgssyp+in9+9sAyh15N22AornBeIDnb8EZ6Rk+6ShfMxd92uO3gfpT0NtZbpow==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -7790,10 +8287,13 @@ "css-what": "^6.1.0", "dom-serializer": "^2.0.0", "domhandler": "^5.0.3", - "htmlparser2": "^9.0.0", + "htmlparser2": "^9.1.0", "picocolors": "^1.1.1", - "postcss": "^8.4.47", + "postcss": "^8.4.49", "postcss-media-query-parser": "^0.2.3" + }, + "engines": { + "node": ">=14.0.0" } }, "node_modules/beasties/node_modules/css-select": { @@ -7845,9 +8345,9 @@ } }, "node_modules/beasties/node_modules/domutils": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.1.tgz", - "integrity": "sha512-xWXmuRnN9OMP6ptPd2+H0cCbcYBULa5YDTbMm/2lvkWvNA3O4wcW+GvzooqBuNM8yy6pl3VIAeJTUUWUbfI5Fw==", + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz", + "integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==", "dev": true, "license": "BSD-2-Clause", "dependencies": { @@ -10156,6 +10656,7 @@ "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", "integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==", "dev": true, + "license": "Apache-2.0", "optional": true, "bin": { "detect-libc": "bin/detect-libc.js" @@ -10725,9 +11226,9 @@ } }, "node_modules/esbuild": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.24.0.tgz", - "integrity": "sha512-FuLPevChGDshgSicjisSooU0cemp/sGXR841D5LHMB7mTVOmsEHcAxaH3irL53+8YDIeVNQEySh4DaYU/iuPqQ==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.24.2.tgz", + "integrity": "sha512-+9egpBW8I3CD5XPe0n6BfT5fxLzxrlDzqydF3aviG+9ni1lDC/OvMHcxqEFV0+LANZG5R1bFMWfUrjVsdwxJvA==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -10738,37 +11239,39 @@ "node": ">=18" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.24.0", - "@esbuild/android-arm": "0.24.0", - "@esbuild/android-arm64": "0.24.0", - "@esbuild/android-x64": "0.24.0", - "@esbuild/darwin-arm64": "0.24.0", - "@esbuild/darwin-x64": "0.24.0", - "@esbuild/freebsd-arm64": "0.24.0", - "@esbuild/freebsd-x64": "0.24.0", - "@esbuild/linux-arm": "0.24.0", - "@esbuild/linux-arm64": "0.24.0", - "@esbuild/linux-ia32": "0.24.0", - "@esbuild/linux-loong64": "0.24.0", - "@esbuild/linux-mips64el": "0.24.0", - "@esbuild/linux-ppc64": "0.24.0", - "@esbuild/linux-riscv64": "0.24.0", - "@esbuild/linux-s390x": "0.24.0", - "@esbuild/linux-x64": "0.24.0", - "@esbuild/netbsd-x64": "0.24.0", - "@esbuild/openbsd-arm64": "0.24.0", - "@esbuild/openbsd-x64": "0.24.0", - "@esbuild/sunos-x64": "0.24.0", - "@esbuild/win32-arm64": "0.24.0", - "@esbuild/win32-ia32": "0.24.0", - "@esbuild/win32-x64": "0.24.0" + "@esbuild/aix-ppc64": "0.24.2", + "@esbuild/android-arm": "0.24.2", + "@esbuild/android-arm64": "0.24.2", + "@esbuild/android-x64": "0.24.2", + "@esbuild/darwin-arm64": "0.24.2", + "@esbuild/darwin-x64": "0.24.2", + "@esbuild/freebsd-arm64": "0.24.2", + "@esbuild/freebsd-x64": "0.24.2", + "@esbuild/linux-arm": "0.24.2", + "@esbuild/linux-arm64": "0.24.2", + "@esbuild/linux-ia32": "0.24.2", + "@esbuild/linux-loong64": "0.24.2", + "@esbuild/linux-mips64el": "0.24.2", + "@esbuild/linux-ppc64": "0.24.2", + "@esbuild/linux-riscv64": "0.24.2", + "@esbuild/linux-s390x": "0.24.2", + "@esbuild/linux-x64": "0.24.2", + "@esbuild/netbsd-arm64": "0.24.2", + "@esbuild/netbsd-x64": "0.24.2", + "@esbuild/openbsd-arm64": "0.24.2", + "@esbuild/openbsd-x64": "0.24.2", + "@esbuild/sunos-x64": "0.24.2", + "@esbuild/win32-arm64": "0.24.2", + "@esbuild/win32-ia32": "0.24.2", + "@esbuild/win32-x64": "0.24.2" } }, "node_modules/esbuild-wasm": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/esbuild-wasm/-/esbuild-wasm-0.24.0.tgz", - "integrity": "sha512-xhNn5tL1AhkPg4ft59yXT6FkwKXiPSYyz1IeinJHUJpjvOHOIPvdmFQc0pGdjxlKSbzZc2mNmtVOWAR1EF/JAg==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/esbuild-wasm/-/esbuild-wasm-0.24.2.tgz", + "integrity": "sha512-03/7Z1gD+ohDnScFztvI4XddTAbKVmMEzCvvkBpQdWKEXJ+73dTyeNrmdxP1Q0zpDMFjzUJwtK4rLjqwiHbzkw==", "dev": true, + "license": "MIT", "bin": { "esbuild": "bin/esbuild" }, @@ -11498,16 +12001,17 @@ "dev": true }, "node_modules/fast-glob": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", - "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", "dev": true, + "license": "MIT", "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", - "micromatch": "^4.0.4" + "micromatch": "^4.0.8" }, "engines": { "node": ">=8.6.0" @@ -12293,12 +12797,16 @@ } }, "node_modules/globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "version": "15.14.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-15.14.0.tgz", + "integrity": "sha512-OkToC372DtlQeje9/zHIo5CT8lRP/FUgEOKBEhU4e0abL7J7CD24fD9ohiLN5hagG/kWCYj4K5oaxxtj2Z0Dig==", "dev": true, + "license": "MIT", "engines": { - "node": ">=4" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/globalthis": { @@ -12611,23 +13119,6 @@ "safe-buffer": "~5.1.0" } }, - "node_modules/html-entities": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.5.2.tgz", - "integrity": "sha512-K//PSRMQk4FZ78Kyau+mZurHn3FH0Vwr+H36eE0rPbeYkRRi9YxceYPhuN60UwWorxyKHhqoAJl2OFKa4BVtaA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/mdevils" - }, - { - "type": "patreon", - "url": "https://patreon.com/mdevils" - } - ], - "license": "MIT" - }, "node_modules/html-escaper": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", @@ -12686,9 +13177,9 @@ } }, "node_modules/htmlparser2/node_modules/domutils": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.1.tgz", - "integrity": "sha512-xWXmuRnN9OMP6ptPd2+H0cCbcYBULa5YDTbMm/2lvkWvNA3O4wcW+GvzooqBuNM8yy6pl3VIAeJTUUWUbfI5Fw==", + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz", + "integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==", "dev": true, "license": "BSD-2-Clause", "dependencies": { @@ -12752,9 +13243,9 @@ } }, "node_modules/http-parser-js": { - "version": "0.5.8", - "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.8.tgz", - "integrity": "sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==", + "version": "0.5.9", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.9.tgz", + "integrity": "sha512-n1XsPy3rXVxlqxVioEWdC+0+M+SQw0DpJynwtOPo1X+ZlvdzTLtDBIJJlDQTnwZIFJrZSzSGmIOUdP8tu+SgLw==", "dev": true, "license": "MIT" }, @@ -12914,7 +13405,8 @@ "version": "5.0.3", "resolved": "https://registry.npmjs.org/immutable/-/immutable-5.0.3.tgz", "integrity": "sha512-P8IdPQHq3lA1xVeBRi5VPqUm5HDgKnx0Ru51wZz5mjxHr5n3RWhjIpOFU7ybkUxfB+5IToy+OLaHYDBIWsv+uw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/import-fresh": { "version": "3.3.0", @@ -14079,4608 +14571,3910 @@ "node_modules/karma-coverage-istanbul-reporter/node_modules/istanbul-lib-source-maps/node_modules/istanbul-lib-coverage": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz", - "integrity": "sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/karma-coverage-istanbul-reporter/node_modules/make-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", - "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", - "dev": true, - "dependencies": { - "pify": "^4.0.1", - "semver": "^5.6.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/karma-coverage-istanbul-reporter/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/karma-coverage-istanbul-reporter/node_modules/pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/karma-coverage-istanbul-reporter/node_modules/rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "deprecated": "Rimraf versions prior to v4 are no longer supported", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - } - }, - "node_modules/karma-coverage-istanbul-reporter/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/karma-coverage-istanbul-reporter/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/karma-coverage/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/karma-coverage/node_modules/istanbul-lib-instrument": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", - "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", - "dev": true, - "dependencies": { - "@babel/core": "^7.12.3", - "@babel/parser": "^7.14.7", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-coverage": "^3.2.0", - "semver": "^6.3.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/karma-coverage/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/karma-coverage/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/karma-jasmine": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/karma-jasmine/-/karma-jasmine-5.1.0.tgz", - "integrity": "sha512-i/zQLFrfEpRyQoJF9fsCdTMOF5c2dK7C7OmsuKg2D0YSsuZSfQDiLuaiktbuio6F2wiCsZSnSnieIQ0ant/uzQ==", - "dev": true, - "dependencies": { - "jasmine-core": "^4.1.0" - }, - "engines": { - "node": ">=12" - }, - "peerDependencies": { - "karma": "^6.0.0" - } - }, - "node_modules/karma-jasmine-html-reporter": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/karma-jasmine-html-reporter/-/karma-jasmine-html-reporter-2.1.0.tgz", - "integrity": "sha512-sPQE1+nlsn6Hwb5t+HHwyy0A1FNCVKuL1192b+XNauMYWThz2kweiBVW1DqloRpVvZIJkIoHVB7XRpK78n1xbQ==", - "dev": true, - "peerDependencies": { - "jasmine-core": "^4.0.0 || ^5.0.0", - "karma": "^6.0.0", - "karma-jasmine": "^5.0.0" - } - }, - "node_modules/karma-jasmine/node_modules/jasmine-core": { - "version": "4.6.1", - "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-4.6.1.tgz", - "integrity": "sha512-VYz/BjjmC3klLJlLwA4Kw8ytk0zDSmbbDLNs794VnWmkcCB7I9aAL/D48VNQtmITyPvea2C3jdUMfc3kAoy0PQ==", - "dev": true - }, - "node_modules/karma-source-map-support": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/karma-source-map-support/-/karma-source-map-support-1.4.0.tgz", - "integrity": "sha512-RsBECncGO17KAoJCYXjv+ckIz+Ii9NCi+9enk+rq6XC81ezYkb4/RHE6CTXdA7IOJqoF3wcaLfVG0CPmE5ca6A==", - "dev": true, - "dependencies": { - "source-map-support": "^0.5.5" - } - }, - "node_modules/karma/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/karma/node_modules/chokidar": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", - "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", - "dev": true, - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/karma/node_modules/cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dev": true, - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "node_modules/karma/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/karma/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/karma/node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/karma/node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/karma/node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "deprecated": "Rimraf versions prior to v4 are no longer supported", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/karma/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/karma/node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/karma/node_modules/yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "dev": true, - "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/keyv": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", - "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", - "dev": true, - "dependencies": { - "json-buffer": "3.0.1" - } - }, - "node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/kleur": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", - "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/launch-editor": { - "version": "2.9.1", - "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.9.1.tgz", - "integrity": "sha512-Gcnl4Bd+hRO9P9icCP/RVVT2o8SFlPXofuCxvA2SaZuH45whSvf5p8x5oih5ftLiVhEI4sp5xDY+R+b3zJBh5w==", - "dev": true, - "license": "MIT", - "dependencies": { - "picocolors": "^1.0.0", - "shell-quote": "^1.8.1" - } - }, - "node_modules/leek": { - "version": "0.0.24", - "resolved": "https://registry.npmjs.org/leek/-/leek-0.0.24.tgz", - "integrity": "sha512-6PVFIYXxlYF0o6hrAsHtGpTmi06otkwNrMcmQ0K96SeSRHPREPa9J3nJZ1frliVH7XT0XFswoJFQoXsDukzGNQ==", - "dev": true, - "dependencies": { - "debug": "^2.1.0", - "lodash.assign": "^3.2.0", - "rsvp": "^3.0.21" - } - }, - "node_modules/leek/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/leek/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - }, - "node_modules/less": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/less/-/less-4.2.0.tgz", - "integrity": "sha512-P3b3HJDBtSzsXUl0im2L7gTO5Ubg8mEN6G8qoTS77iXxXX4Hvu4Qj540PZDvQ8V6DmX6iXo98k7Md0Cm1PrLaA==", - "dev": true, - "dependencies": { - "copy-anything": "^2.0.1", - "parse-node-version": "^1.0.1", - "tslib": "^2.3.0" - }, - "bin": { - "lessc": "bin/lessc" - }, - "engines": { - "node": ">=6" - }, - "optionalDependencies": { - "errno": "^0.1.1", - "graceful-fs": "^4.1.2", - "image-size": "~0.5.0", - "make-dir": "^2.1.0", - "mime": "^1.4.1", - "needle": "^3.1.0", - "source-map": "~0.6.0" - } - }, - "node_modules/less-loader": { - "version": "12.2.0", - "resolved": "https://registry.npmjs.org/less-loader/-/less-loader-12.2.0.tgz", - "integrity": "sha512-MYUxjSQSBUQmowc0l5nPieOYwMzGPUaTzB6inNW/bdPEG9zOL3eAAD1Qw5ZxSPk7we5dMojHwNODYMV1hq4EVg==", - "dev": true, - "engines": { - "node": ">= 18.12.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "@rspack/core": "0.x || 1.x", - "less": "^3.5.0 || ^4.0.0", - "webpack": "^5.0.0" - }, - "peerDependenciesMeta": { - "@rspack/core": { - "optional": true - }, - "webpack": { - "optional": true - } - } - }, - "node_modules/less/node_modules/make-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", - "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", - "dev": true, - "optional": true, - "dependencies": { - "pify": "^4.0.1", - "semver": "^5.6.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/less/node_modules/mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "dev": true, - "optional": true, - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/less/node_modules/pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", - "dev": true, - "optional": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/less/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true, - "optional": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/less/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "optional": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/license-webpack-plugin": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/license-webpack-plugin/-/license-webpack-plugin-4.0.2.tgz", - "integrity": "sha512-771TFWFD70G1wLTC4oU2Cw4qvtmNrIw+wRvBtn+okgHl7slJVi7zfNcdmqDL72BojM30VNJ2UHylr1o77U37Jw==", - "dev": true, - "dependencies": { - "webpack-sources": "^3.0.0" - }, - "peerDependenciesMeta": { - "webpack": { - "optional": true - }, - "webpack-sources": { - "optional": true - } - } - }, - "node_modules/lines-and-columns": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true - }, - "node_modules/listr2": { - "version": "8.2.5", - "resolved": "https://registry.npmjs.org/listr2/-/listr2-8.2.5.tgz", - "integrity": "sha512-iyAZCeyD+c1gPyE9qpFu8af0Y+MRtmKOncdGoA2S5EY8iFq99dmmvkNnHiWo+pj0s7yH7l3KPIgee77tKpXPWQ==", - "dev": true, - "dependencies": { - "cli-truncate": "^4.0.0", - "colorette": "^2.0.20", - "eventemitter3": "^5.0.1", - "log-update": "^6.1.0", - "rfdc": "^1.4.1", - "wrap-ansi": "^9.0.0" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/listr2/node_modules/ansi-regex": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", - "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/listr2/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/listr2/node_modules/emoji-regex": { - "version": "10.4.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz", - "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==", - "dev": true - }, - "node_modules/listr2/node_modules/eventemitter3": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", - "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", - "dev": true - }, - "node_modules/listr2/node_modules/string-width": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", - "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", - "dev": true, - "dependencies": { - "emoji-regex": "^10.3.0", - "get-east-asian-width": "^1.0.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/listr2/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/listr2/node_modules/wrap-ansi": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz", - "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==", - "dev": true, - "dependencies": { - "ansi-styles": "^6.2.1", - "string-width": "^7.0.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/lmdb": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/lmdb/-/lmdb-3.1.5.tgz", - "integrity": "sha512-46Mch5Drq+A93Ss3gtbg+Xuvf5BOgIuvhKDWoGa3HcPHI6BL2NCOkRdSx1D4VfzwrxhnsjbyIVsLRlQHu6URvw==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "dependencies": { - "msgpackr": "^1.11.2", - "node-addon-api": "^6.1.0", - "node-gyp-build-optional-packages": "5.2.2", - "ordered-binary": "^1.5.3", - "weak-lru-cache": "^1.2.2" - }, - "bin": { - "download-lmdb-prebuilds": "bin/download-prebuilds.js" - }, - "optionalDependencies": { - "@lmdb/lmdb-darwin-arm64": "3.1.5", - "@lmdb/lmdb-darwin-x64": "3.1.5", - "@lmdb/lmdb-linux-arm": "3.1.5", - "@lmdb/lmdb-linux-arm64": "3.1.5", - "@lmdb/lmdb-linux-x64": "3.1.5", - "@lmdb/lmdb-win32-x64": "3.1.5" - } - }, - "node_modules/lmdb/node_modules/node-addon-api": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-6.1.0.tgz", - "integrity": "sha512-+eawOlIgy680F0kBzPUNFhMZGtJ1YmqM6l4+Crf4IkImjYrO/mqPwRMh352g23uIaQKFItcQ64I7KMaJxHgAVA==", - "dev": true, - "license": "MIT", - "optional": true - }, - "node_modules/load-json-file": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", - "integrity": "sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "parse-json": "^4.0.0", - "pify": "^3.0.0", - "strip-bom": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/load-json-file/node_modules/parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", - "dev": true, - "dependencies": { - "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/load-json-file/node_modules/pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/loader-runner": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", - "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", - "dev": true, - "engines": { - "node": ">=6.11.5" - } - }, - "node_modules/loader-utils": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-3.3.1.tgz", - "integrity": "sha512-FMJTLMXfCLMLfJxcX9PFqX5qD88Z5MRGaZCVzfuqeZSPsyiBzs+pahDQjbIWz2QIzPZz0NX9Zy4FX3lmK6YHIg==", - "dev": true, - "engines": { - "node": ">= 12.13.0" - } - }, - "node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true - }, - "node_modules/lodash-es": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", - "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==" - }, - "node_modules/lodash._baseassign": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz", - "integrity": "sha512-t3N26QR2IdSN+gqSy9Ds9pBu/J1EAFEshKlUHpJG3rvyJOYgcELIxcIeKKfZk7sjOz11cFfzJRsyFry/JyabJQ==", - "dev": true, - "dependencies": { - "lodash._basecopy": "^3.0.0", - "lodash.keys": "^3.0.0" - } - }, - "node_modules/lodash._basecopy": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", - "integrity": "sha512-rFR6Vpm4HeCK1WPGvjZSJ+7yik8d8PVUdCJx5rT2pogG4Ve/2ZS7kfmO5l5T2o5V2mqlNIfSF5MZlr1+xOoYQQ==", - "dev": true - }, - "node_modules/lodash._bindcallback": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/lodash._bindcallback/-/lodash._bindcallback-3.0.1.tgz", - "integrity": "sha512-2wlI0JRAGX8WEf4Gm1p/mv/SZ+jLijpj0jyaE/AXeuQphzCgD8ZQW4oSpoN8JAopujOFGU3KMuq7qfHBWlGpjQ==", - "dev": true - }, - "node_modules/lodash._createassigner": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/lodash._createassigner/-/lodash._createassigner-3.1.1.tgz", - "integrity": "sha512-LziVL7IDnJjQeeV95Wvhw6G28Z8Q6da87LWKOPWmzBLv4u6FAT/x5v00pyGW0u38UoogNF2JnD3bGgZZDaNEBw==", - "dev": true, - "dependencies": { - "lodash._bindcallback": "^3.0.0", - "lodash._isiterateecall": "^3.0.0", - "lodash.restparam": "^3.0.0" - } - }, - "node_modules/lodash._getnative": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz", - "integrity": "sha512-RrL9VxMEPyDMHOd9uFbvMe8X55X16/cGM5IgOKgRElQZutpX89iS6vwl64duTV1/16w5JY7tuFNXqoekmh1EmA==", - "dev": true - }, - "node_modules/lodash._isiterateecall": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz", - "integrity": "sha512-De+ZbrMu6eThFti/CSzhRvTKMgQToLxbij58LMfM8JnYDNSOjkjTCIaa8ixglOeGh2nyPlakbt5bJWJ7gvpYlQ==", - "dev": true - }, - "node_modules/lodash.assign": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-3.2.0.tgz", - "integrity": "sha512-/VVxzgGBmbphasTg51FrztxQJ/VgAUpol6zmJuSVSGcNg4g7FA4z7rQV8Ovr9V3vFBNWZhvKWHfpAytjTVUfFA==", - "dev": true, - "dependencies": { - "lodash._baseassign": "^3.0.0", - "lodash._createassigner": "^3.0.0", - "lodash.keys": "^3.0.0" - } - }, - "node_modules/lodash.debounce": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", - "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", - "dev": true - }, - "node_modules/lodash.isarguments": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", - "integrity": "sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg==", - "dev": true - }, - "node_modules/lodash.isarray": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", - "integrity": "sha512-JwObCrNJuT0Nnbuecmqr5DgtuBppuCvGD9lxjFpAzwnVtdGoDQ1zig+5W8k5/6Gcn0gZ3936HDAlGd28i7sOGQ==", - "dev": true - }, - "node_modules/lodash.ismatch": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.ismatch/-/lodash.ismatch-4.4.0.tgz", - "integrity": "sha512-fPMfXjGQEV9Xsq/8MTSgUf255gawYRbjwMyDbcvDhXgV7enSZA0hynz6vMPnpAb5iONEzBHBPsT+0zes5Z301g==", - "dev": true - }, - "node_modules/lodash.keys": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", - "integrity": "sha512-CuBsapFjcubOGMn3VD+24HOAPxM79tH+V6ivJL3CHYjtrawauDJHUk//Yew9Hvc6e9rbCrURGk8z6PC+8WJBfQ==", - "dev": true, - "dependencies": { - "lodash._getnative": "^3.0.0", - "lodash.isarguments": "^3.0.0", - "lodash.isarray": "^3.0.0" - } - }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true - }, - "node_modules/lodash.restparam": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/lodash.restparam/-/lodash.restparam-3.6.1.tgz", - "integrity": "sha512-L4/arjjuq4noiUJpt3yS6KIKDtJwNe2fIYgMqyYYKoeIfV1iEqvPwhCx23o+R9dzouGihDAPN1dTIRWa7zk8tw==", - "dev": true - }, - "node_modules/log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "dependencies": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "integrity": "sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA==", + "dev": true, + "engines": { + "node": ">=6" } }, - "node_modules/log-update": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/log-update/-/log-update-6.1.0.tgz", - "integrity": "sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==", + "node_modules/karma-coverage-istanbul-reporter/node_modules/make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", "dev": true, "dependencies": { - "ansi-escapes": "^7.0.0", - "cli-cursor": "^5.0.0", - "slice-ansi": "^7.1.0", - "strip-ansi": "^7.1.0", - "wrap-ansi": "^9.0.0" + "pify": "^4.0.1", + "semver": "^5.6.0" }, "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=6" } }, - "node_modules/log-update/node_modules/ansi-escapes": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.0.0.tgz", - "integrity": "sha512-GdYO7a61mR0fOlAsvC9/rIHf7L96sBc6dEWzeOu+KAea5bZyQRPIpojrVoI4AXGJS/ycu/fBTdLrUkA4ODrvjw==", + "node_modules/karma-coverage-istanbul-reporter/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "dependencies": { - "environment": "^1.0.0" + "brace-expansion": "^1.1.7" }, "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": "*" } }, - "node_modules/log-update/node_modules/ansi-regex": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", - "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "node_modules/karma-coverage-istanbul-reporter/node_modules/pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", "dev": true, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" + "node": ">=6" } }, - "node_modules/log-update/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "node_modules/karma-coverage-istanbul-reporter/node_modules/rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", "dev": true, - "engines": { - "node": ">=12" + "dependencies": { + "glob": "^7.1.3" }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "bin": { + "rimraf": "bin.js" } }, - "node_modules/log-update/node_modules/cli-cursor": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz", - "integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==", + "node_modules/karma-coverage-istanbul-reporter/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", "dev": true, - "dependencies": { - "restore-cursor": "^5.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "bin": { + "semver": "bin/semver" } }, - "node_modules/log-update/node_modules/emoji-regex": { - "version": "10.4.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz", - "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==", - "dev": true - }, - "node_modules/log-update/node_modules/is-fullwidth-code-point": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.0.0.tgz", - "integrity": "sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA==", + "node_modules/karma-coverage-istanbul-reporter/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true, - "dependencies": { - "get-east-asian-width": "^1.0.0" - }, "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=0.10.0" } }, - "node_modules/log-update/node_modules/onetime": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz", - "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==", + "node_modules/karma-coverage/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, "dependencies": { - "mimic-function": "^5.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/log-update/node_modules/restore-cursor": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz", - "integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==", + "node_modules/karma-coverage/node_modules/istanbul-lib-instrument": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", + "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", "dev": true, "dependencies": { - "onetime": "^7.0.0", - "signal-exit": "^4.1.0" + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" }, "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=8" } }, - "node_modules/log-update/node_modules/slice-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.0.tgz", - "integrity": "sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg==", + "node_modules/karma-coverage/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "dependencies": { - "ansi-styles": "^6.2.1", - "is-fullwidth-code-point": "^5.0.0" + "brace-expansion": "^1.1.7" }, "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/chalk/slice-ansi?sponsor=1" + "node": "*" } }, - "node_modules/log-update/node_modules/string-width": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", - "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "node_modules/karma-coverage/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, - "dependencies": { - "emoji-regex": "^10.3.0", - "get-east-asian-width": "^1.0.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "bin": { + "semver": "bin/semver.js" } }, - "node_modules/log-update/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "node_modules/karma-jasmine": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/karma-jasmine/-/karma-jasmine-5.1.0.tgz", + "integrity": "sha512-i/zQLFrfEpRyQoJF9fsCdTMOF5c2dK7C7OmsuKg2D0YSsuZSfQDiLuaiktbuio6F2wiCsZSnSnieIQ0ant/uzQ==", "dev": true, "dependencies": { - "ansi-regex": "^6.0.1" + "jasmine-core": "^4.1.0" }, "engines": { "node": ">=12" }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" + "peerDependencies": { + "karma": "^6.0.0" } }, - "node_modules/log-update/node_modules/wrap-ansi": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz", - "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==", + "node_modules/karma-jasmine-html-reporter": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/karma-jasmine-html-reporter/-/karma-jasmine-html-reporter-2.1.0.tgz", + "integrity": "sha512-sPQE1+nlsn6Hwb5t+HHwyy0A1FNCVKuL1192b+XNauMYWThz2kweiBVW1DqloRpVvZIJkIoHVB7XRpK78n1xbQ==", "dev": true, - "dependencies": { - "ansi-styles": "^6.2.1", - "string-width": "^7.0.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + "peerDependencies": { + "jasmine-core": "^4.0.0 || ^5.0.0", + "karma": "^6.0.0", + "karma-jasmine": "^5.0.0" } }, - "node_modules/log4js": { - "version": "6.9.1", - "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.9.1.tgz", - "integrity": "sha512-1somDdy9sChrr9/f4UlzhdaGfDR2c/SaD2a4T7qEkG4jTS57/B3qmnjLYePwQ8cqWnUHZI0iAKxMBpCZICiZ2g==", + "node_modules/karma-jasmine/node_modules/jasmine-core": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-4.6.1.tgz", + "integrity": "sha512-VYz/BjjmC3klLJlLwA4Kw8ytk0zDSmbbDLNs794VnWmkcCB7I9aAL/D48VNQtmITyPvea2C3jdUMfc3kAoy0PQ==", + "dev": true + }, + "node_modules/karma-source-map-support": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/karma-source-map-support/-/karma-source-map-support-1.4.0.tgz", + "integrity": "sha512-RsBECncGO17KAoJCYXjv+ckIz+Ii9NCi+9enk+rq6XC81ezYkb4/RHE6CTXdA7IOJqoF3wcaLfVG0CPmE5ca6A==", "dev": true, "dependencies": { - "date-format": "^4.0.14", - "debug": "^4.3.4", - "flatted": "^3.2.7", - "rfdc": "^1.3.0", - "streamroller": "^3.1.5" - }, - "engines": { - "node": ">=8.0" + "source-map-support": "^0.5.5" } }, - "node_modules/lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "node_modules/karma/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, "dependencies": { - "yallist": "^3.0.2" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/macos-release": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/macos-release/-/macos-release-2.5.1.tgz", - "integrity": "sha512-DXqXhEM7gW59OjZO8NIjBCz9AQ1BEMrfiOAl4AYByHCtVHRF4KoGNO8mqQeM8lRCtQe/UnJ4imO/d2HdkKsd+A==", + "node_modules/karma/node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", "dev": true, + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, "engines": { - "node": ">=6" + "node": ">= 8.10.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" } }, - "node_modules/magic-string": { - "version": "0.30.12", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.12.tgz", - "integrity": "sha512-Ea8I3sQMVXr8JhN4z+H/d8zwo+tYDgHE9+5G4Wnrwhs0gaK9fXTKx0Tw5Xwsd/bCPTTZNRAdpyzvoeORe9LYpw==", + "node_modules/karma/node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", "dev": true, "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.0" + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" } }, - "node_modules/make-dir": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", - "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", + "node_modules/karma/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, "dependencies": { - "semver": "^7.5.3" + "is-glob": "^4.0.1" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">= 6" } }, - "node_modules/make-error": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", - "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "dev": true - }, - "node_modules/make-fetch-happen": { - "version": "14.0.3", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-14.0.3.tgz", - "integrity": "sha512-QMjGbFTP0blj97EeidG5hk/QhKQ3T4ICckQGLgz38QF7Vgbk6e6FTARN8KhKxyBbWn8R0HU+bnw8aSoFPD4qtQ==", + "node_modules/karma/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "dependencies": { - "@npmcli/agent": "^3.0.0", - "cacache": "^19.0.1", - "http-cache-semantics": "^4.1.1", - "minipass": "^7.0.2", - "minipass-fetch": "^4.0.0", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "negotiator": "^1.0.0", - "proc-log": "^5.0.0", - "promise-retry": "^2.0.1", - "ssri": "^12.0.0" + "brace-expansion": "^1.1.7" }, "engines": { - "node": "^18.17.0 || >=20.5.0" + "node": "*" } }, - "node_modules/map-obj": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz", - "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==", + "node_modules/karma/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true, "engines": { - "node": ">=8" + "node": ">=8.6" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/math-intrinsics": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.0.0.tgz", - "integrity": "sha512-4MqMiKP90ybymYvsut0CH2g4XWbfLtmlCkXmtmdcDCxNB+mQcu1w/1+L/VD7vi/PSv7X2JYV7SCcR+jiPXnQtA==", + "node_modules/karma/node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, "engines": { - "node": ">= 0.4" + "node": ">=8.10.0" } }, - "node_modules/media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "node_modules/karma/node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/karma/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true, "engines": { - "node": ">= 0.6" + "node": ">=0.10.0" } }, - "node_modules/memfs": { - "version": "4.15.2", - "resolved": "https://registry.npmjs.org/memfs/-/memfs-4.15.2.tgz", - "integrity": "sha512-n8/qP8AT6CtY6kxCPYgYVusT5rS6axaT66dD3tYi2lm+l1iMH7YYpmW8H/qL5bfV4YvInCCgUDAWIRvrNS7kbQ==", + "node_modules/karma/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dev": true, - "license": "Apache-2.0", "dependencies": { - "@jsonjoy.com/json-pack": "^1.0.3", - "@jsonjoy.com/util": "^1.3.0", - "tree-dump": "^1.0.1", - "tslib": "^2.0.0" + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" }, "engines": { - "node": ">= 4.0.0" + "node": ">=10" }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/streamich" + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/meow": { - "version": "8.1.2", - "resolved": "https://registry.npmjs.org/meow/-/meow-8.1.2.tgz", - "integrity": "sha512-r85E3NdZ+mpYk1C6RjPFEMSE+s1iZMuHtsHAqY0DT3jZczl0diWUZ8g6oU7h0M9cD2EL+PzaYghhCLzR0ZNn5Q==", + "node_modules/karma/node_modules/yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", "dev": true, "dependencies": { - "@types/minimist": "^1.2.0", - "camelcase-keys": "^6.2.2", - "decamelize-keys": "^1.1.0", - "hard-rejection": "^2.1.0", - "minimist-options": "4.1.0", - "normalize-package-data": "^3.0.0", - "read-pkg-up": "^7.0.1", - "redent": "^3.0.0", - "trim-newlines": "^3.0.0", - "type-fest": "^0.18.0", - "yargs-parser": "^20.2.3" + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" }, "engines": { "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/meow/node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", "dev": true, "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, + "json-buffer": "3.0.1" + } + }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, "engines": { - "node": ">=8" + "node": ">=0.10.0" } }, - "node_modules/meow/node_modules/hosted-git-info": { - "version": "2.8.9", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", - "dev": true + "node_modules/kleur": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", + "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==", + "dev": true, + "engines": { + "node": ">=6" + } }, - "node_modules/meow/node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "node_modules/launch-editor": { + "version": "2.9.1", + "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.9.1.tgz", + "integrity": "sha512-Gcnl4Bd+hRO9P9icCP/RVVT2o8SFlPXofuCxvA2SaZuH45whSvf5p8x5oih5ftLiVhEI4sp5xDY+R+b3zJBh5w==", "dev": true, + "license": "MIT", "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" + "picocolors": "^1.0.0", + "shell-quote": "^1.8.1" } }, - "node_modules/meow/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "node_modules/leek": { + "version": "0.0.24", + "resolved": "https://registry.npmjs.org/leek/-/leek-0.0.24.tgz", + "integrity": "sha512-6PVFIYXxlYF0o6hrAsHtGpTmi06otkwNrMcmQ0K96SeSRHPREPa9J3nJZ1frliVH7XT0XFswoJFQoXsDukzGNQ==", "dev": true, "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "debug": "^2.1.0", + "lodash.assign": "^3.2.0", + "rsvp": "^3.0.21" } }, - "node_modules/meow/node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "node_modules/leek/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" + "ms": "2.0.0" } }, - "node_modules/meow/node_modules/read-pkg": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", - "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", + "node_modules/leek/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "node_modules/less": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/less/-/less-4.2.1.tgz", + "integrity": "sha512-CasaJidTIhWmjcqv0Uj5vccMI7pJgfD9lMkKtlnTHAdJdYK/7l8pM9tumLyJ0zhbD4KJLo/YvTj+xznQd5NBhg==", "dev": true, + "license": "Apache-2.0", "dependencies": { - "@types/normalize-package-data": "^2.4.0", - "normalize-package-data": "^2.5.0", - "parse-json": "^5.0.0", - "type-fest": "^0.6.0" + "copy-anything": "^2.0.1", + "parse-node-version": "^1.0.1", + "tslib": "^2.3.0" + }, + "bin": { + "lessc": "bin/lessc" }, "engines": { - "node": ">=8" + "node": ">=6" + }, + "optionalDependencies": { + "errno": "^0.1.1", + "graceful-fs": "^4.1.2", + "image-size": "~0.5.0", + "make-dir": "^2.1.0", + "mime": "^1.4.1", + "needle": "^3.1.0", + "source-map": "~0.6.0" } }, - "node_modules/meow/node_modules/read-pkg-up": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", - "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", + "node_modules/less-loader": { + "version": "12.2.0", + "resolved": "https://registry.npmjs.org/less-loader/-/less-loader-12.2.0.tgz", + "integrity": "sha512-MYUxjSQSBUQmowc0l5nPieOYwMzGPUaTzB6inNW/bdPEG9zOL3eAAD1Qw5ZxSPk7we5dMojHwNODYMV1hq4EVg==", "dev": true, - "dependencies": { - "find-up": "^4.1.0", - "read-pkg": "^5.2.0", - "type-fest": "^0.8.1" - }, "engines": { - "node": ">=8" + "node": ">= 18.12.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "@rspack/core": "0.x || 1.x", + "less": "^3.5.0 || ^4.0.0", + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "webpack": { + "optional": true + } } }, - "node_modules/meow/node_modules/read-pkg-up/node_modules/type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "node_modules/less/node_modules/make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", "dev": true, + "optional": true, + "dependencies": { + "pify": "^4.0.1", + "semver": "^5.6.0" + }, "engines": { - "node": ">=8" + "node": ">=6" } }, - "node_modules/meow/node_modules/read-pkg/node_modules/normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "node_modules/less/node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", "dev": true, - "dependencies": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" + "optional": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" } }, - "node_modules/meow/node_modules/read-pkg/node_modules/type-fest": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", - "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", + "node_modules/less/node_modules/pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", "dev": true, + "optional": true, "engines": { - "node": ">=8" + "node": ">=6" } }, - "node_modules/meow/node_modules/semver": { + "node_modules/less/node_modules/semver": { "version": "5.7.2", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", "dev": true, + "optional": true, "bin": { "semver": "bin/semver" } }, - "node_modules/meow/node_modules/type-fest": { - "version": "0.18.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.18.1.tgz", - "integrity": "sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==", + "node_modules/less/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true, + "optional": true, "engines": { - "node": ">=10" + "node": ">=0.10.0" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": ">= 0.8.0" } }, - "node_modules/merge-descriptors": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", - "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "node_modules/license-webpack-plugin": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/license-webpack-plugin/-/license-webpack-plugin-4.0.2.tgz", + "integrity": "sha512-771TFWFD70G1wLTC4oU2Cw4qvtmNrIw+wRvBtn+okgHl7slJVi7zfNcdmqDL72BojM30VNJ2UHylr1o77U37Jw==", "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "dependencies": { + "webpack-sources": "^3.0.0" + }, + "peerDependenciesMeta": { + "webpack": { + "optional": true + }, + "webpack-sources": { + "optional": true + } } }, - "node_modules/merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", "dev": true }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "node_modules/listr2": { + "version": "8.2.5", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-8.2.5.tgz", + "integrity": "sha512-iyAZCeyD+c1gPyE9qpFu8af0Y+MRtmKOncdGoA2S5EY8iFq99dmmvkNnHiWo+pj0s7yH7l3KPIgee77tKpXPWQ==", "dev": true, + "dependencies": { + "cli-truncate": "^4.0.0", + "colorette": "^2.0.20", + "eventemitter3": "^5.0.1", + "log-update": "^6.1.0", + "rfdc": "^1.4.1", + "wrap-ansi": "^9.0.0" + }, "engines": { - "node": ">= 8" + "node": ">=18.0.0" } }, - "node_modules/mergexml": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/mergexml/-/mergexml-1.2.4.tgz", - "integrity": "sha512-yiOlDqcVCz7AG1eSboonc18FTlfqDEKYfGoAV3Lul98u6YRV/s0kjtf4bjk47t0hLTFJR0BSYMd6BpmX3xDjNQ==", + "node_modules/listr2/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", "dev": true, - "dependencies": { - "@xmldom/xmldom": "^0.7.0", - "formidable": "^3.5.1", - "xpath": "0.0.27" + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, - "node_modules/mergexml/node_modules/xpath": { - "version": "0.0.27", - "resolved": "https://registry.npmjs.org/xpath/-/xpath-0.0.27.tgz", - "integrity": "sha512-fg03WRxtkCV6ohClePNAECYsmpKKTv5L8y/X3Dn1hQrec3POx2jHZ/0P2qQ6HvsrU1BmeqXcof3NGGueG6LxwQ==", + "node_modules/listr2/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", "dev": true, "engines": { - "node": ">=0.6.0" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "node_modules/listr2/node_modules/emoji-regex": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz", + "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==", + "dev": true + }, + "node_modules/listr2/node_modules/eventemitter3": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", + "dev": true + }, + "node_modules/listr2/node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", "dev": true, + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, "engines": { - "node": ">= 0.6" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/micromatch": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", - "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "node_modules/listr2/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "dev": true, "dependencies": { - "braces": "^3.0.3", - "picomatch": "^2.3.1" + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" }, - "engines": { - "node": ">=8.6" + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, - "node_modules/micromatch/node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "node_modules/listr2/node_modules/wrap-ansi": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz", + "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==", "dev": true, + "dependencies": { + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" + }, "engines": { - "node": ">=8.6" + "node": ">=18" }, "funding": { - "url": "https://github.com/sponsors/jonschlinkert" + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/mime": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", - "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", + "node_modules/lmdb": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/lmdb/-/lmdb-3.2.2.tgz", + "integrity": "sha512-LriG93la4PbmPMwI7Hbv8W+0ncLK7549w4sbZSi4QGDjnnxnmNMgxUkaQTEMzH8TpwsfFvgEjpLX7V8B/I9e3g==", "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "dependencies": { + "msgpackr": "^1.11.2", + "node-addon-api": "^6.1.0", + "node-gyp-build-optional-packages": "5.2.2", + "ordered-binary": "^1.5.3", + "weak-lru-cache": "^1.2.2" + }, "bin": { - "mime": "cli.js" + "download-lmdb-prebuilds": "bin/download-prebuilds.js" }, - "engines": { - "node": ">=4.0.0" + "optionalDependencies": { + "@lmdb/lmdb-darwin-arm64": "3.2.2", + "@lmdb/lmdb-darwin-x64": "3.2.2", + "@lmdb/lmdb-linux-arm": "3.2.2", + "@lmdb/lmdb-linux-arm64": "3.2.2", + "@lmdb/lmdb-linux-x64": "3.2.2", + "@lmdb/lmdb-win32-x64": "3.2.2" } }, - "node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "node_modules/lmdb/node_modules/node-addon-api": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-6.1.0.tgz", + "integrity": "sha512-+eawOlIgy680F0kBzPUNFhMZGtJ1YmqM6l4+Crf4IkImjYrO/mqPwRMh352g23uIaQKFItcQ64I7KMaJxHgAVA==", "dev": true, - "engines": { - "node": ">= 0.6" - } + "license": "MIT", + "optional": true }, - "node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "node_modules/load-json-file": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==", "dev": true, "dependencies": { - "mime-db": "1.52.0" + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" }, "engines": { - "node": ">= 0.6" + "node": ">=4" } }, - "node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "node_modules/load-json-file/node_modules/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", + "dev": true, + "dependencies": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + }, "engines": { - "node": ">=6" + "node": ">=4" } }, - "node_modules/mimic-function": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz", - "integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==", + "node_modules/load-json-file/node_modules/pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", "dev": true, "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=4" } }, - "node_modules/mimic-response": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", - "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "node_modules/loader-runner": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", + "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", "dev": true, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=6.11.5" } }, - "node_modules/min-indent": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", - "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", + "node_modules/loader-utils": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-3.3.1.tgz", + "integrity": "sha512-FMJTLMXfCLMLfJxcX9PFqX5qD88Z5MRGaZCVzfuqeZSPsyiBzs+pahDQjbIWz2QIzPZz0NX9Zy4FX3lmK6YHIg==", "dev": true, "engines": { - "node": ">=4" + "node": ">= 12.13.0" } }, - "node_modules/mini-css-extract-plugin": { - "version": "2.9.2", - "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.9.2.tgz", - "integrity": "sha512-GJuACcS//jtq4kCtd5ii/M0SZf7OZRH+BxdqXZHaJfb8TJiVl+NgQRPwiYt2EuqeSkNydn/7vP+bcE27C5mb9w==", + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, "dependencies": { - "schema-utils": "^4.0.0", - "tapable": "^2.2.1" + "p-locate": "^5.0.0" }, "engines": { - "node": ">= 12.13.0" + "node": ">=10" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.0.0" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/minimalistic-assert": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", - "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", - "dev": true, - "license": "ISC" + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true }, - "node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "node_modules/lodash-es": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", + "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==" + }, + "node_modules/lodash._baseassign": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz", + "integrity": "sha512-t3N26QR2IdSN+gqSy9Ds9pBu/J1EAFEshKlUHpJG3rvyJOYgcELIxcIeKKfZk7sjOz11cFfzJRsyFry/JyabJQ==", "dev": true, "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "lodash._basecopy": "^3.0.0", + "lodash.keys": "^3.0.0" } }, - "node_modules/minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "node_modules/lodash._basecopy": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", + "integrity": "sha512-rFR6Vpm4HeCK1WPGvjZSJ+7yik8d8PVUdCJx5rT2pogG4Ve/2ZS7kfmO5l5T2o5V2mqlNIfSF5MZlr1+xOoYQQ==", + "dev": true + }, + "node_modules/lodash._bindcallback": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._bindcallback/-/lodash._bindcallback-3.0.1.tgz", + "integrity": "sha512-2wlI0JRAGX8WEf4Gm1p/mv/SZ+jLijpj0jyaE/AXeuQphzCgD8ZQW4oSpoN8JAopujOFGU3KMuq7qfHBWlGpjQ==", + "dev": true + }, + "node_modules/lodash._createassigner": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/lodash._createassigner/-/lodash._createassigner-3.1.1.tgz", + "integrity": "sha512-LziVL7IDnJjQeeV95Wvhw6G28Z8Q6da87LWKOPWmzBLv4u6FAT/x5v00pyGW0u38UoogNF2JnD3bGgZZDaNEBw==", "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "dependencies": { + "lodash._bindcallback": "^3.0.0", + "lodash._isiterateecall": "^3.0.0", + "lodash.restparam": "^3.0.0" } }, - "node_modules/minimist-options": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz", - "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==", + "node_modules/lodash._getnative": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz", + "integrity": "sha512-RrL9VxMEPyDMHOd9uFbvMe8X55X16/cGM5IgOKgRElQZutpX89iS6vwl64duTV1/16w5JY7tuFNXqoekmh1EmA==", + "dev": true + }, + "node_modules/lodash._isiterateecall": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz", + "integrity": "sha512-De+ZbrMu6eThFti/CSzhRvTKMgQToLxbij58LMfM8JnYDNSOjkjTCIaa8ixglOeGh2nyPlakbt5bJWJ7gvpYlQ==", + "dev": true + }, + "node_modules/lodash.assign": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-3.2.0.tgz", + "integrity": "sha512-/VVxzgGBmbphasTg51FrztxQJ/VgAUpol6zmJuSVSGcNg4g7FA4z7rQV8Ovr9V3vFBNWZhvKWHfpAytjTVUfFA==", "dev": true, "dependencies": { - "arrify": "^1.0.1", - "is-plain-obj": "^1.1.0", - "kind-of": "^6.0.3" - }, - "engines": { - "node": ">= 6" + "lodash._baseassign": "^3.0.0", + "lodash._createassigner": "^3.0.0", + "lodash.keys": "^3.0.0" } }, - "node_modules/minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "node_modules/lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", + "dev": true + }, + "node_modules/lodash.isarguments": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", + "integrity": "sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg==", + "dev": true + }, + "node_modules/lodash.isarray": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", + "integrity": "sha512-JwObCrNJuT0Nnbuecmqr5DgtuBppuCvGD9lxjFpAzwnVtdGoDQ1zig+5W8k5/6Gcn0gZ3936HDAlGd28i7sOGQ==", + "dev": true + }, + "node_modules/lodash.ismatch": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.ismatch/-/lodash.ismatch-4.4.0.tgz", + "integrity": "sha512-fPMfXjGQEV9Xsq/8MTSgUf255gawYRbjwMyDbcvDhXgV7enSZA0hynz6vMPnpAb5iONEzBHBPsT+0zes5Z301g==", + "dev": true + }, + "node_modules/lodash.keys": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", + "integrity": "sha512-CuBsapFjcubOGMn3VD+24HOAPxM79tH+V6ivJL3CHYjtrawauDJHUk//Yew9Hvc6e9rbCrURGk8z6PC+8WJBfQ==", "dev": true, - "engines": { - "node": ">=16 || 14 >=14.17" + "dependencies": { + "lodash._getnative": "^3.0.0", + "lodash.isarguments": "^3.0.0", + "lodash.isarray": "^3.0.0" } }, - "node_modules/minipass-collect": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-2.0.1.tgz", - "integrity": "sha512-D7V8PO9oaz7PWGLbCACuI1qEOsq7UKfLotx/C0Aet43fCUB/wfQ7DYeq2oR/svFJGYDHPr38SHATeaj/ZoKHKw==", - "dev": true, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "node_modules/lodash.restparam": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/lodash.restparam/-/lodash.restparam-3.6.1.tgz", + "integrity": "sha512-L4/arjjuq4noiUJpt3yS6KIKDtJwNe2fIYgMqyYYKoeIfV1iEqvPwhCx23o+R9dzouGihDAPN1dTIRWa7zk8tw==", + "dev": true + }, + "node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", "dependencies": { - "minipass": "^7.0.3" + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" }, "engines": { - "node": ">=16 || 14 >=14.17" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/minipass-fetch": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-4.0.0.tgz", - "integrity": "sha512-2v6aXUXwLP1Epd/gc32HAMIWoczx+fZwEPRHm/VwtrJzRGwR1qGZXEYV3Zp8ZjjbwaZhMrM6uHV4KVkk+XCc2w==", + "node_modules/log-update": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-6.1.0.tgz", + "integrity": "sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==", "dev": true, "dependencies": { - "minipass": "^7.0.3", - "minipass-sized": "^1.0.3", - "minizlib": "^3.0.1" + "ansi-escapes": "^7.0.0", + "cli-cursor": "^5.0.0", + "slice-ansi": "^7.1.0", + "strip-ansi": "^7.1.0", + "wrap-ansi": "^9.0.0" }, "engines": { - "node": "^18.17.0 || >=20.5.0" + "node": ">=18" }, - "optionalDependencies": { - "encoding": "^0.1.13" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/minipass-flush": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", - "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", + "node_modules/log-update/node_modules/ansi-escapes": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.0.0.tgz", + "integrity": "sha512-GdYO7a61mR0fOlAsvC9/rIHf7L96sBc6dEWzeOu+KAea5bZyQRPIpojrVoI4AXGJS/ycu/fBTdLrUkA4ODrvjw==", "dev": true, "dependencies": { - "minipass": "^3.0.0" + "environment": "^1.0.0" }, "engines": { - "node": ">= 8" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/minipass-flush/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "node_modules/log-update/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, - "node_modules/minipass-flush/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, - "node_modules/minipass-pipeline": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", - "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", + "node_modules/log-update/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", "dev": true, - "dependencies": { - "minipass": "^3.0.0" - }, "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/minipass-pipeline/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "node_modules/log-update/node_modules/cli-cursor": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz", + "integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==", "dev": true, "dependencies": { - "yallist": "^4.0.0" + "restore-cursor": "^5.0.0" }, "engines": { - "node": ">=8" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/minipass-pipeline/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "node_modules/log-update/node_modules/emoji-regex": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz", + "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==", "dev": true }, - "node_modules/minipass-sized": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", - "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", + "node_modules/log-update/node_modules/is-fullwidth-code-point": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.0.0.tgz", + "integrity": "sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA==", "dev": true, "dependencies": { - "minipass": "^3.0.0" + "get-east-asian-width": "^1.0.0" }, "engines": { - "node": ">=8" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/minipass-sized/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "node_modules/log-update/node_modules/onetime": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz", + "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==", "dev": true, "dependencies": { - "yallist": "^4.0.0" + "mimic-function": "^5.0.0" }, "engines": { - "node": ">=8" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/minipass-sized/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, - "node_modules/minizlib": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.0.1.tgz", - "integrity": "sha512-umcy022ILvb5/3Djuu8LWeqUa8D68JaBzlttKeMWen48SjabqS3iY5w/vzeMzMUNhLDifyhbOwKDSznB1vvrwg==", + "node_modules/log-update/node_modules/restore-cursor": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz", + "integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==", "dev": true, "dependencies": { - "minipass": "^7.0.4", - "rimraf": "^5.0.5" + "onetime": "^7.0.0", + "signal-exit": "^4.1.0" }, "engines": { - "node": ">= 18" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/minizlib/node_modules/glob": { - "version": "10.4.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", - "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "node_modules/log-update/node_modules/slice-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.0.tgz", + "integrity": "sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg==", "dev": true, "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^1.11.1" + "ansi-styles": "^6.2.1", + "is-fullwidth-code-point": "^5.0.0" }, - "bin": { - "glob": "dist/esm/bin.mjs" + "engines": { + "node": ">=18" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/chalk/slice-ansi?sponsor=1" } }, - "node_modules/minizlib/node_modules/rimraf": { - "version": "5.0.10", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.10.tgz", - "integrity": "sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ==", + "node_modules/log-update/node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", "dev": true, "dependencies": { - "glob": "^10.3.7" + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" }, - "bin": { - "rimraf": "dist/esm/bin.mjs" + "engines": { + "node": ">=18" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "node_modules/log-update/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "dev": true, "dependencies": { - "minimist": "^1.2.6" - }, - "bin": { - "mkdirp": "bin/cmd.js" - } - }, - "node_modules/mkdirp-classic": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", - "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", - "dev": true - }, - "node_modules/modify-values": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/modify-values/-/modify-values-1.0.1.tgz", - "integrity": "sha512-xV2bxeN6F7oYjZWTe/YPAy6MN2M+sL4u/Rlm2AHCIVGfo2p1yGmBHQ6vHehl4bRTZBdHu3TSkWdYgkwpYzAGSw==", - "dev": true, + "ansi-regex": "^6.0.1" + }, "engines": { - "node": ">=0.10.0" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, - "node_modules/mrmime": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.0.tgz", - "integrity": "sha512-eu38+hdgojoyq63s+yTpN4XMBdt5l8HhMhc4VKLO9KM5caLIBvUm4thi7fFaxyTmCKeNnXZ5pAlBwCUnhA09uw==", + "node_modules/log-update/node_modules/wrap-ansi": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz", + "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==", "dev": true, - "license": "MIT", + "dependencies": { + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" + }, "engines": { - "node": ">=10" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, - "node_modules/msgpackr": { - "version": "1.11.2", - "resolved": "https://registry.npmjs.org/msgpackr/-/msgpackr-1.11.2.tgz", - "integrity": "sha512-F9UngXRlPyWCDEASDpTf6c9uNhGPTqnTeLVt7bN+bU1eajoR/8V9ys2BRaV5C/e5ihE6sJ9uPIKaYt6bFuO32g==", + "node_modules/log4js": { + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.9.1.tgz", + "integrity": "sha512-1somDdy9sChrr9/f4UlzhdaGfDR2c/SaD2a4T7qEkG4jTS57/B3qmnjLYePwQ8cqWnUHZI0iAKxMBpCZICiZ2g==", "dev": true, - "license": "MIT", - "optional": true, - "optionalDependencies": { - "msgpackr-extract": "^3.0.2" + "dependencies": { + "date-format": "^4.0.14", + "debug": "^4.3.4", + "flatted": "^3.2.7", + "rfdc": "^1.3.0", + "streamroller": "^3.1.5" + }, + "engines": { + "node": ">=8.0" } }, - "node_modules/msgpackr-extract": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/msgpackr-extract/-/msgpackr-extract-3.0.3.tgz", - "integrity": "sha512-P0efT1C9jIdVRefqjzOQ9Xml57zpOXnIuS+csaB4MdZbTdmGDLo8XhzBG1N7aO11gKDDkJvBLULeFTo46wwreA==", + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", "dev": true, - "hasInstallScript": true, - "license": "MIT", - "optional": true, "dependencies": { - "node-gyp-build-optional-packages": "5.2.2" - }, - "bin": { - "download-msgpackr-prebuilds": "bin/download-prebuilds.js" - }, - "optionalDependencies": { - "@msgpackr-extract/msgpackr-extract-darwin-arm64": "3.0.3", - "@msgpackr-extract/msgpackr-extract-darwin-x64": "3.0.3", - "@msgpackr-extract/msgpackr-extract-linux-arm": "3.0.3", - "@msgpackr-extract/msgpackr-extract-linux-arm64": "3.0.3", - "@msgpackr-extract/msgpackr-extract-linux-x64": "3.0.3", - "@msgpackr-extract/msgpackr-extract-win32-x64": "3.0.3" + "yallist": "^3.0.2" } }, - "node_modules/multicast-dns": { - "version": "7.2.5", - "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.5.tgz", - "integrity": "sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==", + "node_modules/macos-release": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/macos-release/-/macos-release-2.5.1.tgz", + "integrity": "sha512-DXqXhEM7gW59OjZO8NIjBCz9AQ1BEMrfiOAl4AYByHCtVHRF4KoGNO8mqQeM8lRCtQe/UnJ4imO/d2HdkKsd+A==", "dev": true, - "license": "MIT", - "dependencies": { - "dns-packet": "^5.2.2", - "thunky": "^1.0.2" + "engines": { + "node": ">=6" }, - "bin": { - "multicast-dns": "cli.js" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/mute-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-2.0.0.tgz", - "integrity": "sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA==", + "node_modules/magic-string": { + "version": "0.30.12", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.12.tgz", + "integrity": "sha512-Ea8I3sQMVXr8JhN4z+H/d8zwo+tYDgHE9+5G4Wnrwhs0gaK9fXTKx0Tw5Xwsd/bCPTTZNRAdpyzvoeORe9LYpw==", "dev": true, - "engines": { - "node": "^18.17.0 || >=20.5.0" + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0" } }, - "node_modules/nanoid": { - "version": "3.3.8", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz", - "integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==", + "node_modules/make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "bin": { - "nanoid": "bin/nanoid.cjs" + "dependencies": { + "semver": "^7.5.3" }, "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/napi-build-utils": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", - "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==", + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", "dev": true }, - "node_modules/native-run": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/native-run/-/native-run-2.0.1.tgz", - "integrity": "sha512-XfG1FBZLM50J10xH9361whJRC9SHZ0Bub4iNRhhI61C8Jv0e1ud19muex6sNKB51ibQNUJNuYn25MuYET/rE6w==", + "node_modules/make-fetch-happen": { + "version": "14.0.3", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-14.0.3.tgz", + "integrity": "sha512-QMjGbFTP0blj97EeidG5hk/QhKQ3T4ICckQGLgz38QF7Vgbk6e6FTARN8KhKxyBbWn8R0HU+bnw8aSoFPD4qtQ==", "dev": true, "dependencies": { - "@ionic/utils-fs": "^3.1.7", - "@ionic/utils-terminal": "^2.3.4", - "bplist-parser": "^0.3.2", - "debug": "^4.3.4", - "elementtree": "^0.1.7", - "ini": "^4.1.1", - "plist": "^3.1.0", - "split2": "^4.2.0", - "through2": "^4.0.2", - "tslib": "^2.6.2", - "yauzl": "^2.10.0" - }, - "bin": { - "native-run": "bin/native-run" + "@npmcli/agent": "^3.0.0", + "cacache": "^19.0.1", + "http-cache-semantics": "^4.1.1", + "minipass": "^7.0.2", + "minipass-fetch": "^4.0.0", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^1.0.0", + "proc-log": "^5.0.0", + "promise-retry": "^2.0.1", + "ssri": "^12.0.0" }, "engines": { - "node": ">=16.0.0" + "node": "^18.17.0 || >=20.5.0" } }, - "node_modules/native-run/node_modules/ini": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/ini/-/ini-4.1.3.tgz", - "integrity": "sha512-X7rqawQBvfdjS10YU1y1YVreA3SsLrW9dX2CewP2EbBJM4ypVNLDkO5y04gejPwKIY9lR+7r9gn3rFPt/kmWFg==", + "node_modules/map-obj": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz", + "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==", "dev": true, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/native-run/node_modules/split2": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", - "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", + "node_modules/math-intrinsics": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.0.0.tgz", + "integrity": "sha512-4MqMiKP90ybymYvsut0CH2g4XWbfLtmlCkXmtmdcDCxNB+mQcu1w/1+L/VD7vi/PSv7X2JYV7SCcR+jiPXnQtA==", "dev": true, "engines": { - "node": ">= 10.x" + "node": ">= 0.4" } }, - "node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "dev": true, + "engines": { + "node": ">= 0.6" + } }, - "node_modules/needle": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/needle/-/needle-3.3.1.tgz", - "integrity": "sha512-6k0YULvhpw+RoLNiQCRKOl09Rv1dPLr8hHnVjHqdolKwDrdNyk+Hmrthi4lIGPPz3r39dLx0hsF5s40sZ3Us4Q==", + "node_modules/memfs": { + "version": "4.17.0", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-4.17.0.tgz", + "integrity": "sha512-4eirfZ7thblFmqFjywlTmuWVSvccHAJbn1r8qQLzmTO11qcqpohOjmY2mFce6x7x7WtskzRqApPD0hv+Oa74jg==", "dev": true, - "optional": true, + "license": "Apache-2.0", "dependencies": { - "iconv-lite": "^0.6.3", - "sax": "^1.2.4" - }, - "bin": { - "needle": "bin/needle" + "@jsonjoy.com/json-pack": "^1.0.3", + "@jsonjoy.com/util": "^1.3.0", + "tree-dump": "^1.0.1", + "tslib": "^2.0.0" }, "engines": { - "node": ">= 4.4.x" + "node": ">= 4.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" } }, - "node_modules/needle/node_modules/sax": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.1.tgz", - "integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==", + "node_modules/meow": { + "version": "8.1.2", + "resolved": "https://registry.npmjs.org/meow/-/meow-8.1.2.tgz", + "integrity": "sha512-r85E3NdZ+mpYk1C6RjPFEMSE+s1iZMuHtsHAqY0DT3jZczl0diWUZ8g6oU7h0M9cD2EL+PzaYghhCLzR0ZNn5Q==", "dev": true, - "optional": true + "dependencies": { + "@types/minimist": "^1.2.0", + "camelcase-keys": "^6.2.2", + "decamelize-keys": "^1.1.0", + "hard-rejection": "^2.1.0", + "minimist-options": "4.1.0", + "normalize-package-data": "^3.0.0", + "read-pkg-up": "^7.0.1", + "redent": "^3.0.0", + "trim-newlines": "^3.0.0", + "type-fest": "^0.18.0", + "yargs-parser": "^20.2.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, - "node_modules/negotiator": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", - "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", + "node_modules/meow/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, "engines": { - "node": ">= 0.6" + "node": ">=8" } }, - "node_modules/neo-async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "node_modules/meow/node_modules/hosted-git-info": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", "dev": true }, - "node_modules/netmask": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz", - "integrity": "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==", + "node_modules/meow/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/ng2-charts": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/ng2-charts/-/ng2-charts-7.0.0.tgz", - "integrity": "sha512-HofyPPkz7yOX6Dr9JfV/SDddzmmqCFYCKbn71jeDiyWPRjrj99yTBCyqYtjzzNrnlTfWwbdvynYZ4GAhu/lbgQ==", "dependencies": { - "lodash-es": "^4.17.15", - "tslib": "^2.3.0" + "p-locate": "^4.1.0" }, - "peerDependencies": { - "@angular/cdk": ">=18.0.0", - "@angular/common": ">=18.0.0", - "@angular/core": ">=18.0.0", - "@angular/platform-browser": ">=18.0.0", - "chart.js": "^3.4.0 || ^4.0.0", - "rxjs": "^6.5.3 || ^7.4.0" + "engines": { + "node": ">=8" } }, - "node_modules/ngx-cookie-service": { - "version": "19.0.0", - "resolved": "https://registry.npmjs.org/ngx-cookie-service/-/ngx-cookie-service-19.0.0.tgz", - "integrity": "sha512-itxGY1BlIRoEjEtDsSsRKnJuiQteTMLKPNHrykiH06tjUQ1bi3orE7YKU1D210VBqVy1jNrB7hKuGOOIQtQJDA==", + "node_modules/meow/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, "dependencies": { - "tslib": "^2.8.0" + "p-try": "^2.0.0" }, - "peerDependencies": { - "@angular/common": "^19.0.0", - "@angular/core": "^19.0.0" + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/ngx-device-detector": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/ngx-device-detector/-/ngx-device-detector-9.0.0.tgz", - "integrity": "sha512-zpio/wqH1GnxIpWCdA7cp5fmWf7YLycgzfXzQHmB9vaS7eAcqpBF5mxDS65IhE7TzNTJziDrYJCT+9tVqBcsDg==", + "node_modules/meow/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, "dependencies": { - "tslib": "^2.0.0" + "p-limit": "^2.2.0" }, - "peerDependencies": { - "@angular/common": "^19.0.0", - "@angular/core": "^19.0.0" + "engines": { + "node": ">=8" } }, - "node_modules/ngx-spinner": { - "version": "17.0.0", - "resolved": "https://registry.npmjs.org/ngx-spinner/-/ngx-spinner-17.0.0.tgz", - "integrity": "sha512-VWDSvLlCnaWqu0W1L+ybQIRHTbd+GffkX1sWs++iMPXMGVJ2ZCuzW32FHnu+p0regMUHU8r1/rvUcFD0YooJxQ==", + "node_modules/meow/node_modules/read-pkg": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", + "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", + "dev": true, "dependencies": { - "tslib": "^2.3.0" + "@types/normalize-package-data": "^2.4.0", + "normalize-package-data": "^2.5.0", + "parse-json": "^5.0.0", + "type-fest": "^0.6.0" }, - "peerDependencies": { - "@angular/animations": ">=15.0.0", - "@angular/common": ">=15.0.0", - "@angular/core": ">=15.0.0" + "engines": { + "node": ">=8" } }, - "node_modules/node-abi": { - "version": "3.71.0", - "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.71.0.tgz", - "integrity": "sha512-SZ40vRiy/+wRTf21hxkkEjPJZpARzUMVcJoQse2EF8qkUWbbO2z7vd5oA/H6bVH6SZQ5STGcu0KRDS7biNRfxw==", + "node_modules/meow/node_modules/read-pkg-up": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", + "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", "dev": true, "dependencies": { - "semver": "^7.3.5" + "find-up": "^4.1.0", + "read-pkg": "^5.2.0", + "type-fest": "^0.8.1" }, "engines": { - "node": ">=10" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/node-addon-api": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", - "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", + "node_modules/meow/node_modules/read-pkg-up/node_modules/type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", "dev": true, - "optional": true + "engines": { + "node": ">=8" + } }, - "node_modules/node-fetch": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", - "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "node_modules/meow/node_modules/read-pkg/node_modules/normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", "dev": true, "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" } }, - "node_modules/node-forge": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", - "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", + "node_modules/meow/node_modules/read-pkg/node_modules/type-fest": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", + "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", "dev": true, - "license": "(BSD-3-Clause OR GPL-2.0)", "engines": { - "node": ">= 6.13.0" + "node": ">=8" } }, - "node_modules/node-gyp": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-11.0.0.tgz", - "integrity": "sha512-zQS+9MTTeCMgY0F3cWPyJyRFAkVltQ1uXm+xXu/ES6KFgC6Czo1Seb9vQW2wNxSX2OrDTiqL0ojtkFxBQ0ypIw==", + "node_modules/meow/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", "dev": true, - "dependencies": { - "env-paths": "^2.2.0", - "exponential-backoff": "^3.1.1", - "glob": "^10.3.10", - "graceful-fs": "^4.2.6", - "make-fetch-happen": "^14.0.3", - "nopt": "^8.0.0", - "proc-log": "^5.0.0", - "semver": "^7.3.5", - "tar": "^7.4.3", - "which": "^5.0.0" - }, "bin": { - "node-gyp": "bin/node-gyp.js" - }, + "semver": "bin/semver" + } + }, + "node_modules/meow/node_modules/type-fest": { + "version": "0.18.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.18.1.tgz", + "integrity": "sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==", + "dev": true, "engines": { - "node": "^18.17.0 || >=20.5.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/node-gyp-build-optional-packages": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/node-gyp-build-optional-packages/-/node-gyp-build-optional-packages-5.2.2.tgz", - "integrity": "sha512-s+w+rBWnpTMwSFbaE0UXsRlg7hU4FjekKU4eyAih5T8nJuNZT1nNsskXpxmeqSK9UzkBl6UgRlnKc8hz8IEqOw==", + "node_modules/merge-descriptors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", "dev": true, "license": "MIT", - "optional": true, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/mergexml": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/mergexml/-/mergexml-1.2.4.tgz", + "integrity": "sha512-yiOlDqcVCz7AG1eSboonc18FTlfqDEKYfGoAV3Lul98u6YRV/s0kjtf4bjk47t0hLTFJR0BSYMd6BpmX3xDjNQ==", + "dev": true, "dependencies": { - "detect-libc": "^2.0.1" - }, - "bin": { - "node-gyp-build-optional-packages": "bin.js", - "node-gyp-build-optional-packages-optional": "optional.js", - "node-gyp-build-optional-packages-test": "build-test.js" + "@xmldom/xmldom": "^0.7.0", + "formidable": "^3.5.1", + "xpath": "0.0.27" } }, - "node_modules/node-gyp-build-optional-packages/node_modules/detect-libc": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz", - "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==", + "node_modules/mergexml/node_modules/xpath": { + "version": "0.0.27", + "resolved": "https://registry.npmjs.org/xpath/-/xpath-0.0.27.tgz", + "integrity": "sha512-fg03WRxtkCV6ohClePNAECYsmpKKTv5L8y/X3Dn1hQrec3POx2jHZ/0P2qQ6HvsrU1BmeqXcof3NGGueG6LxwQ==", "dev": true, - "license": "Apache-2.0", - "optional": true, "engines": { - "node": ">=8" + "node": ">=0.6.0" } }, - "node_modules/node-gyp/node_modules/chownr": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz", - "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==", + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", "dev": true, "engines": { - "node": ">=18" + "node": ">= 0.6" } }, - "node_modules/node-gyp/node_modules/glob": { - "version": "10.4.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", - "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dev": true, "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^1.11.1" - }, - "bin": { - "glob": "dist/esm/bin.mjs" + "braces": "^3.0.3", + "picomatch": "^2.3.1" }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "engines": { + "node": ">=8.6" } }, - "node_modules/node-gyp/node_modules/isexe": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", - "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==", + "node_modules/micromatch/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true, "engines": { - "node": ">=16" + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/node-gyp/node_modules/mkdirp": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz", - "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==", + "node_modules/mime": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", + "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", "dev": true, "bin": { - "mkdirp": "dist/cjs/src/bin.js" + "mime": "cli.js" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": ">=4.0.0" } }, - "node_modules/node-gyp/node_modules/tar": { - "version": "7.4.3", - "resolved": "https://registry.npmjs.org/tar/-/tar-7.4.3.tgz", - "integrity": "sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==", + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", "dev": true, - "dependencies": { - "@isaacs/fs-minipass": "^4.0.0", - "chownr": "^3.0.0", - "minipass": "^7.1.2", - "minizlib": "^3.0.1", - "mkdirp": "^3.0.1", - "yallist": "^5.0.0" - }, "engines": { - "node": ">=18" + "node": ">= 0.6" } }, - "node_modules/node-gyp/node_modules/which": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/which/-/which-5.0.0.tgz", - "integrity": "sha512-JEdGzHwwkrbWoGOlIHqQ5gtprKGOenpDHpxE9zVR1bWbOtYRyPPHMe9FaP6x61CmNaTThSkb0DAJte5jD+DmzQ==", + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", "dev": true, "dependencies": { - "isexe": "^3.1.1" - }, - "bin": { - "node-which": "bin/which.js" + "mime-db": "1.52.0" }, "engines": { - "node": "^18.17.0 || >=20.5.0" + "node": ">= 0.6" } }, - "node_modules/node-gyp/node_modules/yallist": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", - "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==", + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/mimic-function": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz", + "integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==", "dev": true, "engines": { "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/node-html-parser": { - "version": "5.4.2", - "resolved": "https://registry.npmjs.org/node-html-parser/-/node-html-parser-5.4.2.tgz", - "integrity": "sha512-RaBPP3+51hPne/OolXxcz89iYvQvKOydaqoePpOgXcrOKZhjVIzmpKZz+Hd/RBO2/zN2q6CNJhQzucVz+u3Jyw==", + "node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", "dev": true, - "dependencies": { - "css-select": "^4.2.1", - "he": "1.2.0" + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/node-releases": { - "version": "2.0.19", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", - "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==", - "dev": true + "node_modules/min-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", + "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", + "dev": true, + "engines": { + "node": ">=4" + } }, - "node_modules/nopt": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-8.0.0.tgz", - "integrity": "sha512-1L/fTJ4UmV/lUxT2Uf006pfZKTvAgCF+chz+0OgBHO8u2Z67pE7AaAUUj7CJy0lXqHmymUvGFt6NE9R3HER0yw==", + "node_modules/mini-css-extract-plugin": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.9.2.tgz", + "integrity": "sha512-GJuACcS//jtq4kCtd5ii/M0SZf7OZRH+BxdqXZHaJfb8TJiVl+NgQRPwiYt2EuqeSkNydn/7vP+bcE27C5mb9w==", "dev": true, "dependencies": { - "abbrev": "^2.0.0" - }, - "bin": { - "nopt": "bin/nopt.js" + "schema-utils": "^4.0.0", + "tapable": "^2.2.1" }, "engines": { - "node": "^18.17.0 || >=20.5.0" + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" } }, - "node_modules/normalize-package-data": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", - "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", + "node_modules/minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", + "dev": true, + "license": "ISC" + }, + "node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "dev": true, "dependencies": { - "hosted-git-info": "^4.0.1", - "is-core-module": "^2.5.0", - "semver": "^7.3.4", - "validate-npm-package-license": "^3.0.1" + "brace-expansion": "^2.0.1" }, "engines": { - "node": ">=10" + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "devOptional": true, - "engines": { - "node": ">=0.10.0" + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/normalize-range": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", - "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", + "node_modules/minimist-options": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz", + "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==", "dev": true, + "dependencies": { + "arrify": "^1.0.1", + "is-plain-obj": "^1.1.0", + "kind-of": "^6.0.3" + }, "engines": { - "node": ">=0.10.0" + "node": ">= 6" } }, - "node_modules/npm-bundled": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-4.0.0.tgz", - "integrity": "sha512-IxaQZDMsqfQ2Lz37VvyyEtKLe8FsRZuysmedy/N06TU1RyVppYKXrO4xIhR0F+7ubIBox6Q7nir6fQI3ej39iA==", + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", "dev": true, - "dependencies": { - "npm-normalize-package-bin": "^4.0.0" - }, "engines": { - "node": "^18.17.0 || >=20.5.0" + "node": ">=16 || 14 >=14.17" } }, - "node_modules/npm-install-checks": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/npm-install-checks/-/npm-install-checks-7.1.1.tgz", - "integrity": "sha512-u6DCwbow5ynAX5BdiHQ9qvexme4U3qHW3MWe5NqH+NeBm0LbiH6zvGjNNew1fY+AZZUtVHbOPF3j7mJxbUzpXg==", + "node_modules/minipass-collect": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-2.0.1.tgz", + "integrity": "sha512-D7V8PO9oaz7PWGLbCACuI1qEOsq7UKfLotx/C0Aet43fCUB/wfQ7DYeq2oR/svFJGYDHPr38SHATeaj/ZoKHKw==", "dev": true, "dependencies": { - "semver": "^7.1.1" + "minipass": "^7.0.3" }, "engines": { - "node": "^18.17.0 || >=20.5.0" + "node": ">=16 || 14 >=14.17" } }, - "node_modules/npm-normalize-package-bin": { + "node_modules/minipass-fetch": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-4.0.0.tgz", - "integrity": "sha512-TZKxPvItzai9kN9H/TkmCtx/ZN/hvr3vUycjlfmH0ootY9yFBzNOpiXAdIn1Iteqsvk4lQn6B5PTrt+n6h8k/w==", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-4.0.0.tgz", + "integrity": "sha512-2v6aXUXwLP1Epd/gc32HAMIWoczx+fZwEPRHm/VwtrJzRGwR1qGZXEYV3Zp8ZjjbwaZhMrM6uHV4KVkk+XCc2w==", "dev": true, + "dependencies": { + "minipass": "^7.0.3", + "minipass-sized": "^1.0.3", + "minizlib": "^3.0.1" + }, "engines": { "node": "^18.17.0 || >=20.5.0" + }, + "optionalDependencies": { + "encoding": "^0.1.13" } }, - "node_modules/npm-package-arg": { - "version": "12.0.0", - "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-12.0.0.tgz", - "integrity": "sha512-ZTE0hbwSdTNL+Stx2zxSqdu2KZfNDcrtrLdIk7XGnQFYBWYDho/ORvXtn5XEePcL3tFpGjHCV3X3xrtDh7eZ+A==", + "node_modules/minipass-flush": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", + "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", "dev": true, "dependencies": { - "hosted-git-info": "^8.0.0", - "proc-log": "^5.0.0", - "semver": "^7.3.5", - "validate-npm-package-name": "^6.0.0" + "minipass": "^3.0.0" }, "engines": { - "node": "^18.17.0 || >=20.5.0" + "node": ">= 8" } }, - "node_modules/npm-package-arg/node_modules/hosted-git-info": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-8.0.2.tgz", - "integrity": "sha512-sYKnA7eGln5ov8T8gnYlkSOxFJvywzEx9BueN6xo/GKO8PGiI6uK6xx+DIGe45T3bdVjLAQDQW1aicT8z8JwQg==", + "node_modules/minipass-flush/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", "dev": true, "dependencies": { - "lru-cache": "^10.0.1" + "yallist": "^4.0.0" }, "engines": { - "node": "^18.17.0 || >=20.5.0" + "node": ">=8" } }, - "node_modules/npm-package-arg/node_modules/lru-cache": { - "version": "10.4.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", - "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "node_modules/minipass-flush/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true }, - "node_modules/npm-packlist": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-9.0.0.tgz", - "integrity": "sha512-8qSayfmHJQTx3nJWYbbUmflpyarbLMBc6LCAjYsiGtXxDB68HaZpb8re6zeaLGxZzDuMdhsg70jryJe+RrItVQ==", + "node_modules/minipass-pipeline": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", + "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", "dev": true, "dependencies": { - "ignore-walk": "^7.0.0" + "minipass": "^3.0.0" }, "engines": { - "node": "^18.17.0 || >=20.5.0" + "node": ">=8" } }, - "node_modules/npm-pick-manifest": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-10.0.0.tgz", - "integrity": "sha512-r4fFa4FqYY8xaM7fHecQ9Z2nE9hgNfJR+EmoKv0+chvzWkBcORX3r0FpTByP+CbOVJDladMXnPQGVN8PBLGuTQ==", + "node_modules/minipass-pipeline/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", "dev": true, "dependencies": { - "npm-install-checks": "^7.1.0", - "npm-normalize-package-bin": "^4.0.0", - "npm-package-arg": "^12.0.0", - "semver": "^7.3.5" + "yallist": "^4.0.0" }, "engines": { - "node": "^18.17.0 || >=20.5.0" + "node": ">=8" } }, - "node_modules/npm-registry-fetch": { - "version": "18.0.2", - "resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-18.0.2.tgz", - "integrity": "sha512-LeVMZBBVy+oQb5R6FDV9OlJCcWDU+al10oKpe+nsvcHnG24Z3uM3SvJYKfGJlfGjVU8v9liejCrUR/M5HO5NEQ==", + "node_modules/minipass-pipeline/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/minipass-sized": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", + "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", "dev": true, "dependencies": { - "@npmcli/redact": "^3.0.0", - "jsonparse": "^1.3.1", - "make-fetch-happen": "^14.0.0", - "minipass": "^7.0.2", - "minipass-fetch": "^4.0.0", - "minizlib": "^3.0.1", - "npm-package-arg": "^12.0.0", - "proc-log": "^5.0.0" + "minipass": "^3.0.0" }, "engines": { - "node": "^18.17.0 || >=20.5.0" + "node": ">=8" } }, - "node_modules/npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "node_modules/minipass-sized/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", "dev": true, "dependencies": { - "path-key": "^3.0.0" + "yallist": "^4.0.0" }, "engines": { "node": ">=8" } }, - "node_modules/nth-check": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", - "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "node_modules/minipass-sized/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/minizlib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.0.1.tgz", + "integrity": "sha512-umcy022ILvb5/3Djuu8LWeqUa8D68JaBzlttKeMWen48SjabqS3iY5w/vzeMzMUNhLDifyhbOwKDSznB1vvrwg==", "dev": true, "dependencies": { - "boolbase": "^1.0.0" + "minipass": "^7.0.4", + "rimraf": "^5.0.5" }, - "funding": { - "url": "https://github.com/fb55/nth-check?sponsor=1" - } - }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">= 18" } }, - "node_modules/object-inspect": { - "version": "1.13.3", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.3.tgz", - "integrity": "sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA==", + "node_modules/minizlib/node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", "dev": true, - "engines": { - "node": ">= 0.4" + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" }, "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true, - "engines": { - "node": ">= 0.4" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/object.assign": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", - "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", + "node_modules/minizlib/node_modules/rimraf": { + "version": "5.0.10", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.10.tgz", + "integrity": "sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.5", - "define-properties": "^1.2.1", - "has-symbols": "^1.0.3", - "object-keys": "^1.1.1" + "glob": "^10.3.7" }, - "engines": { - "node": ">= 0.4" + "bin": { + "rimraf": "dist/esm/bin.mjs" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/object.fromentries": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", - "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", + "node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", "dev": true, "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-object-atoms": "^1.0.0" + "minimist": "^1.2.6" }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", + "dev": true + }, + "node_modules/modify-values": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/modify-values/-/modify-values-1.0.1.tgz", + "integrity": "sha512-xV2bxeN6F7oYjZWTe/YPAy6MN2M+sL4u/Rlm2AHCIVGfo2p1yGmBHQ6vHehl4bRTZBdHu3TSkWdYgkwpYzAGSw==", + "dev": true, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=0.10.0" } }, - "node_modules/object.groupby": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", - "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", + "node_modules/mrmime": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.0.tgz", + "integrity": "sha512-eu38+hdgojoyq63s+yTpN4XMBdt5l8HhMhc4VKLO9KM5caLIBvUm4thi7fFaxyTmCKeNnXZ5pAlBwCUnhA09uw==", "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2" - }, + "license": "MIT", "engines": { - "node": ">= 0.4" + "node": ">=10" } }, - "node_modules/object.values": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.0.tgz", - "integrity": "sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==", + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "node_modules/msgpackr": { + "version": "1.11.2", + "resolved": "https://registry.npmjs.org/msgpackr/-/msgpackr-1.11.2.tgz", + "integrity": "sha512-F9UngXRlPyWCDEASDpTf6c9uNhGPTqnTeLVt7bN+bU1eajoR/8V9ys2BRaV5C/e5ihE6sJ9uPIKaYt6bFuO32g==", + "dev": true, + "license": "MIT", + "optional": true, + "optionalDependencies": { + "msgpackr-extract": "^3.0.2" + } + }, + "node_modules/msgpackr-extract": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/msgpackr-extract/-/msgpackr-extract-3.0.3.tgz", + "integrity": "sha512-P0efT1C9jIdVRefqjzOQ9Xml57zpOXnIuS+csaB4MdZbTdmGDLo8XhzBG1N7aO11gKDDkJvBLULeFTo46wwreA==", "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" + "node-gyp-build-optional-packages": "5.2.2" }, - "engines": { - "node": ">= 0.4" + "bin": { + "download-msgpackr-prebuilds": "bin/download-prebuilds.js" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "optionalDependencies": { + "@msgpackr-extract/msgpackr-extract-darwin-arm64": "3.0.3", + "@msgpackr-extract/msgpackr-extract-darwin-x64": "3.0.3", + "@msgpackr-extract/msgpackr-extract-linux-arm": "3.0.3", + "@msgpackr-extract/msgpackr-extract-linux-arm64": "3.0.3", + "@msgpackr-extract/msgpackr-extract-linux-x64": "3.0.3", + "@msgpackr-extract/msgpackr-extract-win32-x64": "3.0.3" } }, - "node_modules/obuf": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", - "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", - "dev": true, - "license": "MIT" - }, - "node_modules/on-finished": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", - "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "node_modules/multicast-dns": { + "version": "7.2.5", + "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.5.tgz", + "integrity": "sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==", "dev": true, + "license": "MIT", "dependencies": { - "ee-first": "1.1.1" + "dns-packet": "^5.2.2", + "thunky": "^1.0.2" }, - "engines": { - "node": ">= 0.8" + "bin": { + "multicast-dns": "cli.js" } }, - "node_modules/on-headers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", - "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "node_modules/mute-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-2.0.0.tgz", + "integrity": "sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA==", "dev": true, - "license": "MIT", "engines": { - "node": ">= 0.8" + "node": "^18.17.0 || >=20.5.0" } }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "node_modules/nanoid": { + "version": "3.3.8", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz", + "integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==", "dev": true, - "dependencies": { - "wrappy": "1" + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, - "node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "node_modules/napi-build-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", + "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==", + "dev": true + }, + "node_modules/native-run": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/native-run/-/native-run-2.0.1.tgz", + "integrity": "sha512-XfG1FBZLM50J10xH9361whJRC9SHZ0Bub4iNRhhI61C8Jv0e1ud19muex6sNKB51ibQNUJNuYn25MuYET/rE6w==", + "dev": true, "dependencies": { - "mimic-fn": "^2.1.0" + "@ionic/utils-fs": "^3.1.7", + "@ionic/utils-terminal": "^2.3.4", + "bplist-parser": "^0.3.2", + "debug": "^4.3.4", + "elementtree": "^0.1.7", + "ini": "^4.1.1", + "plist": "^3.1.0", + "split2": "^4.2.0", + "through2": "^4.0.2", + "tslib": "^2.6.2", + "yauzl": "^2.10.0" }, - "engines": { - "node": ">=6" + "bin": { + "native-run": "bin/native-run" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": ">=16.0.0" } }, - "node_modules/open": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/open/-/open-10.1.0.tgz", - "integrity": "sha512-mnkeQ1qP5Ue2wd+aivTD3NHd/lZ96Lu0jgf0pwktLPtx6cTZiH7tyeGRRHs0zX0rbrahXPnXlUnbeXyaBBuIaw==", + "node_modules/native-run/node_modules/ini": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/ini/-/ini-4.1.3.tgz", + "integrity": "sha512-X7rqawQBvfdjS10YU1y1YVreA3SsLrW9dX2CewP2EbBJM4ypVNLDkO5y04gejPwKIY9lR+7r9gn3rFPt/kmWFg==", "dev": true, - "license": "MIT", - "dependencies": { - "default-browser": "^5.2.1", - "define-lazy-prop": "^3.0.0", - "is-inside-container": "^1.0.0", - "is-wsl": "^3.1.0" - }, "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/optionator": { - "version": "0.9.4", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", - "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "node_modules/native-run/node_modules/split2": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", "dev": true, - "dependencies": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.5" - }, "engines": { - "node": ">= 0.8.0" + "node": ">= 10.x" } }, - "node_modules/ora": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", - "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "node_modules/needle": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/needle/-/needle-3.3.1.tgz", + "integrity": "sha512-6k0YULvhpw+RoLNiQCRKOl09Rv1dPLr8hHnVjHqdolKwDrdNyk+Hmrthi4lIGPPz3r39dLx0hsF5s40sZ3Us4Q==", + "dev": true, + "optional": true, "dependencies": { - "bl": "^4.1.0", - "chalk": "^4.1.0", - "cli-cursor": "^3.1.0", - "cli-spinners": "^2.5.0", - "is-interactive": "^1.0.0", - "is-unicode-supported": "^0.1.0", - "log-symbols": "^4.1.0", - "strip-ansi": "^6.0.0", - "wcwidth": "^1.0.1" + "iconv-lite": "^0.6.3", + "sax": "^1.2.4" }, - "engines": { - "node": ">=10" + "bin": { + "needle": "bin/needle" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": ">= 4.4.x" } }, - "node_modules/ordered-binary": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/ordered-binary/-/ordered-binary-1.5.3.tgz", - "integrity": "sha512-oGFr3T+pYdTGJ+YFEILMpS3es+GiIbs9h/XQrclBXUtd44ey7XwfsMzM31f64I1SQOawDoDr/D823kNCADI8TA==", + "node_modules/needle/node_modules/sax": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.1.tgz", + "integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==", "dev": true, - "license": "MIT", "optional": true }, - "node_modules/os-name": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/os-name/-/os-name-4.0.1.tgz", - "integrity": "sha512-xl9MAoU97MH1Xt5K9ERft2YfCAoaO6msy1OBA0ozxEC0x0TmIoE6K3QvgJMMZA9yKGLmHXNY/YZoDbiGDj4zYw==", + "node_modules/negotiator": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", + "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", "dev": true, - "dependencies": { - "macos-release": "^2.5.0", - "windows-release": "^4.0.0" - }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">= 0.6" } }, - "node_modules/os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true + }, + "node_modules/netmask": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz", + "integrity": "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==", "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">= 0.4.0" } }, - "node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, + "node_modules/ng2-charts": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/ng2-charts/-/ng2-charts-7.0.0.tgz", + "integrity": "sha512-HofyPPkz7yOX6Dr9JfV/SDddzmmqCFYCKbn71jeDiyWPRjrj99yTBCyqYtjzzNrnlTfWwbdvynYZ4GAhu/lbgQ==", "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" + "lodash-es": "^4.17.15", + "tslib": "^2.3.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependencies": { + "@angular/cdk": ">=18.0.0", + "@angular/common": ">=18.0.0", + "@angular/core": ">=18.0.0", + "@angular/platform-browser": ">=18.0.0", + "chart.js": "^3.4.0 || ^4.0.0", + "rxjs": "^6.5.3 || ^7.4.0" + } + }, + "node_modules/ngx-cookie-service": { + "version": "19.0.0", + "resolved": "https://registry.npmjs.org/ngx-cookie-service/-/ngx-cookie-service-19.0.0.tgz", + "integrity": "sha512-itxGY1BlIRoEjEtDsSsRKnJuiQteTMLKPNHrykiH06tjUQ1bi3orE7YKU1D210VBqVy1jNrB7hKuGOOIQtQJDA==", + "dependencies": { + "tslib": "^2.8.0" + }, + "peerDependencies": { + "@angular/common": "^19.0.0", + "@angular/core": "^19.0.0" } }, - "node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, + "node_modules/ngx-device-detector": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/ngx-device-detector/-/ngx-device-detector-9.0.0.tgz", + "integrity": "sha512-zpio/wqH1GnxIpWCdA7cp5fmWf7YLycgzfXzQHmB9vaS7eAcqpBF5mxDS65IhE7TzNTJziDrYJCT+9tVqBcsDg==", "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" + "tslib": "^2.0.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependencies": { + "@angular/common": "^19.0.0", + "@angular/core": "^19.0.0" } }, - "node_modules/p-map": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-7.0.3.tgz", - "integrity": "sha512-VkndIv2fIB99swvQoA65bm+fsmt6UNdGeIB0oxBs+WhAhdh08QA04JXpI7rbB9r08/nkbysKoya9rtDERYOYMA==", - "dev": true, - "engines": { - "node": ">=18" + "node_modules/ngx-spinner": { + "version": "17.0.0", + "resolved": "https://registry.npmjs.org/ngx-spinner/-/ngx-spinner-17.0.0.tgz", + "integrity": "sha512-VWDSvLlCnaWqu0W1L+ybQIRHTbd+GffkX1sWs++iMPXMGVJ2ZCuzW32FHnu+p0regMUHU8r1/rvUcFD0YooJxQ==", + "dependencies": { + "tslib": "^2.3.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependencies": { + "@angular/animations": ">=15.0.0", + "@angular/common": ">=15.0.0", + "@angular/core": ">=15.0.0" } }, - "node_modules/p-retry": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-6.2.1.tgz", - "integrity": "sha512-hEt02O4hUct5wtwg4H4KcWgDdm+l1bOaEy/hWzd8xtXB9BqxTWBBhb+2ImAtH4Cv4rPjV76xN3Zumqk3k3AhhQ==", + "node_modules/node-abi": { + "version": "3.71.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.71.0.tgz", + "integrity": "sha512-SZ40vRiy/+wRTf21hxkkEjPJZpARzUMVcJoQse2EF8qkUWbbO2z7vd5oA/H6bVH6SZQ5STGcu0KRDS7biNRfxw==", "dev": true, - "license": "MIT", "dependencies": { - "@types/retry": "0.12.2", - "is-network-error": "^1.0.0", - "retry": "^0.13.1" + "semver": "^7.3.5" }, "engines": { - "node": ">=16.17" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=10" } }, - "node_modules/p-retry/node_modules/retry": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", - "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", + "node_modules/node-addon-api": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", + "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", "dev": true, "license": "MIT", - "engines": { - "node": ">= 4" - } - }, - "node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true, - "engines": { - "node": ">=6" - } + "optional": true }, - "node_modules/pac-proxy-agent": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-7.1.0.tgz", - "integrity": "sha512-Z5FnLVVZSnX7WjBg0mhDtydeRZ1xMcATZThjySQUHqr+0ksP8kqaw23fNKkaaN/Z8gwLUs/W7xdl0I75eP2Xyw==", + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", "dev": true, "dependencies": { - "@tootallnate/quickjs-emscripten": "^0.23.0", - "agent-base": "^7.1.2", - "debug": "^4.3.4", - "get-uri": "^6.0.1", - "http-proxy-agent": "^7.0.0", - "https-proxy-agent": "^7.0.6", - "pac-resolver": "^7.0.1", - "socks-proxy-agent": "^8.0.5" + "whatwg-url": "^5.0.0" }, "engines": { - "node": ">= 14" + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } } }, - "node_modules/pac-resolver": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-7.0.1.tgz", - "integrity": "sha512-5NPgf87AT2STgwa2ntRMr45jTKrYBGkVU36yT0ig/n/GMAa3oPqhZfIQ2kMEimReg0+t9kZViDVZ83qfVUlckg==", + "node_modules/node-forge": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", + "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", "dev": true, - "dependencies": { - "degenerator": "^5.0.0", - "netmask": "^2.0.2" - }, + "license": "(BSD-3-Clause OR GPL-2.0)", "engines": { - "node": ">= 14" + "node": ">= 6.13.0" } }, - "node_modules/package-json-from-dist": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", - "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", - "dev": true - }, - "node_modules/pacote": { - "version": "20.0.0", - "resolved": "https://registry.npmjs.org/pacote/-/pacote-20.0.0.tgz", - "integrity": "sha512-pRjC5UFwZCgx9kUFDVM9YEahv4guZ1nSLqwmWiLUnDbGsjs+U5w7z6Uc8HNR1a6x8qnu5y9xtGE6D1uAuYz+0A==", + "node_modules/node-gyp": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-11.0.0.tgz", + "integrity": "sha512-zQS+9MTTeCMgY0F3cWPyJyRFAkVltQ1uXm+xXu/ES6KFgC6Czo1Seb9vQW2wNxSX2OrDTiqL0ojtkFxBQ0ypIw==", "dev": true, "dependencies": { - "@npmcli/git": "^6.0.0", - "@npmcli/installed-package-contents": "^3.0.0", - "@npmcli/package-json": "^6.0.0", - "@npmcli/promise-spawn": "^8.0.0", - "@npmcli/run-script": "^9.0.0", - "cacache": "^19.0.0", - "fs-minipass": "^3.0.0", - "minipass": "^7.0.2", - "npm-package-arg": "^12.0.0", - "npm-packlist": "^9.0.0", - "npm-pick-manifest": "^10.0.0", - "npm-registry-fetch": "^18.0.0", + "env-paths": "^2.2.0", + "exponential-backoff": "^3.1.1", + "glob": "^10.3.10", + "graceful-fs": "^4.2.6", + "make-fetch-happen": "^14.0.3", + "nopt": "^8.0.0", "proc-log": "^5.0.0", - "promise-retry": "^2.0.1", - "sigstore": "^3.0.0", - "ssri": "^12.0.0", - "tar": "^6.1.11" + "semver": "^7.3.5", + "tar": "^7.4.3", + "which": "^5.0.0" }, "bin": { - "pacote": "bin/index.js" + "node-gyp": "bin/node-gyp.js" }, "engines": { "node": "^18.17.0 || >=20.5.0" } }, - "node_modules/parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "dependencies": { - "callsites": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/parse-imports": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/parse-imports/-/parse-imports-2.2.1.tgz", - "integrity": "sha512-OL/zLggRp8mFhKL0rNORUTR4yBYujK/uU+xZL+/0Rgm2QE4nLO9v8PzEweSJEbMGKmDRjJE4R3IMJlL2di4JeQ==", + "node_modules/node-gyp-build-optional-packages": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/node-gyp-build-optional-packages/-/node-gyp-build-optional-packages-5.2.2.tgz", + "integrity": "sha512-s+w+rBWnpTMwSFbaE0UXsRlg7hU4FjekKU4eyAih5T8nJuNZT1nNsskXpxmeqSK9UzkBl6UgRlnKc8hz8IEqOw==", "dev": true, + "license": "MIT", + "optional": true, "dependencies": { - "es-module-lexer": "^1.5.3", - "slashes": "^3.0.12" + "detect-libc": "^2.0.1" }, - "engines": { - "node": ">= 18" + "bin": { + "node-gyp-build-optional-packages": "bin.js", + "node-gyp-build-optional-packages-optional": "optional.js", + "node-gyp-build-optional-packages-test": "build-test.js" } }, - "node_modules/parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "node_modules/node-gyp-build-optional-packages/node_modules/detect-libc": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz", + "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==", "dev": true, - "dependencies": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" - }, + "license": "Apache-2.0", + "optional": true, "engines": { "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/parse-json/node_modules/json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true - }, - "node_modules/parse-node-version": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz", - "integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==", + "node_modules/node-gyp/node_modules/chownr": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz", + "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==", "dev": true, "engines": { - "node": ">= 0.10" - } - }, - "node_modules/parse5": { - "version": "7.2.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.2.1.tgz", - "integrity": "sha512-BuBYQYlv1ckiPdQi/ohiivi9Sagc9JG+Ozs0r7b/0iK3sKmrb0b9FdWdBbOdx6hBCM/F9Ir82ofnBhtZOjCRPQ==", - "devOptional": true, - "dependencies": { - "entities": "^4.5.0" - }, - "funding": { - "url": "https://github.com/inikulin/parse5?sponsor=1" + "node": ">=18" } }, - "node_modules/parse5-html-rewriting-stream": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/parse5-html-rewriting-stream/-/parse5-html-rewriting-stream-7.0.0.tgz", - "integrity": "sha512-mazCyGWkmCRWDI15Zp+UiCqMp/0dgEmkZRvhlsqqKYr4SsVm/TvnSpD9fCvqCA2zoWJcfRym846ejWBBHRiYEg==", + "node_modules/node-gyp/node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", "dev": true, - "license": "MIT", "dependencies": { - "entities": "^4.3.0", - "parse5": "^7.0.0", - "parse5-sax-parser": "^7.0.0" + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" }, "funding": { - "url": "https://github.com/inikulin/parse5?sponsor=1" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/parse5-html-rewriting-stream/node_modules/entities": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "node_modules/node-gyp/node_modules/isexe": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", + "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==", "dev": true, - "license": "BSD-2-Clause", "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" + "node": ">=16" } }, - "node_modules/parse5-sax-parser": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/parse5-sax-parser/-/parse5-sax-parser-7.0.0.tgz", - "integrity": "sha512-5A+v2SNsq8T6/mG3ahcz8ZtQ0OUFTatxPbeidoMB7tkJSGDY3tdfl4MHovtLQHkEn5CGxijNWRQHhRQ6IRpXKg==", + "node_modules/node-gyp/node_modules/mkdirp": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz", + "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==", "dev": true, - "license": "MIT", - "dependencies": { - "parse5": "^7.0.0" + "bin": { + "mkdirp": "dist/cjs/src/bin.js" }, - "funding": { - "url": "https://github.com/inikulin/parse5?sponsor=1" - } - }, - "node_modules/parse5/node_modules/entities": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", - "devOptional": true, "engines": { - "node": ">=0.12" + "node": ">=10" }, "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "node_modules/node-gyp/node_modules/tar": { + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/tar/-/tar-7.4.3.tgz", + "integrity": "sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==", "dev": true, + "dependencies": { + "@isaacs/fs-minipass": "^4.0.0", + "chownr": "^3.0.0", + "minipass": "^7.1.2", + "minizlib": "^3.0.1", + "mkdirp": "^3.0.1", + "yallist": "^5.0.0" + }, "engines": { - "node": ">= 0.8" + "node": ">=18" } }, - "node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "node_modules/node-gyp/node_modules/which": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/which/-/which-5.0.0.tgz", + "integrity": "sha512-JEdGzHwwkrbWoGOlIHqQ5gtprKGOenpDHpxE9zVR1bWbOtYRyPPHMe9FaP6x61CmNaTThSkb0DAJte5jD+DmzQ==", "dev": true, + "dependencies": { + "isexe": "^3.1.1" + }, + "bin": { + "node-which": "bin/which.js" + }, "engines": { - "node": ">=8" + "node": "^18.17.0 || >=20.5.0" } }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "node_modules/node-gyp/node_modules/yallist": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", + "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==", "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">=18" } }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "node_modules/node-html-parser": { + "version": "5.4.2", + "resolved": "https://registry.npmjs.org/node-html-parser/-/node-html-parser-5.4.2.tgz", + "integrity": "sha512-RaBPP3+51hPne/OolXxcz89iYvQvKOydaqoePpOgXcrOKZhjVIzmpKZz+Hd/RBO2/zN2q6CNJhQzucVz+u3Jyw==", "dev": true, - "engines": { - "node": ">=8" + "dependencies": { + "css-select": "^4.2.1", + "he": "1.2.0" } }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "node_modules/node-releases": { + "version": "2.0.19", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", + "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==", "dev": true }, - "node_modules/path-scurry": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", - "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "node_modules/nopt": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-8.0.0.tgz", + "integrity": "sha512-1L/fTJ4UmV/lUxT2Uf006pfZKTvAgCF+chz+0OgBHO8u2Z67pE7AaAUUj7CJy0lXqHmymUvGFt6NE9R3HER0yw==", "dev": true, "dependencies": { - "lru-cache": "^10.2.0", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + "abbrev": "^2.0.0" }, - "engines": { - "node": ">=16 || 14 >=14.18" + "bin": { + "nopt": "bin/nopt.js" }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "engines": { + "node": "^18.17.0 || >=20.5.0" } }, - "node_modules/path-scurry/node_modules/lru-cache": { - "version": "10.4.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", - "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", - "dev": true - }, - "node_modules/path-to-regexp": { - "version": "0.1.12", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", - "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/path-type": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-5.0.0.tgz", - "integrity": "sha512-5HviZNaZcfqP95rwpv+1HDgUamezbqdSYTyzjTvwtJSnIH+3vnbmWsItli8OFEndS984VT55M3jduxZbX351gg==", + "node_modules/normalize-package-data": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", + "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", "dev": true, - "engines": { - "node": ">=12" + "dependencies": { + "hosted-git-info": "^4.0.1", + "is-core-module": "^2.5.0", + "semver": "^7.3.4", + "validate-npm-package-license": "^3.0.1" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": ">=10" } }, - "node_modules/pend": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", - "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", - "dev": true - }, - "node_modules/picocolors": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "dev": true - }, - "node_modules/picomatch": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", - "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", - "dev": true, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "devOptional": true, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" + "node": ">=0.10.0" } }, - "node_modules/pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "node_modules/normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", "dev": true, "engines": { "node": ">=0.10.0" } }, - "node_modules/piscina": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/piscina/-/piscina-4.7.0.tgz", - "integrity": "sha512-b8hvkpp9zS0zsfa939b/jXbe64Z2gZv0Ha7FYPNUiDIB1y2AtxcOZdfP8xN8HFjUaqQiT9gRlfjAsoL8vdJ1Iw==", + "node_modules/npm-bundled": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-4.0.0.tgz", + "integrity": "sha512-IxaQZDMsqfQ2Lz37VvyyEtKLe8FsRZuysmedy/N06TU1RyVppYKXrO4xIhR0F+7ubIBox6Q7nir6fQI3ej39iA==", "dev": true, - "license": "MIT", - "optionalDependencies": { - "@napi-rs/nice": "^1.0.1" + "dependencies": { + "npm-normalize-package-bin": "^4.0.0" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" } }, - "node_modules/pkg-dir": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-7.0.0.tgz", - "integrity": "sha512-Ie9z/WINcxxLp27BKOCHGde4ITq9UklYKDzVo1nhk5sqGEXU3FpkwP5GM2voTGJkGd9B3Otl+Q4uwSOeSUtOBA==", + "node_modules/npm-install-checks": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/npm-install-checks/-/npm-install-checks-7.1.1.tgz", + "integrity": "sha512-u6DCwbow5ynAX5BdiHQ9qvexme4U3qHW3MWe5NqH+NeBm0LbiH6zvGjNNew1fY+AZZUtVHbOPF3j7mJxbUzpXg==", "dev": true, "dependencies": { - "find-up": "^6.3.0" + "semver": "^7.1.1" }, "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": "^18.17.0 || >=20.5.0" } }, - "node_modules/pkg-dir/node_modules/find-up": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-6.3.0.tgz", - "integrity": "sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw==", + "node_modules/npm-normalize-package-bin": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-4.0.0.tgz", + "integrity": "sha512-TZKxPvItzai9kN9H/TkmCtx/ZN/hvr3vUycjlfmH0ootY9yFBzNOpiXAdIn1Iteqsvk4lQn6B5PTrt+n6h8k/w==", "dev": true, - "dependencies": { - "locate-path": "^7.1.0", - "path-exists": "^5.0.0" - }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm-package-arg": { + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-12.0.0.tgz", + "integrity": "sha512-ZTE0hbwSdTNL+Stx2zxSqdu2KZfNDcrtrLdIk7XGnQFYBWYDho/ORvXtn5XEePcL3tFpGjHCV3X3xrtDh7eZ+A==", + "dev": true, + "dependencies": { + "hosted-git-info": "^8.0.0", + "proc-log": "^5.0.0", + "semver": "^7.3.5", + "validate-npm-package-name": "^6.0.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": "^18.17.0 || >=20.5.0" } }, - "node_modules/pkg-dir/node_modules/locate-path": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-7.2.0.tgz", - "integrity": "sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==", + "node_modules/npm-package-arg/node_modules/hosted-git-info": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-8.0.2.tgz", + "integrity": "sha512-sYKnA7eGln5ov8T8gnYlkSOxFJvywzEx9BueN6xo/GKO8PGiI6uK6xx+DIGe45T3bdVjLAQDQW1aicT8z8JwQg==", "dev": true, "dependencies": { - "p-locate": "^6.0.0" + "lru-cache": "^10.0.1" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": "^18.17.0 || >=20.5.0" } }, - "node_modules/pkg-dir/node_modules/p-limit": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz", - "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==", + "node_modules/npm-package-arg/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true + }, + "node_modules/npm-packlist": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-9.0.0.tgz", + "integrity": "sha512-8qSayfmHJQTx3nJWYbbUmflpyarbLMBc6LCAjYsiGtXxDB68HaZpb8re6zeaLGxZzDuMdhsg70jryJe+RrItVQ==", "dev": true, "dependencies": { - "yocto-queue": "^1.0.0" + "ignore-walk": "^7.0.0" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": "^18.17.0 || >=20.5.0" } }, - "node_modules/pkg-dir/node_modules/p-locate": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-6.0.0.tgz", - "integrity": "sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==", + "node_modules/npm-pick-manifest": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-10.0.0.tgz", + "integrity": "sha512-r4fFa4FqYY8xaM7fHecQ9Z2nE9hgNfJR+EmoKv0+chvzWkBcORX3r0FpTByP+CbOVJDladMXnPQGVN8PBLGuTQ==", "dev": true, "dependencies": { - "p-limit": "^4.0.0" + "npm-install-checks": "^7.1.0", + "npm-normalize-package-bin": "^4.0.0", + "npm-package-arg": "^12.0.0", + "semver": "^7.3.5" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": "^18.17.0 || >=20.5.0" } }, - "node_modules/pkg-dir/node_modules/path-exists": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz", - "integrity": "sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==", + "node_modules/npm-registry-fetch": { + "version": "18.0.2", + "resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-18.0.2.tgz", + "integrity": "sha512-LeVMZBBVy+oQb5R6FDV9OlJCcWDU+al10oKpe+nsvcHnG24Z3uM3SvJYKfGJlfGjVU8v9liejCrUR/M5HO5NEQ==", "dev": true, + "dependencies": { + "@npmcli/redact": "^3.0.0", + "jsonparse": "^1.3.1", + "make-fetch-happen": "^14.0.0", + "minipass": "^7.0.2", + "minipass-fetch": "^4.0.0", + "minizlib": "^3.0.1", + "npm-package-arg": "^12.0.0", + "proc-log": "^5.0.0" + }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": "^18.17.0 || >=20.5.0" } }, - "node_modules/pkg-dir/node_modules/yocto-queue": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.1.1.tgz", - "integrity": "sha512-b4JR1PFR10y1mKjhHY9LaGo6tmrgjit7hxVIeAmyMw3jegXR4dhYqLaQF5zMXZxY7tLpMyJeLjr1C4rLmkVe8g==", + "node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", "dev": true, - "engines": { - "node": ">=12.20" + "dependencies": { + "path-key": "^3.0.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": ">=8" } }, - "node_modules/plist": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/plist/-/plist-3.1.0.tgz", - "integrity": "sha512-uysumyrvkUX0rX/dEVqt8gC3sTBzd4zoWfLeS29nb53imdaXVvLINYXTI2GNqzaMuvacNx4uJQ8+b3zXR0pkgQ==", + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", "dev": true, "dependencies": { - "@xmldom/xmldom": "^0.8.8", - "base64-js": "^1.5.1", - "xmlbuilder": "^15.1.1" + "boolbase": "^1.0.0" }, - "engines": { - "node": ">=10.4.0" + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" } }, - "node_modules/plist/node_modules/@xmldom/xmldom": { - "version": "0.8.10", - "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.10.tgz", - "integrity": "sha512-2WALfTl4xo2SkGCYRt6rDTFfk9R1czmBvUQy12gK2KuRKIpWEhcbbzy8EZXtz/jkRqHX8bFEc6FC1HjX4TUWYw==", + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", "dev": true, "engines": { - "node": ">=10.0.0" + "node": ">=0.10.0" } }, - "node_modules/possible-typed-array-names": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", - "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", + "node_modules/object-inspect": { + "version": "1.13.3", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.3.tgz", + "integrity": "sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA==", "dev": true, "engines": { "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/postcss": { - "version": "8.4.49", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.49.tgz", - "integrity": "sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==", + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "dependencies": { - "nanoid": "^3.3.7", - "picocolors": "^1.1.1", - "source-map-js": "^1.2.1" - }, "engines": { - "node": "^10 || ^12 || >=14" + "node": ">= 0.4" } }, - "node_modules/postcss-loader": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-8.1.1.tgz", - "integrity": "sha512-0IeqyAsG6tYiDRCYKQJLAmgQr47DX6N7sFSWvQxt6AcupX8DIdmykuk/o/tx0Lze3ErGHJEp5OSRxrelC6+NdQ==", + "node_modules/object.assign": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", + "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", "dev": true, "dependencies": { - "cosmiconfig": "^9.0.0", - "jiti": "^1.20.0", - "semver": "^7.5.4" + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" }, "engines": { - "node": ">= 18.12.0" + "node": ">= 0.4" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "@rspack/core": "0.x || 1.x", - "postcss": "^7.0.0 || ^8.0.1", - "webpack": "^5.0.0" - }, - "peerDependenciesMeta": { - "@rspack/core": { - "optional": true - }, - "webpack": { - "optional": true - } - } - }, - "node_modules/postcss-media-query-parser": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/postcss-media-query-parser/-/postcss-media-query-parser-0.2.3.tgz", - "integrity": "sha512-3sOlxmbKcSHMjlUXQZKQ06jOswE7oVkXPxmZdoB1r5l0q6gTFTQSHxNxOrCccElbW7dxNytifNEo8qidX2Vsig==", - "dev": true, - "license": "MIT" - }, - "node_modules/postcss-modules-extract-imports": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.1.0.tgz", - "integrity": "sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q==", - "dev": true, - "engines": { - "node": "^10 || ^12 || >= 14" - }, - "peerDependencies": { - "postcss": "^8.1.0" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/postcss-modules-local-by-default": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.2.0.tgz", - "integrity": "sha512-5kcJm/zk+GJDSfw+V/42fJ5fhjL5YbFDl8nVdXkJPLLW+Vf9mTD5Xe0wqIaDnLuL2U6cDNpTr+UQ+v2HWIBhzw==", + "node_modules/object.fromentries": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", + "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", "dev": true, "dependencies": { - "icss-utils": "^5.0.0", - "postcss-selector-parser": "^7.0.0", - "postcss-value-parser": "^4.1.0" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" }, "engines": { - "node": "^10 || ^12 || >= 14" + "node": ">= 0.4" }, - "peerDependencies": { - "postcss": "^8.1.0" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/postcss-modules-scope": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.2.1.tgz", - "integrity": "sha512-m9jZstCVaqGjTAuny8MdgE88scJnCiQSlSrOWcTQgM2t32UBe+MUmFSO5t7VMSfAf/FJKImAxBav8ooCHJXCJA==", + "node_modules/object.groupby": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", + "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", "dev": true, "dependencies": { - "postcss-selector-parser": "^7.0.0" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2" }, "engines": { - "node": "^10 || ^12 || >= 14" - }, - "peerDependencies": { - "postcss": "^8.1.0" + "node": ">= 0.4" } }, - "node_modules/postcss-modules-values": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", - "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", + "node_modules/object.values": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.0.tgz", + "integrity": "sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==", "dev": true, "dependencies": { - "icss-utils": "^5.0.0" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" }, "engines": { - "node": "^10 || ^12 || >= 14" + "node": ">= 0.4" }, - "peerDependencies": { - "postcss": "^8.1.0" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/postcss-selector-parser": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.0.0.tgz", - "integrity": "sha512-9RbEr1Y7FFfptd/1eEdntyjMwLeghW1bHX9GWjXo19vx4ytPQhANltvVxDggzJl7mnWM+dX28kb6cyS/4iQjlQ==", + "node_modules/obuf": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", + "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", + "dev": true, + "license": "MIT" + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", "dev": true, "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" + "ee-first": "1.1.1" }, "engines": { - "node": ">=4" + "node": ">= 0.8" } }, - "node_modules/postcss-value-parser": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true + "node_modules/on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } }, - "node_modules/prebuild-install": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.2.tgz", - "integrity": "sha512-UnNke3IQb6sgarcZIDU3gbMeTp/9SSU1DAIkil7PrqG1vZlBtY5msYccSKSHDqa3hNg436IXK+SNImReuA1wEQ==", + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", "dev": true, "dependencies": { - "detect-libc": "^2.0.0", - "expand-template": "^2.0.3", - "github-from-package": "0.0.0", - "minimist": "^1.2.3", - "mkdirp-classic": "^0.5.3", - "napi-build-utils": "^1.0.1", - "node-abi": "^3.3.0", - "pump": "^3.0.0", - "rc": "^1.2.7", - "simple-get": "^4.0.0", - "tar-fs": "^2.0.0", - "tunnel-agent": "^0.6.0" - }, - "bin": { - "prebuild-install": "bin.js" + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dependencies": { + "mimic-fn": "^2.1.0" }, "engines": { - "node": ">=10" + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/prebuild-install/node_modules/chownr": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", - "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", - "dev": true - }, - "node_modules/prebuild-install/node_modules/detect-libc": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz", - "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==", + "node_modules/open": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/open/-/open-10.1.0.tgz", + "integrity": "sha512-mnkeQ1qP5Ue2wd+aivTD3NHd/lZ96Lu0jgf0pwktLPtx6cTZiH7tyeGRRHs0zX0rbrahXPnXlUnbeXyaBBuIaw==", "dev": true, + "license": "MIT", + "dependencies": { + "default-browser": "^5.2.1", + "define-lazy-prop": "^3.0.0", + "is-inside-container": "^1.0.0", + "is-wsl": "^3.1.0" + }, "engines": { - "node": ">=8" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/prebuild-install/node_modules/tar-fs": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", - "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", "dev": true, "dependencies": { - "chownr": "^1.1.1", - "mkdirp-classic": "^0.5.2", - "pump": "^3.0.0", - "tar-stream": "^2.1.4" + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" } }, - "node_modules/prebuild-install/node_modules/tar-stream": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", - "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", - "dev": true, + "node_modules/ora": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", + "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", "dependencies": { - "bl": "^4.0.3", - "end-of-stream": "^1.4.1", - "fs-constants": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^3.1.1" + "bl": "^4.1.0", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-spinners": "^2.5.0", + "is-interactive": "^1.0.0", + "is-unicode-supported": "^0.1.0", + "log-symbols": "^4.1.0", + "strip-ansi": "^6.0.0", + "wcwidth": "^1.0.1" }, "engines": { - "node": ">=6" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "node_modules/ordered-binary": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/ordered-binary/-/ordered-binary-1.5.3.tgz", + "integrity": "sha512-oGFr3T+pYdTGJ+YFEILMpS3es+GiIbs9h/XQrclBXUtd44ey7XwfsMzM31f64I1SQOawDoDr/D823kNCADI8TA==", "dev": true, - "engines": { - "node": ">= 0.8.0" - } + "license": "MIT", + "optional": true }, - "node_modules/prettier": { - "version": "2.8.8", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", - "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", + "node_modules/os-name": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/os-name/-/os-name-4.0.1.tgz", + "integrity": "sha512-xl9MAoU97MH1Xt5K9ERft2YfCAoaO6msy1OBA0ozxEC0x0TmIoE6K3QvgJMMZA9yKGLmHXNY/YZoDbiGDj4zYw==", "dev": true, - "bin": { - "prettier": "bin-prettier.js" + "dependencies": { + "macos-release": "^2.5.0", + "windows-release": "^4.0.0" }, "engines": { - "node": ">=10.13.0" + "node": ">=10" }, "funding": { - "url": "https://github.com/prettier/prettier?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/proc-log": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-5.0.0.tgz", - "integrity": "sha512-Azwzvl90HaF0aCz1JrDdXQykFakSSNPaPoiZ9fm5qJIMHioDZEi7OAdRwSm6rSoPtY3Qutnm3L7ogmg3dc+wbQ==", + "node_modules/os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", "dev": true, "engines": { - "node": "^18.17.0 || >=20.5.0" + "node": ">=0.10.0" } }, - "node_modules/process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true - }, - "node_modules/promise-inflight": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", - "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==", - "dev": true - }, - "node_modules/promise-retry": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", - "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, "dependencies": { - "err-code": "^2.0.2", - "retry": "^0.12.0" + "yocto-queue": "^0.1.0" }, "engines": { "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/prompts": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", - "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, "dependencies": { - "kleur": "^3.0.3", - "sisteransi": "^1.0.5" + "p-limit": "^3.0.2" }, "engines": { - "node": ">= 6" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/prompts/node_modules/kleur": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", - "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "node_modules/p-map": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-7.0.3.tgz", + "integrity": "sha512-VkndIv2fIB99swvQoA65bm+fsmt6UNdGeIB0oxBs+WhAhdh08QA04JXpI7rbB9r08/nkbysKoya9rtDERYOYMA==", "dev": true, "engines": { - "node": ">=6" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/proxy-addr": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", - "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "node_modules/p-retry": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-6.2.1.tgz", + "integrity": "sha512-hEt02O4hUct5wtwg4H4KcWgDdm+l1bOaEy/hWzd8xtXB9BqxTWBBhb+2ImAtH4Cv4rPjV76xN3Zumqk3k3AhhQ==", "dev": true, "license": "MIT", "dependencies": { - "forwarded": "0.2.0", - "ipaddr.js": "1.9.1" + "@types/retry": "0.12.2", + "is-network-error": "^1.0.0", + "retry": "^0.13.1" }, "engines": { - "node": ">= 0.10" + "node": ">=16.17" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/proxy-addr/node_modules/ipaddr.js": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "node_modules/p-retry/node_modules/retry": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", + "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", "dev": true, "license": "MIT", "engines": { - "node": ">= 0.10" + "node": ">= 4" } }, - "node_modules/proxy-agent": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.5.0.tgz", - "integrity": "sha512-TmatMXdr2KlRiA2CyDu8GqR8EjahTG3aY3nXjdzFyoZbmB8hrBsTyMezhULIXKnC0jpfjlmiZ3+EaCzoInSu/A==", + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/pac-proxy-agent": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-7.1.0.tgz", + "integrity": "sha512-Z5FnLVVZSnX7WjBg0mhDtydeRZ1xMcATZThjySQUHqr+0ksP8kqaw23fNKkaaN/Z8gwLUs/W7xdl0I75eP2Xyw==", "dev": true, "dependencies": { + "@tootallnate/quickjs-emscripten": "^0.23.0", "agent-base": "^7.1.2", "debug": "^4.3.4", - "http-proxy-agent": "^7.0.1", + "get-uri": "^6.0.1", + "http-proxy-agent": "^7.0.0", "https-proxy-agent": "^7.0.6", - "lru-cache": "^7.14.1", - "pac-proxy-agent": "^7.1.0", - "proxy-from-env": "^1.1.0", + "pac-resolver": "^7.0.1", "socks-proxy-agent": "^8.0.5" }, "engines": { "node": ">= 14" } }, - "node_modules/proxy-agent/node_modules/lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "node_modules/pac-resolver": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-7.0.1.tgz", + "integrity": "sha512-5NPgf87AT2STgwa2ntRMr45jTKrYBGkVU36yT0ig/n/GMAa3oPqhZfIQ2kMEimReg0+t9kZViDVZ83qfVUlckg==", "dev": true, + "dependencies": { + "degenerator": "^5.0.0", + "netmask": "^2.0.2" + }, "engines": { - "node": ">=12" + "node": ">= 14" } }, - "node_modules/proxy-from-env": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", "dev": true }, - "node_modules/prr": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", - "integrity": "sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==", + "node_modules/pacote": { + "version": "20.0.0", + "resolved": "https://registry.npmjs.org/pacote/-/pacote-20.0.0.tgz", + "integrity": "sha512-pRjC5UFwZCgx9kUFDVM9YEahv4guZ1nSLqwmWiLUnDbGsjs+U5w7z6Uc8HNR1a6x8qnu5y9xtGE6D1uAuYz+0A==", "dev": true, - "optional": true + "dependencies": { + "@npmcli/git": "^6.0.0", + "@npmcli/installed-package-contents": "^3.0.0", + "@npmcli/package-json": "^6.0.0", + "@npmcli/promise-spawn": "^8.0.0", + "@npmcli/run-script": "^9.0.0", + "cacache": "^19.0.0", + "fs-minipass": "^3.0.0", + "minipass": "^7.0.2", + "npm-package-arg": "^12.0.0", + "npm-packlist": "^9.0.0", + "npm-pick-manifest": "^10.0.0", + "npm-registry-fetch": "^18.0.0", + "proc-log": "^5.0.0", + "promise-retry": "^2.0.1", + "sigstore": "^3.0.0", + "ssri": "^12.0.0", + "tar": "^6.1.11" + }, + "bin": { + "pacote": "bin/index.js" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } }, - "node_modules/pump": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", - "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==", + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", "dev": true, "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" } }, - "node_modules/punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==", - "dev": true + "node_modules/parse-imports": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/parse-imports/-/parse-imports-2.2.1.tgz", + "integrity": "sha512-OL/zLggRp8mFhKL0rNORUTR4yBYujK/uU+xZL+/0Rgm2QE4nLO9v8PzEweSJEbMGKmDRjJE4R3IMJlL2di4JeQ==", + "dev": true, + "dependencies": { + "es-module-lexer": "^1.5.3", + "slashes": "^3.0.12" + }, + "engines": { + "node": ">= 18" + } }, - "node_modules/q": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", - "integrity": "sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw==", - "deprecated": "You or someone you depend on is using Q, the JavaScript Promise library that gave JavaScript developers strong feelings about promises. They can almost certainly migrate to the native JavaScript promise now. Thank you literally everyone for joining me in this bet against the odds. Be excellent to each other.\n\n(For a CapTP with native promises, see @endo/eventual-send and @endo/captp)", + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", "dev": true, + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, "engines": { - "node": ">=0.6.0", - "teleport": ">=0.2.0" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/qjobs": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/qjobs/-/qjobs-1.2.0.tgz", - "integrity": "sha512-8YOJEHtxpySA3fFDyCRxA+UUV+fA+rTWnuWvylOK/NCjhY+b4ocCtmu8TtsWb+mYeU+GCHf/S66KZF/AsteKHg==", + "node_modules/parse-json/node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true + }, + "node_modules/parse-node-version": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz", + "integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==", "dev": true, "engines": { - "node": ">=0.9" + "node": ">= 0.10" } }, - "node_modules/qs": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", - "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "node_modules/parse5": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.2.1.tgz", + "integrity": "sha512-BuBYQYlv1ckiPdQi/ohiivi9Sagc9JG+Ozs0r7b/0iK3sKmrb0b9FdWdBbOdx6hBCM/F9Ir82ofnBhtZOjCRPQ==", + "devOptional": true, + "dependencies": { + "entities": "^4.5.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parse5-html-rewriting-stream": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/parse5-html-rewriting-stream/-/parse5-html-rewriting-stream-7.0.0.tgz", + "integrity": "sha512-mazCyGWkmCRWDI15Zp+UiCqMp/0dgEmkZRvhlsqqKYr4SsVm/TvnSpD9fCvqCA2zoWJcfRym846ejWBBHRiYEg==", "dev": true, + "license": "MIT", "dependencies": { - "side-channel": "^1.0.6" + "entities": "^4.3.0", + "parse5": "^7.0.0", + "parse5-sax-parser": "^7.0.0" }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parse5-html-rewriting-stream/node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "dev": true, + "license": "BSD-2-Clause", "engines": { - "node": ">=0.6" + "node": ">=0.12" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/fb55/entities?sponsor=1" } }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "node_modules/parse5-sax-parser": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/parse5-sax-parser/-/parse5-sax-parser-7.0.0.tgz", + "integrity": "sha512-5A+v2SNsq8T6/mG3ahcz8ZtQ0OUFTatxPbeidoMB7tkJSGDY3tdfl4MHovtLQHkEn5CGxijNWRQHhRQ6IRpXKg==", "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/queue-tick": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/queue-tick/-/queue-tick-1.0.1.tgz", - "integrity": "sha512-kJt5qhMxoszgU/62PLP1CJytzd2NKetjSRnyuj31fDd3Rlcz3fzlFdFLD1SItunPwyqEOkca6GbV612BWfaBag==", - "dev": true + "license": "MIT", + "dependencies": { + "parse5": "^7.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } }, - "node_modules/quick-lru": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz", - "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==", - "dev": true, + "node_modules/parse5/node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "devOptional": true, "engines": { - "node": ">=8" + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" } }, - "node_modules/randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", "dev": true, - "dependencies": { - "safe-buffer": "^5.1.0" + "engines": { + "node": ">= 0.8" } }, - "node_modules/range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "dev": true, "engines": { - "node": ">= 0.6" + "node": ">=8" } }, - "node_modules/raw-body": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", - "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", "dev": true, - "dependencies": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - }, "engines": { - "node": ">= 0.8" + "node": ">=0.10.0" } }, - "node_modules/raw-body/node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "dev": true, - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - }, "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/rc": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", - "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", "dev": true, "dependencies": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" }, - "bin": { - "rc": "cli.js" + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/rc/node_modules/ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", "dev": true }, - "node_modules/rc/node_modules/strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "node_modules/path-to-regexp": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", + "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", "dev": true, - "engines": { - "node": ">=0.10.0" - } + "license": "MIT" }, - "node_modules/read-pkg": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", - "integrity": "sha512-BLq/cCO9two+lBgiTYNqD6GdtK8s4NpaWrl6/rCO9w0TUS8oJl7cmToOZfRYllKTISY6nt1U7jQ53brmKqY6BA==", + "node_modules/path-type": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-5.0.0.tgz", + "integrity": "sha512-5HviZNaZcfqP95rwpv+1HDgUamezbqdSYTyzjTvwtJSnIH+3vnbmWsItli8OFEndS984VT55M3jduxZbX351gg==", "dev": true, - "dependencies": { - "load-json-file": "^4.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^3.0.0" - }, "engines": { - "node": ">=4" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/read-pkg-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-3.0.0.tgz", - "integrity": "sha512-YFzFrVvpC6frF1sz8psoHDBGF7fLPc+llq/8NB43oagqWkx8ar5zYtsTORtOjw9W2RHLpWP+zTWwBvf1bCmcSw==", + "node_modules/pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", + "dev": true + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true + }, + "node_modules/picomatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", + "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", "dev": true, - "dependencies": { - "find-up": "^2.0.0", - "read-pkg": "^3.0.0" - }, "engines": { - "node": ">=4" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/read-pkg-up/node_modules/find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ==", + "node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", "dev": true, - "dependencies": { - "locate-path": "^2.0.0" - }, "engines": { - "node": ">=4" + "node": ">=0.10.0" } }, - "node_modules/read-pkg-up/node_modules/locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==", + "node_modules/piscina": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/piscina/-/piscina-4.8.0.tgz", + "integrity": "sha512-EZJb+ZxDrQf3dihsUL7p42pjNyrNIFJCrRHPMgxu/svsj+P3xS3fuEWp7k2+rfsavfl1N0G29b1HGs7J0m8rZA==", "dev": true, - "dependencies": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" - }, - "engines": { - "node": ">=4" + "license": "MIT", + "optionalDependencies": { + "@napi-rs/nice": "^1.0.1" } }, - "node_modules/read-pkg-up/node_modules/p-limit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "node_modules/pkg-dir": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-7.0.0.tgz", + "integrity": "sha512-Ie9z/WINcxxLp27BKOCHGde4ITq9UklYKDzVo1nhk5sqGEXU3FpkwP5GM2voTGJkGd9B3Otl+Q4uwSOeSUtOBA==", "dev": true, "dependencies": { - "p-try": "^1.0.0" + "find-up": "^6.3.0" }, "engines": { - "node": ">=4" + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/read-pkg-up/node_modules/p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==", + "node_modules/pkg-dir/node_modules/find-up": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-6.3.0.tgz", + "integrity": "sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw==", "dev": true, "dependencies": { - "p-limit": "^1.1.0" + "locate-path": "^7.1.0", + "path-exists": "^5.0.0" }, "engines": { - "node": ">=4" - } - }, - "node_modules/read-pkg-up/node_modules/p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/read-pkg-up/node_modules/path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", - "dev": true, - "engines": { - "node": ">=4" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/read-pkg/node_modules/hosted-git-info": { - "version": "2.8.9", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", - "dev": true - }, - "node_modules/read-pkg/node_modules/normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "node_modules/pkg-dir/node_modules/locate-path": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-7.2.0.tgz", + "integrity": "sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==", "dev": true, "dependencies": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" + "p-locate": "^6.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/read-pkg/node_modules/path-type": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", - "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "node_modules/pkg-dir/node_modules/p-limit": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz", + "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==", "dev": true, "dependencies": { - "pify": "^3.0.0" + "yocto-queue": "^1.0.0" }, "engines": { - "node": ">=4" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/read-pkg/node_modules/pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", + "node_modules/pkg-dir/node_modules/p-locate": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-6.0.0.tgz", + "integrity": "sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==", "dev": true, + "dependencies": { + "p-limit": "^4.0.0" + }, "engines": { - "node": ">=4" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/read-pkg/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "node_modules/pkg-dir/node_modules/path-exists": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz", + "integrity": "sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==", "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, "engines": { - "node": ">= 6" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" } }, - "node_modules/readdirp": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.0.2.tgz", - "integrity": "sha512-yDMz9g+VaZkqBYS/ozoBJwaBhTbZo3UNYQHNRw1D3UFQB8oHB4uS/tAODO+ZLjGWmUbKnIlOWO+aaIiAxrUWHA==", + "node_modules/pkg-dir/node_modules/yocto-queue": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.1.1.tgz", + "integrity": "sha512-b4JR1PFR10y1mKjhHY9LaGo6tmrgjit7hxVIeAmyMw3jegXR4dhYqLaQF5zMXZxY7tLpMyJeLjr1C4rLmkVe8g==", "dev": true, "engines": { - "node": ">= 14.16.0" + "node": ">=12.20" }, "funding": { - "type": "individual", - "url": "https://paulmillr.com/funding/" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/redent": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", - "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", + "node_modules/plist": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/plist/-/plist-3.1.0.tgz", + "integrity": "sha512-uysumyrvkUX0rX/dEVqt8gC3sTBzd4zoWfLeS29nb53imdaXVvLINYXTI2GNqzaMuvacNx4uJQ8+b3zXR0pkgQ==", "dev": true, "dependencies": { - "indent-string": "^4.0.0", - "strip-indent": "^3.0.0" + "@xmldom/xmldom": "^0.8.8", + "base64-js": "^1.5.1", + "xmlbuilder": "^15.1.1" }, "engines": { - "node": ">=8" + "node": ">=10.4.0" } }, - "node_modules/reflect-metadata": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.2.2.tgz", - "integrity": "sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==", + "node_modules/plist/node_modules/@xmldom/xmldom": { + "version": "0.8.10", + "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.10.tgz", + "integrity": "sha512-2WALfTl4xo2SkGCYRt6rDTFfk9R1czmBvUQy12gK2KuRKIpWEhcbbzy8EZXtz/jkRqHX8bFEc6FC1HjX4TUWYw==", "dev": true, - "license": "Apache-2.0" + "engines": { + "node": ">=10.0.0" + } }, - "node_modules/reflect.getprototypeof": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.8.tgz", - "integrity": "sha512-B5dj6usc5dkk8uFliwjwDHM8To5/QwdKz9JcBZ8Ic4G1f0YmeeJTtE/ZTdgRFPAfxZFiUaPhZ1Jcs4qeagItGQ==", + "node_modules/possible-typed-array-names": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", + "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", "dev": true, - "dependencies": { - "call-bind": "^1.0.8", - "define-properties": "^1.2.1", - "dunder-proto": "^1.0.0", - "es-abstract": "^1.23.5", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4", - "gopd": "^1.2.0", - "which-builtin-type": "^1.2.0" - }, "engines": { "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/regenerate": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", - "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", - "dev": true - }, - "node_modules/regenerate-unicode-properties": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.2.0.tgz", - "integrity": "sha512-DqHn3DwbmmPVzeKj9woBadqmXxLvQoQIwu7nopMc72ztvxVmVk2SBhSnx67zuye5TP+lJsb/TBQsjLKhnDf3MA==", + "node_modules/postcss": { + "version": "8.4.49", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.49.tgz", + "integrity": "sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==", "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], "dependencies": { - "regenerate": "^1.4.2" + "nanoid": "^3.3.7", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" }, "engines": { - "node": ">=4" + "node": "^10 || ^12 || >=14" } }, - "node_modules/regenerator-runtime": { - "version": "0.14.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", - "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", - "dev": true - }, - "node_modules/regenerator-transform": { - "version": "0.15.2", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz", - "integrity": "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==", + "node_modules/postcss-loader": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-8.1.1.tgz", + "integrity": "sha512-0IeqyAsG6tYiDRCYKQJLAmgQr47DX6N7sFSWvQxt6AcupX8DIdmykuk/o/tx0Lze3ErGHJEp5OSRxrelC6+NdQ==", "dev": true, "dependencies": { - "@babel/runtime": "^7.8.4" + "cosmiconfig": "^9.0.0", + "jiti": "^1.20.0", + "semver": "^7.5.4" + }, + "engines": { + "node": ">= 18.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "@rspack/core": "0.x || 1.x", + "postcss": "^7.0.0 || ^8.0.1", + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "webpack": { + "optional": true + } } }, - "node_modules/regex-parser": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/regex-parser/-/regex-parser-2.3.0.tgz", - "integrity": "sha512-TVILVSz2jY5D47F4mA4MppkBrafEaiUWJO/TcZHEIuI13AqoZMkK1WMA4Om1YkYbTx+9Ki1/tSUXbceyr9saRg==", - "dev": true + "node_modules/postcss-media-query-parser": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/postcss-media-query-parser/-/postcss-media-query-parser-0.2.3.tgz", + "integrity": "sha512-3sOlxmbKcSHMjlUXQZKQ06jOswE7oVkXPxmZdoB1r5l0q6gTFTQSHxNxOrCccElbW7dxNytifNEo8qidX2Vsig==", + "dev": true, + "license": "MIT" }, - "node_modules/regexp-to-ast": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/regexp-to-ast/-/regexp-to-ast-0.5.0.tgz", - "integrity": "sha512-tlbJqcMHnPKI9zSrystikWKwHkBqu2a/Sgw01h3zFjvYrMxEDYHzzoMZnUrbIfpTFEsoRnnviOXNCzFiSc54Qw==", - "dev": true + "node_modules/postcss-modules-extract-imports": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.1.0.tgz", + "integrity": "sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q==", + "dev": true, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } }, - "node_modules/regexp.prototype.flags": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.3.tgz", - "integrity": "sha512-vqlC04+RQoFalODCbCumG2xIOvapzVMHwsyIGM/SIE8fRhFFsXeH8/QQ+s0T0kDAhKc4k30s73/0ydkHQz6HlQ==", + "node_modules/postcss-modules-local-by-default": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.2.0.tgz", + "integrity": "sha512-5kcJm/zk+GJDSfw+V/42fJ5fhjL5YbFDl8nVdXkJPLLW+Vf9mTD5Xe0wqIaDnLuL2U6cDNpTr+UQ+v2HWIBhzw==", "dev": true, "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-errors": "^1.3.0", - "set-function-name": "^2.0.2" + "icss-utils": "^5.0.0", + "postcss-selector-parser": "^7.0.0", + "postcss-value-parser": "^4.1.0" }, "engines": { - "node": ">= 0.4" + "node": "^10 || ^12 || >= 14" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "peerDependencies": { + "postcss": "^8.1.0" } }, - "node_modules/regexpu-core": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-6.2.0.tgz", - "integrity": "sha512-H66BPQMrv+V16t8xtmq+UC0CBpiTBA60V8ibS1QVReIp8T1z8hwFxqcGzm9K6lgsN7sB5edVH8a+ze6Fqm4weA==", + "node_modules/postcss-modules-scope": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.2.1.tgz", + "integrity": "sha512-m9jZstCVaqGjTAuny8MdgE88scJnCiQSlSrOWcTQgM2t32UBe+MUmFSO5t7VMSfAf/FJKImAxBav8ooCHJXCJA==", "dev": true, "dependencies": { - "regenerate": "^1.4.2", - "regenerate-unicode-properties": "^10.2.0", - "regjsgen": "^0.8.0", - "regjsparser": "^0.12.0", - "unicode-match-property-ecmascript": "^2.0.0", - "unicode-match-property-value-ecmascript": "^2.1.0" + "postcss-selector-parser": "^7.0.0" }, "engines": { - "node": ">=4" + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" } }, - "node_modules/regjsgen": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.8.0.tgz", - "integrity": "sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q==", - "dev": true - }, - "node_modules/regjsparser": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.12.0.tgz", - "integrity": "sha512-cnE+y8bz4NhMjISKbgeVJtqNbtf5QpjZP+Bslo+UqkIt9QPnX9q095eiRRASJG1/tz6dlNr6Z5NsBiWYokp6EQ==", + "node_modules/postcss-modules-values": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", + "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", "dev": true, "dependencies": { - "jsesc": "~3.0.2" + "icss-utils": "^5.0.0" }, - "bin": { - "regjsparser": "bin/parser" + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" } }, - "node_modules/regjsparser/node_modules/jsesc": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz", - "integrity": "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==", + "node_modules/postcss-selector-parser": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.0.0.tgz", + "integrity": "sha512-9RbEr1Y7FFfptd/1eEdntyjMwLeghW1bHX9GWjXo19vx4ytPQhANltvVxDggzJl7mnWM+dX28kb6cyS/4iQjlQ==", "dev": true, - "bin": { - "jsesc": "bin/jsesc" + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" }, "engines": { - "node": ">=6" + "node": ">=4" } }, - "node_modules/replace": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/replace/-/replace-1.2.2.tgz", - "integrity": "sha512-C4EDifm22XZM2b2JOYe6Mhn+lBsLBAvLbK8drfUQLTfD1KYl/n3VaW/CDju0Ny4w3xTtegBpg8YNSpFJPUDSjA==", + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true + }, + "node_modules/prebuild-install": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.2.tgz", + "integrity": "sha512-UnNke3IQb6sgarcZIDU3gbMeTp/9SSU1DAIkil7PrqG1vZlBtY5msYccSKSHDqa3hNg436IXK+SNImReuA1wEQ==", "dev": true, "dependencies": { - "chalk": "2.4.2", - "minimatch": "3.0.5", - "yargs": "^15.3.1" + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^1.0.1", + "node-abi": "^3.3.0", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" }, "bin": { - "replace": "bin/replace.js", - "search": "bin/search.js" + "prebuild-install": "bin.js" }, "engines": { - "node": ">= 6" + "node": ">=10" } }, - "node_modules/replace/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "node_modules/prebuild-install/node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "dev": true + }, + "node_modules/prebuild-install/node_modules/detect-libc": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz", + "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==", "dev": true, - "dependencies": { - "color-convert": "^1.9.0" - }, "engines": { - "node": ">=4" + "node": ">=8" } }, - "node_modules/replace/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "node_modules/prebuild-install/node_modules/tar-fs": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", "dev": true, "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" } }, - "node_modules/replace/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "node_modules/prebuild-install/node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", "dev": true, "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" }, "engines": { - "node": ">=4" + "node": ">=6" } }, - "node_modules/replace/node_modules/cliui": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", - "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "dev": true, - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^6.2.0" + "engines": { + "node": ">= 0.8.0" } }, - "node_modules/replace/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "node_modules/prettier": { + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", + "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", "dev": true, - "dependencies": { - "color-name": "1.1.3" + "bin": { + "prettier": "bin-prettier.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" } }, - "node_modules/replace/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true - }, - "node_modules/replace/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "node_modules/proc-log": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-5.0.0.tgz", + "integrity": "sha512-Azwzvl90HaF0aCz1JrDdXQykFakSSNPaPoiZ9fm5qJIMHioDZEi7OAdRwSm6rSoPtY3Qutnm3L7ogmg3dc+wbQ==", "dev": true, "engines": { - "node": ">=0.8.0" + "node": "^18.17.0 || >=20.5.0" } }, - "node_modules/replace/node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, + "node_modules/promise-inflight": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", + "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==", + "dev": true + }, + "node_modules/promise-retry": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", + "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", "dev": true, "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" + "err-code": "^2.0.2", + "retry": "^0.12.0" }, "engines": { - "node": ">=8" + "node": ">=10" } }, - "node_modules/replace/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "node_modules/prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", "dev": true, + "dependencies": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + }, "engines": { - "node": ">=4" + "node": ">= 6" } }, - "node_modules/replace/node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "node_modules/prompts/node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", "dev": true, - "dependencies": { - "p-locate": "^4.1.0" - }, "engines": { - "node": ">=8" + "node": ">=6" } }, - "node_modules/replace/node_modules/minimatch": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.5.tgz", - "integrity": "sha512-tUpxzX0VAzJHjLu0xUfFv1gwVp9ba3IOuRAVH2EGuRW8a5emA2FlACLqiT/lDVtS1W+TGNwqz3sWaNyLgDJWuw==", + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", "dev": true, + "license": "MIT", "dependencies": { - "brace-expansion": "^1.1.7" + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" }, "engines": { - "node": "*" + "node": ">= 0.10" } }, - "node_modules/replace/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "node_modules/proxy-addr/node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", "dev": true, - "dependencies": { - "p-try": "^2.0.0" - }, + "license": "MIT", "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">= 0.10" } }, - "node_modules/replace/node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "node_modules/proxy-agent": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.5.0.tgz", + "integrity": "sha512-TmatMXdr2KlRiA2CyDu8GqR8EjahTG3aY3nXjdzFyoZbmB8hrBsTyMezhULIXKnC0jpfjlmiZ3+EaCzoInSu/A==", "dev": true, "dependencies": { - "p-limit": "^2.2.0" + "agent-base": "^7.1.2", + "debug": "^4.3.4", + "http-proxy-agent": "^7.0.1", + "https-proxy-agent": "^7.0.6", + "lru-cache": "^7.14.1", + "pac-proxy-agent": "^7.1.0", + "proxy-from-env": "^1.1.0", + "socks-proxy-agent": "^8.0.5" }, "engines": { - "node": ">=8" + "node": ">= 14" } }, - "node_modules/replace/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "node_modules/proxy-agent/node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, "engines": { - "node": ">=4" + "node": ">=12" } }, - "node_modules/replace/node_modules/y18n": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", - "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", "dev": true }, - "node_modules/replace/node_modules/yargs": { - "version": "15.4.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", - "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", + "node_modules/prr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", + "integrity": "sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==", "dev": true, - "dependencies": { - "cliui": "^6.0.0", - "decamelize": "^1.2.0", - "find-up": "^4.1.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^4.2.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^18.1.2" - }, - "engines": { - "node": ">=8" - } + "optional": true }, - "node_modules/replace/node_modules/yargs-parser": { - "version": "18.1.3", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", - "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "node_modules/pump": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", + "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==", "dev": true, "dependencies": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - }, - "engines": { - "node": ">=6" + "end-of-stream": "^1.1.0", + "once": "^1.3.1" } }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "node_modules/punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==", + "dev": true + }, + "node_modules/q": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", + "integrity": "sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw==", + "deprecated": "You or someone you depend on is using Q, the JavaScript Promise library that gave JavaScript developers strong feelings about promises. They can almost certainly migrate to the native JavaScript promise now. Thank you literally everyone for joining me in this bet against the odds. Be excellent to each other.\n\n(For a CapTP with native promises, see @endo/eventual-send and @endo/captp)", "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">=0.6.0", + "teleport": ">=0.2.0" } }, - "node_modules/require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "node_modules/qjobs": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/qjobs/-/qjobs-1.2.0.tgz", + "integrity": "sha512-8YOJEHtxpySA3fFDyCRxA+UUV+fA+rTWnuWvylOK/NCjhY+b4ocCtmu8TtsWb+mYeU+GCHf/S66KZF/AsteKHg==", + "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">=0.9" } }, - "node_modules/require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", - "dev": true - }, - "node_modules/requires-port": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", - "dev": true - }, - "node_modules/resolve": { - "version": "1.22.8", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", - "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "node_modules/qs": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", "dev": true, "dependencies": { - "is-core-module": "^2.13.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" + "side-channel": "^1.0.6" }, - "bin": { - "resolve": "bin/resolve" + "engines": { + "node": ">=0.6" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/queue-tick": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/queue-tick/-/queue-tick-1.0.1.tgz", + "integrity": "sha512-kJt5qhMxoszgU/62PLP1CJytzd2NKetjSRnyuj31fDd3Rlcz3fzlFdFLD1SItunPwyqEOkca6GbV612BWfaBag==", + "dev": true + }, + "node_modules/quick-lru": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz", + "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==", "dev": true, "engines": { - "node": ">=4" + "node": ">=8" } }, - "node_modules/resolve-pkg-maps": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", - "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", "dev": true, - "funding": { - "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + "dependencies": { + "safe-buffer": "^5.1.0" } }, - "node_modules/resolve-url-loader": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-url-loader/-/resolve-url-loader-5.0.0.tgz", - "integrity": "sha512-uZtduh8/8srhBoMx//5bwqjQ+rfYOUq8zC9NrMUGtjBiGTtFJM42s58/36+hTqeqINcnYe08Nj3LkK9lW4N8Xg==", + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", "dev": true, "dependencies": { - "adjust-sourcemap-loader": "^4.0.0", - "convert-source-map": "^1.7.0", - "loader-utils": "^2.0.0", - "postcss": "^8.2.14", - "source-map": "0.6.1" + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" }, "engines": { - "node": ">=12" + "node": ">= 0.8" } }, - "node_modules/resolve-url-loader/node_modules/loader-utils": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", - "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", + "node_modules/raw-body/node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", "dev": true, "dependencies": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^2.1.2" + "safer-buffer": ">= 2.1.2 < 3" }, "engines": { - "node": ">=8.9.0" + "node": ">=0.10.0" } }, - "node_modules/resolve-url-loader/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dev": true, + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/rc/node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true + }, + "node_modules/rc/node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", "dev": true, "engines": { "node": ">=0.10.0" } }, - "node_modules/restore-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "node_modules/read-pkg": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", + "integrity": "sha512-BLq/cCO9two+lBgiTYNqD6GdtK8s4NpaWrl6/rCO9w0TUS8oJl7cmToOZfRYllKTISY6nt1U7jQ53brmKqY6BA==", + "dev": true, "dependencies": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" + "load-json-file": "^4.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^3.0.0" }, "engines": { - "node": ">=8" + "node": ">=4" } }, - "node_modules/restore-cursor/node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" - }, - "node_modules/retry": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", - "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", + "node_modules/read-pkg-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-3.0.0.tgz", + "integrity": "sha512-YFzFrVvpC6frF1sz8psoHDBGF7fLPc+llq/8NB43oagqWkx8ar5zYtsTORtOjw9W2RHLpWP+zTWwBvf1bCmcSw==", "dev": true, + "dependencies": { + "find-up": "^2.0.0", + "read-pkg": "^3.0.0" + }, "engines": { - "node": ">= 4" + "node": ">=4" } }, - "node_modules/reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "node_modules/read-pkg-up/node_modules/find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ==", "dev": true, + "dependencies": { + "locate-path": "^2.0.0" + }, "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" + "node": ">=4" } }, - "node_modules/rfdc": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", - "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", - "dev": true - }, - "node_modules/rimraf": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-4.4.1.tgz", - "integrity": "sha512-Gk8NlF062+T9CqNGn6h4tls3k6T1+/nXdOcSZVikNVtlRdYpA7wRJJMoXmuvOnLW844rPjdQ7JgXCYM6PPC/og==", + "node_modules/read-pkg-up/node_modules/locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==", "dev": true, "dependencies": { - "glob": "^9.2.0" - }, - "bin": { - "rimraf": "dist/cjs/src/bin.js" + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" }, "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": ">=4" } }, - "node_modules/rimraf/node_modules/glob": { - "version": "9.3.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-9.3.5.tgz", - "integrity": "sha512-e1LleDykUz2Iu+MTYdkSsuWX8lvAjAcs0Xef0lNIu0S2wOAzuTxCJtcd9S3cijlwYF18EsU3rzb8jPVobxDh9Q==", + "node_modules/read-pkg-up/node_modules/p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", "dev": true, "dependencies": { - "fs.realpath": "^1.0.0", - "minimatch": "^8.0.2", - "minipass": "^4.2.4", - "path-scurry": "^1.6.1" + "p-try": "^1.0.0" }, "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": ">=4" } }, - "node_modules/rimraf/node_modules/minimatch": { - "version": "8.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-8.0.4.tgz", - "integrity": "sha512-W0Wvr9HyFXZRGIDgCicunpQ299OKXs9RgZfaukz4qAW/pJhcpUfupc9c+OObPOFueNy8VSrZgEmDtk6Kh4WzDA==", + "node_modules/read-pkg-up/node_modules/p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==", "dev": true, "dependencies": { - "brace-expansion": "^2.0.1" + "p-limit": "^1.1.0" }, "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": ">=4" } }, - "node_modules/rimraf/node_modules/minipass": { - "version": "4.2.8", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-4.2.8.tgz", - "integrity": "sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ==", + "node_modules/read-pkg-up/node_modules/p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==", "dev": true, "engines": { - "node": ">=8" + "node": ">=4" } }, - "node_modules/roboto-fontface": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/roboto-fontface/-/roboto-fontface-0.10.0.tgz", - "integrity": "sha512-OlwfYEgA2RdboZohpldlvJ1xngOins5d7ejqnIBWr9KaMxsnBqotpptRXTyfNRLnFpqzX6sTDt+X+a+6udnU8g==" + "node_modules/read-pkg-up/node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "dev": true, + "engines": { + "node": ">=4" + } }, - "node_modules/robust-predicates": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/robust-predicates/-/robust-predicates-3.0.2.tgz", - "integrity": "sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg==" + "node_modules/read-pkg/node_modules/hosted-git-info": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "dev": true }, - "node_modules/rollup": { - "version": "4.26.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.26.0.tgz", - "integrity": "sha512-ilcl12hnWonG8f+NxU6BlgysVA0gvY2l8N0R84S1HcINbW20bvwuCngJkkInV6LXhwRpucsW5k1ovDwEdBVrNg==", + "node_modules/read-pkg/node_modules/normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", "dev": true, - "license": "MIT", "dependencies": { - "@types/estree": "1.0.6" - }, - "bin": { - "rollup": "dist/bin/rollup" - }, - "engines": { - "node": ">=18.0.0", - "npm": ">=8.0.0" - }, - "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.26.0", - "@rollup/rollup-android-arm64": "4.26.0", - "@rollup/rollup-darwin-arm64": "4.26.0", - "@rollup/rollup-darwin-x64": "4.26.0", - "@rollup/rollup-freebsd-arm64": "4.26.0", - "@rollup/rollup-freebsd-x64": "4.26.0", - "@rollup/rollup-linux-arm-gnueabihf": "4.26.0", - "@rollup/rollup-linux-arm-musleabihf": "4.26.0", - "@rollup/rollup-linux-arm64-gnu": "4.26.0", - "@rollup/rollup-linux-arm64-musl": "4.26.0", - "@rollup/rollup-linux-powerpc64le-gnu": "4.26.0", - "@rollup/rollup-linux-riscv64-gnu": "4.26.0", - "@rollup/rollup-linux-s390x-gnu": "4.26.0", - "@rollup/rollup-linux-x64-gnu": "4.26.0", - "@rollup/rollup-linux-x64-musl": "4.26.0", - "@rollup/rollup-win32-arm64-msvc": "4.26.0", - "@rollup/rollup-win32-ia32-msvc": "4.26.0", - "@rollup/rollup-win32-x64-msvc": "4.26.0", - "fsevents": "~2.3.2" + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" } }, - "node_modules/rsvp": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/rsvp/-/rsvp-3.6.2.tgz", - "integrity": "sha512-OfWGQTb9vnwRjwtA2QwpG2ICclHC3pgXZO5xt8H2EfgDquO0qVdSb5T88L4qJVAEugbS56pAuV4XZM58UX8ulw==", + "node_modules/read-pkg/node_modules/path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", "dev": true, + "dependencies": { + "pify": "^3.0.0" + }, "engines": { - "node": "0.12.* || 4.* || 6.* || >= 7.*" + "node": ">=4" } }, - "node_modules/run-applescript": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.0.0.tgz", - "integrity": "sha512-9by4Ij99JUr/MCFBUkDKLWK3G9HVXmabKz9U5MlIAIuvuzkiOicRYs8XJLxX+xahD+mLiiCYDqF9dKAgtzKP1A==", + "node_modules/read-pkg/node_modules/pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", "dev": true, - "license": "MIT", "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=4" } }, - "node_modules/run-async": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", - "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", + "node_modules/read-pkg/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", "dev": true, - "engines": { - "node": ">=0.12.0" + "bin": { + "semver": "bin/semver" } }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", "dependencies": { - "queue-microtask": "^1.2.2" + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" } }, - "node_modules/rw": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz", - "integrity": "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==" - }, - "node_modules/rxjs": { - "version": "7.8.1", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", - "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", - "dependencies": { - "tslib": "^2.1.0" + "node_modules/readdirp": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.0.2.tgz", + "integrity": "sha512-yDMz9g+VaZkqBYS/ozoBJwaBhTbZo3UNYQHNRw1D3UFQB8oHB4uS/tAODO+ZLjGWmUbKnIlOWO+aaIiAxrUWHA==", + "dev": true, + "engines": { + "node": ">= 14.16.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" } }, - "node_modules/safe-array-concat": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.3.tgz", - "integrity": "sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==", + "node_modules/redent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", + "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", "dev": true, "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.2", - "get-intrinsic": "^1.2.6", - "has-symbols": "^1.1.0", - "isarray": "^2.0.5" + "indent-string": "^4.0.0", + "strip-indent": "^3.0.0" }, "engines": { - "node": ">=0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=8" } }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] + "node_modules/reflect-metadata": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.2.2.tgz", + "integrity": "sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==", + "dev": true, + "license": "Apache-2.0" }, - "node_modules/safe-regex-test": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", - "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", + "node_modules/reflect.getprototypeof": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.8.tgz", + "integrity": "sha512-B5dj6usc5dkk8uFliwjwDHM8To5/QwdKz9JcBZ8Ic4G1f0YmeeJTtE/ZTdgRFPAfxZFiUaPhZ1Jcs4qeagItGQ==", "dev": true, "dependencies": { - "call-bound": "^1.0.2", + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "dunder-proto": "^1.0.0", + "es-abstract": "^1.23.5", "es-errors": "^1.3.0", - "is-regex": "^1.2.1" + "get-intrinsic": "^1.2.4", + "gopd": "^1.2.0", + "which-builtin-type": "^1.2.0" }, "engines": { "node": ">= 0.4" @@ -18689,555 +18483,620 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + "node_modules/regenerate": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", + "dev": true }, - "node_modules/sass": { - "version": "1.80.7", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.80.7.tgz", - "integrity": "sha512-MVWvN0u5meytrSjsU7AWsbhoXi1sc58zADXFllfZzbsBT1GHjjar6JwBINYPRrkx/zqnQ6uqbQuHgE95O+C+eQ==", + "node_modules/regenerate-unicode-properties": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.2.0.tgz", + "integrity": "sha512-DqHn3DwbmmPVzeKj9woBadqmXxLvQoQIwu7nopMc72ztvxVmVk2SBhSnx67zuye5TP+lJsb/TBQsjLKhnDf3MA==", "dev": true, "dependencies": { - "chokidar": "^4.0.0", - "immutable": "^5.0.2", - "source-map-js": ">=0.6.2 <2.0.0" - }, - "bin": { - "sass": "sass.js" + "regenerate": "^1.4.2" }, "engines": { - "node": ">=14.0.0" - }, - "optionalDependencies": { - "@parcel/watcher": "^2.4.1" + "node": ">=4" } }, - "node_modules/sass-loader": { - "version": "16.0.3", - "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-16.0.3.tgz", - "integrity": "sha512-gosNorT1RCkuCMyihv6FBRR7BMV06oKRAs+l4UMp1mlcVg9rWN6KMmUj3igjQwmYys4mDP3etEYJgiHRbgHCHA==", + "node_modules/regenerator-runtime": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", + "dev": true + }, + "node_modules/regenerator-transform": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz", + "integrity": "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==", "dev": true, "dependencies": { - "neo-async": "^2.6.2" + "@babel/runtime": "^7.8.4" + } + }, + "node_modules/regex-parser": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/regex-parser/-/regex-parser-2.3.0.tgz", + "integrity": "sha512-TVILVSz2jY5D47F4mA4MppkBrafEaiUWJO/TcZHEIuI13AqoZMkK1WMA4Om1YkYbTx+9Ki1/tSUXbceyr9saRg==", + "dev": true + }, + "node_modules/regexp-to-ast": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/regexp-to-ast/-/regexp-to-ast-0.5.0.tgz", + "integrity": "sha512-tlbJqcMHnPKI9zSrystikWKwHkBqu2a/Sgw01h3zFjvYrMxEDYHzzoMZnUrbIfpTFEsoRnnviOXNCzFiSc54Qw==", + "dev": true + }, + "node_modules/regexp.prototype.flags": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.3.tgz", + "integrity": "sha512-vqlC04+RQoFalODCbCumG2xIOvapzVMHwsyIGM/SIE8fRhFFsXeH8/QQ+s0T0kDAhKc4k30s73/0ydkHQz6HlQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "set-function-name": "^2.0.2" }, "engines": { - "node": ">= 18.12.0" + "node": ">= 0.4" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "@rspack/core": "0.x || 1.x", - "node-sass": "^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0", - "sass": "^1.3.0", - "sass-embedded": "*", - "webpack": "^5.0.0" + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/regexpu-core": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-6.2.0.tgz", + "integrity": "sha512-H66BPQMrv+V16t8xtmq+UC0CBpiTBA60V8ibS1QVReIp8T1z8hwFxqcGzm9K6lgsN7sB5edVH8a+ze6Fqm4weA==", + "dev": true, + "dependencies": { + "regenerate": "^1.4.2", + "regenerate-unicode-properties": "^10.2.0", + "regjsgen": "^0.8.0", + "regjsparser": "^0.12.0", + "unicode-match-property-ecmascript": "^2.0.0", + "unicode-match-property-value-ecmascript": "^2.1.0" }, - "peerDependenciesMeta": { - "@rspack/core": { - "optional": true - }, - "node-sass": { - "optional": true - }, - "sass": { - "optional": true - }, - "sass-embedded": { - "optional": true - }, - "webpack": { - "optional": true - } + "engines": { + "node": ">=4" } }, - "node_modules/sax": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.1.4.tgz", - "integrity": "sha512-5f3k2PbGGp+YtKJjOItpg3P99IMD84E4HOvcfleTb5joCHNXYLsR9yWFPOYGgaeMPDubQILTCMdsFb2OMeOjtg==", + "node_modules/regjsgen": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.8.0.tgz", + "integrity": "sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q==", "dev": true }, - "node_modules/schema-utils": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.0.tgz", - "integrity": "sha512-Gf9qqc58SpCA/xdziiHz35F4GNIWYWZrEshUc/G/r5BnLph6xpKuLeoJoQuj5WfBIx/eQLf+hmVPYHaxJu7V2g==", + "node_modules/regjsparser": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.12.0.tgz", + "integrity": "sha512-cnE+y8bz4NhMjISKbgeVJtqNbtf5QpjZP+Bslo+UqkIt9QPnX9q095eiRRASJG1/tz6dlNr6Z5NsBiWYokp6EQ==", "dev": true, "dependencies": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.9.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.1.0" + "jsesc": "~3.0.2" }, - "engines": { - "node": ">= 10.13.0" + "bin": { + "regjsparser": "bin/parser" + } + }, + "node_modules/regjsparser/node_modules/jsesc": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz", + "integrity": "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" + "engines": { + "node": ">=6" } }, - "node_modules/schema-utils/node_modules/ajv-formats": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", - "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "node_modules/replace": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/replace/-/replace-1.2.2.tgz", + "integrity": "sha512-C4EDifm22XZM2b2JOYe6Mhn+lBsLBAvLbK8drfUQLTfD1KYl/n3VaW/CDju0Ny4w3xTtegBpg8YNSpFJPUDSjA==", "dev": true, "dependencies": { - "ajv": "^8.0.0" + "chalk": "2.4.2", + "minimatch": "3.0.5", + "yargs": "^15.3.1" }, - "peerDependencies": { - "ajv": "^8.0.0" + "bin": { + "replace": "bin/replace.js", + "search": "bin/search.js" }, - "peerDependenciesMeta": { - "ajv": { - "optional": true - } + "engines": { + "node": ">= 6" } }, - "node_modules/select-hose": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", - "integrity": "sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==", - "dev": true, - "license": "MIT" - }, - "node_modules/selfsigned": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.4.1.tgz", - "integrity": "sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==", + "node_modules/replace/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, - "license": "MIT", "dependencies": { - "@types/node-forge": "^1.3.0", - "node-forge": "^1" + "color-convert": "^1.9.0" }, "engines": { - "node": ">=10" + "node": ">=4" } }, - "node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "node_modules/replace/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/replace/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, - "bin": { - "semver": "bin/semver.js" + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" }, "engines": { - "node": ">=10" + "node": ">=4" } }, - "node_modules/send": { - "version": "0.19.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", - "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", + "node_modules/replace/node_modules/cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", "dev": true, - "license": "MIT", "dependencies": { - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "2.4.1", - "range-parser": "~1.2.1", - "statuses": "2.0.1" - }, - "engines": { - "node": ">= 0.8.0" + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" } }, - "node_modules/send/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "node_modules/replace/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "dev": true, - "license": "MIT", "dependencies": { - "ms": "2.0.0" + "color-name": "1.1.3" } }, - "node_modules/send/node_modules/debug/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "node_modules/replace/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/replace/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "dev": true, - "license": "MIT" + "engines": { + "node": ">=0.8.0" + } }, - "node_modules/send/node_modules/mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "node_modules/replace/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, - "license": "MIT", - "bin": { - "mime": "cli.js" + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" }, "engines": { - "node": ">=4" + "node": ">=8" } }, - "node_modules/send/node_modules/statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "node_modules/replace/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", "dev": true, - "license": "MIT", "engines": { - "node": ">= 0.8" + "node": ">=4" } }, - "node_modules/serialize-javascript": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", - "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", + "node_modules/replace/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, "dependencies": { - "randombytes": "^2.1.0" + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/serve-index": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", - "integrity": "sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==", + "node_modules/replace/node_modules/minimatch": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.5.tgz", + "integrity": "sha512-tUpxzX0VAzJHjLu0xUfFv1gwVp9ba3IOuRAVH2EGuRW8a5emA2FlACLqiT/lDVtS1W+TGNwqz3sWaNyLgDJWuw==", "dev": true, - "license": "MIT", "dependencies": { - "accepts": "~1.3.4", - "batch": "0.6.1", - "debug": "2.6.9", - "escape-html": "~1.0.3", - "http-errors": "~1.6.2", - "mime-types": "~2.1.17", - "parseurl": "~1.3.2" + "brace-expansion": "^1.1.7" }, "engines": { - "node": ">= 0.8.0" + "node": "*" } }, - "node_modules/serve-index/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "node_modules/replace/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, - "license": "MIT", "dependencies": { - "ms": "2.0.0" + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/serve-index/node_modules/depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", + "node_modules/replace/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "dev": true, - "license": "MIT", + "dependencies": { + "p-limit": "^2.2.0" + }, "engines": { - "node": ">= 0.6" + "node": ">=8" } }, - "node_modules/serve-index/node_modules/http-errors": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", - "integrity": "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==", + "node_modules/replace/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dev": true, - "license": "MIT", "dependencies": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.0", - "statuses": ">= 1.4.0 < 2" + "has-flag": "^3.0.0" }, "engines": { - "node": ">= 0.6" + "node": ">=4" } }, - "node_modules/serve-index/node_modules/inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==", - "dev": true, - "license": "ISC" - }, - "node_modules/serve-index/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true, - "license": "MIT" + "node_modules/replace/node_modules/y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "dev": true }, - "node_modules/serve-index/node_modules/setprototypeof": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", - "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", + "node_modules/replace/node_modules/yargs": { + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", "dev": true, - "license": "ISC" + "dependencies": { + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.2" + }, + "engines": { + "node": ">=8" + } }, - "node_modules/serve-static": { - "version": "1.16.2", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", - "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", + "node_modules/replace/node_modules/yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", "dev": true, - "license": "MIT", "dependencies": { - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.19.0" + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" }, "engines": { - "node": ">= 0.8.0" + "node": ">=6" } }, - "node_modules/serve-static/node_modules/encodeurl": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", - "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", "dev": true, - "license": "MIT", "engines": { - "node": ">= 0.8" + "node": ">=0.10.0" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "engines": { + "node": ">=0.10.0" } }, - "node_modules/set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", + "node_modules/require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "dev": true + }, + "node_modules/requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", "dev": true }, - "node_modules/set-function-length": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", - "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "node_modules/resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", "dev": true, "dependencies": { - "define-data-property": "^1.1.4", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.2" + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" }, - "engines": { - "node": ">= 0.4" + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/set-function-name": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", - "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true, - "dependencies": { - "define-data-property": "^1.1.4", - "es-errors": "^1.3.0", - "functions-have-names": "^1.2.3", - "has-property-descriptors": "^1.0.2" - }, "engines": { - "node": ">= 0.4" + "node": ">=4" } }, - "node_modules/setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", - "dev": true + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "dev": true, + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } }, - "node_modules/shallow-clone": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", - "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", + "node_modules/resolve-url-loader": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-url-loader/-/resolve-url-loader-5.0.0.tgz", + "integrity": "sha512-uZtduh8/8srhBoMx//5bwqjQ+rfYOUq8zC9NrMUGtjBiGTtFJM42s58/36+hTqeqINcnYe08Nj3LkK9lW4N8Xg==", "dev": true, "dependencies": { - "kind-of": "^6.0.2" + "adjust-sourcemap-loader": "^4.0.0", + "convert-source-map": "^1.7.0", + "loader-utils": "^2.0.0", + "postcss": "^8.2.14", + "source-map": "0.6.1" }, "engines": { - "node": ">=8" + "node": ">=12" } }, - "node_modules/sharp": { - "version": "0.32.6", - "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.32.6.tgz", - "integrity": "sha512-KyLTWwgcR9Oe4d9HwCwNM2l7+J0dUQwn/yf7S0EnTtb0eVS4RxO0eUSvxPtzT4F3SY+C4K6fqdv/DO27sJ/v/w==", + "node_modules/resolve-url-loader/node_modules/loader-utils": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", + "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", "dev": true, - "hasInstallScript": true, "dependencies": { - "color": "^4.2.3", - "detect-libc": "^2.0.2", - "node-addon-api": "^6.1.0", - "prebuild-install": "^7.1.1", - "semver": "^7.5.4", - "simple-get": "^4.0.1", - "tar-fs": "^3.0.4", - "tunnel-agent": "^0.6.0" + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" }, "engines": { - "node": ">=14.15.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" + "node": ">=8.9.0" } }, - "node_modules/sharp/node_modules/detect-libc": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz", - "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==", + "node_modules/resolve-url-loader/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true, "engines": { - "node": ">=8" + "node": ">=0.10.0" } }, - "node_modules/sharp/node_modules/node-addon-api": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-6.1.0.tgz", - "integrity": "sha512-+eawOlIgy680F0kBzPUNFhMZGtJ1YmqM6l4+Crf4IkImjYrO/mqPwRMh352g23uIaQKFItcQ64I7KMaJxHgAVA==", - "dev": true - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, + "node_modules/restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", "dependencies": { - "shebang-regex": "^3.0.0" + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" }, "engines": { "node": ">=8" } }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "node_modules/restore-cursor/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "node_modules/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", "dev": true, "engines": { - "node": ">=8" + "node": ">= 4" } }, - "node_modules/shell-quote": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.2.tgz", - "integrity": "sha512-AzqKpGKjrj7EM6rKVQEPpB288oCfnrEIuyoT9cyF4nmGa7V8Zk6f7RRqYisX8X9m+Q7bd632aZW4ky7EhbQztA==", + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", "dev": true, - "license": "MIT", "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "iojs": ">=1.0.0", + "node": ">=0.10.0" } }, - "node_modules/side-channel": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", - "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "node_modules/rfdc": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", + "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", + "dev": true + }, + "node_modules/rimraf": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-4.4.1.tgz", + "integrity": "sha512-Gk8NlF062+T9CqNGn6h4tls3k6T1+/nXdOcSZVikNVtlRdYpA7wRJJMoXmuvOnLW844rPjdQ7JgXCYM6PPC/og==", "dev": true, "dependencies": { - "es-errors": "^1.3.0", - "object-inspect": "^1.13.3", - "side-channel-list": "^1.0.0", - "side-channel-map": "^1.0.1", - "side-channel-weakmap": "^1.0.2" + "glob": "^9.2.0" + }, + "bin": { + "rimraf": "dist/cjs/src/bin.js" }, "engines": { - "node": ">= 0.4" + "node": ">=14" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/side-channel-list": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", - "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "node_modules/rimraf/node_modules/glob": { + "version": "9.3.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-9.3.5.tgz", + "integrity": "sha512-e1LleDykUz2Iu+MTYdkSsuWX8lvAjAcs0Xef0lNIu0S2wOAzuTxCJtcd9S3cijlwYF18EsU3rzb8jPVobxDh9Q==", "dev": true, "dependencies": { - "es-errors": "^1.3.0", - "object-inspect": "^1.13.3" + "fs.realpath": "^1.0.0", + "minimatch": "^8.0.2", + "minipass": "^4.2.4", + "path-scurry": "^1.6.1" }, "engines": { - "node": ">= 0.4" + "node": ">=16 || 14 >=14.17" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/side-channel-map": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", - "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "node_modules/rimraf/node_modules/minimatch": { + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-8.0.4.tgz", + "integrity": "sha512-W0Wvr9HyFXZRGIDgCicunpQ299OKXs9RgZfaukz4qAW/pJhcpUfupc9c+OObPOFueNy8VSrZgEmDtk6Kh4WzDA==", "dev": true, "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.5", - "object-inspect": "^1.13.3" + "brace-expansion": "^2.0.1" }, "engines": { - "node": ">= 0.4" + "node": ">=16 || 14 >=14.17" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/side-channel-weakmap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", - "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "node_modules/rimraf/node_modules/minipass": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-4.2.8.tgz", + "integrity": "sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/roboto-fontface": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/roboto-fontface/-/roboto-fontface-0.10.0.tgz", + "integrity": "sha512-OlwfYEgA2RdboZohpldlvJ1xngOins5d7ejqnIBWr9KaMxsnBqotpptRXTyfNRLnFpqzX6sTDt+X+a+6udnU8g==" + }, + "node_modules/robust-predicates": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/robust-predicates/-/robust-predicates-3.0.2.tgz", + "integrity": "sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg==" + }, + "node_modules/rollup": { + "version": "4.34.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.34.0.tgz", + "integrity": "sha512-+4C/cgJ9w6sudisA0nZz0+O7lTP9a3CzNLsoDwaRumM8QHwghUsu6tqHXiTmNUp/rqNiM14++7dkzHDyCRs0Jg==", "dev": true, + "license": "MIT", "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.5", - "object-inspect": "^1.13.3", - "side-channel-map": "^1.0.1" + "@types/estree": "1.0.6" + }, + "bin": { + "rollup": "dist/bin/rollup" }, "engines": { - "node": ">= 0.4" + "node": ">=18.0.0", + "npm": ">=8.0.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.34.0", + "@rollup/rollup-android-arm64": "4.34.0", + "@rollup/rollup-darwin-arm64": "4.34.0", + "@rollup/rollup-darwin-x64": "4.34.0", + "@rollup/rollup-freebsd-arm64": "4.34.0", + "@rollup/rollup-freebsd-x64": "4.34.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.34.0", + "@rollup/rollup-linux-arm-musleabihf": "4.34.0", + "@rollup/rollup-linux-arm64-gnu": "4.34.0", + "@rollup/rollup-linux-arm64-musl": "4.34.0", + "@rollup/rollup-linux-loongarch64-gnu": "4.34.0", + "@rollup/rollup-linux-powerpc64le-gnu": "4.34.0", + "@rollup/rollup-linux-riscv64-gnu": "4.34.0", + "@rollup/rollup-linux-s390x-gnu": "4.34.0", + "@rollup/rollup-linux-x64-gnu": "4.34.0", + "@rollup/rollup-linux-x64-musl": "4.34.0", + "@rollup/rollup-win32-arm64-msvc": "4.34.0", + "@rollup/rollup-win32-ia32-msvc": "4.34.0", + "@rollup/rollup-win32-x64-msvc": "4.34.0", + "fsevents": "~2.3.2" } }, - "node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "node_modules/rsvp": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/rsvp/-/rsvp-3.6.2.tgz", + "integrity": "sha512-OfWGQTb9vnwRjwtA2QwpG2ICclHC3pgXZO5xt8H2EfgDquO0qVdSb5T88L4qJVAEugbS56pAuV4XZM58UX8ulw==", "dev": true, "engines": { - "node": ">=14" + "node": "0.12.* || 4.* || 6.* || >= 7.*" + } + }, + "node_modules/run-applescript": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.0.0.tgz", + "integrity": "sha512-9by4Ij99JUr/MCFBUkDKLWK3G9HVXmabKz9U5MlIAIuvuzkiOicRYs8XJLxX+xahD+mLiiCYDqF9dKAgtzKP1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/sigstore": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/sigstore/-/sigstore-3.0.0.tgz", - "integrity": "sha512-PHMifhh3EN4loMcHCz6l3v/luzgT3za+9f8subGgeMNjbJjzH4Ij/YoX3Gvu+kaouJRIlVdTHHCREADYf+ZteA==", + "node_modules/run-async": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", + "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", "dev": true, - "dependencies": { - "@sigstore/bundle": "^3.0.0", - "@sigstore/core": "^2.0.0", - "@sigstore/protobuf-specs": "^0.3.2", - "@sigstore/sign": "^3.0.0", - "@sigstore/tuf": "^3.0.0", - "@sigstore/verify": "^2.0.0" - }, "engines": { - "node": "^18.17.0 || >=20.5.0" + "node": ">=0.12.0" } }, - "node_modules/simple-concat": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", - "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", "dev": true, "funding": [ { @@ -19252,13 +19111,47 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } }, - "node_modules/simple-get": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", - "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "node_modules/rw": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz", + "integrity": "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==" + }, + "node_modules/rxjs": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", + "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/safe-array-concat": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.3.tgz", + "integrity": "sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==", "dev": true, + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", + "has-symbols": "^1.1.0", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", "funding": [ { "type": "github", @@ -19272,2283 +19165,2471 @@ "type": "consulting", "url": "https://feross.org/support" } - ], - "dependencies": { - "decompress-response": "^6.0.0", - "once": "^1.3.1", - "simple-concat": "^1.0.0" - } + ] }, - "node_modules/simple-plist": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/simple-plist/-/simple-plist-1.3.1.tgz", - "integrity": "sha512-iMSw5i0XseMnrhtIzRb7XpQEXepa9xhWxGUojHBL43SIpQuDQkh3Wpy67ZbDzZVr6EKxvwVChnVpdl8hEVLDiw==", + "node_modules/safe-regex-test": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", + "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", "dev": true, "dependencies": { - "bplist-creator": "0.1.0", - "bplist-parser": "0.3.1", - "plist": "^3.0.5" + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-regex": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/simple-plist/node_modules/bplist-parser": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.3.1.tgz", - "integrity": "sha512-PyJxiNtA5T2PlLIeBot4lbp7rj4OadzjnMZD/G5zuBNt8ei/yCU7+wW0h2bag9vr8c+/WuRWmSxbqAl9hL1rBA==", + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/sass": { + "version": "1.83.1", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.83.1.tgz", + "integrity": "sha512-EVJbDaEs4Rr3F0glJzFSOvtg2/oy2V/YrGFPqPY24UqcLDWcI9ZY5sN+qyO3c/QCZwzgfirvhXvINiJCE/OLcA==", "dev": true, + "license": "MIT", "dependencies": { - "big-integer": "1.6.x" + "chokidar": "^4.0.0", + "immutable": "^5.0.2", + "source-map-js": ">=0.6.2 <2.0.0" + }, + "bin": { + "sass": "sass.js" }, "engines": { - "node": ">= 5.10.0" + "node": ">=14.0.0" + }, + "optionalDependencies": { + "@parcel/watcher": "^2.4.1" } }, - "node_modules/simple-swizzle": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", - "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==", + "node_modules/sass-loader": { + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-16.0.4.tgz", + "integrity": "sha512-LavLbgbBGUt3wCiYzhuLLu65+fWXaXLmq7YxivLhEqmiupCFZ5sKUAipK3do6V80YSU0jvSxNhEdT13IXNr3rg==", "dev": true, + "license": "MIT", "dependencies": { - "is-arrayish": "^0.3.1" + "neo-async": "^2.6.2" + }, + "engines": { + "node": ">= 18.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "@rspack/core": "0.x || 1.x", + "node-sass": "^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0", + "sass": "^1.3.0", + "sass-embedded": "*", + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "node-sass": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "webpack": { + "optional": true + } } }, - "node_modules/simple-swizzle/node_modules/is-arrayish": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", - "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==", - "dev": true - }, - "node_modules/sisteransi": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", - "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "node_modules/sax": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.1.4.tgz", + "integrity": "sha512-5f3k2PbGGp+YtKJjOItpg3P99IMD84E4HOvcfleTb5joCHNXYLsR9yWFPOYGgaeMPDubQILTCMdsFb2OMeOjtg==", "dev": true }, - "node_modules/slash": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", - "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", + "node_modules/schema-utils": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.0.tgz", + "integrity": "sha512-Gf9qqc58SpCA/xdziiHz35F4GNIWYWZrEshUc/G/r5BnLph6xpKuLeoJoQuj5WfBIx/eQLf+hmVPYHaxJu7V2g==", "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.9.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.1.0" + }, "engines": { - "node": ">=14.16" + "node": ">= 10.13.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "type": "opencollective", + "url": "https://opencollective.com/webpack" } }, - "node_modules/slashes": { - "version": "3.0.12", - "resolved": "https://registry.npmjs.org/slashes/-/slashes-3.0.12.tgz", - "integrity": "sha512-Q9VME8WyGkc7pJf6QEkj3wE+2CnvZMI+XJhwdTPR8Z/kWQRXi7boAWLDibRPyHRTUTPx5FaU7MsyrjI3yLB4HA==", - "dev": true + "node_modules/schema-utils/node_modules/ajv-formats": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "dev": true, + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } }, - "node_modules/slice-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", - "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "node_modules/select-hose": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", + "integrity": "sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==", + "dev": true, + "license": "MIT" + }, + "node_modules/selfsigned": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.4.1.tgz", + "integrity": "sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==", "dev": true, + "license": "MIT", "dependencies": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" + "@types/node-forge": "^1.3.0", + "node-forge": "^1" }, "engines": { "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/slice-ansi?sponsor=1" } }, - "node_modules/smart-buffer": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", - "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", "dev": true, + "bin": { + "semver": "bin/semver.js" + }, "engines": { - "node": ">= 6.0.0", - "npm": ">= 3.0.0" + "node": ">=10" } }, - "node_modules/socket.io": { - "version": "4.8.1", - "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.8.1.tgz", - "integrity": "sha512-oZ7iUCxph8WYRHHcjBEc9unw3adt5CmSNlppj/5Q4k2RIrhl8Z5yY2Xr4j9zj0+wzVZ0bxmYoGSzKJnRl6A4yg==", + "node_modules/send": { + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", + "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", "dev": true, + "license": "MIT", "dependencies": { - "accepts": "~1.3.4", - "base64id": "~2.0.0", - "cors": "~2.8.5", - "debug": "~4.3.2", - "engine.io": "~6.6.0", - "socket.io-adapter": "~2.5.2", - "socket.io-parser": "~4.2.4" + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" }, "engines": { - "node": ">=10.2.0" + "node": ">= 0.8.0" } }, - "node_modules/socket.io-adapter": { - "version": "2.5.5", - "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.5.tgz", - "integrity": "sha512-eLDQas5dzPgOWCk9GuuJC2lBqItuhKI4uxGgo9aIV7MYbk2h9Q6uULEh8WBzThoI7l+qU9Ast9fVUmkqPP9wYg==", + "node_modules/send/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, + "license": "MIT", "dependencies": { - "debug": "~4.3.4", - "ws": "~8.17.1" + "ms": "2.0.0" } }, - "node_modules/socket.io-adapter/node_modules/debug": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", - "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "node_modules/send/node_modules/debug/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "dev": true, - "dependencies": { - "ms": "^2.1.3" + "license": "MIT" + }, + "node_modules/send/node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true, + "license": "MIT", + "bin": { + "mime": "cli.js" }, "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } + "node": ">=4" } }, - "node_modules/socket.io-parser": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz", - "integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==", + "node_modules/send/node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", "dev": true, - "dependencies": { - "@socket.io/component-emitter": "~3.1.0", - "debug": "~4.3.1" - }, + "license": "MIT", "engines": { - "node": ">=10.0.0" + "node": ">= 0.8" } }, - "node_modules/socket.io-parser/node_modules/debug": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", - "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "node_modules/serialize-javascript": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", + "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", "dev": true, "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } + "randombytes": "^2.1.0" } }, - "node_modules/socket.io/node_modules/debug": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", - "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "node_modules/serve-index": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", + "integrity": "sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==", "dev": true, + "license": "MIT", "dependencies": { - "ms": "^2.1.3" + "accepts": "~1.3.4", + "batch": "0.6.1", + "debug": "2.6.9", + "escape-html": "~1.0.3", + "http-errors": "~1.6.2", + "mime-types": "~2.1.17", + "parseurl": "~1.3.2" }, "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } + "node": ">= 0.8.0" } }, - "node_modules/sockjs": { - "version": "0.3.24", - "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz", - "integrity": "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==", + "node_modules/serve-index/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, "license": "MIT", "dependencies": { - "faye-websocket": "^0.11.3", - "uuid": "^8.3.2", - "websocket-driver": "^0.7.4" + "ms": "2.0.0" } }, - "node_modules/sockjs/node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "node_modules/serve-index/node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", "dev": true, "license": "MIT", - "bin": { - "uuid": "dist/bin/uuid" + "engines": { + "node": ">= 0.6" } }, - "node_modules/socks": { - "version": "2.8.3", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.3.tgz", - "integrity": "sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==", + "node_modules/serve-index/node_modules/http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==", "dev": true, + "license": "MIT", "dependencies": { - "ip-address": "^9.0.5", - "smart-buffer": "^4.2.0" + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" }, "engines": { - "node": ">= 10.0.0", - "npm": ">= 3.0.0" + "node": ">= 0.6" } }, - "node_modules/socks-proxy-agent": { - "version": "8.0.5", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.5.tgz", - "integrity": "sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw==", + "node_modules/serve-index/node_modules/inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==", + "dev": true, + "license": "ISC" + }, + "node_modules/serve-index/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true, + "license": "MIT" + }, + "node_modules/serve-index/node_modules/setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", "dev": true, + "license": "ISC" + }, + "node_modules/serve-static": { + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", + "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", + "dev": true, + "license": "MIT", "dependencies": { - "agent-base": "^7.1.2", - "debug": "^4.3.4", - "socks": "^2.8.3" + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.19.0" }, "engines": { - "node": ">= 14" + "node": ">= 0.8.0" } }, - "node_modules/source-map": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", - "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "node_modules/serve-static/node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", "dev": true, + "license": "MIT", "engines": { - "node": ">= 8" + "node": ">= 0.8" } }, - "node_modules/source-map-js": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", - "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", + "dev": true }, - "node_modules/source-map-loader": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/source-map-loader/-/source-map-loader-5.0.0.tgz", - "integrity": "sha512-k2Dur7CbSLcAH73sBcIkV5xjPV4SzqO1NJ7+XaQl8if3VODDUj3FNchNGpqgJSKbvUfJuhVdv8K2Eu8/TNl2eA==", + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", "dev": true, "dependencies": { - "iconv-lite": "^0.6.3", - "source-map-js": "^1.0.2" + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" }, "engines": { - "node": ">= 18.12.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.72.1" + "node": ">= 0.4" } }, - "node_modules/source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "node_modules/set-function-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", "dev": true, "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "node_modules/source-map-support/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2" + }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.4" } }, - "node_modules/sourcemap-codec": { - "version": "1.4.8", - "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", - "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", - "deprecated": "Please use @jridgewell/sourcemap-codec instead" + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "dev": true }, - "node_modules/spdx-correct": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", - "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", + "node_modules/shallow-clone": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", + "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", "dev": true, "dependencies": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=8" } }, - "node_modules/spdx-correct/node_modules/spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "node_modules/sharp": { + "version": "0.32.6", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.32.6.tgz", + "integrity": "sha512-KyLTWwgcR9Oe4d9HwCwNM2l7+J0dUQwn/yf7S0EnTtb0eVS4RxO0eUSvxPtzT4F3SY+C4K6fqdv/DO27sJ/v/w==", "dev": true, + "hasInstallScript": true, "dependencies": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" + "color": "^4.2.3", + "detect-libc": "^2.0.2", + "node-addon-api": "^6.1.0", + "prebuild-install": "^7.1.1", + "semver": "^7.5.4", + "simple-get": "^4.0.1", + "tar-fs": "^3.0.4", + "tunnel-agent": "^0.6.0" + }, + "engines": { + "node": ">=14.15.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/spdx-exceptions": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", - "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==", - "dev": true - }, - "node_modules/spdx-expression-parse": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-4.0.0.tgz", - "integrity": "sha512-Clya5JIij/7C6bRR22+tnGXbc4VKlibKSVj2iHvVeX5iMW7s1SIQlqu699JkODJJIhh/pUu8L0/VLh8xflD+LQ==", + "node_modules/sharp/node_modules/detect-libc": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz", + "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==", "dev": true, - "dependencies": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" + "engines": { + "node": ">=8" } }, - "node_modules/spdx-license-ids": { - "version": "3.0.20", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.20.tgz", - "integrity": "sha512-jg25NiDV/1fLtSgEgyvVyDunvaNHbuwF9lfNV17gSmPFAlYzdfNBlLtLzXTevwkPj7DhGbmN9VnmJIgLnhvaBw==", + "node_modules/sharp/node_modules/node-addon-api": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-6.1.0.tgz", + "integrity": "sha512-+eawOlIgy680F0kBzPUNFhMZGtJ1YmqM6l4+Crf4IkImjYrO/mqPwRMh352g23uIaQKFItcQ64I7KMaJxHgAVA==", "dev": true }, - "node_modules/spdy": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", - "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==", + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "dev": true, - "license": "MIT", "dependencies": { - "debug": "^4.1.0", - "handle-thing": "^2.0.0", - "http-deceiver": "^1.2.7", - "select-hose": "^2.0.0", - "spdy-transport": "^3.0.0" + "shebang-regex": "^3.0.0" }, "engines": { - "node": ">=6.0.0" + "node": ">=8" } }, - "node_modules/spdy-transport": { + "node_modules/shebang-regex": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", - "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/shell-quote": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.2.tgz", + "integrity": "sha512-AzqKpGKjrj7EM6rKVQEPpB288oCfnrEIuyoT9cyF4nmGa7V8Zk6f7RRqYisX8X9m+Q7bd632aZW4ky7EhbQztA==", "dev": true, "license": "MIT", - "dependencies": { - "debug": "^4.1.0", - "detect-node": "^2.0.4", - "hpack.js": "^2.1.6", - "obuf": "^1.1.2", - "readable-stream": "^3.0.6", - "wbuf": "^1.7.3" + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/split": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", - "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==", + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", "dev": true, "dependencies": { - "through": "2" + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" }, "engines": { - "node": "*" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/split2": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", - "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", "dev": true, "dependencies": { - "readable-stream": "^3.0.0" + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/sprintf-js": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", - "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", - "dev": true - }, - "node_modules/ssh-config": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/ssh-config/-/ssh-config-1.1.6.tgz", - "integrity": "sha512-ZPO9rECxzs5JIQ6G/2EfL1I9ho/BVZkx9HRKn8+0af7QgwAmumQ7XBFP1ggMyPMo+/tUbmv0HFdv4qifdO/9JA==", - "dev": true - }, - "node_modules/ssri": { - "version": "12.0.0", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-12.0.0.tgz", - "integrity": "sha512-S7iGNosepx9RadX82oimUkvr0Ct7IjJbEbs4mJcTxst8um95J3sDYU1RBEOvdu6oL1Wek2ODI5i4MAw+dZ6cAQ==", + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", "dev": true, "dependencies": { - "minipass": "^7.0.3" + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" }, "engines": { - "node": "^18.17.0 || >=20.5.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/stable-hash": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/stable-hash/-/stable-hash-0.0.4.tgz", - "integrity": "sha512-LjdcbuBeLcdETCrPn9i8AYAZ1eCtu4ECAWtP7UleOiZ9LzVxRzzUZEoZ8zB24nhkQnDWyET0I+3sWokSDS3E7g==", - "dev": true - }, - "node_modules/statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", "dev": true, + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, "engines": { - "node": ">= 0.6" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/stream-buffers": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/stream-buffers/-/stream-buffers-2.2.0.tgz", - "integrity": "sha512-uyQK/mx5QjHun80FLJTfaWE7JtwfRMKBLkMne6udYOmvH0CawotVa7TfgYHzAnpphn4+TweIx1QKMnRIbipmUg==", + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", "dev": true, "engines": { - "node": ">= 0.10.0" + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/stream-combiner2": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/stream-combiner2/-/stream-combiner2-1.1.1.tgz", - "integrity": "sha512-3PnJbYgS56AeWgtKF5jtJRT6uFJe56Z0Hc5Ngg/6sI6rIt8iiMBTa9cvdyFfpMQjaVHr8dusbNeFGIIonxOvKw==", + "node_modules/sigstore": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/sigstore/-/sigstore-3.0.0.tgz", + "integrity": "sha512-PHMifhh3EN4loMcHCz6l3v/luzgT3za+9f8subGgeMNjbJjzH4Ij/YoX3Gvu+kaouJRIlVdTHHCREADYf+ZteA==", "dev": true, "dependencies": { - "duplexer2": "~0.1.0", - "readable-stream": "^2.0.2" + "@sigstore/bundle": "^3.0.0", + "@sigstore/core": "^2.0.0", + "@sigstore/protobuf-specs": "^0.3.2", + "@sigstore/sign": "^3.0.0", + "@sigstore/tuf": "^3.0.0", + "@sigstore/verify": "^2.0.0" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" } }, - "node_modules/stream-combiner2/node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "dev": true + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] }, - "node_modules/stream-combiner2/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "node_modules/simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" } }, - "node_modules/stream-combiner2/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "node_modules/stream-combiner2/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "node_modules/simple-plist": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/simple-plist/-/simple-plist-1.3.1.tgz", + "integrity": "sha512-iMSw5i0XseMnrhtIzRb7XpQEXepa9xhWxGUojHBL43SIpQuDQkh3Wpy67ZbDzZVr6EKxvwVChnVpdl8hEVLDiw==", "dev": true, "dependencies": { - "safe-buffer": "~5.1.0" + "bplist-creator": "0.1.0", + "bplist-parser": "0.3.1", + "plist": "^3.0.5" } }, - "node_modules/streamroller": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.1.5.tgz", - "integrity": "sha512-KFxaM7XT+irxvdqSP1LGLgNWbYN7ay5owZ3r/8t77p+EtSUAfUgtl7be3xtqtOmGUl9K9YPO2ca8133RlTjvKw==", + "node_modules/simple-plist/node_modules/bplist-parser": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.3.1.tgz", + "integrity": "sha512-PyJxiNtA5T2PlLIeBot4lbp7rj4OadzjnMZD/G5zuBNt8ei/yCU7+wW0h2bag9vr8c+/WuRWmSxbqAl9hL1rBA==", "dev": true, "dependencies": { - "date-format": "^4.0.14", - "debug": "^4.3.4", - "fs-extra": "^8.1.0" + "big-integer": "1.6.x" }, "engines": { - "node": ">=8.0" + "node": ">= 5.10.0" } }, - "node_modules/streamroller/node_modules/fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "node_modules/simple-swizzle": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", + "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==", "dev": true, "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - }, - "engines": { - "node": ">=6 <7 || >=8" + "is-arrayish": "^0.3.1" } }, - "node_modules/streamroller/node_modules/jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", - "dev": true, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } + "node_modules/simple-swizzle/node_modules/is-arrayish": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", + "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==", + "dev": true }, - "node_modules/streamroller/node_modules/universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "dev": true + }, + "node_modules/slash": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", + "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", "dev": true, "engines": { - "node": ">= 4.0.0" + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/streamx": { - "version": "2.21.1", - "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.21.1.tgz", - "integrity": "sha512-PhP9wUnFLa+91CPy3N6tiQsK+gnYyUNuk15S3YG/zjYE7RuPeCjJngqnzpC31ow0lzBHQ+QGO4cNJnd0djYUsw==", + "node_modules/slashes": { + "version": "3.0.12", + "resolved": "https://registry.npmjs.org/slashes/-/slashes-3.0.12.tgz", + "integrity": "sha512-Q9VME8WyGkc7pJf6QEkj3wE+2CnvZMI+XJhwdTPR8Z/kWQRXi7boAWLDibRPyHRTUTPx5FaU7MsyrjI3yLB4HA==", + "dev": true + }, + "node_modules/slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", "dev": true, "dependencies": { - "fast-fifo": "^1.3.2", - "queue-tick": "^1.0.1", - "text-decoder": "^1.1.0" + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" }, - "optionalDependencies": { - "bare-events": "^2.2.0" + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" } }, - "node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dependencies": { - "safe-buffer": "~5.2.0" + "node_modules/smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "dev": true, + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" } }, - "node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "node_modules/socket.io": { + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.8.1.tgz", + "integrity": "sha512-oZ7iUCxph8WYRHHcjBEc9unw3adt5CmSNlppj/5Q4k2RIrhl8Z5yY2Xr4j9zj0+wzVZ0bxmYoGSzKJnRl6A4yg==", "dev": true, "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" + "accepts": "~1.3.4", + "base64id": "~2.0.0", + "cors": "~2.8.5", + "debug": "~4.3.2", + "engine.io": "~6.6.0", + "socket.io-adapter": "~2.5.2", + "socket.io-parser": "~4.2.4" }, "engines": { - "node": ">=8" + "node": ">=10.2.0" } }, - "node_modules/string-width-cjs": { - "name": "string-width", - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "node_modules/socket.io-adapter": { + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.5.tgz", + "integrity": "sha512-eLDQas5dzPgOWCk9GuuJC2lBqItuhKI4uxGgo9aIV7MYbk2h9Q6uULEh8WBzThoI7l+qU9Ast9fVUmkqPP9wYg==", "dev": true, "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" + "debug": "~4.3.4", + "ws": "~8.17.1" } }, - "node_modules/string.prototype.trim": { - "version": "1.2.10", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz", - "integrity": "sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==", + "node_modules/socket.io-adapter/node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.2", - "define-data-property": "^1.1.4", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.5", - "es-object-atoms": "^1.0.0", - "has-property-descriptors": "^1.0.2" + "ms": "^2.1.3" }, "engines": { - "node": ">= 0.4" + "node": ">=6.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, - "node_modules/string.prototype.trimend": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.9.tgz", - "integrity": "sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==", + "node_modules/socket.io-parser": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz", + "integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==", "dev": true, "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.2", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.1" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=10.0.0" } }, - "node_modules/string.prototype.trimstart": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", - "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", + "node_modules/socket.io-parser/node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" + "ms": "^2.1.3" }, "engines": { - "node": ">= 0.4" + "node": ">=6.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "node_modules/socket.io/node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "dev": true, "dependencies": { - "ansi-regex": "^5.0.1" + "ms": "^2.1.3" }, "engines": { - "node": ">=8" + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, - "node_modules/strip-ansi-cjs": { - "name": "strip-ansi", - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "node_modules/sockjs": { + "version": "0.3.24", + "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz", + "integrity": "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==", "dev": true, + "license": "MIT", "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" + "faye-websocket": "^0.11.3", + "uuid": "^8.3.2", + "websocket-driver": "^0.7.4" } }, - "node_modules/strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "node_modules/sockjs/node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", "dev": true, - "engines": { - "node": ">=4" + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" } }, - "node_modules/strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "node_modules/socks": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.3.tgz", + "integrity": "sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==", "dev": true, + "dependencies": { + "ip-address": "^9.0.5", + "smart-buffer": "^4.2.0" + }, "engines": { - "node": ">=6" + "node": ">= 10.0.0", + "npm": ">= 3.0.0" } }, - "node_modules/strip-indent": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", - "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", + "node_modules/socks-proxy-agent": { + "version": "8.0.5", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.5.tgz", + "integrity": "sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw==", "dev": true, "dependencies": { - "min-indent": "^1.0.0" + "agent-base": "^7.1.2", + "debug": "^4.3.4", + "socks": "^2.8.3" }, "engines": { - "node": ">=8" + "node": ">= 14" } }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "node_modules/source-map": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", "dev": true, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">= 8" } }, - "node_modules/superagent": { - "version": "8.1.2", - "resolved": "https://registry.npmjs.org/superagent/-/superagent-8.1.2.tgz", - "integrity": "sha512-6WTxW1EB6yCxV5VFOIPQruWGHqc3yI7hEmZK6h+pyk69Lk/Ut7rLUY6W/ONF2MjBuGjvmMiIpsrVJ2vjrHlslA==", - "deprecated": "Please upgrade to v9.0.0+ as we have fixed a public vulnerability with formidable dependency. Note that v9.0.0+ requires Node.js v14.18.0+. See https://github.com/ladjs/superagent/pull/1800 for insight. This project is supported and maintained by the team at Forward Email @ https://forwardemail.net", + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", "dev": true, - "dependencies": { - "component-emitter": "^1.3.0", - "cookiejar": "^2.1.4", - "debug": "^4.3.4", - "fast-safe-stringify": "^2.1.1", - "form-data": "^4.0.0", - "formidable": "^2.1.2", - "methods": "^1.1.2", - "mime": "2.6.0", - "qs": "^6.11.0", - "semver": "^7.3.8" - }, "engines": { - "node": ">=6.4.0 <13 || >=14" + "node": ">=0.10.0" } }, - "node_modules/superagent/node_modules/formidable": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/formidable/-/formidable-2.1.2.tgz", - "integrity": "sha512-CM3GuJ57US06mlpQ47YcunuUZ9jpm8Vx+P2CGt2j7HpgkKZO/DJYQ0Bobim8G6PFQmK5lOqOOdUXboU+h73A4g==", + "node_modules/source-map-loader": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/source-map-loader/-/source-map-loader-5.0.0.tgz", + "integrity": "sha512-k2Dur7CbSLcAH73sBcIkV5xjPV4SzqO1NJ7+XaQl8if3VODDUj3FNchNGpqgJSKbvUfJuhVdv8K2Eu8/TNl2eA==", "dev": true, "dependencies": { - "dezalgo": "^1.0.4", - "hexoid": "^1.0.0", - "once": "^1.4.0", - "qs": "^6.11.0" + "iconv-lite": "^0.6.3", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": ">= 18.12.0" }, "funding": { - "url": "https://ko-fi.com/tunnckoCore/commissions" + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.72.1" } }, - "node_modules/superagent/node_modules/hexoid": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/hexoid/-/hexoid-1.0.0.tgz", - "integrity": "sha512-QFLV0taWQOZtvIRIAdBChesmogZrtuXvVWsFHZTk2SU+anspqZ2vMnoLg7IE1+Uk16N19APic1BuF8bC8c2m5g==", + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", "dev": true, - "engines": { - "node": ">=8" + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" } }, - "node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dependencies": { - "has-flag": "^4.0.0" - }, + "node_modules/source-map-support/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, "engines": { - "node": ">=8" + "node": ">=0.10.0" } }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "node_modules/sourcemap-codec": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", + "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", + "deprecated": "Please use @jridgewell/sourcemap-codec instead" + }, + "node_modules/spdx-correct": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", + "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" } }, - "node_modules/swiper": { - "version": "11.1.15", - "resolved": "https://registry.npmjs.org/swiper/-/swiper-11.1.15.tgz", - "integrity": "sha512-IzWeU34WwC7gbhjKsjkImTuCRf+lRbO6cnxMGs88iVNKDwV+xQpBCJxZ4bNH6gSrIbbyVJ1kuGzo3JTtz//CBw==", - "funding": [ - { - "type": "patreon", - "url": "https://www.patreon.com/swiperjs" - }, - { - "type": "open_collective", - "url": "http://opencollective.com/swiper" - } - ], - "engines": { - "node": ">= 4.7.0" + "node_modules/spdx-correct/node_modules/spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" } }, - "node_modules/symbol-observable": { + "node_modules/spdx-exceptions": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", + "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==", + "dev": true + }, + "node_modules/spdx-expression-parse": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-4.0.0.tgz", - "integrity": "sha512-b19dMThMV4HVFynSAM1++gBHAbk2Tc/osgLIBZMKsyqh34jb2e8Os7T6ZW/Bt3pJFdBTd2JwAnAAEQV7rSNvcQ==", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-4.0.0.tgz", + "integrity": "sha512-Clya5JIij/7C6bRR22+tnGXbc4VKlibKSVj2iHvVeX5iMW7s1SIQlqu699JkODJJIhh/pUu8L0/VLh8xflD+LQ==", "dev": true, - "engines": { - "node": ">=0.10" + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" } }, - "node_modules/synckit": { - "version": "0.9.2", - "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.9.2.tgz", - "integrity": "sha512-vrozgXDQwYO72vHjUb/HnFbQx1exDjoKzqx23aXEg2a9VIg2TSFZ8FmeZpTjUCFMYw7mpX4BE2SFu8wI7asYsw==", + "node_modules/spdx-license-ids": { + "version": "3.0.20", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.20.tgz", + "integrity": "sha512-jg25NiDV/1fLtSgEgyvVyDunvaNHbuwF9lfNV17gSmPFAlYzdfNBlLtLzXTevwkPj7DhGbmN9VnmJIgLnhvaBw==", + "dev": true + }, + "node_modules/spdy": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", + "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==", "dev": true, + "license": "MIT", "dependencies": { - "@pkgr/core": "^0.1.0", - "tslib": "^2.6.2" + "debug": "^4.1.0", + "handle-thing": "^2.0.0", + "http-deceiver": "^1.2.7", + "select-hose": "^2.0.0", + "spdy-transport": "^3.0.0" }, "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/unts" + "node": ">=6.0.0" } }, - "node_modules/tapable": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "node_modules/spdy-transport": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", + "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", "dev": true, - "engines": { - "node": ">=6" + "license": "MIT", + "dependencies": { + "debug": "^4.1.0", + "detect-node": "^2.0.4", + "hpack.js": "^2.1.6", + "obuf": "^1.1.2", + "readable-stream": "^3.0.6", + "wbuf": "^1.7.3" } }, - "node_modules/tar": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", - "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", + "node_modules/split": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", + "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==", "dev": true, "dependencies": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^5.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" + "through": "2" }, "engines": { - "node": ">=10" + "node": "*" } }, - "node_modules/tar-fs": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.0.6.tgz", - "integrity": "sha512-iokBDQQkUyeXhgPYaZxmczGPhnhXZ0CmrqI+MOb/WFGS9DW5wnfrLgtjUJBvz50vQ3qfRwJ62QVoCFu8mPVu5w==", + "node_modules/split2": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", + "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", "dev": true, "dependencies": { - "pump": "^3.0.0", - "tar-stream": "^3.1.5" - }, - "optionalDependencies": { - "bare-fs": "^2.1.1", - "bare-path": "^2.1.0" + "readable-stream": "^3.0.0" } }, - "node_modules/tar-stream": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.1.7.tgz", - "integrity": "sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==", - "dev": true, - "dependencies": { - "b4a": "^1.6.4", - "fast-fifo": "^1.2.0", - "streamx": "^2.15.0" - } + "node_modules/sprintf-js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", + "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", + "dev": true }, - "node_modules/tar/node_modules/fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "node_modules/ssh-config": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/ssh-config/-/ssh-config-1.1.6.tgz", + "integrity": "sha512-ZPO9rECxzs5JIQ6G/2EfL1I9ho/BVZkx9HRKn8+0af7QgwAmumQ7XBFP1ggMyPMo+/tUbmv0HFdv4qifdO/9JA==", + "dev": true + }, + "node_modules/ssri": { + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-12.0.0.tgz", + "integrity": "sha512-S7iGNosepx9RadX82oimUkvr0Ct7IjJbEbs4mJcTxst8um95J3sDYU1RBEOvdu6oL1Wek2ODI5i4MAw+dZ6cAQ==", "dev": true, "dependencies": { - "minipass": "^3.0.0" + "minipass": "^7.0.3" }, "engines": { - "node": ">= 8" + "node": "^18.17.0 || >=20.5.0" } }, - "node_modules/tar/node_modules/fs-minipass/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "node_modules/stable-hash": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/stable-hash/-/stable-hash-0.0.4.tgz", + "integrity": "sha512-LjdcbuBeLcdETCrPn9i8AYAZ1eCtu4ECAWtP7UleOiZ9LzVxRzzUZEoZ8zB24nhkQnDWyET0I+3sWokSDS3E7g==", + "dev": true + }, + "node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, "engines": { - "node": ">=8" + "node": ">= 0.6" } }, - "node_modules/tar/node_modules/minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "node_modules/stream-buffers": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/stream-buffers/-/stream-buffers-2.2.0.tgz", + "integrity": "sha512-uyQK/mx5QjHun80FLJTfaWE7JtwfRMKBLkMne6udYOmvH0CawotVa7TfgYHzAnpphn4+TweIx1QKMnRIbipmUg==", "dev": true, "engines": { - "node": ">=8" + "node": ">= 0.10.0" } }, - "node_modules/tar/node_modules/minizlib": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "node_modules/stream-combiner2": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/stream-combiner2/-/stream-combiner2-1.1.1.tgz", + "integrity": "sha512-3PnJbYgS56AeWgtKF5jtJRT6uFJe56Z0Hc5Ngg/6sI6rIt8iiMBTa9cvdyFfpMQjaVHr8dusbNeFGIIonxOvKw==", "dev": true, "dependencies": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">= 8" + "duplexer2": "~0.1.0", + "readable-stream": "^2.0.2" } }, - "node_modules/tar/node_modules/minizlib/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "node_modules/stream-combiner2/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true + }, + "node_modules/stream-combiner2/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", "dev": true, "dependencies": { - "yallist": "^4.0.0" + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/stream-combiner2/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/stream-combiner2/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/streamroller": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.1.5.tgz", + "integrity": "sha512-KFxaM7XT+irxvdqSP1LGLgNWbYN7ay5owZ3r/8t77p+EtSUAfUgtl7be3xtqtOmGUl9K9YPO2ca8133RlTjvKw==", + "dev": true, + "dependencies": { + "date-format": "^4.0.14", + "debug": "^4.3.4", + "fs-extra": "^8.1.0" }, "engines": { - "node": ">=8" + "node": ">=8.0" } }, - "node_modules/tar/node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "node_modules/streamroller/node_modules/fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", "dev": true, - "bin": { - "mkdirp": "bin/cmd.js" + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" }, "engines": { - "node": ">=10" + "node": ">=6 <7 || >=8" } }, - "node_modules/tar/node_modules/yallist": { + "node_modules/streamroller/node_modules/jsonfile": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "dev": true, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } }, - "node_modules/temp-dir": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-2.0.0.tgz", - "integrity": "sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==", + "node_modules/streamroller/node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", "dev": true, "engines": { - "node": ">=8" + "node": ">= 4.0.0" } }, - "node_modules/tempy": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/tempy/-/tempy-1.0.1.tgz", - "integrity": "sha512-biM9brNqxSc04Ee71hzFbryD11nX7VPhQQY32AdDmjFvodsRFz/3ufeoTZ6uYkRFfGo188tENcASNs3vTdsM0w==", + "node_modules/streamx": { + "version": "2.21.1", + "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.21.1.tgz", + "integrity": "sha512-PhP9wUnFLa+91CPy3N6tiQsK+gnYyUNuk15S3YG/zjYE7RuPeCjJngqnzpC31ow0lzBHQ+QGO4cNJnd0djYUsw==", "dev": true, "dependencies": { - "del": "^6.0.0", - "is-stream": "^2.0.0", - "temp-dir": "^2.0.0", - "type-fest": "^0.16.0", - "unique-string": "^2.0.0" - }, - "engines": { - "node": ">=10" + "fast-fifo": "^1.3.2", + "queue-tick": "^1.0.1", + "text-decoder": "^1.1.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "optionalDependencies": { + "bare-events": "^2.2.0" } }, - "node_modules/tempy/node_modules/type-fest": { - "version": "0.16.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.16.0.tgz", - "integrity": "sha512-eaBzG6MxNzEn9kiwvtre90cXaNLkmadMWa1zQMs3XORCXNbsH/OewwbxC5ia9dCxIxnTAsSxXJaa/p5y8DlvJg==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dependencies": { + "safe-buffer": "~5.2.0" } }, - "node_modules/terser": { - "version": "5.36.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.36.0.tgz", - "integrity": "sha512-IYV9eNMuFAV4THUspIRXkLakHnV6XO7FEdtKjf/mDyrnqUg9LnlOn6/RwRvM9SZjR4GUq8Nk8zj67FzVARr74w==", + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, "dependencies": { - "@jridgewell/source-map": "^0.3.3", - "acorn": "^8.8.2", - "commander": "^2.20.0", - "source-map-support": "~0.5.20" - }, - "bin": { - "terser": "bin/terser" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" }, "engines": { - "node": ">=10" + "node": ">=8" } }, - "node_modules/terser-webpack-plugin": { - "version": "5.3.11", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.11.tgz", - "integrity": "sha512-RVCsMfuD0+cTt3EwX8hSl2Ks56EbFHWmhluwcqoPKtBnfjiT6olaq7PRIRfhyU8nnC2MrnDrBLfrD/RGE+cVXQ==", + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, "dependencies": { - "@jridgewell/trace-mapping": "^0.3.25", - "jest-worker": "^27.4.5", - "schema-utils": "^4.3.0", - "serialize-javascript": "^6.0.2", - "terser": "^5.31.1" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" }, "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.1.0" - }, - "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "esbuild": { - "optional": true - }, - "uglify-js": { - "optional": true - } + "node": ">=8" } }, - "node_modules/terser/node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true - }, - "node_modules/text-decoder": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.2.3.tgz", - "integrity": "sha512-3/o9z3X0X0fTupwsYvR03pJ/DjWuqqrfwBgTQzdWDiQSm9KitAyz/9WqsT2JQW7KV2m+bC2ol/zqpW37NHxLaA==", + "node_modules/string.prototype.trim": { + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz", + "integrity": "sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==", "dev": true, "dependencies": { - "b4a": "^1.6.4" - } - }, - "node_modules/text-extensions": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/text-extensions/-/text-extensions-1.9.0.tgz", - "integrity": "sha512-wiBrwC1EhBelW12Zy26JeOUkQ5mRu+5o8rpsJk5+2t+Y5vE7e842qtZDQ2g1NpX/29HdyFeJ4nSIhI47ENSxlQ==", - "dev": true, + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "define-data-property": "^1.1.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-object-atoms": "^1.0.0", + "has-property-descriptors": "^1.0.2" + }, "engines": { - "node": ">=0.10" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/thingies": { - "version": "1.21.0", - "resolved": "https://registry.npmjs.org/thingies/-/thingies-1.21.0.tgz", - "integrity": "sha512-hsqsJsFMsV+aD4s3CWKk85ep/3I9XzYV/IXaSouJMYIoDlgyi11cBhsqYe9/geRfB0YIikBQg6raRaM+nIMP9g==", + "node_modules/string.prototype.trimend": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.9.tgz", + "integrity": "sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==", "dev": true, - "license": "Unlicense", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, "engines": { - "node": ">=10.18" + "node": ">= 0.4" }, - "peerDependencies": { - "tslib": "^2" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", - "dev": true - }, - "node_modules/through2": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz", - "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==", + "node_modules/string.prototype.trimstart": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", + "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", "dev": true, "dependencies": { - "readable-stream": "3" - } - }, - "node_modules/thunky": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", - "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", - "dev": true, - "license": "MIT" - }, - "node_modules/tmp": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.3.tgz", - "integrity": "sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==", - "dev": true, + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, "engines": { - "node": ">=14.14" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "devOptional": true, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dependencies": { - "is-number": "^7.0.0" + "ansi-regex": "^5.0.1" }, "engines": { - "node": ">=8.0" + "node": ">=8" } }, - "node_modules/toidentifier": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, "engines": { - "node": ">=0.6" + "node": ">=8" } }, - "node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", - "dev": true - }, - "node_modules/tree-dump": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/tree-dump/-/tree-dump-1.0.2.tgz", - "integrity": "sha512-dpev9ABuLWdEubk+cIaI9cHwRNNDjkBBLXTwI4UCUFdQ5xXKqNXoK4FEciw/vxf+NQ7Cb7sGUyeUtORvHIdRXQ==", + "node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", "dev": true, - "license": "Apache-2.0", "engines": { - "node": ">=10.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/streamich" - }, - "peerDependencies": { - "tslib": "2" + "node": ">=4" } }, - "node_modules/tree-kill": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", - "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", "dev": true, - "bin": { - "tree-kill": "cli.js" + "engines": { + "node": ">=6" } }, - "node_modules/trim-newlines": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz", - "integrity": "sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==", + "node_modules/strip-indent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", + "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", "dev": true, + "dependencies": { + "min-indent": "^1.0.0" + }, "engines": { "node": ">=8" } }, - "node_modules/ts-api-utils": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.4.3.tgz", - "integrity": "sha512-i3eMG77UTMD0hZhgRS562pv83RC6ukSAC2GMNWc+9dieh/+jDM5u5YG+NHX6VNDRHQcHwmsTHctP9LhbC3WxVw==", + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true, "engines": { - "node": ">=16" + "node": ">=8" }, - "peerDependencies": { - "typescript": ">=4.2.0" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/ts-node": { - "version": "10.9.2", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", - "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", + "node_modules/superagent": { + "version": "8.1.2", + "resolved": "https://registry.npmjs.org/superagent/-/superagent-8.1.2.tgz", + "integrity": "sha512-6WTxW1EB6yCxV5VFOIPQruWGHqc3yI7hEmZK6h+pyk69Lk/Ut7rLUY6W/ONF2MjBuGjvmMiIpsrVJ2vjrHlslA==", + "deprecated": "Please upgrade to v9.0.0+ as we have fixed a public vulnerability with formidable dependency. Note that v9.0.0+ requires Node.js v14.18.0+. See https://github.com/ladjs/superagent/pull/1800 for insight. This project is supported and maintained by the team at Forward Email @ https://forwardemail.net", "dev": true, "dependencies": { - "@cspotcode/source-map-support": "^0.8.0", - "@tsconfig/node10": "^1.0.7", - "@tsconfig/node12": "^1.0.7", - "@tsconfig/node14": "^1.0.0", - "@tsconfig/node16": "^1.0.2", - "acorn": "^8.4.1", - "acorn-walk": "^8.1.1", - "arg": "^4.1.0", - "create-require": "^1.1.0", - "diff": "^4.0.1", - "make-error": "^1.1.1", - "v8-compile-cache-lib": "^3.0.1", - "yn": "3.1.1" - }, - "bin": { - "ts-node": "dist/bin.js", - "ts-node-cwd": "dist/bin-cwd.js", - "ts-node-esm": "dist/bin-esm.js", - "ts-node-script": "dist/bin-script.js", - "ts-node-transpile-only": "dist/bin-transpile.js", - "ts-script": "dist/bin-script-deprecated.js" - }, - "peerDependencies": { - "@swc/core": ">=1.2.50", - "@swc/wasm": ">=1.2.50", - "@types/node": "*", - "typescript": ">=2.7" + "component-emitter": "^1.3.0", + "cookiejar": "^2.1.4", + "debug": "^4.3.4", + "fast-safe-stringify": "^2.1.1", + "form-data": "^4.0.0", + "formidable": "^2.1.2", + "methods": "^1.1.2", + "mime": "2.6.0", + "qs": "^6.11.0", + "semver": "^7.3.8" }, - "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "@swc/wasm": { - "optional": true - } + "engines": { + "node": ">=6.4.0 <13 || >=14" } }, - "node_modules/tsconfig-paths": { - "version": "3.15.0", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", - "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", + "node_modules/superagent/node_modules/formidable": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/formidable/-/formidable-2.1.2.tgz", + "integrity": "sha512-CM3GuJ57US06mlpQ47YcunuUZ9jpm8Vx+P2CGt2j7HpgkKZO/DJYQ0Bobim8G6PFQmK5lOqOOdUXboU+h73A4g==", "dev": true, "dependencies": { - "@types/json5": "^0.0.29", - "json5": "^1.0.2", - "minimist": "^1.2.6", - "strip-bom": "^3.0.0" + "dezalgo": "^1.0.4", + "hexoid": "^1.0.0", + "once": "^1.4.0", + "qs": "^6.11.0" + }, + "funding": { + "url": "https://ko-fi.com/tunnckoCore/commissions" } }, - "node_modules/tsconfig-paths/node_modules/json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "node_modules/superagent/node_modules/hexoid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/hexoid/-/hexoid-1.0.0.tgz", + "integrity": "sha512-QFLV0taWQOZtvIRIAdBChesmogZrtuXvVWsFHZTk2SU+anspqZ2vMnoLg7IE1+Uk16N19APic1BuF8bC8c2m5g==", "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dependencies": { - "minimist": "^1.2.0" + "has-flag": "^4.0.0" }, - "bin": { - "json5": "lib/cli.js" + "engines": { + "node": ">=8" } }, - "node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" - }, - "node_modules/tuf-js": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/tuf-js/-/tuf-js-3.0.1.tgz", - "integrity": "sha512-+68OP1ZzSF84rTckf3FA95vJ1Zlx/uaXyiiKyPd1pA4rZNkpEvDAKmsu1xUSmbF/chCRYgZ6UZkDwC7PmzmAyA==", + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", "dev": true, - "dependencies": { - "@tufjs/models": "3.0.1", - "debug": "^4.3.6", - "make-fetch-happen": "^14.0.1" + "engines": { + "node": ">= 0.4" }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/swiper": { + "version": "11.2.1", + "resolved": "https://registry.npmjs.org/swiper/-/swiper-11.2.1.tgz", + "integrity": "sha512-62G69+iQRIfUqTmJkWpZDcX891Ra8O9050ckt1/JI2H+0483g+gq0m7gINecDqMtDh2zt5dK+uzBRxGhGOOvQA==", + "funding": [ + { + "type": "patreon", + "url": "https://www.patreon.com/swiperjs" + }, + { + "type": "open_collective", + "url": "http://opencollective.com/swiper" + } + ], "engines": { - "node": "^18.17.0 || >=20.5.0" + "node": ">= 4.7.0" } }, - "node_modules/tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "node_modules/symbol-observable": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-4.0.0.tgz", + "integrity": "sha512-b19dMThMV4HVFynSAM1++gBHAbk2Tc/osgLIBZMKsyqh34jb2e8Os7T6ZW/Bt3pJFdBTd2JwAnAAEQV7rSNvcQ==", "dev": true, - "dependencies": { - "safe-buffer": "^5.0.1" - }, "engines": { - "node": "*" + "node": ">=0.10" } }, - "node_modules/type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "node_modules/synckit": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.9.2.tgz", + "integrity": "sha512-vrozgXDQwYO72vHjUb/HnFbQx1exDjoKzqx23aXEg2a9VIg2TSFZ8FmeZpTjUCFMYw7mpX4BE2SFu8wI7asYsw==", "dev": true, "dependencies": { - "prelude-ls": "^1.2.1" + "@pkgr/core": "^0.1.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">= 0.8.0" + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts" } }, - "node_modules/type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "node_modules/tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", "dev": true, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=6" } }, - "node_modules/type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "node_modules/tar": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", + "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", "dev": true, "dependencies": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" }, "engines": { - "node": ">= 0.6" + "node": ">=10" } }, - "node_modules/typed-array-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", - "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", + "node_modules/tar-fs": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.0.6.tgz", + "integrity": "sha512-iokBDQQkUyeXhgPYaZxmczGPhnhXZ0CmrqI+MOb/WFGS9DW5wnfrLgtjUJBvz50vQ3qfRwJ62QVoCFu8mPVu5w==", "dev": true, "dependencies": { - "call-bind": "^1.0.7", - "es-errors": "^1.3.0", - "is-typed-array": "^1.1.13" + "pump": "^3.0.0", + "tar-stream": "^3.1.5" + }, + "optionalDependencies": { + "bare-fs": "^2.1.1", + "bare-path": "^2.1.0" + } + }, + "node_modules/tar-stream": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.1.7.tgz", + "integrity": "sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==", + "dev": true, + "dependencies": { + "b4a": "^1.6.4", + "fast-fifo": "^1.2.0", + "streamx": "^2.15.0" + } + }, + "node_modules/tar/node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0" }, "engines": { - "node": ">= 0.4" + "node": ">= 8" } }, - "node_modules/typed-array-byte-length": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", - "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", + "node_modules/tar/node_modules/fs-minipass/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", "dev": true, "dependencies": { - "call-bind": "^1.0.7", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-proto": "^1.0.3", - "is-typed-array": "^1.1.13" + "yallist": "^4.0.0" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=8" } }, - "node_modules/typed-array-byte-offset": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.3.tgz", - "integrity": "sha512-GsvTyUHTriq6o/bHcTd0vM7OQ9JEdlvluu9YISaA7+KzDzPaIzEeDFNkTfhdE3MYcNhNi0vq/LlegYgIs5yPAw==", + "node_modules/tar/node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", "dev": true, - "dependencies": { - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.7", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-proto": "^1.0.3", - "is-typed-array": "^1.1.13", - "reflect.getprototypeof": "^1.0.6" - }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=8" } }, - "node_modules/typed-array-length": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.7.tgz", - "integrity": "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==", + "node_modules/tar/node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", "dev": true, "dependencies": { - "call-bind": "^1.0.7", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "is-typed-array": "^1.1.13", - "possible-typed-array-names": "^1.0.0", - "reflect.getprototypeof": "^1.0.6" + "minipass": "^3.0.0", + "yallist": "^4.0.0" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">= 8" } }, - "node_modules/typed-assert": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/typed-assert/-/typed-assert-1.0.9.tgz", - "integrity": "sha512-KNNZtayBCtmnNmbo5mG47p1XsCyrx6iVqomjcZnec/1Y5GGARaxPs6r49RnSPeUP3YjNYiU9sQHAtY4BBvnZwg==", - "dev": true - }, - "node_modules/typedarray-to-buffer": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", - "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "node_modules/tar/node_modules/minizlib/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", "dev": true, "dependencies": { - "is-typedarray": "^1.0.0" + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/typescript": { - "version": "5.6.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz", - "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==", + "node_modules/tar/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", "dev": true, "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" + "mkdirp": "bin/cmd.js" }, "engines": { - "node": ">=14.17" + "node": ">=10" } }, - "node_modules/typescript-strict-plugin": { - "version": "2.4.4", - "resolved": "https://registry.npmjs.org/typescript-strict-plugin/-/typescript-strict-plugin-2.4.4.tgz", - "integrity": "sha512-OXcWHQk+pW9gqEL/Mb1eTgj/Yiqk1oHBERr9v4VInPOYN++p+cXejmQK/h/VlUPGD++FXQ8pgiqVMyEtxU4T6A==", - "dev": true, - "dependencies": { - "chalk": "^3.0.0", - "execa": "^4.0.0", - "minimatch": "^9.0.3", - "ora": "^5.4.1", - "yargs": "^16.2.0" - }, - "bin": { - "tsc-strict": "dist/cli/tsc-strict/index.js", - "update-strict-comments": "dist/cli/update-strict-comments/index.js" - } + "node_modules/tar/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true }, - "node_modules/typescript-strict-plugin/node_modules/chalk": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "node_modules/temp-dir": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-2.0.0.tgz", + "integrity": "sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==", "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, "engines": { "node": ">=8" } }, - "node_modules/typescript-strict-plugin/node_modules/cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "node_modules/tempy": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tempy/-/tempy-1.0.1.tgz", + "integrity": "sha512-biM9brNqxSc04Ee71hzFbryD11nX7VPhQQY32AdDmjFvodsRFz/3ufeoTZ6uYkRFfGo188tENcASNs3vTdsM0w==", "dev": true, "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" + "del": "^6.0.0", + "is-stream": "^2.0.0", + "temp-dir": "^2.0.0", + "type-fest": "^0.16.0", + "unique-string": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/typescript-strict-plugin/node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "node_modules/tempy/node_modules/type-fest": { + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.16.0.tgz", + "integrity": "sha512-eaBzG6MxNzEn9kiwvtre90cXaNLkmadMWa1zQMs3XORCXNbsH/OewwbxC5ia9dCxIxnTAsSxXJaa/p5y8DlvJg==", "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, "engines": { "node": ">=10" }, "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/typescript-strict-plugin/node_modules/yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "node_modules/terser": { + "version": "5.37.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.37.0.tgz", + "integrity": "sha512-B8wRRkmre4ERucLM/uXx4MOV5cbnOlVAqUst+1+iLKPI0dOgFO28f84ptoQt9HEI537PMzfYa/d+GEPKTRXmYA==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.8.2", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" }, "engines": { "node": ">=10" } }, - "node_modules/ua-parser-js": { - "version": "0.7.39", - "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.39.tgz", - "integrity": "sha512-IZ6acm6RhQHNibSt7+c09hhvsKy9WUr4DVbeq9U8o71qxyYtJpQeDxQnMrVqnIFMLcQjHO0I9wgfO2vIahht4w==", + "node_modules/terser-webpack-plugin": { + "version": "5.3.11", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.11.tgz", + "integrity": "sha512-RVCsMfuD0+cTt3EwX8hSl2Ks56EbFHWmhluwcqoPKtBnfjiT6olaq7PRIRfhyU8nnC2MrnDrBLfrD/RGE+cVXQ==", "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/ua-parser-js" + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.25", + "jest-worker": "^27.4.5", + "schema-utils": "^4.3.0", + "serialize-javascript": "^6.0.2", + "terser": "^5.31.1" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true }, - { - "type": "paypal", - "url": "https://paypal.me/faisalman" + "esbuild": { + "optional": true }, - { - "type": "github", - "url": "https://github.com/sponsors/faisalman" + "uglify-js": { + "optional": true } - ], - "bin": { - "ua-parser-js": "script/cli.js" - }, + } + }, + "node_modules/terser/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "node_modules/text-decoder": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.2.3.tgz", + "integrity": "sha512-3/o9z3X0X0fTupwsYvR03pJ/DjWuqqrfwBgTQzdWDiQSm9KitAyz/9WqsT2JQW7KV2m+bC2ol/zqpW37NHxLaA==", + "dev": true, + "dependencies": { + "b4a": "^1.6.4" + } + }, + "node_modules/text-extensions": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/text-extensions/-/text-extensions-1.9.0.tgz", + "integrity": "sha512-wiBrwC1EhBelW12Zy26JeOUkQ5mRu+5o8rpsJk5+2t+Y5vE7e842qtZDQ2g1NpX/29HdyFeJ4nSIhI47ENSxlQ==", + "dev": true, "engines": { - "node": "*" + "node": ">=0.10" } }, - "node_modules/uglify-js": { - "version": "3.19.3", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz", - "integrity": "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==", + "node_modules/thingies": { + "version": "1.21.0", + "resolved": "https://registry.npmjs.org/thingies/-/thingies-1.21.0.tgz", + "integrity": "sha512-hsqsJsFMsV+aD4s3CWKk85ep/3I9XzYV/IXaSouJMYIoDlgyi11cBhsqYe9/geRfB0YIikBQg6raRaM+nIMP9g==", "dev": true, - "optional": true, - "bin": { - "uglifyjs": "bin/uglifyjs" - }, + "license": "Unlicense", "engines": { - "node": ">=0.8.0" + "node": ">=10.18" + }, + "peerDependencies": { + "tslib": "^2" } }, - "node_modules/unbox-primitive": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", - "integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==", + "node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", + "dev": true + }, + "node_modules/through2": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz", + "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==", "dev": true, "dependencies": { - "call-bound": "^1.0.3", - "has-bigints": "^1.0.2", - "has-symbols": "^1.1.0", - "which-boxed-primitive": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "readable-stream": "3" } }, - "node_modules/undici-types": { - "version": "6.19.8", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", - "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", - "dev": true + "node_modules/thunky": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", + "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", + "dev": true, + "license": "MIT" }, - "node_modules/unicode-canonical-property-names-ecmascript": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.1.tgz", - "integrity": "sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==", + "node_modules/tmp": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.3.tgz", + "integrity": "sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==", "dev": true, "engines": { - "node": ">=4" + "node": ">=14.14" } }, - "node_modules/unicode-match-property-ecmascript": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", - "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", - "dev": true, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "devOptional": true, "dependencies": { - "unicode-canonical-property-names-ecmascript": "^2.0.0", - "unicode-property-aliases-ecmascript": "^2.0.0" + "is-number": "^7.0.0" }, "engines": { - "node": ">=4" + "node": ">=8.0" } }, - "node_modules/unicode-match-property-value-ecmascript": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.2.0.tgz", - "integrity": "sha512-4IehN3V/+kkr5YeSSDDQG8QLqO26XpL2XP3GQtqwlT/QYSECAwFztxVHjlbh0+gjJ3XmNLS0zDsbgs9jWKExLg==", + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", "dev": true, "engines": { - "node": ">=4" + "node": ">=0.6" } }, - "node_modules/unicode-property-aliases-ecmascript": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", - "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "dev": true + }, + "node_modules/tree-dump": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/tree-dump/-/tree-dump-1.0.2.tgz", + "integrity": "sha512-dpev9ABuLWdEubk+cIaI9cHwRNNDjkBBLXTwI4UCUFdQ5xXKqNXoK4FEciw/vxf+NQ7Cb7sGUyeUtORvHIdRXQ==", "dev": true, + "license": "Apache-2.0", "engines": { - "node": ">=4" + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" } }, - "node_modules/unicorn-magic": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.1.0.tgz", - "integrity": "sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==", + "node_modules/tree-kill": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", + "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", + "dev": true, + "bin": { + "tree-kill": "cli.js" + } + }, + "node_modules/trim-newlines": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz", + "integrity": "sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==", "dev": true, "engines": { - "node": ">=18" + "node": ">=8" + } + }, + "node_modules/ts-api-utils": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.4.3.tgz", + "integrity": "sha512-i3eMG77UTMD0hZhgRS562pv83RC6ukSAC2GMNWc+9dieh/+jDM5u5YG+NHX6VNDRHQcHwmsTHctP9LhbC3WxVw==", + "dev": true, + "engines": { + "node": ">=16" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependencies": { + "typescript": ">=4.2.0" } }, - "node_modules/unique-filename": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-4.0.0.tgz", - "integrity": "sha512-XSnEewXmQ+veP7xX2dS5Q4yZAvO40cBN2MWkJ7D/6sW4Dg6wYBNwM1Vrnz1FhH5AdeLIlUXRI9e28z1YZi71NQ==", + "node_modules/ts-node": { + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", + "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", "dev": true, "dependencies": { - "unique-slug": "^5.0.0" + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" }, - "engines": { - "node": "^18.17.0 || >=20.5.0" + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } } }, - "node_modules/unique-slug": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-5.0.0.tgz", - "integrity": "sha512-9OdaqO5kwqR+1kVgHAhsp5vPNU0hnxRa26rBFNfNgM7M6pNtgzeBn3s/xbyCQL3dcjzOatcef6UUHpB/6MaETg==", + "node_modules/tsconfig-paths": { + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", + "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", "dev": true, "dependencies": { - "imurmurhash": "^0.1.4" + "@types/json5": "^0.0.29", + "json5": "^1.0.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + } + }, + "node_modules/tsconfig-paths/node_modules/json5": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "dev": true, + "dependencies": { + "minimist": "^1.2.0" }, - "engines": { - "node": "^18.17.0 || >=20.5.0" + "bin": { + "json5": "lib/cli.js" } }, - "node_modules/unique-string": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", - "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" + }, + "node_modules/tuf-js": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/tuf-js/-/tuf-js-3.0.1.tgz", + "integrity": "sha512-+68OP1ZzSF84rTckf3FA95vJ1Zlx/uaXyiiKyPd1pA4rZNkpEvDAKmsu1xUSmbF/chCRYgZ6UZkDwC7PmzmAyA==", "dev": true, "dependencies": { - "crypto-random-string": "^2.0.0" + "@tufjs/models": "3.0.1", + "debug": "^4.3.6", + "make-fetch-happen": "^14.0.1" }, "engines": { - "node": ">=8" + "node": "^18.17.0 || >=20.5.0" } }, - "node_modules/universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", "dev": true, + "dependencies": { + "safe-buffer": "^5.0.1" + }, "engines": { - "node": ">= 10.0.0" + "node": "*" } }, - "node_modules/unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1" + }, "engines": { - "node": ">= 0.8" + "node": ">= 0.8.0" } }, - "node_modules/untildify": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", - "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==", + "node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", "dev": true, "engines": { - "node": ">=8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/update-browserslist-db": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz", - "integrity": "sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==", + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], "dependencies": { - "escalade": "^3.2.0", - "picocolors": "^1.1.0" - }, - "bin": { - "update-browserslist-db": "cli.js" + "media-typer": "0.3.0", + "mime-types": "~2.1.24" }, - "peerDependencies": { - "browserslist": ">= 4.21.0" + "engines": { + "node": ">= 0.6" } }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "node_modules/typed-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", + "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", + "dev": true, "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/uri-js/node_modules/punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.13" + }, "engines": { - "node": ">=6" + "node": ">= 0.4" } }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" - }, - "node_modules/utils-merge": { + "node_modules/typed-array-byte-length": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", + "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" + }, "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/uuid": { - "version": "11.0.3", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.0.3.tgz", - "integrity": "sha512-d0z310fCWv5dJwnX1Y/MncBAqGMKEzlBb1AOf7z9K8ALnd0utBX/msg/fA0+sbyN1ihbMsLhrBlnl1ak7Wa0rg==", - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], - "bin": { - "uuid": "dist/esm/bin/uuid" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/v8-compile-cache-lib": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", - "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", - "dev": true - }, - "node_modules/validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "node_modules/typed-array-byte-offset": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.3.tgz", + "integrity": "sha512-GsvTyUHTriq6o/bHcTd0vM7OQ9JEdlvluu9YISaA7+KzDzPaIzEeDFNkTfhdE3MYcNhNi0vq/LlegYgIs5yPAw==", "dev": true, "dependencies": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13", + "reflect.getprototypeof": "^1.0.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/validate-npm-package-license/node_modules/spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "node_modules/typed-array-length": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.7.tgz", + "integrity": "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==", "dev": true, "dependencies": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "is-typed-array": "^1.1.13", + "possible-typed-array-names": "^1.0.0", + "reflect.getprototypeof": "^1.0.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/validate-npm-package-name": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-6.0.0.tgz", - "integrity": "sha512-d7KLgL1LD3U3fgnvWEY1cQXoO/q6EQ1BSz48Sa149V/5zVTAbgmZIpyI8TRi6U9/JNyeYLlTKsEMPtLC27RFUg==", + "node_modules/typed-assert": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/typed-assert/-/typed-assert-1.0.9.tgz", + "integrity": "sha512-KNNZtayBCtmnNmbo5mG47p1XsCyrx6iVqomjcZnec/1Y5GGARaxPs6r49RnSPeUP3YjNYiU9sQHAtY4BBvnZwg==", + "dev": true + }, + "node_modules/typedarray-to-buffer": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", + "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", "dev": true, - "engines": { - "node": "^18.17.0 || >=20.5.0" + "dependencies": { + "is-typedarray": "^1.0.0" } }, - "node_modules/vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "node_modules/typescript": { + "version": "5.6.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz", + "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==", "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, "engines": { - "node": ">= 0.8" + "node": ">=14.17" } }, - "node_modules/vite": { - "version": "5.4.11", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.11.tgz", - "integrity": "sha512-c7jFQRklXua0mTzneGW9QVyxFjUgwcihC4bXEtujIo2ouWCe1Ajt/amn2PCxYnhYfd5k09JX3SB7OYWFKYqj8Q==", + "node_modules/typescript-strict-plugin": { + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/typescript-strict-plugin/-/typescript-strict-plugin-2.4.4.tgz", + "integrity": "sha512-OXcWHQk+pW9gqEL/Mb1eTgj/Yiqk1oHBERr9v4VInPOYN++p+cXejmQK/h/VlUPGD++FXQ8pgiqVMyEtxU4T6A==", "dev": true, - "license": "MIT", "dependencies": { - "esbuild": "^0.21.3", - "postcss": "^8.4.43", - "rollup": "^4.20.0" + "chalk": "^3.0.0", + "execa": "^4.0.0", + "minimatch": "^9.0.3", + "ora": "^5.4.1", + "yargs": "^16.2.0" }, "bin": { - "vite": "bin/vite.js" - }, - "engines": { - "node": "^18.0.0 || >=20.0.0" - }, - "funding": { - "url": "https://github.com/vitejs/vite?sponsor=1" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" - }, - "peerDependencies": { - "@types/node": "^18.0.0 || >=20.0.0", - "less": "*", - "lightningcss": "^1.21.0", - "sass": "*", - "sass-embedded": "*", - "stylus": "*", - "sugarss": "*", - "terser": "^5.4.0" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "less": { - "optional": true - }, - "lightningcss": { - "optional": true - }, - "sass": { - "optional": true - }, - "sass-embedded": { - "optional": true - }, - "stylus": { - "optional": true - }, - "sugarss": { - "optional": true - }, - "terser": { - "optional": true - } + "tsc-strict": "dist/cli/tsc-strict/index.js", + "update-strict-comments": "dist/cli/update-strict-comments/index.js" + } + }, + "node_modules/typescript-strict-plugin/node_modules/chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/vite/node_modules/@esbuild/aix-ppc64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", - "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", - "cpu": [ - "ppc64" - ], + "node_modules/typescript-strict-plugin/node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=12" + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" } }, - "node_modules/vite/node_modules/@esbuild/android-arm": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", - "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", - "cpu": [ - "arm" - ], + "node_modules/typescript-strict-plugin/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, "engines": { - "node": ">=12" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/vite/node_modules/@esbuild/android-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", - "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", - "cpu": [ - "arm64" - ], + "node_modules/typescript-strict-plugin/node_modules/yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, "engines": { - "node": ">=12" + "node": ">=10" } }, - "node_modules/vite/node_modules/@esbuild/android-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", - "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", - "cpu": [ - "x64" - ], + "node_modules/ua-parser-js": { + "version": "0.7.39", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.39.tgz", + "integrity": "sha512-IZ6acm6RhQHNibSt7+c09hhvsKy9WUr4DVbeq9U8o71qxyYtJpQeDxQnMrVqnIFMLcQjHO0I9wgfO2vIahht4w==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/ua-parser-js" + }, + { + "type": "paypal", + "url": "https://paypal.me/faisalman" + }, + { + "type": "github", + "url": "https://github.com/sponsors/faisalman" + } ], + "bin": { + "ua-parser-js": "script/cli.js" + }, "engines": { - "node": ">=12" + "node": "*" } }, - "node_modules/vite/node_modules/@esbuild/darwin-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", - "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", - "cpu": [ - "arm64" - ], + "node_modules/uglify-js": { + "version": "3.19.3", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz", + "integrity": "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==", "dev": true, - "license": "MIT", "optional": true, - "os": [ - "darwin" - ], + "bin": { + "uglifyjs": "bin/uglifyjs" + }, "engines": { - "node": ">=12" + "node": ">=0.8.0" } }, - "node_modules/vite/node_modules/@esbuild/darwin-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", - "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", - "cpu": [ - "x64" - ], + "node_modules/unbox-primitive": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", + "integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], + "dependencies": { + "call-bound": "^1.0.3", + "has-bigints": "^1.0.2", + "has-symbols": "^1.1.0", + "which-boxed-primitive": "^1.1.1" + }, "engines": { - "node": ">=12" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/vite/node_modules/@esbuild/freebsd-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", - "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", - "cpu": [ - "arm64" - ], + "node_modules/undici-types": { + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", + "dev": true + }, + "node_modules/unicode-canonical-property-names-ecmascript": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.1.tgz", + "integrity": "sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], "engines": { - "node": ">=12" + "node": ">=4" } }, - "node_modules/vite/node_modules/@esbuild/freebsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", - "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", - "cpu": [ - "x64" - ], + "node_modules/unicode-match-property-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", + "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], + "dependencies": { + "unicode-canonical-property-names-ecmascript": "^2.0.0", + "unicode-property-aliases-ecmascript": "^2.0.0" + }, "engines": { - "node": ">=12" + "node": ">=4" } }, - "node_modules/vite/node_modules/@esbuild/linux-arm": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", - "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", - "cpu": [ - "arm" - ], + "node_modules/unicode-match-property-value-ecmascript": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.2.0.tgz", + "integrity": "sha512-4IehN3V/+kkr5YeSSDDQG8QLqO26XpL2XP3GQtqwlT/QYSECAwFztxVHjlbh0+gjJ3XmNLS0zDsbgs9jWKExLg==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], "engines": { - "node": ">=12" + "node": ">=4" } }, - "node_modules/vite/node_modules/@esbuild/linux-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", - "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", - "cpu": [ - "arm64" - ], + "node_modules/unicode-property-aliases-ecmascript": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", + "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], "engines": { - "node": ">=12" + "node": ">=4" } }, - "node_modules/vite/node_modules/@esbuild/linux-ia32": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", - "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", - "cpu": [ - "ia32" - ], + "node_modules/unicorn-magic": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.1.0.tgz", + "integrity": "sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], "engines": { - "node": ">=12" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/vite/node_modules/@esbuild/linux-loong64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", - "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", - "cpu": [ - "loong64" - ], + "node_modules/unique-filename": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-4.0.0.tgz", + "integrity": "sha512-XSnEewXmQ+veP7xX2dS5Q4yZAvO40cBN2MWkJ7D/6sW4Dg6wYBNwM1Vrnz1FhH5AdeLIlUXRI9e28z1YZi71NQ==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "unique-slug": "^5.0.0" + }, "engines": { - "node": ">=12" + "node": "^18.17.0 || >=20.5.0" } }, - "node_modules/vite/node_modules/@esbuild/linux-mips64el": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", - "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", - "cpu": [ - "mips64el" - ], + "node_modules/unique-slug": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-5.0.0.tgz", + "integrity": "sha512-9OdaqO5kwqR+1kVgHAhsp5vPNU0hnxRa26rBFNfNgM7M6pNtgzeBn3s/xbyCQL3dcjzOatcef6UUHpB/6MaETg==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "imurmurhash": "^0.1.4" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/unique-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", + "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", + "dev": true, + "dependencies": { + "crypto-random-string": "^2.0.0" + }, "engines": { - "node": ">=12" + "node": ">=8" } }, - "node_modules/vite/node_modules/@esbuild/linux-ppc64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", - "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", - "cpu": [ - "ppc64" - ], + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], "engines": { - "node": ">=12" + "node": ">= 10.0.0" } }, - "node_modules/vite/node_modules/@esbuild/linux-riscv64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", - "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", - "cpu": [ - "riscv64" - ], + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], "engines": { - "node": ">=12" + "node": ">= 0.8" } }, - "node_modules/vite/node_modules/@esbuild/linux-s390x": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", - "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", - "cpu": [ - "s390x" - ], + "node_modules/untildify": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", + "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], "engines": { - "node": ">=12" + "node": ">=8" } }, - "node_modules/vite/node_modules/@esbuild/linux-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", - "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", - "cpu": [ - "x64" - ], + "node_modules/update-browserslist-db": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz", + "integrity": "sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } ], + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.0" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/uri-js/node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "engines": { - "node": ">=12" + "node": ">=6" } }, - "node_modules/vite/node_modules/@esbuild/netbsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", - "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", - "cpu": [ - "x64" - ], + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], "engines": { - "node": ">=12" + "node": ">= 0.4.0" } }, - "node_modules/vite/node_modules/@esbuild/openbsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", - "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", - "cpu": [ - "x64" + "node_modules/uuid": { + "version": "11.0.5", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.0.5.tgz", + "integrity": "sha512-508e6IcKLrhxKdBbcA2b4KQZlLVp2+J5UwQ6F7Drckkc5N9ZJwFa4TgWtsww9UG8fGHbm6gbV19TdM5pQ4GaIA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" ], - "dev": true, "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=12" + "bin": { + "uuid": "dist/esm/bin/uuid" } }, - "node_modules/vite/node_modules/@esbuild/sunos-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", - "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", - "cpu": [ - "x64" - ], + "node_modules/v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "dev": true + }, + "node_modules/validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=12" + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" } }, - "node_modules/vite/node_modules/@esbuild/win32-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", - "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", - "cpu": [ - "arm64" - ], + "node_modules/validate-npm-package-license/node_modules/spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" } }, - "node_modules/vite/node_modules/@esbuild/win32-ia32": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", - "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", - "cpu": [ - "ia32" - ], + "node_modules/validate-npm-package-name": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-6.0.0.tgz", + "integrity": "sha512-d7KLgL1LD3U3fgnvWEY1cQXoO/q6EQ1BSz48Sa149V/5zVTAbgmZIpyI8TRi6U9/JNyeYLlTKsEMPtLC27RFUg==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], "engines": { - "node": ">=12" + "node": "^18.17.0 || >=20.5.0" } }, - "node_modules/vite/node_modules/@esbuild/win32-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", - "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", - "cpu": [ - "x64" - ], + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], "engines": { - "node": ">=12" + "node": ">= 0.8" } }, - "node_modules/vite/node_modules/esbuild": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", - "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", + "node_modules/vite": { + "version": "6.0.11", + "resolved": "https://registry.npmjs.org/vite/-/vite-6.0.11.tgz", + "integrity": "sha512-4VL9mQPKoHy4+FE0NnRE/kbY51TOfaknxAjt3fJbGJxhIpBZiqVzlZDEesWWsuREXHwNdAoOFZ9MkPEVXczHwg==", "dev": true, - "hasInstallScript": true, "license": "MIT", + "dependencies": { + "esbuild": "^0.24.2", + "postcss": "^8.4.49", + "rollup": "^4.23.0" + }, "bin": { - "esbuild": "bin/esbuild" + "vite": "bin/vite.js" }, "engines": { - "node": ">=12" + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.21.5", - "@esbuild/android-arm": "0.21.5", - "@esbuild/android-arm64": "0.21.5", - "@esbuild/android-x64": "0.21.5", - "@esbuild/darwin-arm64": "0.21.5", - "@esbuild/darwin-x64": "0.21.5", - "@esbuild/freebsd-arm64": "0.21.5", - "@esbuild/freebsd-x64": "0.21.5", - "@esbuild/linux-arm": "0.21.5", - "@esbuild/linux-arm64": "0.21.5", - "@esbuild/linux-ia32": "0.21.5", - "@esbuild/linux-loong64": "0.21.5", - "@esbuild/linux-mips64el": "0.21.5", - "@esbuild/linux-ppc64": "0.21.5", - "@esbuild/linux-riscv64": "0.21.5", - "@esbuild/linux-s390x": "0.21.5", - "@esbuild/linux-x64": "0.21.5", - "@esbuild/netbsd-x64": "0.21.5", - "@esbuild/openbsd-x64": "0.21.5", - "@esbuild/sunos-x64": "0.21.5", - "@esbuild/win32-arm64": "0.21.5", - "@esbuild/win32-ia32": "0.21.5", - "@esbuild/win32-x64": "0.21.5" + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", + "jiti": ">=1.21.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "sass-embedded": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } } }, "node_modules/void-elements": { @@ -21606,16 +21687,17 @@ "dev": true }, "node_modules/webpack": { - "version": "5.96.1", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.96.1.tgz", - "integrity": "sha512-l2LlBSvVZGhL4ZrPwyr8+37AunkcYj5qh8o6u2/2rzoPc8gxFJkLj1WxNgooi9pnoc06jh0BjuXnamM4qlujZA==", + "version": "5.97.1", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.97.1.tgz", + "integrity": "sha512-EksG6gFY3L1eFMROS/7Wzgrii5mBAFe4rIr3r2BTfo7bcc+DWwFZ4OJ/miOuHJO/A85HwyI4eQ0F6IKXesO7Fg==", "dev": true, + "license": "MIT", "dependencies": { "@types/eslint-scope": "^3.7.7", "@types/estree": "^1.0.6", - "@webassemblyjs/ast": "^1.12.1", - "@webassemblyjs/wasm-edit": "^1.12.1", - "@webassemblyjs/wasm-parser": "^1.12.1", + "@webassemblyjs/ast": "^1.14.1", + "@webassemblyjs/wasm-edit": "^1.14.1", + "@webassemblyjs/wasm-parser": "^1.14.1", "acorn": "^8.14.0", "browserslist": "^4.24.0", "chrome-trace-event": "^1.0.2", @@ -21682,9 +21764,9 @@ } }, "node_modules/webpack-dev-server": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-5.1.0.tgz", - "integrity": "sha512-aQpaN81X6tXie1FoOB7xlMfCsN19pSvRAeYUHOdFWOlhpQ/LlbfTqYwwmEDFV0h8GGuqmCmKmT+pxcUV/Nt2gQ==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-5.2.0.tgz", + "integrity": "sha512-90SqqYXA2SK36KcT6o1bvwvZfJFcmoamqeJY7+boioffX9g9C0wjjJRGUrQIuh43pb0ttX7+ssavmj/WN2RHtA==", "dev": true, "license": "MIT", "dependencies": { @@ -21701,10 +21783,9 @@ "colorette": "^2.0.10", "compression": "^1.7.4", "connect-history-api-fallback": "^2.0.0", - "express": "^4.19.2", + "express": "^4.21.2", "graceful-fs": "^4.2.6", - "html-entities": "^2.4.0", - "http-proxy-middleware": "^2.0.3", + "http-proxy-middleware": "^2.0.7", "ipaddr.js": "^2.1.0", "launch-editor": "^2.6.1", "open": "^10.0.3", diff --git a/ui/package.json b/ui/package.json index 9470ce7a696..f424933fa97 100644 --- a/ui/package.json +++ b/ui/package.json @@ -1,6 +1,6 @@ { "name": "openems-ui", - "version": "2025.1.0", + "version": "2025.2.0", "license": "AGPL-3.0", "private": true, "dependencies": { @@ -12,8 +12,8 @@ "@angular/platform-browser-dynamic": "19.0.5", "@angular/router": "19.0.5", "@angular/service-worker": "19.0.5", - "@awesome-cordova-plugins/core": "^6.13.0", - "@awesome-cordova-plugins/file-opener": "^6.13.0", + "@awesome-cordova-plugins/core": "^6.14.0", + "@awesome-cordova-plugins/file-opener": "^6.14.0", "@capacitor-community/file-opener": "^6.0.1", "@capacitor/android": "^6.2.0", "@capacitor/app": "^6.0.2", @@ -46,9 +46,9 @@ "ngx-spinner": "^17.0.0", "roboto-fontface": "^0.10.0", "rxjs": "~7.8.1", - "swiper": "11.1.15", + "swiper": "11.2.1", "tslib": "^2.8.1", - "uuid": "^11.0.3", + "uuid": "^11.0.5", "zone.js": "~0.15.0" }, "devDependencies": { @@ -68,18 +68,18 @@ "@ionic/angular-toolkit": "^12.1.1", "@ionic/cli": "^7.2.0", "@schematics/angular": "^19.0.6", - "@stylistic/eslint-plugin": "^2.12.1", + "@stylistic/eslint-plugin": "^2.13.0", "@types/jasmine": "~5.1.5", "@types/jasminewd2": "~2.0.13", "@types/json-schema": "^7.0.15", "@types/node": "^20.12.6", - "@types/qs": "^6.9.17", + "@types/qs": "^6.9.18", "@types/range-parser": "^1.2.7", "@types/send": "^0.17.4", "@types/uuid": "^10.0.0", "@typescript-eslint/eslint-plugin": "^8.19.0", "@typescript-eslint/parser": "^8.19.0", - "@typescript-eslint/types": "^8.19.0", + "@typescript-eslint/types": "^8.20.0", "eslint": "^9.17.0", "eslint-import-resolver-typescript": "^3.7.0", "eslint-plugin-check-file": "^2.8.0", @@ -87,6 +87,7 @@ "eslint-plugin-jsdoc": "50.6.1", "eslint-plugin-prefer-arrow": "1.2.3", "eslint-plugin-unused-imports": "^4.1.4", + "globals": "^15.9.0", "jasmine-core": "~5.5.0", "jasmine-spec-reporter": "~7.0.0", "karma": "~6.4.4", diff --git a/ui/src/app/app-routing.module.ts b/ui/src/app/app-routing.module.ts index 639c4b40cf3..1001553cedf 100644 --- a/ui/src/app/app-routing.module.ts +++ b/ui/src/app/app-routing.module.ts @@ -18,7 +18,6 @@ import { OverviewComponent as DigitalOutputChartOverviewComponent } from "./edge import { OverviewComponent as HeatingelementChartOverviewComponent } from "./edge/history/Controller/Io/heatingelement/overview/overview"; import { OverviewComponent as ModbusTcpApiOverviewComponent } from "./edge/history/Controller/ModbusTcpApi/overview/overview"; import { DelayedSellToGridChartOverviewComponent } from "./edge/history/delayedselltogrid/symmetricpeakshavingchartoverview/delayedselltogridchartoverview.component"; -import { HeatPumpChartOverviewComponent } from "./edge/history/heatpump/heatpumpchartoverview/heatpumpchartoverview.component"; import { HistoryComponent as EdgeHistoryComponent } from "./edge/history/history.component"; import { HistoryDataService } from "./edge/history/historydataservice"; import { HistoryParentComponent } from "./edge/history/historyparent.component"; @@ -89,7 +88,7 @@ export const routes: Routes = [ { path: ":componentId/delayedselltogridchart", component: DelayedSellToGridChartOverviewComponent }, { path: ":componentId/gridOptimizedChargeChart", component: GridOptimizedChargeChartOverviewComponent }, { path: ":componentId/heatingelementchart", component: HeatingelementChartOverviewComponent }, - { path: ":componentId/heatpumpchart", component: HeatPumpChartOverviewComponent }, + { path: ":componentId/heatpumpchart", loadChildren: () => import("./edge/history/Controller/Io/heatpump/heat-pump.module").then(m => m.HeatPumpModule) }, { path: ":componentId/modbusTcpApi", component: ModbusTcpApiOverviewComponent }, { path: ":componentId/scheduleChart", component: TimeOfUseTariffOverviewComponent }, { path: ":componentId/symmetricpeakshavingchart", component: SymmetricPeakshavingChartOverviewComponent }, diff --git a/ui/src/app/app.module.ts b/ui/src/app/app.module.ts index 58af2d37c2d..4a96690019b 100644 --- a/ui/src/app/app.module.ts +++ b/ui/src/app/app.module.ts @@ -57,7 +57,7 @@ import { UserModule } from "./user/user.module"; { provide: RouteReuseStrategy, useClass: IonicRouteStrategy }, CookieService, { provide: ErrorHandler, useClass: MyErrorHandler }, - { provide: LOCALE_ID, useValue: Language.DEFAULT.key }, + { provide: LOCALE_ID, useFactory: () => (Language.getByKey(localStorage.LANGUAGE) ?? Language.getByBrowserLang(navigator.language) ?? Language.DEFAULT).key }, // Use factory for formly. This allows us to use translations in validationMessages. { provide: FORMLY_CONFIG, multi: true, useFactory: registerTranslateExtension, deps: [TranslateService] }, DeviceDetectorService, diff --git a/ui/src/app/changelog/view/component/changelog.constants.ts b/ui/src/app/changelog/view/component/changelog.constants.ts index 9b4f6bf340e..eb60fbde7f6 100644 --- a/ui/src/app/changelog/view/component/changelog.constants.ts +++ b/ui/src/app/changelog/view/component/changelog.constants.ts @@ -2,7 +2,7 @@ import { Role } from "src/app/shared/type/role"; export class Changelog { - public static readonly UI_VERSION = "2025.1.0"; + public static readonly UI_VERSION = "2025.2.0"; public static product(...products: Product[]) { return products.map(product => Changelog.link(product.name, product.url)).join(", ") + ". "; diff --git a/ui/src/app/edge/history/Controller/Ess/TimeOfUseTariff/chart/chart.ts b/ui/src/app/edge/history/Controller/Ess/TimeOfUseTariff/chart/chart.ts index 6b845eb9cf6..2cb22245343 100644 --- a/ui/src/app/edge/history/Controller/Ess/TimeOfUseTariff/chart/chart.ts +++ b/ui/src/app/edge/history/Controller/Ess/TimeOfUseTariff/chart/chart.ts @@ -127,7 +127,7 @@ export class ChartComponent extends AbstractHistoryChart { }; } - protected override loadChart(): void { + protected override async loadChart() { this.labels = []; this.errorResponse = null; @@ -175,16 +175,15 @@ export class ChartComponent extends AbstractHistoryChart { }); const chartObject = this.chartObject; - this.options.scales[ChartAxis.LEFT].ticks = { - callback: function (value, index, ticks) { + this.options.scales[ChartAxis.LEFT].ticks.callback = + function (value, index, ticks) { if (index == (ticks.length - 1)) { const upperMostTick = chartObject.yAxes.find(el => el.unit === YAxisType.CURRENCY).customTitle; AssertionUtils.assertHasMaxLength(upperMostTick, ChartConstants.MAX_LENGTH_OF_Y_AXIS_TITLE); return upperMostTick; } return value; - }, - }; + }; this.options.scales.x["offset"] = false; this.options["animation"] = false; }); diff --git a/ui/src/app/edge/history/Controller/Io/DigitalOutput/details/chart/chart.ts b/ui/src/app/edge/history/Controller/Io/DigitalOutput/details/chart/chart.ts index 46a3e12c8e3..a746220993b 100644 --- a/ui/src/app/edge/history/Controller/Io/DigitalOutput/details/chart/chart.ts +++ b/ui/src/app/edge/history/Controller/Io/DigitalOutput/details/chart/chart.ts @@ -156,9 +156,8 @@ export class ChartComponent extends AbstractHistoryChart { stack: 1, }; } + protected override getChartData(): HistoryUtils.ChartData { return ChartComponent.getChartData(this.config, this.chartType, this.route, this.translate); } - - } diff --git a/ui/src/app/edge/history/Controller/Io/heatingelement/chart/chart.ts b/ui/src/app/edge/history/Controller/Io/heatingelement/chart/chart.ts index fbff518e075..12580184095 100644 --- a/ui/src/app/edge/history/Controller/Io/heatingelement/chart/chart.ts +++ b/ui/src/app/edge/history/Controller/Io/heatingelement/chart/chart.ts @@ -61,18 +61,13 @@ export class ChartComponent extends AbstractHistoryChart { tooltip: { formatNumber: ChartConstants.NumberFormat.NO_DECIMALS, }, - yAxes: [ - chartType === "line" - ? { - unit: YAxisType.LEVEL, - position: "left", - yAxisId: ChartAxis.LEFT, - } - : { - unit: YAxisType.TIME, - position: "left", - yAxisId: ChartAxis.LEFT, - }, + yAxes: [{ + unit: chartType === "line" + ? YAxisType.HEATING_ELEMENT + : YAxisType.TIME, + position: "left", + yAxisId: ChartAxis.LEFT, + }, ], }; } diff --git a/ui/src/app/edge/history/Controller/Io/heatpump/chart/chart.constants.spec.ts b/ui/src/app/edge/history/Controller/Io/heatpump/chart/chart.constants.spec.ts new file mode 100644 index 00000000000..4644c357034 --- /dev/null +++ b/ui/src/app/edge/history/Controller/Io/heatpump/chart/chart.constants.spec.ts @@ -0,0 +1,43 @@ +import { OeTester } from "src/app/shared/components/shared/testing/common"; +import { OeChartTester } from "src/app/shared/components/shared/testing/tester"; +import { TestContext, TestingUtils } from "src/app/shared/components/shared/testing/utils.spec"; + +import { QueryHistoricTimeseriesDataResponse } from "src/app/shared/jsonrpc/response/queryHistoricTimeseriesDataResponse"; +import { QueryHistoricTimeseriesEnergyPerPeriodResponse } from "src/app/shared/jsonrpc/response/queryHistoricTimeseriesEnergyPerPeriodResponse"; +import { QueryHistoricTimeseriesEnergyResponse } from "src/app/shared/jsonrpc/response/queryHistoricTimeseriesEnergyResponse"; +import { EdgeConfig } from "src/app/shared/shared"; +import { ChartComponent } from "./chart"; + +export function expectView(config: EdgeConfig, component: EdgeConfig.Component, testContext: TestContext, chartType: "line" | "bar", channels: OeTester.Types.Channels, view: OeChartTester.View): void { + expect(TestingUtils.removeFunctions(OeChartTester + .apply(ChartComponent + .getChartData(component, testContext.translate, chartType, testContext.service.periodString), chartType, channels, testContext, config))) + .toEqual(TestingUtils.removeFunctions(view)); +} +export namespace History { + + export const DAY: OeTester.Types.Channels = { + energyChannelWithValues: new QueryHistoricTimeseriesEnergyResponse("0", { + data: {}, + }), + dataChannelWithValues: new QueryHistoricTimeseriesDataResponse("0", { + data: { "ctrlIoHeatPump0/Status": [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 2, 1, 2, 2, 2, 1, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] }, + timestamps: ["2023-07-02T22:00:00Z", "2023-07-02T22:05:00Z", "2023-07-02T22:10:00Z", "2023-07-02T22:15:00Z", "2023-07-02T22:20:00Z", "2023-07-02T22:25:00Z", "2023-07-02T22:30:00Z", "2023-07-02T22:35:00Z", "2023-07-02T22:40:00Z", "2023-07-02T22:45:00Z", "2023-07-02T22:50:00Z", "2023-07-02T22:55:00Z", "2023-07-02T23:00:00Z", "2023-07-02T23:05:00Z", "2023-07-02T23:10:00Z", "2023-07-02T23:15:00Z", "2023-07-02T23:20:00Z", "2023-07-02T23:25:00Z", "2023-07-02T23:30:00Z", "2023-07-02T23:35:00Z", "2023-07-02T23:40:00Z", "2023-07-02T23:45:00Z", "2023-07-02T23:50:00Z", "2023-07-02T23:55:00Z", "2023-07-03T00:00:00Z", "2023-07-03T00:05:00Z", "2023-07-03T00:10:00Z", "2023-07-03T00:15:00Z", "2023-07-03T00:20:00Z", "2023-07-03T00:25:00Z", "2023-07-03T00:30:00Z", "2023-07-03T00:35:00Z", "2023-07-03T00:40:00Z", "2023-07-03T00:45:00Z", "2023-07-03T00:50:00Z", "2023-07-03T00:55:00Z", "2023-07-03T01:00:00Z", "2023-07-03T01:05:00Z", "2023-07-03T01:10:00Z", "2023-07-03T01:15:00Z", "2023-07-03T01:20:00Z", "2023-07-03T01:25:00Z", "2023-07-03T01:30:00Z", "2023-07-03T01:35:00Z", "2023-07-03T01:40:00Z", "2023-07-03T01:45:00Z", "2023-07-03T01:50:00Z", "2023-07-03T01:55:00Z", "2023-07-03T02:00:00Z", "2023-07-03T02:05:00Z", "2023-07-03T02:10:00Z", "2023-07-03T02:15:00Z", "2023-07-03T02:20:00Z", "2023-07-03T02:25:00Z", "2023-07-03T02:30:00Z", "2023-07-03T02:35:00Z", "2023-07-03T02:40:00Z", "2023-07-03T02:45:00Z", "2023-07-03T02:50:00Z", "2023-07-03T02:55:00Z", "2023-07-03T03:00:00Z", "2023-07-03T03:05:00Z", "2023-07-03T03:10:00Z", "2023-07-03T03:15:00Z", "2023-07-03T03:20:00Z", "2023-07-03T03:25:00Z", "2023-07-03T03:30:00Z", "2023-07-03T03:35:00Z", "2023-07-03T03:40:00Z", "2023-07-03T03:45:00Z", "2023-07-03T03:50:00Z", "2023-07-03T03:55:00Z", "2023-07-03T04:00:00Z", "2023-07-03T04:05:00Z", "2023-07-03T04:10:00Z", "2023-07-03T04:15:00Z", "2023-07-03T04:20:00Z", "2023-07-03T04:25:00Z", "2023-07-03T04:30:00Z", "2023-07-03T04:35:00Z", "2023-07-03T04:40:00Z", "2023-07-03T04:45:00Z", "2023-07-03T04:50:00Z", "2023-07-03T04:55:00Z", "2023-07-03T05:00:00Z", "2023-07-03T05:05:00Z", "2023-07-03T05:10:00Z", "2023-07-03T05:15:00Z", "2023-07-03T05:20:00Z", "2023-07-03T05:25:00Z", "2023-07-03T05:30:00Z", "2023-07-03T05:35:00Z", "2023-07-03T05:40:00Z", "2023-07-03T05:45:00Z", "2023-07-03T05:50:00Z", "2023-07-03T05:55:00Z", "2023-07-03T06:00:00Z", "2023-07-03T06:05:00Z", "2023-07-03T06:10:00Z", "2023-07-03T06:15:00Z", "2023-07-03T06:20:00Z", "2023-07-03T06:25:00Z", "2023-07-03T06:30:00Z", "2023-07-03T06:35:00Z", "2023-07-03T06:40:00Z", "2023-07-03T06:45:00Z", "2023-07-03T06:50:00Z", "2023-07-03T06:55:00Z", "2023-07-03T07:00:00Z", "2023-07-03T07:05:00Z", "2023-07-03T07:10:00Z", "2023-07-03T07:15:00Z", "2023-07-03T07:20:00Z", "2023-07-03T07:25:00Z", "2023-07-03T07:30:00Z", "2023-07-03T07:35:00Z", "2023-07-03T07:40:00Z", "2023-07-03T07:45:00Z", "2023-07-03T07:50:00Z", "2023-07-03T07:55:00Z", "2023-07-03T08:00:00Z", "2023-07-03T08:05:00Z", "2023-07-03T08:10:00Z", "2023-07-03T08:15:00Z", "2023-07-03T08:20:00Z", "2023-07-03T08:25:00Z", "2023-07-03T08:30:00Z", "2023-07-03T08:35:00Z", "2023-07-03T08:40:00Z", "2023-07-03T08:45:00Z", "2023-07-03T08:50:00Z", "2023-07-03T08:55:00Z", "2023-07-03T09:00:00Z", "2023-07-03T09:05:00Z", "2023-07-03T09:10:00Z", "2023-07-03T09:15:00Z", "2023-07-03T09:20:00Z", "2023-07-03T09:25:00Z", "2023-07-03T09:30:00Z", "2023-07-03T09:35:00Z", "2023-07-03T09:40:00Z", "2023-07-03T09:45:00Z", "2023-07-03T09:50:00Z", "2023-07-03T09:55:00Z", "2023-07-03T10:00:00Z", "2023-07-03T10:05:00Z", "2023-07-03T10:10:00Z", "2023-07-03T10:15:00Z", "2023-07-03T10:20:00Z", "2023-07-03T10:25:00Z", "2023-07-03T10:30:00Z", "2023-07-03T10:35:00Z", "2023-07-03T10:40:00Z", "2023-07-03T10:45:00Z", "2023-07-03T10:50:00Z", "2023-07-03T10:55:00Z", "2023-07-03T11:00:00Z", "2023-07-03T11:05:00Z", "2023-07-03T11:10:00Z", "2023-07-03T11:15:00Z", "2023-07-03T11:20:00Z", "2023-07-03T11:25:00Z", "2023-07-03T11:30:00Z", "2023-07-03T11:35:00Z", "2023-07-03T11:40:00Z", "2023-07-03T11:45:00Z", "2023-07-03T11:50:00Z", "2023-07-03T11:55:00Z", "2023-07-03T12:00:00Z", "2023-07-03T12:05:00Z", "2023-07-03T12:10:00Z", "2023-07-03T12:15:00Z", "2023-07-03T12:20:00Z", "2023-07-03T12:25:00Z", "2023-07-03T12:30:00Z", "2023-07-03T12:35:00Z", "2023-07-03T12:40:00Z", "2023-07-03T12:45:00Z", "2023-07-03T12:50:00Z", "2023-07-03T12:55:00Z", "2023-07-03T13:00:00Z", "2023-07-03T13:05:00Z", "2023-07-03T13:10:00Z", "2023-07-03T13:15:00Z", "2023-07-03T13:20:00Z", "2023-07-03T13:25:00Z", "2023-07-03T13:30:00Z", "2023-07-03T13:35:00Z", "2023-07-03T13:40:00Z", "2023-07-03T13:45:00Z", "2023-07-03T13:50:00Z", "2023-07-03T13:55:00Z", "2023-07-03T14:00:00Z", "2023-07-03T14:05:00Z", "2023-07-03T14:10:00Z", "2023-07-03T14:15:00Z", "2023-07-03T14:20:00Z", "2023-07-03T14:25:00Z", "2023-07-03T14:30:00Z", "2023-07-03T14:35:00Z", "2023-07-03T14:40:00Z", "2023-07-03T14:45:00Z", "2023-07-03T14:50:00Z", "2023-07-03T14:55:00Z", "2023-07-03T15:00:00Z", "2023-07-03T15:05:00Z", "2023-07-03T15:10:00Z", "2023-07-03T15:15:00Z", "2023-07-03T15:20:00Z", "2023-07-03T15:25:00Z", "2023-07-03T15:30:00Z", "2023-07-03T15:35:00Z", "2023-07-03T15:40:00Z", "2023-07-03T15:45:00Z", "2023-07-03T15:50:00Z", "2023-07-03T15:55:00Z", "2023-07-03T16:00:00Z", "2023-07-03T16:05:00Z", "2023-07-03T16:10:00Z", "2023-07-03T16:15:00Z", "2023-07-03T16:20:00Z", "2023-07-03T16:25:00Z", "2023-07-03T16:30:00Z", "2023-07-03T16:35:00Z", "2023-07-03T16:40:00Z", "2023-07-03T16:45:00Z", "2023-07-03T16:50:00Z", "2023-07-03T16:55:00Z", "2023-07-03T17:00:00Z", "2023-07-03T17:05:00Z", "2023-07-03T17:10:00Z", "2023-07-03T17:15:00Z", "2023-07-03T17:20:00Z", "2023-07-03T17:25:00Z", "2023-07-03T17:30:00Z", "2023-07-03T17:35:00Z", "2023-07-03T17:40:00Z", "2023-07-03T17:45:00Z", "2023-07-03T17:50:00Z", "2023-07-03T17:55:00Z", "2023-07-03T18:00:00Z", "2023-07-03T18:05:00Z", "2023-07-03T18:10:00Z", "2023-07-03T18:15:00Z", "2023-07-03T18:20:00Z", "2023-07-03T18:25:00Z", "2023-07-03T18:30:00Z", "2023-07-03T18:35:00Z", "2023-07-03T18:40:00Z", "2023-07-03T18:45:00Z", "2023-07-03T18:50:00Z", "2023-07-03T18:55:00Z", "2023-07-03T19:00:00Z", "2023-07-03T19:05:00Z", "2023-07-03T19:10:00Z", "2023-07-03T19:15:00Z", "2023-07-03T19:20:00Z", "2023-07-03T19:25:00Z", "2023-07-03T19:30:00Z", "2023-07-03T19:35:00Z", "2023-07-03T19:40:00Z", "2023-07-03T19:45:00Z", "2023-07-03T19:50:00Z", "2023-07-03T19:55:00Z", "2023-07-03T20:00:00Z", "2023-07-03T20:05:00Z", "2023-07-03T20:10:00Z", "2023-07-03T20:15:00Z", "2023-07-03T20:20:00Z", "2023-07-03T20:25:00Z", "2023-07-03T20:30:00Z", "2023-07-03T20:35:00Z", "2023-07-03T20:40:00Z", "2023-07-03T20:45:00Z", "2023-07-03T20:50:00Z", "2023-07-03T20:55:00Z", "2023-07-03T21:00:00Z", "2023-07-03T21:05:00Z", "2023-07-03T21:10:00Z", "2023-07-03T21:15:00Z", "2023-07-03T21:20:00Z", "2023-07-03T21:25:00Z", "2023-07-03T21:30:00Z", "2023-07-03T21:35:00Z", "2023-07-03T21:40:00Z", "2023-07-03T21:45:00Z", "2023-07-03T21:50:00Z", "2023-07-03T21:55:00Z"], + }), + }; + + export const MONTH: OeTester.Types.Channels = { + energyChannelWithValues: new QueryHistoricTimeseriesEnergyResponse("0", { + data: {}, + }), + energyPerPeriodChannelWithValues: new QueryHistoricTimeseriesEnergyPerPeriodResponse("0", { + data: { + "ctrlIoHeatPump0/ForceOnStateTime": [0, 0, 0, 0, 0, 9519, 0, 0, 0, 0, 3921, 0, 0, 0, 5795, 8510, 0, 0, 0, 0, 1798, 0, 0, 0, 5883, 0, 0, 0, 0, 0, null], + "ctrlIoHeatPump0/LockStateTime": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, null], + "ctrlIoHeatPump0/RecommendationStateTime": [0, 0, 0, 0, 0, 5396, 0, 0, 0, 0, 5395, 0, 0, 0, 3597, 3597, 0, 0, 0, 0, 1798, 0, 0, 0, 7194, 0, 0, 0, 0, 0, null], + "ctrlIoHeatPump0/RegularStateTime": [86353, 86353, 86354, 86353, 86352, 71428, 86353, 86352, 86354, 85866, 77027, 86353, 86352, 86352, 76953, 74238, 85915, 86352, 86352, 86354, 82752, 86353, 86352, 86353, 73268, 86352, 89950, 86353, 86352, 35419, null], + }, + timestamps: ["2024-09-30T22:00:00Z", "2024-10-01T22:00:00Z", "2024-10-02T22:00:00Z", "2024-10-03T22:00:00Z", "2024-10-04T22:00:00Z", "2024-10-05T22:00:00Z", "2024-10-06T22:00:00Z", "2024-10-07T22:00:00Z", "2024-10-08T22:00:00Z", "2024-10-09T22:00:00Z", "2024-10-10T22:00:00Z", "2024-10-11T22:00:00Z", "2024-10-12T22:00:00Z", "2024-10-13T22:00:00Z", "2024-10-14T22:00:00Z", "2024-10-15T22:00:00Z", "2024-10-16T22:00:00Z", "2024-10-17T22:00:00Z", "2024-10-18T22:00:00Z", "2024-10-19T22:00:00Z", "2024-10-20T22:00:00Z", "2024-10-21T22:00:00Z", "2024-10-22T22:00:00Z", "2024-10-23T22:00:00Z", "2024-10-24T22:00:00Z", "2024-10-25T22:00:00Z", "2024-10-26T22:00:00Z", "2024-10-27T23:00:00Z", "2024-10-28T23:00:00Z", "2024-10-29T23:00:00Z", "2024-10-30T23:00:00Z"], + }), + }; +} diff --git a/ui/src/app/edge/history/Controller/Io/heatpump/chart/chart.spec.ts b/ui/src/app/edge/history/Controller/Io/heatpump/chart/chart.spec.ts new file mode 100644 index 00000000000..e8d9daf86a7 --- /dev/null +++ b/ui/src/app/edge/history/Controller/Io/heatpump/chart/chart.spec.ts @@ -0,0 +1,80 @@ +// @ts-strict-ignore +import { TimeUnit } from "chart.js"; +import { DATA, LABELS } from "src/app/edge/history/common/energy/chart/chart.constants.spec"; + +import { DummyConfig } from "src/app/shared/components/edge/edgeconfig.spec"; +import { OeTester } from "src/app/shared/components/shared/testing/common"; +import { OeChartTester } from "src/app/shared/components/shared/testing/tester"; +import { TestContext, TestingUtils } from "src/app/shared/components/shared/testing/utils.spec"; +import { ChartAxis } from "src/app/shared/service/utils"; +import { ChartConstants } from "src/app/shared/shared"; +import { History, expectView } from "./chart.constants.spec"; + +describe("History Heatpump", () => { + + const config = DummyConfig.from( + DummyConfig.Component.HEAT_PUMP_SG_READY("ctrlIoHeatPump0", "Wärmepumpe"), + ); + + let TEST_CONTEXT: TestContext; + beforeEach(async () => + TEST_CONTEXT = await TestingUtils.sharedSetup(), + ); + + it("#getChartData()", () => { + { + // Line-Chart + expectView(config, Object.values(config.components)[0], TEST_CONTEXT, "line", History.DAY, + { + datasets: { + data: [ + DATA("Zustand", [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 2, 1, 2, 2, 2, 1, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]), + ], + labels: LABELS(History.DAY.dataChannelWithValues.result.timestamps), + options: LINE_CHART_OPTIONS("hour", "line", { + [ChartAxis.LEFT]: { scale: { beginAtZero: true } }, + }), + }, + }); + } + { + // Line-Chart + expectView(config, Object.values(config.components)[0], TEST_CONTEXT, "bar", History.MONTH, + { + datasets: { + data: [ + DATA("Sperre", [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, null]), + DATA("Normalbetrieb", [86353, 86353, 86354, 86353, 86352, 71428, 86353, 86352, 86354, 85866, 77027, 86353, 86352, 86352, 76953, 74238, 85915, 86352, 86352, 86354, 82752, 86353, 86352, 86353, 73268, 86352, 89950, 86353, 86352, 35419, null]), + DATA("Einschaltempfehlung", [0, 0, 0, 0, 0, 5396, 0, 0, 0, 0, 5395, 0, 0, 0, 3597, 3597, 0, 0, 0, 0, 1798, 0, 0, 0, 7194, 0, 0, 0, 0, 0, null]), + DATA("Einschaltbefehl", [0, 0, 0, 0, 0, 9519, 0, 0, 0, 0, 3921, 0, 0, 0, 5795, 8510, 0, 0, 0, 0, 1798, 0, 0, 0, 5883, 0, 0, 0, 0, 0, null]), + ], + labels: LABELS(History.MONTH.energyPerPeriodChannelWithValues.result.timestamps), + options: OeTester.ChartOptions.BAR_CHART_OPTIONS("day", "bar", {}, "Aktive Zeit"), + }, + }); + } + }); +}); + +export const LINE_CHART_OPTIONS = (period: string, chartType: "line" | "bar", options: { [key: string]: { scale: { min?: number, max?: number, beginAtZero?: boolean }, ticks?: { stepSize: number; min?: number, max?: number }; }; }): OeChartTester.Dataset.Option => ({ + type: "option", + options: { + "responsive": true, "maintainAspectRatio": false, "elements": { "point": { "radius": 0, "hitRadius": 0, "hoverRadius": 0 }, "line": { "stepped": false, "fill": true } }, "datasets": { "bar": {}, "line": {} }, "plugins": { + "colors": { "enabled": false }, "legend": { "display": true, "position": "bottom", "labels": { "color": "" } }, "tooltip": { "intersect": false, "mode": "index", "callbacks": {}, "enabled": true }, "annotation": { "annotations": {} }, "datalabels": { + display: false, + }, + }, "scales": { + "x": { "stacked": true, "offset": false, "type": "time", "ticks": { "source": "auto", "maxTicksLimit": 31 }, "bounds": "ticks", "adapters": { "date": { "locale": { "code": "de", "formatLong": {}, "localize": {}, "match": {}, "options": { "weekStartsOn": 1, "firstWeekContainsDate": 4 } } } }, "time": { "unit": period as TimeUnit, "displayFormats": { "datetime": "yyyy-MM-dd HH:mm:ss", "millisecond": "SSS [ms]", "second": "HH:mm:ss a", "minute": "HH:mm", "hour": "HH:00", "day": "dd", "week": "ll", "month": "MM", "quarter": "[Q]Q - YYYY", "year": "yyyy" } } }, + "left": { + "stacked": false, + "beginAtZero": false, ...options["left"]?.scale, ...(chartType === "line" ? { stacked: false } : {}), "title": { "text": "kW", "display": false, "padding": 5, "font": { "size": 11 } }, "position": "left", "grid": { "display": true }, + "ticks": { + ...options["left"]?.ticks, + "color": "", + "padding": 5, + "maxTicksLimit": ChartConstants.NUMBER_OF_Y_AXIS_TICKS, + }, + }, + }, + }, +}); diff --git a/ui/src/app/edge/history/Controller/Io/heatpump/chart/chart.ts b/ui/src/app/edge/history/Controller/Io/heatpump/chart/chart.ts new file mode 100644 index 00000000000..3ebef104904 --- /dev/null +++ b/ui/src/app/edge/history/Controller/Io/heatpump/chart/chart.ts @@ -0,0 +1,171 @@ +import { CommonModule } from "@angular/common"; +import { Component } from "@angular/core"; +import { ReactiveFormsModule } from "@angular/forms"; +import { IonicModule } from "@ionic/angular"; +import { TranslateModule, TranslateService } from "@ngx-translate/core"; +import { BaseChartDirective } from "ng2-charts"; +import { NgxSpinnerModule } from "ngx-spinner"; +import { AbstractHistoryChart } from "src/app/shared/components/chart/abstracthistorychart"; +import { ChartConstants } from "src/app/shared/components/chart/chart.constants"; +import { ChartComponentsModule } from "src/app/shared/components/chart/chart.module"; +import { HistoryDataErrorModule } from "src/app/shared/components/history-data-error/history-data-error.module"; +import { QueryHistoricTimeseriesEnergyResponse } from "src/app/shared/jsonrpc/response/queryHistoricTimeseriesEnergyResponse"; +import { DefaultTypes } from "src/app/shared/service/defaulttypes"; +import { ChartAxis, HistoryUtils, Utils, YAxisType } from "src/app/shared/service/utils"; +import { ChannelAddress, EdgeConfig } from "src/app/shared/shared"; +import { ArrayUtils } from "src/app/shared/utils/array/array.utils"; +import { AssertionUtils } from "src/app/shared/utils/assertions/assertions-utils"; + +@Component({ + selector: "controller-io-heatpump-chart", + templateUrl: "../../../../../../shared/components/chart/abstracthistorychart.html", + standalone: true, + imports: [ + BaseChartDirective, + ReactiveFormsModule, + CommonModule, + IonicModule, + TranslateModule, + ChartComponentsModule, + HistoryDataErrorModule, + NgxSpinnerModule, + ], +}) +export class ChartComponent extends AbstractHistoryChart { + + public static getChartData(component: EdgeConfig.Component | undefined, translate: TranslateService, chartType: "line" | "bar", periodString: DefaultTypes.PeriodString): HistoryUtils.ChartData { + AssertionUtils.assertIsDefined(component); + const input: HistoryUtils.InputChannel[] = [ + { name: "Status", powerChannel: new ChannelAddress(component.id, "Status") }, + { name: "ForceOnStateTime", energyChannel: new ChannelAddress(component.id, "ForceOnStateTime") }, + { name: "LockStateTime", energyChannel: new ChannelAddress(component.id, "LockStateTime") }, + { name: "RecommendationStateTime", energyChannel: new ChannelAddress(component.id, "RecommendationStateTime") }, + { name: "RegularStateTime", energyChannel: new ChannelAddress(component.id, "RegularStateTime") }, + ]; + return { + input: input, + output: (rawData: HistoryUtils.ChannelData) => { + let data = rawData; + if (chartType === "line") { + return [{ + name: translate.instant("General.state"), + converter: () => data["Status"]?.map(val => Utils.multiplySafely(val, 1000)), + color: ChartConstants.Colors.RED, + stack: 0, + }]; + } + + data = ChartComponent.sanitizeData(rawData, periodString); + return [ + { + name: translate.instant("Edge.Index.Widgets.HeatPump.lock"), + nameSuffix: (energyValues: QueryHistoricTimeseriesEnergyResponse) => energyValues?.result.data[component.id + "/LockStateTime"], + converter: () => data["LockStateTime"], + color: ChartConstants.Colors.DARK_GREY, + stack: 0, + }, + { + name: translate.instant("Edge.Index.Widgets.HeatPump.normalOperation"), + nameSuffix: (energyValues: QueryHistoricTimeseriesEnergyResponse) => energyValues?.result.data[component.id + "/RegularStateTime"], + converter: () => data["RegularStateTime"], + color: ChartConstants.Colors.YELLOW, + stack: 0, + }, { + name: translate.instant("Edge.Index.Widgets.HeatPump.switchOnRec"), + nameSuffix: (energyValues: QueryHistoricTimeseriesEnergyResponse) => energyValues?.result.data[component.id + "/RecommendationStateTime"], + converter: () => data["RecommendationStateTime"], + color: ChartConstants.Colors.ORANGE, + stack: 0, + }, { + name: translate.instant("Edge.Index.Widgets.HeatPump.switchOnCom"), + nameSuffix: (energyValues: QueryHistoricTimeseriesEnergyResponse) => { + return energyValues?.result.data[component.id + "/ForceOnStateTime"]; + }, + converter: () => data["ForceOnStateTime"], + color: ChartConstants.Colors.RED, + stack: 0, + }]; + }, + tooltip: { + formatNumber: ChartConstants.NumberFormat.NO_DECIMALS, + }, + yAxes: [{ + unit: chartType === "line" ? YAxisType.HEAT_PUMP : YAxisType.TIME, + position: "left", + yAxisId: ChartAxis.LEFT, + }], + }; + } + + /** + * Converts the number to have a max value + * + * @param value the value + * @param atMost the max number to be allowed + * @returns the value + */ + private static CONVERT_NUMBER_TO_BE_AT_MOST = (value: number | null, atMost: number) => { + if (value == null) { + return value; + } + return Math.min(value, atMost); + }; + + /** + * Sanitizes channel data + * + * @param rawData the rawData + * @param period the current period + * @returns the sanitized channelData + */ + private static sanitizeData(rawData: HistoryUtils.ChannelData, period: DefaultTypes.PeriodString): HistoryUtils.ChannelData { + + const ONE_DAY_IN_S = 86400; + const ONE_HOUR = 60 * 60; + const DAY_MINUS_ONE_MINUTE_IN_S = 86340; + const channelData: HistoryUtils.ChannelData = {}; + + const summarizedData = ArrayUtils.summarizeValuesByIndex(rawData).map(el => Utils.multiplySafely(el, 1000)); + for (let i = 0; i < Object.keys(rawData).length; i++) { + const [key, arr] = Object.entries(rawData)[i]; + let data: (number | null)[] = arr.map(el => Utils.multiplySafely(el, 1000)); + + // Only adjust regular state time if it doesnt add up to full days, months ... + if (key !== "RegularStateTime") { + channelData[key] = data as number[]; + continue; + } + + switch (period) { + case DefaultTypes.PeriodString.MONTH: + data = data.map((el, index) => { + if (el == null) { + return null; + } + const diff: number = Utils.orElse(Utils.subtractSafely(ONE_DAY_IN_S, summarizedData[index]), 0) as number; + return ChartComponent.CONVERT_NUMBER_TO_BE_AT_MOST(summarizedData[index] > DAY_MINUS_ONE_MINUTE_IN_S ? Utils.addSafely(el, diff) : el, ONE_DAY_IN_S); + }); + break; + case DefaultTypes.PeriodString.YEAR: + data = data.map((el, index) => { + if (el == null) { + return null; + } + + const daysInMonth = Utils.floorSafely(Utils.divideSafely(el, ONE_DAY_IN_S)) as number; + const MONTH_IN_S = Utils.multiplySafely(daysInMonth + 1, ONE_DAY_IN_S); + const MONTH_MINUS_ONE_HOUR = Utils.orElse(Utils.subtractSafely(Utils.multiplySafely(daysInMonth + 1, ONE_DAY_IN_S), ONE_HOUR), MONTH_IN_S); + const diff = Utils.subtractSafely(MONTH_IN_S, summarizedData[index]); + return ChartComponent.CONVERT_NUMBER_TO_BE_AT_MOST(summarizedData[index] > MONTH_MINUS_ONE_HOUR ? Utils.addSafely(el, diff) : el, MONTH_IN_S); + }); + break; + } + channelData[key] = data as number[]; + } + return channelData; + } + + protected override getChartData(): HistoryUtils.ChartData { + return ChartComponent.getChartData(this.component, this.translate, this.chartType, this.service.periodString); + } +} diff --git a/ui/src/app/edge/history/Controller/Io/heatpump/flat/flat.html b/ui/src/app/edge/history/Controller/Io/heatpump/flat/flat.html new file mode 100644 index 00000000000..a8d993c55b9 --- /dev/null +++ b/ui/src/app/edge/history/Controller/Io/heatpump/flat/flat.html @@ -0,0 +1,18 @@ + + + + + + + + + + diff --git a/ui/src/app/edge/history/Controller/Io/heatpump/flat/flat.ts b/ui/src/app/edge/history/Controller/Io/heatpump/flat/flat.ts new file mode 100644 index 00000000000..95549abc88d --- /dev/null +++ b/ui/src/app/edge/history/Controller/Io/heatpump/flat/flat.ts @@ -0,0 +1,13 @@ +import { Component } from "@angular/core"; +import { AbstractFlatWidget } from "src/app/shared/components/flat/abstract-flat-widget"; +import { Filter } from "src/app/shared/components/shared/filter"; + +@Component({ + selector: "controller-io-heatpump-widget", + templateUrl: "./flat.html", + standalone: false, +}) +export class FlatComponent extends AbstractFlatWidget { + protected FORMAT_SECONDS_TO_DURATION = this.Converter.FORMAT_SECONDS_TO_DURATION(this.translate.currentLang); + protected FILTER_NULL_WITH_THRESHOLD: Filter = (value: number | string | null): boolean => value !== null && Number.isFinite(value) && value as number > 59; +} diff --git a/ui/src/app/edge/history/Controller/Io/heatpump/heat-pump.module.ts b/ui/src/app/edge/history/Controller/Io/heatpump/heat-pump.module.ts new file mode 100644 index 00000000000..93c4ee383c9 --- /dev/null +++ b/ui/src/app/edge/history/Controller/Io/heatpump/heat-pump.module.ts @@ -0,0 +1,44 @@ +import { CommonModule } from "@angular/common"; +import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from "@angular/core"; +import { ReactiveFormsModule } from "@angular/forms"; +import { RouterModule, Routes } from "@angular/router"; +import { IonicModule } from "@ionic/angular"; +import { TranslateModule } from "@ngx-translate/core"; +import { NgxSpinnerModule } from "ngx-spinner"; +import { HistoryDataErrorModule } from "src/app/shared/components/history-data-error/history-data-error.module"; +import { PickdateComponentModule } from "src/app/shared/components/pickdate/pickdate.module"; +import { FlatComponent } from "./flat/flat"; +import { OverviewComponent } from "./overview/overview"; + +const routes: Routes = [ + { + path: "", + component: OverviewComponent, + }, +]; + +@NgModule({ + imports: [ + ReactiveFormsModule, + CommonModule, + IonicModule, + TranslateModule, + PickdateComponentModule, + RouterModule.forChild(routes), + HistoryDataErrorModule, + NgxSpinnerModule, + ], + declarations: [ + FlatComponent, + ], + exports: [ + FlatComponent, + RouterModule, + ], + schemas: [ + CUSTOM_ELEMENTS_SCHEMA, + ], +}) +export class HeatPumpModule { +} + diff --git a/ui/src/app/edge/history/Controller/Io/heatpump/overview/overview.html b/ui/src/app/edge/history/Controller/Io/heatpump/overview/overview.html new file mode 100644 index 00000000000..1b8579961b5 --- /dev/null +++ b/ui/src/app/edge/history/Controller/Io/heatpump/overview/overview.html @@ -0,0 +1,8 @@ + + + + @if (chartType === "line") { + + } + diff --git a/ui/src/app/edge/history/Controller/Io/heatpump/overview/overview.ts b/ui/src/app/edge/history/Controller/Io/heatpump/overview/overview.ts new file mode 100644 index 00000000000..907949df827 --- /dev/null +++ b/ui/src/app/edge/history/Controller/Io/heatpump/overview/overview.ts @@ -0,0 +1,61 @@ +import { CommonModule } from "@angular/common"; +import { Component, LOCALE_ID } from "@angular/core"; +import { ReactiveFormsModule } from "@angular/forms"; +import { ActivatedRoute } from "@angular/router"; +import { IonicModule, ModalController } from "@ionic/angular"; +import { TranslateModule, TranslateService } from "@ngx-translate/core"; +import { AbstractHistoryChartOverview } from "src/app/shared/components/chart/abstractHistoryChartOverview"; +import { ChartComponentsModule } from "src/app/shared/components/chart/chart.module"; +import { ChartTypes } from "src/app/shared/components/chart/chart.types"; +import { HistoryDataErrorModule } from "src/app/shared/components/history-data-error/history-data-error.module"; +import { PickdateComponentModule } from "src/app/shared/components/pickdate/pickdate.module"; +import { Service } from "src/app/shared/shared"; +import { Language } from "src/app/shared/type/language"; +import { ChartComponent } from "../chart/chart"; +import tr from "./translation.json"; +@Component({ + selector: "controller-io-heatpump-overview", + templateUrl: "./overview.html", + standalone: true, + imports: [ + ReactiveFormsModule, + CommonModule, + IonicModule, + TranslateModule, + ChartComponentsModule, + PickdateComponentModule, + HistoryDataErrorModule, + ChartComponent, + ], + providers: [ + { provide: LOCALE_ID, useFactory: () => (Language.getByKey(localStorage.LANGUAGE) ?? Language.getByBrowserLang(navigator.language) ?? Language.DEFAULT).key }, + + ], +}) +export class OverviewComponent extends AbstractHistoryChartOverview { + + protected readonly STATES: string = ` + 1.${this.translate.instant("Edge.Index.Widgets.HeatPump.lock")} + 2.${this.translate.instant("Edge.Index.Widgets.HeatPump.normalOperation")} + 3.${this.translate.instant("Edge.Index.Widgets.HeatPump.switchOnRec")} + 4.${this.translate.instant("Edge.Index.Widgets.HeatPump.switchOnCom")} + `; + protected chartType: "line" | "bar" = "line"; + + constructor( + public override service: Service, + protected override route: ActivatedRoute, + public override modalCtrl: ModalController, + private translate: TranslateService, + ) { + super(service, route, modalCtrl); + Language.setAdditionalTranslationFile(tr, this.translate).then(({ lang, translations, shouldMerge }) => { + this.translate.setTranslation(lang, translations, shouldMerge); + }); + } + + protected setChartConfig(event: ChartTypes.ChartConfig) { + this.chartType = event.chartType; + } + +} diff --git a/ui/src/app/edge/history/Controller/Io/heatpump/overview/translation.json b/ui/src/app/edge/history/Controller/Io/heatpump/overview/translation.json new file mode 100644 index 00000000000..a2a9ff9ca67 --- /dev/null +++ b/ui/src/app/edge/history/Controller/Io/heatpump/overview/translation.json @@ -0,0 +1,8 @@ +{ + "de": { + "LEGEND_DESCRIPTION": "Legende Betriebszustand" + }, + "en": { + "LEGEND_DESCRIPTION": "Legend operating status" + } +} diff --git a/ui/src/app/edge/history/Controller/ModbusTcpApi/overview/overview.html b/ui/src/app/edge/history/Controller/ModbusTcpApi/overview/overview.html index c08da36f604..db62436e5d5 100644 --- a/ui/src/app/edge/history/Controller/ModbusTcpApi/overview/overview.html +++ b/ui/src/app/edge/history/Controller/ModbusTcpApi/overview/overview.html @@ -1,23 +1,23 @@

    - - - - - - - Edge.Index.Widgets.InfoStorageForCharge - - - - - Edge.Index.Widgets.InfoStorageForDischarge - - - - - -
    - + + + + + + + Edge.Index.Widgets.InfoStorageForCharge + + + + + Edge.Index.Widgets.InfoStorageForDischarge + + + + + + + diff --git a/ui/src/app/edge/history/abstracthistorychart.ts b/ui/src/app/edge/history/abstracthistorychart.ts index 00e9bf4a256..a9968fcf779 100644 --- a/ui/src/app/edge/history/abstracthistorychart.ts +++ b/ui/src/app/edge/history/abstracthistorychart.ts @@ -116,7 +116,6 @@ export abstract class AbstractHistoryChart { public setOptions(options: Chart.ChartOptions): Promise { return new Promise((resolve) => { - const locale = this.service.translate.currentLang; const yAxis: HistoryUtils.yAxes = { position: "left", unit: this.unit, yAxisId: ChartAxis.LEFT }; const chartObject: HistoryUtils.ChartData = { input: [], @@ -153,7 +152,7 @@ export abstract class AbstractHistoryChart { const value = tooltipItem.dataset.data[tooltipItem.dataIndex]; const customUnit = tooltipItem.dataset.unit ?? null; - return label.split(":")[0] + ": " + NewAbstractHistoryChart.getToolTipsSuffix("", value, formatNumber, customUnit ?? unit, "line", locale, translate, conf); + return label.split(":")[0] + ": " + NewAbstractHistoryChart.getToolTipsSuffix("", value, formatNumber, customUnit ?? unit, "line", translate, conf); }; options.plugins.tooltip.callbacks.labelColor = (item: Chart.TooltipItem) => { @@ -247,7 +246,7 @@ export abstract class AbstractHistoryChart { }); // Only one yAxis defined - options = NewAbstractHistoryChart.getYAxisOptions(options, yAxis, this.translate, "line", locale, this.datasets, true); + options = NewAbstractHistoryChart.getYAxisOptions(options, yAxis, this.translate, "line", this.datasets, true); options = NewAbstractHistoryChart.applyChartTypeSpecificOptionsChanges("line", options, this.service, chartObject); options.scales[ChartAxis.LEFT]["stacked"] = false; options.scales.x["stacked"] = true; diff --git a/ui/src/app/edge/history/chpsoc/chpsocchartoverview/chpsocchartoverview.component.html b/ui/src/app/edge/history/chpsoc/chpsocchartoverview/chpsocchartoverview.component.html index 44ed82a5b13..0b45e3d0298 100644 --- a/ui/src/app/edge/history/chpsoc/chpsocchartoverview/chpsocchartoverview.component.html +++ b/ui/src/app/edge/history/chpsoc/chpsocchartoverview/chpsocchartoverview.component.html @@ -4,7 +4,7 @@ {{ component.alias }} - + diff --git a/ui/src/app/edge/history/shared.ts b/ui/src/app/edge/history/shared.ts index c946f9b6b3c..0311f8c4b2d 100644 --- a/ui/src/app/edge/history/shared.ts +++ b/ui/src/app/edge/history/shared.ts @@ -1,10 +1,10 @@ // @ts-strict-ignore import * as Chart from "chart.js"; -/* eslint-disable import/no-duplicates */ + // cf. https://github.com/import-js/eslint-plugin-import/issues/1479 import { differenceInDays, differenceInMinutes, startOfDay } from "date-fns"; import { de } from "date-fns/locale"; -/* eslint-enable import/no-duplicates */ + import { QueryHistoricTimeseriesDataResponse } from "src/app/shared/jsonrpc/response/queryHistoricTimeseriesDataResponse"; import { ChannelAddress, Service } from "src/app/shared/shared"; import { DateUtils } from "src/app/shared/utils/date/dateutils"; diff --git a/ui/src/app/edge/history/storage/singlechart.component.ts b/ui/src/app/edge/history/storage/singlechart.component.ts index 8be7f1ec9ce..573f7145b0e 100644 --- a/ui/src/app/edge/history/storage/singlechart.component.ts +++ b/ui/src/app/edge/history/storage/singlechart.component.ts @@ -6,6 +6,7 @@ import { TranslateService } from "@ngx-translate/core"; import * as Chart from "chart.js"; import { DefaultTypes } from "src/app/shared/service/defaulttypes"; import { ChartAxis, YAxisType } from "src/app/shared/service/utils"; +import { Language } from "src/app/shared/type/language"; import { ObjectUtils } from "src/app/shared/utils/object/object.utils"; import { ChannelAddress, Edge, EdgeConfig, Service, Utils } from "../../../shared/shared"; @@ -210,6 +211,7 @@ export class StorageSingleChartComponent extends AbstractHistoryChart implements private applyControllerSpecificChartOptions(options: Chart.ChartOptions) { const translate = this.translate; + const locale: string = (Language.getByKey(localStorage.LANGUAGE) ?? Language.DEFAULT).i18nLocaleKey; options.scales[ChartAxis.LEFT].min = null; options.plugins.tooltip.callbacks.label = function (tooltipItem: Chart.TooltipItem) { @@ -229,7 +231,7 @@ export class StorageSingleChartComponent extends AbstractHistoryChart implements label = translate.instant("General.DISCHARGE"); } } - return label + ": " + formatNumber(value, "de", "1.0-2") + " kW"; + return label + ": " + formatNumber(value, locale, "1.0-2") + " kW"; }; // Data doesnt have all datapoints for period diff --git a/ui/src/app/edge/history/storage/storagechartoverview/storagechartoverview.component.html b/ui/src/app/edge/history/storage/storagechartoverview/storagechartoverview.component.html index e145a52ca1e..3377d42d37a 100644 --- a/ui/src/app/edge/history/storage/storagechartoverview/storagechartoverview.component.html +++ b/ui/src/app/edge/history/storage/storagechartoverview/storagechartoverview.component.html @@ -1,4 +1,24 @@ + + + + + + + + + + Edge.Index.Widgets.InfoStorageForCharge + + + Edge.Index.Widgets.InfoStorageForDischarge + + + + + + + General.TOTAL - - - - - - - - - - Edge.Index.Widgets.InfoStorageForCharge - - - - - Edge.Index.Widgets.InfoStorageForDischarge - - - - - + + @@ -69,26 +71,7 @@ - - - - - - - - - Edge.Index.Widgets.InfoStorageForCharge - - - - - Edge.Index.Widgets.InfoStorageForDischarge - - - - - - + @@ -113,26 +96,7 @@ [componentId]="component.id"> - - - - - - - - - Edge.Index.Widgets.InfoStorageForCharge - - - - - Edge.Index.Widgets.InfoStorageForDischarge - - - - - - + diff --git a/ui/src/app/edge/history/storage/totalchart.component.ts b/ui/src/app/edge/history/storage/totalchart.component.ts index 452cae7557b..4be181bc8fa 100644 --- a/ui/src/app/edge/history/storage/totalchart.component.ts +++ b/ui/src/app/edge/history/storage/totalchart.component.ts @@ -7,6 +7,7 @@ import * as Chart from "chart.js"; import { DefaultTypes } from "src/app/shared/service/defaulttypes"; import { ChartAxis, Utils, YAxisType } from "src/app/shared/service/utils"; import { ChannelAddress, Edge, EdgeConfig, Service } from "src/app/shared/shared"; +import { Language } from "src/app/shared/type/language"; import { ObjectUtils } from "src/app/shared/utils/object/object.utils"; import { AbstractHistoryChart } from "../abstracthistorychart"; @@ -248,6 +249,7 @@ export class StorageTotalChartComponent extends AbstractHistoryChart implements private applyControllerSpecificChartOptions(options: Chart.ChartOptions) { const translate = this.translate; + const locale: string = (Language.getByKey(localStorage.LANGUAGE) ?? Language.DEFAULT).i18nLocaleKey; options.scales[ChartAxis.LEFT].min = null; options.plugins.tooltip.callbacks.label = function (tooltipItem: Chart.TooltipItem) { @@ -259,7 +261,7 @@ export class StorageTotalChartComponent extends AbstractHistoryChart implements } else if (value > 0.005) { label += " " + translate.instant("General.DISCHARGE"); } - return label + ": " + formatNumber(value, "de", "1.0-2") + " kW"; + return label + ": " + formatNumber(value, locale, "1.0-2") + " kW"; }; } } diff --git a/ui/src/app/edge/live/Controller/ChpSoc/modal/modal.component.html b/ui/src/app/edge/live/Controller/ChpSoc/modal/modal.component.html index 5d70991a5f3..9446a8a4b84 100644 --- a/ui/src/app/edge/live/Controller/ChpSoc/modal/modal.component.html +++ b/ui/src/app/edge/live/Controller/ChpSoc/modal/modal.component.html @@ -4,7 +4,7 @@ - + diff --git a/ui/src/app/edge/live/Controller/Ess/TimeOfUseTariff/modal/powerSocChart.ts b/ui/src/app/edge/live/Controller/Ess/TimeOfUseTariff/modal/powerSocChart.ts index 1814b01ed84..0d19eab02ba 100644 --- a/ui/src/app/edge/live/Controller/Ess/TimeOfUseTariff/modal/powerSocChart.ts +++ b/ui/src/app/edge/live/Controller/Ess/TimeOfUseTariff/modal/powerSocChart.ts @@ -206,10 +206,9 @@ export class SchedulePowerAndSocChartComponent extends AbstractHistoryChart impl private applyControllerSpecificOptions() { const rightYAxis: HistoryUtils.yAxes = { position: "right", unit: YAxisType.PERCENTAGE, yAxisId: ChartAxis.RIGHT }; const leftYAxis: HistoryUtils.yAxes = { position: "left", unit: YAxisType.POWER, yAxisId: ChartAxis.LEFT }; - const locale = this.service.translate.currentLang; - this.options = NewAbstractHistoryChart.getYAxisOptions(this.options, rightYAxis, this.translate, "line", locale, ChartConstants.EMPTY_DATASETS, true); - this.options = NewAbstractHistoryChart.getYAxisOptions(this.options, leftYAxis, this.translate, "line", locale, ChartConstants.EMPTY_DATASETS, true); + this.options = NewAbstractHistoryChart.getYAxisOptions(this.options, rightYAxis, this.translate, "line", ChartConstants.EMPTY_DATASETS, true); + this.options = NewAbstractHistoryChart.getYAxisOptions(this.options, leftYAxis, this.translate, "line", ChartConstants.EMPTY_DATASETS, true); this.datasets = this.datasets.map((el: Chart.ChartDataset) => { diff --git a/ui/src/app/edge/live/Controller/Ess/TimeOfUseTariff/modal/statePriceChart.ts b/ui/src/app/edge/live/Controller/Ess/TimeOfUseTariff/modal/statePriceChart.ts index 1b10751ca53..6e348cd5ea8 100644 --- a/ui/src/app/edge/live/Controller/Ess/TimeOfUseTariff/modal/statePriceChart.ts +++ b/ui/src/app/edge/live/Controller/Ess/TimeOfUseTariff/modal/statePriceChart.ts @@ -114,12 +114,11 @@ export class ScheduleStateAndPriceChartComponent extends AbstractHistoryChart im } private applyControllerSpecificOptions() { - const locale = this.service.translate.currentLang; const rightYaxisSoc: HistoryUtils.yAxes = { position: "right", unit: YAxisType.PERCENTAGE, yAxisId: ChartAxis.RIGHT, displayGrid: true }; - this.options = NewAbstractHistoryChart.getYAxisOptions(this.options, rightYaxisSoc, this.translate, "line", locale, this.datasets, true); + this.options = NewAbstractHistoryChart.getYAxisOptions(this.options, rightYaxisSoc, this.translate, "line", this.datasets, true); const rightYAxisPower: HistoryUtils.yAxes = { position: "right", unit: YAxisType.POWER, yAxisId: ChartAxis.RIGHT_2 }; - this.options = NewAbstractHistoryChart.getYAxisOptions(this.options, rightYAxisPower, this.translate, "line", locale, this.datasets, true); + this.options = NewAbstractHistoryChart.getYAxisOptions(this.options, rightYAxisPower, this.translate, "line", this.datasets, true); this.options.scales.x["time"].unit = calculateResolution(this.service, this.service.historyPeriod.value.from, this.service.historyPeriod.value.to).timeFormat; this.options.scales.x["ticks"] = { source: "auto", autoSkip: false }; @@ -176,7 +175,7 @@ export class ScheduleStateAndPriceChartComponent extends AbstractHistoryChart im }); const leftYAxis: HistoryUtils.yAxes = { position: "left", unit: this.unit, yAxisId: ChartAxis.LEFT, customTitle: this.currencyUnit, scale: { dynamicScale: true } }; [rightYaxisSoc, rightYAxisPower].forEach((element) => { - this.options = NewAbstractHistoryChart.getYAxisOptions(this.options, element, this.translate, "line", locale, this.datasets, true); + this.options = NewAbstractHistoryChart.getYAxisOptions(this.options, element, this.translate, "line", this.datasets, true); }); this.options.scales[ChartAxis.LEFT] = { diff --git a/ui/src/app/edge/live/Controller/Evcs/administration/administration.component.html b/ui/src/app/edge/live/Controller/Evcs/administration/administration.component.html index 6d2c10d1903..d0278987eb2 100644 --- a/ui/src/app/edge/live/Controller/Evcs/administration/administration.component.html +++ b/ui/src/app/edge/live/Controller/Evcs/administration/administration.component.html @@ -5,7 +5,7 @@ - + diff --git a/ui/src/app/edge/live/Controller/Io/ChannelSingleThreshold/modal/modal.component.html b/ui/src/app/edge/live/Controller/Io/ChannelSingleThreshold/modal/modal.component.html index 49b85982a56..a3848ec9ec9 100644 --- a/ui/src/app/edge/live/Controller/Io/ChannelSingleThreshold/modal/modal.component.html +++ b/ui/src/app/edge/live/Controller/Io/ChannelSingleThreshold/modal/modal.component.html @@ -5,7 +5,7 @@ - + diff --git a/ui/src/app/edge/live/Controller/Io/FixDigitalOutput/modal/modal.component.html b/ui/src/app/edge/live/Controller/Io/FixDigitalOutput/modal/modal.component.html index b95fc16e6cf..e4d26da7802 100644 --- a/ui/src/app/edge/live/Controller/Io/FixDigitalOutput/modal/modal.component.html +++ b/ui/src/app/edge/live/Controller/Io/FixDigitalOutput/modal/modal.component.html @@ -5,7 +5,7 @@ - + diff --git a/ui/src/app/edge/live/Controller/Io/HeatingRoom/Io_HeatingRoom.ts b/ui/src/app/edge/live/Controller/Io/HeatingRoom/Io_HeatingRoom.ts new file mode 100644 index 00000000000..e85376069e3 --- /dev/null +++ b/ui/src/app/edge/live/Controller/Io/HeatingRoom/Io_HeatingRoom.ts @@ -0,0 +1,20 @@ +import { NgModule } from "@angular/core"; +import { BrowserModule } from "@angular/platform-browser"; +import { SharedModule } from "src/app/shared/shared.module"; +import { FlatComponent } from "./flat/flat"; +import { ModalComponent } from "./modal/modal"; + +@NgModule({ + imports: [ + BrowserModule, + SharedModule, + ], + declarations: [ + FlatComponent, + ModalComponent, + ], + exports: [ + FlatComponent, + ], +}) +export class Controller_Io_HeatingRoom { } diff --git a/ui/src/app/edge/live/Controller/Io/HeatingRoom/flat/flat.html b/ui/src/app/edge/live/Controller/Io/HeatingRoom/flat/flat.html new file mode 100644 index 00000000000..f9631d92b80 --- /dev/null +++ b/ui/src/app/edge/live/Controller/Io/HeatingRoom/flat/flat.html @@ -0,0 +1,14 @@ + + + + + + + + + + diff --git a/ui/src/app/edge/live/Controller/Io/HeatingRoom/flat/flat.ts b/ui/src/app/edge/live/Controller/Io/HeatingRoom/flat/flat.ts new file mode 100644 index 00000000000..21c5c3e2893 --- /dev/null +++ b/ui/src/app/edge/live/Controller/Io/HeatingRoom/flat/flat.ts @@ -0,0 +1,21 @@ +import { Component } from "@angular/core"; +import { AbstractFlatWidget } from "src/app/shared/components/flat/abstract-flat-widget"; +import { ModalComponent } from "../modal/modal"; + +@Component({ + selector: "oe-controller-io-heating-room", + templateUrl: "./flat.html", + standalone: false, +}) +export class FlatComponent extends AbstractFlatWidget { + + async presentModal() { + const modal = await this.modalController.create({ + component: ModalComponent, + componentProps: { + component: this.component, + }, + }); + return await modal.present(); + } +} diff --git a/ui/src/app/edge/live/Controller/Io/HeatingRoom/modal/modal.html b/ui/src/app/edge/live/Controller/Io/HeatingRoom/modal/modal.html new file mode 100644 index 00000000000..24173aeb907 --- /dev/null +++ b/ui/src/app/edge/live/Controller/Io/HeatingRoom/modal/modal.html @@ -0,0 +1,40 @@ + + + + + + @if (formGroup.value.mode !== 'OFF') { + + + } + + + + + + @if (formGroup.value.mode !== 'OFF') { + + } + + + + @if (formGroup.value.mode !== 'OFF') { + + } + + @if (formGroup.value.mode === 'AUTOMATIC') { + + + + + } + diff --git a/ui/src/app/edge/live/Controller/Io/HeatingRoom/modal/modal.ts b/ui/src/app/edge/live/Controller/Io/HeatingRoom/modal/modal.ts new file mode 100644 index 00000000000..10dcb478713 --- /dev/null +++ b/ui/src/app/edge/live/Controller/Io/HeatingRoom/modal/modal.ts @@ -0,0 +1,18 @@ +// @ts-strict-ignore +import { Component } from "@angular/core"; +import { FormControl, FormGroup } from "@angular/forms"; +import { AbstractModal } from "src/app/shared/components/modal/abstractModal"; + +@Component({ + selector: "heatingelement-modal", + templateUrl: "./modal.html", + standalone: false, +}) +export class ModalComponent extends AbstractModal { + + protected override getFormGroup(): FormGroup { + return this.formBuilder.group({ + mode: new FormControl(this.component.properties.mode), + }); + } +} diff --git a/ui/src/app/edge/live/Controller/Io/Heatpump/modal/modal.component.html b/ui/src/app/edge/live/Controller/Io/Heatpump/modal/modal.component.html index 7d3e87bb60f..230b04a9cb8 100644 --- a/ui/src/app/edge/live/Controller/Io/Heatpump/modal/modal.component.html +++ b/ui/src/app/edge/live/Controller/Io/Heatpump/modal/modal.component.html @@ -5,7 +5,7 @@ - + diff --git a/ui/src/app/edge/live/Controller/ModbusTcpApi/modal/modal.ts b/ui/src/app/edge/live/Controller/ModbusTcpApi/modal/modal.ts index c4a8ef62502..98d58510605 100644 --- a/ui/src/app/edge/live/Controller/ModbusTcpApi/modal/modal.ts +++ b/ui/src/app/edge/live/Controller/ModbusTcpApi/modal/modal.ts @@ -47,8 +47,8 @@ export class ModalComponent extends AbstractModal { }); } - protected getModbusProtocol(componentId: string) { - return this.profile.getModbusProtocol(componentId); + protected getModbusProtocol(componentId: string, type: string) { + return this.profile.getModbusProtocol(componentId, type); } protected override onCurrentData(currentData: CurrentData) { @@ -91,13 +91,14 @@ export class ModalComponent extends AbstractModal { private getFormatChannelNames(): void { this.formattedWriteChannels = []; this.writeChannels.forEach(channel => { + let formattedString = `(${channel.channelId})`; for (const registerName in ChannelRegister) { - if (channel.channelId.includes(registerName)) { - // If channelId is included in ChannelRegister, get key/value e.g. SetActivePowerEquals/706 - const formattedString = `(${registerName}/${ChannelRegister[registerName]})`; - this.formattedWriteChannels.push(formattedString); + if (channel.channelId.includes(registerName) && channel.channelId.startsWith("Ess0")) { + formattedString = `(${registerName}/${ChannelRegister[registerName]})`; + break; } } + this.formattedWriteChannels.push(formattedString); }); } } diff --git a/ui/src/app/edge/live/Controller/PeakShaving/Asymmetric/modal/modal.component.html b/ui/src/app/edge/live/Controller/PeakShaving/Asymmetric/modal/modal.component.html index 0f99848add1..7c4f27dbb61 100644 --- a/ui/src/app/edge/live/Controller/PeakShaving/Asymmetric/modal/modal.component.html +++ b/ui/src/app/edge/live/Controller/PeakShaving/Asymmetric/modal/modal.component.html @@ -4,7 +4,7 @@ {{ component.alias }} - + diff --git a/ui/src/app/edge/live/Controller/PeakShaving/Symmetric/modal/modal.component.html b/ui/src/app/edge/live/Controller/PeakShaving/Symmetric/modal/modal.component.html index 25ec2b0d9dc..2dc4aadddca 100644 --- a/ui/src/app/edge/live/Controller/PeakShaving/Symmetric/modal/modal.component.html +++ b/ui/src/app/edge/live/Controller/PeakShaving/Symmetric/modal/modal.component.html @@ -4,7 +4,7 @@ {{ component.alias }} - + diff --git a/ui/src/app/edge/live/Controller/PeakShaving/Symmetric_TimeSlot/modal/modal.component.html b/ui/src/app/edge/live/Controller/PeakShaving/Symmetric_TimeSlot/modal/modal.component.html index e997871f447..1297f3549e1 100644 --- a/ui/src/app/edge/live/Controller/PeakShaving/Symmetric_TimeSlot/modal/modal.component.html +++ b/ui/src/app/edge/live/Controller/PeakShaving/Symmetric_TimeSlot/modal/modal.component.html @@ -4,7 +4,7 @@ {{ component.alias }} - + diff --git a/ui/src/app/edge/live/Io/Api_DigitalInput/modal/modal.component.html b/ui/src/app/edge/live/Io/Api_DigitalInput/modal/modal.component.html index b38e74c1204..71f08efa38a 100644 --- a/ui/src/app/edge/live/Io/Api_DigitalInput/modal/modal.component.html +++ b/ui/src/app/edge/live/Io/Api_DigitalInput/modal/modal.component.html @@ -4,7 +4,7 @@ General.digitalInputs - + diff --git a/ui/src/app/edge/live/Multiple/Evcs_Api_Cluster/modal/evcsCluster-modal.page.html b/ui/src/app/edge/live/Multiple/Evcs_Api_Cluster/modal/evcsCluster-modal.page.html index cda4f41f556..b648e43982e 100644 --- a/ui/src/app/edge/live/Multiple/Evcs_Api_Cluster/modal/evcsCluster-modal.page.html +++ b/ui/src/app/edge/live/Multiple/Evcs_Api_Cluster/modal/evcsCluster-modal.page.html @@ -13,7 +13,7 @@ - + @@ -77,255 +77,7 @@ - - - - - - - - - - - - - {{ evcsConfig.properties.alias }} - - - {{ evcs_id }} - - - - - - - - - - - - - - - - -
    - Edge.Index.Widgets.EVCS.chargingPower - - {{ getState(currentData[evcs_id + "/ChargePower"] | - number:'1.0-0', - currentData[evcs_id + "/Status"], - currentData[evcs_id + "/Plug"], evcsCtrl)}} -
    - Edge.Index.Widgets.EVCS.energySinceBeginning - {{ (currentData[evcs_id + "/EnergySession"] * 0.1) | - number:'1.0-0' }} - Wh -
    -
    - - - - - - - - - - - - - - - - - -
    - Edge.Index.Widgets.EVCS.activateCharging - - - -
    - - - - - - - - - Edge.Index.Widgets.EVCS.OptimizedChargeMode.shortName - - - - - - - - - - General.Manually - - - - - - - -
    - - Edge.Index.Widgets.EVCS.OptimizedChargeMode.info - - - - Edge.Index.Widgets.EVCS.ForceChargeMode.info - -
    -
    - - - - - - - - - - -
    - - - - - -
    - Edge.Index.Widgets.EVCS.OptimizedChargeMode.minCharging - - - -
    - - - {{ formatNumber(currentData[evcs_id + - '/MinimumHardwarePower']) | number:'1.0-0'}} -  W - - - {{ formatNumber(currentData[evcs_id + - '/MaximumHardwarePower']) | number:'1.0-0'}} W - - - - - - - - -
    Priorisierung: - - - Auto - - - - Speicher - - - -
    -
    - - Edge.Index.Widgets.EVCS.OptimizedChargeMode.ChargingPriority.info - -
    - - - - -
    - Edge.Index.Widgets.EVCS.ForceChargeMode.maxCharging -
    - - - {{ formatNumber(currentData[evcs_id + - '/MinimumHardwarePower']) | number:'1.0-0'}} W - - - {{ formatNumber(currentData[evcs_id + - '/MaximumHardwarePower']) | number:'1.0-0'}} W - - - - Edge.Index.Widgets.EVCS.ForceChargeMode.maxChargingDetails - -
    -
    -
    - - - - - Diese Ladesäule kann nicht gesteuert werden - - - -
    - - - - Edge.Index.Widgets.EVCS.NoConnection.description - - - - -
      -
    • Edge.Index.Widgets.EVCS.NoConnection.help1
    • -
    - - -
    -
    -
    -
    -
    -
    -
    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 391b36d33cc..c9092ab1115 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 @@ -5,7 +5,7 @@ - + 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 e26dbdf19ef..4bcaad43273 100644 --- a/ui/src/app/edge/live/common/storage/storage.component.ts +++ b/ui/src/app/edge/live/common/storage/storage.component.ts @@ -3,6 +3,7 @@ import { formatNumber } from "@angular/common"; import { Component } from "@angular/core"; import { AbstractFlatWidget } from "src/app/shared/components/flat/abstract-flat-widget"; import { ChannelAddress, CurrentData, EdgeConfig, Utils } from "src/app/shared/shared"; +import { Language } from "src/app/shared/type/language"; import { DateUtils } from "src/app/shared/utils/date/dateutils"; import { StorageModalComponent } from "./modal/modal.component"; @@ -51,6 +52,7 @@ export class StorageComponent extends AbstractFlatWidget { * @returns only positive and 0 */ public convertPower(value: number, isCharge?: boolean) { + const locale: string = (Language.getByKey(localStorage.LANGUAGE) ?? Language.DEFAULT).i18nLocaleKey; if (value == null) { return "-"; } @@ -59,7 +61,7 @@ export class StorageComponent extends AbstractFlatWidget { // Round thisValue to Integer when decimal place equals 0 if (thisValue > 0) { - return formatNumber(thisValue, "de", "1.0-1") + " kW"; // TODO get locale dynamically + return formatNumber(thisValue, locale, "1.0-1") + " kW"; } else if (thisValue == 0 && isCharge) { // if thisValue is 0, then show only when charge and not discharge diff --git a/ui/src/app/edge/live/delayedselltogrid/modal/modal.component.html b/ui/src/app/edge/live/delayedselltogrid/modal/modal.component.html index 5d23d380fc2..717c0fe5571 100644 --- a/ui/src/app/edge/live/delayedselltogrid/modal/modal.component.html +++ b/ui/src/app/edge/live/delayedselltogrid/modal/modal.component.html @@ -4,7 +4,7 @@ {{ component.alias }} - + diff --git a/ui/src/app/edge/live/live.component.html b/ui/src/app/edge/live/live.component.html index 9749758d16d..dee4efcbb57 100644 --- a/ui/src/app/edge/live/live.component.html +++ b/ui/src/app/edge/live/live.component.html @@ -96,6 +96,10 @@ + + + + diff --git a/ui/src/app/edge/live/live.module.ts b/ui/src/app/edge/live/live.module.ts index e8da5f6ff81..bcf8f7594d1 100644 --- a/ui/src/app/edge/live/live.module.ts +++ b/ui/src/app/edge/live/live.module.ts @@ -24,6 +24,7 @@ import { Controller_Io_ChannelSingleThresholdModalComponent } from "./Controller import { Controller_Io_FixDigitalOutputComponent } from "./Controller/Io/FixDigitalOutput/Io_FixDigitalOutput"; import { Controller_Io_FixDigitalOutputModalComponent } from "./Controller/Io/FixDigitalOutput/modal/modal.component"; import { Controller_Io_HeatingElement } from "./Controller/Io/HeatingElement/Io_HeatingElement"; +import { Controller_Io_HeatingRoom } from "./Controller/Io/HeatingRoom/Io_HeatingRoom"; import { Controller_Io_HeatpumpComponent } from "./Controller/Io/Heatpump/Io_Heatpump"; import { Controller_Io_HeatpumpModalComponent } from "./Controller/Io/Heatpump/modal/modal.component"; import { Controller_Api_ModbusTcp } from "./Controller/ModbusTcpApi/modbusTcpApi.module"; @@ -59,6 +60,7 @@ import { Evcs_Api_ClusterModalComponent } from "./Multiple/Evcs_Api_Cluster/moda Controller_Ess_TimeOfUseTariff, Controller_Evcs, Controller_Io_HeatingElement, + Controller_Io_HeatingRoom, EdgeOfflineModule, EnergymonitorModule, SharedModule, @@ -70,7 +72,6 @@ import { Evcs_Api_ClusterModalComponent } from "./Multiple/Evcs_Api_Cluster/moda Controller_Asymmetric_PeakShavingModalComponent, Controller_ChannelthresholdComponent, Controller_ChpSocComponent, - Controller_ChpSocComponent, Controller_ChpSocModalComponent, Controller_Io_ChannelSingleThresholdComponent, Controller_Io_ChannelSingleThresholdModalComponent, diff --git a/ui/src/app/edge/settings/app/formly/safe-input/formly-safe-input-modal.component.html b/ui/src/app/edge/settings/app/formly/safe-input/formly-safe-input-modal.component.html index 56855d3e69d..5acc54771d0 100644 --- a/ui/src/app/edge/settings/app/formly/safe-input/formly-safe-input-modal.component.html +++ b/ui/src/app/edge/settings/app/formly/safe-input/formly-safe-input-modal.component.html @@ -3,14 +3,14 @@ {{ title }} - +
    - + diff --git a/ui/src/app/edge/settings/component/install/index.component.html b/ui/src/app/edge/settings/component/install/index.component.html index 7724f09a979..c3a24abed0d 100644 --- a/ui/src/app/edge/settings/component/install/index.component.html +++ b/ui/src/app/edge/settings/component/install/index.component.html @@ -1,6 +1,6 @@ + (ionInput)="updateFilter($event.detail.value)"> diff --git a/ui/src/app/edge/settings/powerassistant/powerassistant.ts b/ui/src/app/edge/settings/powerassistant/powerassistant.ts index b6861e4fe30..cbbc6bec221 100644 --- a/ui/src/app/edge/settings/powerassistant/powerassistant.ts +++ b/ui/src/app/edge/settings/powerassistant/powerassistant.ts @@ -3,6 +3,7 @@ import { formatNumber } from "@angular/common"; import { Component } from "@angular/core"; import { AbstractFlatWidget } from "src/app/shared/components/flat/abstract-flat-widget"; import { DataService } from "src/app/shared/components/shared/dataservice"; +import { Language } from "src/app/shared/type/language"; import { ChannelAddress, CurrentData, EdgeConfig, Utils } from "../../../shared/shared"; import { LiveDataService } from "../../live/livedataservice"; @@ -222,10 +223,11 @@ export class PowerAssistantComponent extends AbstractFlatWidget { export namespace Converter { export function unit(unit: string): (value: any) => string { return function (value: any): string { + const locale: string = (Language.getByKey(localStorage.LANGUAGE) ?? Language.DEFAULT).i18nLocaleKey; if (value == null) { return "-"; } else if (value >= 0) { - return formatNumber(value, "de", "1.0-0") + " " + unit; + return formatNumber(value, locale, "1.0-0") + " " + unit; } }; } diff --git a/ui/src/app/edge/settings/profile/profile.component.html b/ui/src/app/edge/settings/profile/profile.component.html index 9cde0096885..388f2734929 100644 --- a/ui/src/app/edge/settings/profile/profile.component.html +++ b/ui/src/app/edge/settings/profile/profile.component.html @@ -98,21 +98,27 @@

    {{ item.alias }} - Download Protocol + Download Protocol General.manual + + Download Protocol + - Download Protocol + Download Protocol General.manual + + Download Protocol + diff --git a/ui/src/app/edge/settings/profile/profile.component.ts b/ui/src/app/edge/settings/profile/profile.component.ts index cbc086d4715..ebd165df44e 100644 --- a/ui/src/app/edge/settings/profile/profile.component.ts +++ b/ui/src/app/edge/settings/profile/profile.component.ts @@ -46,11 +46,11 @@ export class ProfileComponent implements OnInit { }); } - public getModbusProtocol(componentId: string) { + public getModbusProtocol(componentId: string, type: string) { this.service.getCurrentEdge().then(edge => { const request = new ComponentJsonApiRequest({ componentId: componentId, payload: new GetModbusProtocolExportXlsxRequest() }); edge.sendRequest(this.service.websocket, request).then(response => { - Utils.downloadXlsx(response as Base64PayloadResponse, "Modbus-TCP-" + edge.id); + Utils.downloadXlsx(response as Base64PayloadResponse, "Modbus-" + type + "-" + edge.id); }).catch(reason => { this.service.toast(this.translate.instant("Edge.Config.PROFILE.ERROR_DOWNLOADING_MODBUS_PROTOCOL") + ": " + (reason as JsonrpcResponseError).error.message, "danger"); }); diff --git a/ui/src/app/index/login.component.ts b/ui/src/app/index/login.component.ts index 8c738c710ba..1cbe39146da 100644 --- a/ui/src/app/index/login.component.ts +++ b/ui/src/app/index/login.component.ts @@ -9,6 +9,7 @@ import { environment } from "src/environments"; import { AppService } from "../app.service"; import { AuthenticateWithPasswordRequest } from "../shared/jsonrpc/request/authenticateWithPasswordRequest"; +import { GetEdgesRequest } from "../shared/jsonrpc/request/getEdgesRequest"; import { States } from "../shared/ngrx-store/states"; import { Edge, Service, Utils, Websocket } from "../shared/shared"; import { UserComponent } from "../user/user.component"; @@ -19,16 +20,19 @@ import { UserComponent } from "../user/user.component"; standalone: false, }) export class LoginComponent implements ViewWillEnter, AfterContentChecked, OnDestroy, OnInit { + public currentThemeMode: string; public environment = environment; public form: FormGroup; protected formIsDisabled: boolean = false; protected popoverActive: "android" | "ios" | null = null; + protected showPassword: boolean = false; protected readonly operatingSystem = AppService.deviceInfo.os; protected readonly isApp: boolean = Capacitor.getPlatform() !== "web"; private stopOnDestroy: Subject = new Subject(); private page = 0; + constructor( public service: Service, public websocket: Websocket, @@ -135,7 +139,9 @@ export class LoginComponent implements ViewWillEnter, AfterContentChecked, OnDes return new Promise((resolve, reject) => { - this.service.getEdges(this.page) + const req = new GetEdgesRequest({ page: this.page }); + + this.service.getEdges(req) .then((edges) => { setTimeout(() => { this.router.navigate(["/device", edges[0].id]); @@ -163,4 +169,5 @@ export class LoginComponent implements ViewWillEnter, AfterContentChecked, OnDes this.popoverActive = operatingSystem; } } + } diff --git a/ui/src/app/index/overview/overview.component.html b/ui/src/app/index/overview/overview.component.html index 62afa44537f..342c53efeec 100644 --- a/ui/src/app/index/overview/overview.component.html +++ b/ui/src/app/index/overview/overview.component.html @@ -42,7 +42,7 @@ + [(ngModel)]="query" (ionInput)="searchOnChange()" [debounce]="1000"> diff --git a/ui/src/app/index/overview/overview.component.ts b/ui/src/app/index/overview/overview.component.ts index cbfd985dea2..0d5fac73d67 100644 --- a/ui/src/app/index/overview/overview.component.ts +++ b/ui/src/app/index/overview/overview.component.ts @@ -6,6 +6,7 @@ import { InfiniteScrollCustomEvent, ViewWillEnter } from "@ionic/angular"; import { TranslateService } from "@ngx-translate/core"; import { Subject } from "rxjs"; import { filter, take } from "rxjs/operators"; +import { GetEdgesRequest } from "src/app/shared/jsonrpc/request/getEdgesRequest"; import { Pagination } from "src/app/shared/service/pagination"; import { Edge, Service, Utils, Websocket } from "src/app/shared/shared"; import { Role } from "src/app/shared/type/role"; @@ -40,6 +41,8 @@ export class OverViewComponent implements ViewWillEnter, OnDestroy { /** True, if all available edges for this user had been retrieved */ private limitReached: boolean = false; + private lastReqId: string | null = null; + constructor( public service: Service, public websocket: Websocket, @@ -96,8 +99,20 @@ export class OverViewComponent implements ViewWillEnter, OnDestroy { searchParamsObj[key] = value; } } - this.service.getEdges(this.page, this.query, this.limit, searchParamsObj) + const req = new GetEdgesRequest({ + page: this.page, + ...(this.query && this.query != "" && { query: this.query }), + ...(this.limit && { limit: this.limit }), + ...(searchParamsObj && { searchParams: searchParamsObj }), + }); + + this.lastReqId = req.id; + + this.service.getEdges(req) .then((edges) => { + if (this.lastReqId !== req.id) { + resolve(this.filteredEdges); + } this.limitReached = edges.length < this.limit; resolve(edges); }).catch((err) => { diff --git a/ui/src/app/registration/modal/modal.component.html b/ui/src/app/registration/modal/modal.component.html index 87cbc68a2dc..3f760f29854 100644 --- a/ui/src/app/registration/modal/modal.component.html +++ b/ui/src/app/registration/modal/modal.component.html @@ -3,7 +3,7 @@ Register.title - + diff --git a/ui/src/app/shared/components/chart/abstracthistorychart.ts b/ui/src/app/shared/components/chart/abstracthistorychart.ts index 2e16ca13128..63728084a0c 100644 --- a/ui/src/app/shared/components/chart/abstracthistorychart.ts +++ b/ui/src/app/shared/components/chart/abstracthistorychart.ts @@ -1,6 +1,6 @@ // @ts-strict-ignore import { DecimalPipe, formatNumber } from "@angular/common"; -import { ChangeDetectorRef, Directive, Input, OnDestroy, OnInit } from "@angular/core"; +import { ChangeDetectorRef, Directive, EventEmitter, Input, OnDestroy, OnInit, Output, signal, WritableSignal } from "@angular/core"; import { ActivatedRoute } from "@angular/router"; import { TranslateService } from "@ngx-translate/core"; import * as Chart from "chart.js"; @@ -8,7 +8,7 @@ import "chartjs-adapter-date-fns"; import annotationPlugin from "chartjs-plugin-annotation"; import { v4 as uuidv4 } from "uuid"; -import { ChronoUnit, DEFAULT_NUMBER_CHART_OPTIONS, DEFAULT_TIME_CHART_OPTIONS, Resolution, calculateResolution, isLabelVisible, setLabelVisible } from "src/app/edge/history/shared"; +import { calculateResolution, ChronoUnit, DEFAULT_NUMBER_CHART_OPTIONS, DEFAULT_TIME_CHART_OPTIONS, isLabelVisible, Resolution, setLabelVisible } from "src/app/edge/history/shared"; import { QueryHistoricTimeseriesEnergyPerPeriodResponse } from "src/app/shared/jsonrpc/response/queryHistoricTimeseriesEnergyPerPeriodResponse"; import { DefaultTypes } from "src/app/shared/service/defaulttypes"; import { JsonrpcResponseError } from "../../jsonrpc/base"; @@ -22,12 +22,14 @@ import { FormatSecondsToDurationPipe } from "../../pipe/formatSecondsToDuration/ import { ChartAxis, HistoryUtils, YAxisType } from "../../service/utils"; import { ChannelAddress, Currency, Edge, EdgeConfig, Logger, Service, Utils } from "../../shared"; import { Language } from "../../type/language"; +import { ArrayUtils } from "../../utils/array/array.utils"; import { ColorUtils } from "../../utils/color/color.utils"; import { DateUtils } from "../../utils/date/dateutils"; import { DateTimeUtils } from "../../utils/datetime/datetime-utils"; import { TimeUtils } from "../../utils/time/timeutils"; import { Converter } from "../shared/converter"; import { ChartConstants, XAxisType } from "./chart.constants"; +import { ChartTypes } from "./chart.types"; Chart.Chart.register(annotationPlugin); @@ -47,6 +49,7 @@ export abstract class AbstractHistoryChart implements OnInit, OnDestroy { @Input() public showTotal: boolean = false; @Input() public isOnlyChart: boolean = false; @Input() public xAxisScalingType: XAxisType = XAxisType.TIMESERIES; + @Output() public setChartConfig: EventEmitter = new EventEmitter(); public edge: Edge | null = null; public loading: boolean = true; @@ -58,12 +61,13 @@ export abstract class AbstractHistoryChart implements OnInit, OnDestroy { protected spinnerId: string = uuidv4(); protected chartType: "line" | "bar" = "line"; + protected chartTypeSignal: WritableSignal<"line" | "bar"> = signal("line"); protected isDataExisting: boolean = true; protected config: EdgeConfig = null; protected errorResponse: JsonrpcResponseError | null = null; - protected legendOptions: { label: string, strokeThroughHidingStyle: boolean, hideLabelInLegend: boolean }[] = []; protected debounceTimeout: any | null = null; + private channelData: { data: { [name: string]: number[] } } = { data: {} }; constructor( @@ -352,19 +356,17 @@ export abstract class AbstractHistoryChart implements OnInit, OnDestroy { translate: TranslateService, legendOptions: { label: string, strokeThroughHidingStyle: boolean; }[], channelData: { data: { [name: string]: number[]; }; }, - locale: string, config: EdgeConfig, datasets: Chart.ChartDataset[], chartOptionsType: XAxisType, labels: (Date | string)[], ): Chart.ChartOptions { - let tooltipsLabel: string | null = null; let options: Chart.ChartOptions = Utils.deepCopy(Utils.deepCopy(AbstractHistoryChart.getDefaultOptions(chartOptionsType, service, labels))); const displayValues: HistoryUtils.DisplayValue[] = chartObject.output(channelData.data, labels); chartObject.yAxes.forEach((element) => { - options = AbstractHistoryChart.getYAxisOptions(options, element, translate, chartType, locale, datasets, true); + options = AbstractHistoryChart.getYAxisOptions(options, element, translate, chartType, datasets, true); }); options.plugins.tooltip.callbacks.title = (tooltipItems: Chart.TooltipItem[]): string => { @@ -395,7 +397,7 @@ export abstract class AbstractHistoryChart implements OnInit, OnDestroy { tooltipsLabel = AbstractHistoryChart.getToolTipsAfterTitleLabel(unit, chartType, value, translate); } - return label.split(":")[0] + ": " + AbstractHistoryChart.getToolTipsSuffix(tooltipsLabel, value, displayValue.custom?.formatNumber ?? chartObject.tooltip.formatNumber, unit, chartType, locale, translate, config); + return AbstractHistoryChart.getToolTipsSuffix(label, value, displayValue.custom?.formatNumber ?? chartObject.tooltip.formatNumber, unit, chartType, translate, config); }; options.plugins.tooltip.callbacks.labelColor = (item: Chart.TooltipItem) => { @@ -445,6 +447,7 @@ export abstract class AbstractHistoryChart implements OnInit, OnDestroy { }; options.plugins.tooltip.callbacks.afterTitle = function (items: Chart.TooltipItem[]) { + const locale: string = (Language.getByKey(localStorage.LANGUAGE) ?? Language.DEFAULT).i18nLocaleKey; if (items?.length === 0) { return null; @@ -468,7 +471,7 @@ export abstract class AbstractHistoryChart implements OnInit, OnDestroy { const totalValue = datasets.filter(el => el.stack == stack).reduce((_total, dataset) => Utils.addSafely(_total, Math.abs(dataset.data[datasetIndex])), 0); if (afterTitle) { - return afterTitle + ": " + formatNumber(totalValue, "de", chartObject.tooltip.formatNumber) + " " + tooltipsLabel; + return afterTitle + ": " + formatNumber(totalValue, locale, chartObject.tooltip.formatNumber) + " " + tooltipsLabel; } return null; @@ -483,7 +486,7 @@ export abstract class AbstractHistoryChart implements OnInit, OnDestroy { function rebuildScales(chart: Chart.Chart) { let options = chart.options; chartObject.yAxes.forEach((element) => { - options = AbstractHistoryChart.getYAxisOptions(options, element, translate, chartType, locale, _dataSets, true); + options = AbstractHistoryChart.getYAxisOptions(options, element, translate, chartType, _dataSets, true); }); } @@ -534,8 +537,8 @@ export abstract class AbstractHistoryChart implements OnInit, OnDestroy { * @param locale the current locale * @returns the chart options {@link Chart.ChartOptions} */ - public static getYAxisOptions(options: Chart.ChartOptions, element: HistoryUtils.yAxes, translate: TranslateService, chartType: "line" | "bar", locale: string, datasets: Chart.ChartDataset[], showYAxisType?: boolean): Chart.ChartOptions { - + public static getYAxisOptions(options: Chart.ChartOptions, element: HistoryUtils.yAxes, translate: TranslateService, chartType: "line" | "bar", datasets: Chart.ChartDataset[], showYAxisType?: boolean): Chart.ChartOptions { + const locale: string = (Language.getByKey(localStorage.LANGUAGE) ?? Language.DEFAULT).i18nLocaleKey; const baseConfig = ChartConstants.DEFAULT_Y_SCALE_OPTIONS(element, translate, chartType, datasets, showYAxisType); switch (element.unit) { case YAxisType.RELAY: @@ -570,7 +573,6 @@ export abstract class AbstractHistoryChart implements OnInit, OnDestroy { }, }; break; - case YAxisType.TIME: options.scales[element.yAxisId] = { ...baseConfig, @@ -586,16 +588,33 @@ export abstract class AbstractHistoryChart implements OnInit, OnDestroy { }, }; break; - case YAxisType.LEVEL: + case YAxisType.HEAT_PUMP: { + const { callback, ...rest } = baseConfig.ticks; + options.scales[element.yAxisId] = { + ...baseConfig, + min: 1, + max: 4, + beginAtZero: true, + ticks: { + ...rest, + stepSize: 1, + }, + }; + } + break; + case YAxisType.HEATING_ELEMENT: { + const { callback, ...rest } = baseConfig.ticks; options.scales[element.yAxisId] = { ...baseConfig, min: 0, max: 3, beginAtZero: true, ticks: { + ...rest, stepSize: 1, }, }; + } break; case YAxisType.VOLTAGE: case YAxisType.CURRENT: @@ -633,16 +652,18 @@ export abstract class AbstractHistoryChart implements OnInit, OnDestroy { * @returns a string, that is either the baseName, if no suffix is provided, or a baseName with a formatted number */ public static getTooltipsLabelName(baseName: string, unit: YAxisType, suffix?: number | string): string { + const locale: string = (Language.getByKey(localStorage.LANGUAGE) ?? Language.DEFAULT).i18nLocaleKey; if (suffix != null) { if (typeof suffix === "string") { return baseName + " " + suffix; } else { switch (unit) { case YAxisType.ENERGY: - return baseName + ": " + formatNumber(suffix / 1000, "de", "1.0-1") + " kWh"; + return baseName + ": " + formatNumber(suffix / 1000, locale, "1.0-1") + " kWh"; case YAxisType.PERCENTAGE: - return baseName + ": " + formatNumber(suffix, "de", "1.0-1") + " %"; + return baseName + ": " + formatNumber(suffix, locale, "1.0-1") + " %"; case YAxisType.RELAY: + case YAxisType.HEAT_PUMP: case YAxisType.TIME: { const pipe = new FormatSecondsToDurationPipe(new DecimalPipe(Language.DE.key)); return baseName + ": " + pipe.transform(suffix); @@ -661,52 +682,61 @@ export abstract class AbstractHistoryChart implements OnInit, OnDestroy { * @param title the YAxisType * @returns the tooltips suffix */ - public static getToolTipsSuffix(label: any, value: number, format: string, title: YAxisType, chartType: "bar" | "line", language: string, translate: TranslateService, config: EdgeConfig): string { - let tooltipsLabel: string | null = null; + public static getToolTipsSuffix(label: any, value: number, format: string, title: YAxisType, chartType: "bar" | "line", translate: TranslateService, config: EdgeConfig): string { + const locale: string = (Language.getByKey(localStorage.LANGUAGE) ?? Language.DEFAULT).i18nLocaleKey; + const prefix: string = label.split(":")[0]; + let suffix: string; switch (title) { - case YAxisType.RELAY: { - return Converter.ON_OFF(translate)(value); - } + case YAxisType.RELAY: + return prefix + ": " + Converter.ON_OFF(translate)(value); + case YAxisType.HEAT_PUMP: + return prefix + ": " + ChartConstants.Plugins.ToolTips.HEAT_PUMP_SUFFIX(translate, value); case YAxisType.TIME: { - const pipe = new FormatSecondsToDurationPipe(new DecimalPipe(language)); - return pipe.transform(value); + const pipe = new FormatSecondsToDurationPipe(new DecimalPipe(locale)); + return prefix + ": " + pipe.transform(value, true); } case YAxisType.CURRENCY: { const meta: EdgeConfig.Component = config?.getComponent("_meta"); const currency: string = config?.getPropertyFromComponent(meta, "currency"); - tooltipsLabel = Currency.getCurrencyLabelByCurrency(currency); - break; + suffix = Currency.getCurrencyLabelByCurrency(currency); break; } case YAxisType.PERCENTAGE: - tooltipsLabel = AbstractHistoryChart.getToolTipsAfterTitleLabel(title, chartType, value, translate); - break; + suffix = AbstractHistoryChart.getToolTipsAfterTitleLabel(title, chartType, value, translate); break; case YAxisType.VOLTAGE: - tooltipsLabel = "V"; + suffix = "V"; break; case YAxisType.CURRENT: - tooltipsLabel = "A"; + suffix = "A"; break; case YAxisType.POWER: - tooltipsLabel = "W"; + suffix = "W"; break; case YAxisType.ENERGY: if (chartType == "bar") { - tooltipsLabel = "kWh"; + suffix = "kWh"; } else { - tooltipsLabel = "kW"; + suffix = "kW"; } break; case YAxisType.REACTIVE: - tooltipsLabel = "var"; + suffix = "var"; break; default: - tooltipsLabel = ""; + suffix = ""; break; } - return formatNumber(value, "de", format) + " " + tooltipsLabel; + return prefix + ": " + formatNumber(value, locale, format) + " " + suffix; } + /** + * Gets the default x axis chart options + * + * @param xAxisType the x axis type + * @param service the service + * @param labels the x axis ticks labels + * @returns chartoptions + */ public static getDefaultOptions(xAxisType: XAxisType, service: Service, labels: (Date | string)[]): Chart.ChartOptions { let options: Chart.ChartOptions; @@ -752,6 +782,12 @@ export abstract class AbstractHistoryChart implements OnInit, OnDestroy { } } + /** + * Removes the external plugin features + * + * @param options the chart options + * @returns the chart options + */ protected static removeExternalPluginFeatures(options: Chart.ChartOptions): Chart.ChartOptions { options.plugins["annotation"] = {}; options.plugins["datalabels"] = { @@ -884,51 +920,18 @@ export abstract class AbstractHistoryChart implements OnInit, OnDestroy { /** * Used to loadChart, dependent on the resolution */ - protected loadChart() { + protected async loadChart() { this.labels = []; this.errorResponse = null; const unit: ChronoUnit.Type = calculateResolution(this.service, this.service.historyPeriod.value.from, this.service.historyPeriod.value.to).resolution.unit; - // Show Barchart if resolution is days or months if (ChronoUnit.isAtLeast(unit, ChronoUnit.Type.DAYS)) { - Promise.all([ - this.queryHistoricTimeseriesEnergyPerPeriod(this.service.historyPeriod.value.from, this.service.historyPeriod.value.to), - this.queryHistoricTimeseriesEnergy(this.service.historyPeriod.value.from, this.service.historyPeriod.value.to), - ]).then(([energyPeriodResponse, energyResponse]) => { - this.chartType = "bar"; - this.chartObject = this.getChartData(); - - // TODO after chartjs migration, look for config - energyPeriodResponse = DateTimeUtils.normalizeTimestamps(unit, energyPeriodResponse); - - const displayValues = AbstractHistoryChart.fillChart(this.chartType, this.chartObject, energyPeriodResponse, energyResponse); - this.datasets = displayValues.datasets; - this.legendOptions = displayValues.legendOptions; - this.labels = displayValues.labels; - this.channelData = displayValues.channelData; - this.beforeSetChartLabel(); - this.setChartLabel(); - }); + await this.loadBarChart(unit); } else { - - // Shows Line-Chart - Promise.all([ - this.queryHistoricTimeseriesData(this.service.historyPeriod.value.from, this.service.historyPeriod.value.to), - this.queryHistoricTimeseriesEnergy(this.service.historyPeriod.value.from, this.service.historyPeriod.value.to), - ]) - .then(([dataResponse, energyResponse]) => { - dataResponse = DateTimeUtils.normalizeTimestamps(unit, dataResponse); - this.chartType = "line"; - this.chartObject = this.getChartData(); - const displayValues = AbstractHistoryChart.fillChart(this.chartType, this.chartObject, dataResponse, energyResponse); - this.datasets = displayValues.datasets; - this.legendOptions = displayValues.legendOptions; - this.labels = displayValues.labels; - this.channelData = displayValues.channelData; - this.beforeSetChartLabel(); - this.setChartLabel(); - }); + await this.loadLineChart(unit); } + + this.setChartConfig.emit({ chartType: this.chartType, datasets: this.datasets, labels: this.labels, options: this.options }); } /** @@ -1084,8 +1087,7 @@ export abstract class AbstractHistoryChart implements OnInit, OnDestroy { * Sets the Labels of the Chart */ protected setChartLabel() { - const locale = this.service.translate.currentLang; - this.options = AbstractHistoryChart.getOptions(this.chartObject, this.chartType, this.service, this.translate, this.legendOptions, this.channelData, locale, this.config, this.datasets, this.xAxisScalingType, this.labels); + this.options = AbstractHistoryChart.getOptions(this.chartObject, this.chartType, this.service, this.translate, this.legendOptions, this.channelData, this.config, this.datasets, this.xAxisScalingType, this.labels); this.loading = false; this.stopSpinner(); } @@ -1128,12 +1130,56 @@ export abstract class AbstractHistoryChart implements OnInit, OnDestroy { return new Promise<{ powerChannels: ChannelAddress[], energyChannels: ChannelAddress[] }>(resolve => { if (this.chartObject?.input) { resolve({ - powerChannels: this.chartObject.input.map(element => element.powerChannel), - energyChannels: this.chartObject.input.map(element => element.energyChannel), + powerChannels: ArrayUtils.sanitize(this.chartObject.input.map(element => element.powerChannel)), + energyChannels: ArrayUtils.sanitize(this.chartObject.input.map(element => element.energyChannel)), }); } }); } + private loadLineChart(unit: ChronoUnit.Type) { + return new Promise((resolve) => { + Promise.all([ + this.queryHistoricTimeseriesData(this.service.historyPeriod.value.from, this.service.historyPeriod.value.to), + this.queryHistoricTimeseriesEnergy(this.service.historyPeriod.value.from, this.service.historyPeriod.value.to), + ]) + .then(([dataResponse, energyResponse]) => { + this.chartType = "line"; + dataResponse = DateTimeUtils.normalizeTimestamps(unit, dataResponse); + this.chartObject = this.getChartData(); + const displayValues = AbstractHistoryChart.fillChart(this.chartType, this.chartObject, dataResponse, energyResponse); + this.datasets = displayValues.datasets; + this.legendOptions = displayValues.legendOptions; + this.labels = displayValues.labels; + this.channelData = displayValues.channelData; + this.beforeSetChartLabel(); + this.setChartLabel(); + }).finally(() => resolve()); + }); + } + + private loadBarChart(unit: ChronoUnit.Type): Promise { + return new Promise((resolve) => { + Promise.all([ + this.queryHistoricTimeseriesEnergyPerPeriod(this.service.historyPeriod.value.from, this.service.historyPeriod.value.to), + this.queryHistoricTimeseriesEnergy(this.service.historyPeriod.value.from, this.service.historyPeriod.value.to), + ]).then(([energyPeriodResponse, energyResponse]) => { + this.chartType = "bar"; + this.chartObject = this.getChartData(); + // TODO after chartjs migration, look for config + energyPeriodResponse = DateTimeUtils.normalizeTimestamps(unit, energyPeriodResponse); + + const displayValues = AbstractHistoryChart.fillChart(this.chartType, this.chartObject, energyPeriodResponse, energyResponse); + this.datasets = displayValues.datasets; + this.legendOptions = displayValues.legendOptions; + this.labels = displayValues.labels; + this.channelData = displayValues.channelData; + this.beforeSetChartLabel(); + this.setChartLabel(); + resolve(); + }).finally(() => resolve()); + }); + } + protected abstract getChartData(): HistoryUtils.ChartData | null; } diff --git a/ui/src/app/shared/components/chart/chart.constants.ts b/ui/src/app/shared/components/chart/chart.constants.ts index 7c3d97ae2a3..903ffdd9d03 100644 --- a/ui/src/app/shared/components/chart/chart.constants.ts +++ b/ui/src/app/shared/components/chart/chart.constants.ts @@ -18,6 +18,25 @@ export namespace ChartConstants { export class Plugins { + public static ToolTips = class { + public static HEAT_PUMP_SUFFIX = (translate: TranslateService, value: number | null): string => { + switch (value) { + case -1: + return translate.instant("Edge.Index.Widgets.HeatPump.undefined"); + case 0: + return translate.instant("Edge.Index.Widgets.HeatPump.lock"); + case 1: + return translate.instant("Edge.Index.Widgets.HeatPump.normalOperation"); + case 2: + return translate.instant("Edge.Index.Widgets.HeatPump.switchOnRec"); + case 3: + return translate.instant("Edge.Index.Widgets.HeatPump.switchOnCom"); + default: + return ""; + } + }; + }; + public static readonly DEFAULT_EMPTY_SCREEN: (text: string) => ChartComponentLike = (text) => ({ id: "empty_chart", beforeDraw: (chart, args, options) => { @@ -64,6 +83,7 @@ export namespace ChartConstants { export const PURPLE: string = new RGBColor(91, 92, 214).toString(); export const YELLOW: string = new RGBColor(255, 206, 0).toString(); export const BLUE_GREY: string = new RGBColor(77, 106, 130).toString(); + export const DARK_GREY: string = new RGBColor(169, 169, 169).toString(); export const GREY: string = new RGBColor(189, 189, 189).toString(); export const SHADES_OF_RED: string[] = [RED, "rgb(204,78,50)", "rgb(153,59,38)", "rgb(102,39,25)", "rgb(51,20,13)"]; diff --git a/ui/src/app/shared/components/chart/chart.module.ts b/ui/src/app/shared/components/chart/chart.module.ts index b1993f939a4..5e5cba76610 100644 --- a/ui/src/app/shared/components/chart/chart.module.ts +++ b/ui/src/app/shared/components/chart/chart.module.ts @@ -7,16 +7,16 @@ import { TranslateModule } from "@ngx-translate/core"; import { BaseChartDirective } from "ng2-charts"; import { NgxSpinnerModule } from "ngx-spinner"; -import { PipeModule } from "../../pipe/pipe"; +import { PipeComponentsModule, PipeModule } from "../../pipe/pipe"; import { HistoryDataErrorModule } from "../history-data-error/history-data-error.module"; -import { PickdateModule } from "../pickdate/pickdate.module"; +import { PickdateComponentModule, PickdateModule } from "../pickdate/pickdate.module"; import { ChartComponent } from "./chart"; +import { ChartLegendComponent } from "./legend/legend"; @NgModule({ imports: [ - BrowserModule, IonicModule, - PipeModule, + PipeComponentsModule, TranslateModule, BaseChartDirective, CommonModule, @@ -25,13 +25,34 @@ import { ChartComponent } from "./chart"; }), HistoryDataErrorModule, RouterModule, - PickdateModule, + PickdateComponentModule, ], declarations: [ ChartComponent, + ChartLegendComponent, ], exports: [ ChartComponent, + ChartLegendComponent, + ], +}) +export class ChartComponentsModule { } + +/** +* @deprecated should avoid creating modules with browsermodule imported +*/ +@NgModule({ + imports: [ + BrowserModule, + ChartComponentsModule, + PipeModule, + PickdateModule, + ], + exports: [ + ChartComponentsModule, + PickdateModule, + PipeModule, ], }) export class ChartModule { } + diff --git a/ui/src/app/shared/components/chart/chart.types.ts b/ui/src/app/shared/components/chart/chart.types.ts new file mode 100644 index 00000000000..e17af7b1804 --- /dev/null +++ b/ui/src/app/shared/components/chart/chart.types.ts @@ -0,0 +1,5 @@ +import { ChartDataset, ChartOptions } from "chart.js"; + +export namespace ChartTypes { + export type ChartConfig = { chartType: "line" | "bar", labels: (Date | string)[], datasets: ChartDataset[], options: ChartOptions | null }; +} diff --git a/ui/src/app/shared/components/chart/legend/legend.html b/ui/src/app/shared/components/chart/legend/legend.html new file mode 100644 index 00000000000..1aac7274206 --- /dev/null +++ b/ui/src/app/shared/components/chart/legend/legend.html @@ -0,0 +1,15 @@ + + + + + + + {{header}} + + + + {{description}} + + + + diff --git a/ui/src/app/shared/components/chart/legend/legend.ts b/ui/src/app/shared/components/chart/legend/legend.ts new file mode 100644 index 00000000000..37d6ce51b48 --- /dev/null +++ b/ui/src/app/shared/components/chart/legend/legend.ts @@ -0,0 +1,12 @@ +import { Component, Input } from "@angular/core"; + +@Component({ + selector: "oe-chart-legend", + templateUrl: "./legend.html", + standalone: false, +}) +export class ChartLegendComponent { + + @Input({ required: true }) public header: string | null = null; + @Input({ required: true }) public description: string | null = null; +} diff --git a/ui/src/app/shared/components/components.module.ts b/ui/src/app/shared/components/components.module.ts index cb3b444a6fb..2501654a44c 100644 --- a/ui/src/app/shared/components/components.module.ts +++ b/ui/src/app/shared/components/components.module.ts @@ -25,14 +25,14 @@ import { NotificationComponent } from "./shared/notification/notification"; BrowserModule, IonicModule, PipeModule, - ReactiveFormsModule, - RouterModule, TranslateModule, HistoryDataErrorModule, FooterNavigationModule, ChartModule, PickdateModule, ModalModule, + ReactiveFormsModule, + RouterModule, ], declarations: [ diff --git a/ui/src/app/shared/components/edge/edgeconfig.spec.ts b/ui/src/app/shared/components/edge/edgeconfig.spec.ts index e4d7ecfc6ec..e0bc39fbbe6 100644 --- a/ui/src/app/shared/components/edge/edgeconfig.spec.ts +++ b/ui/src/app/shared/components/edge/edgeconfig.spec.ts @@ -197,6 +197,28 @@ export namespace DummyConfig { "io.openems.edge.timedata.api.TimedataProvider", ], }; + + export const MODBUS_RTU_READWRITE = { + id: "Controller.Api.ModbusRtu.ReadWrite", + natureIds: [ + "io.openems.edge.common.jsonapi.JsonApi", + "io.openems.edge.common.component.OpenemsComponent", + "io.openems.edge.controller.api.modbus.ModbusRtuApi", + "io.openems.edge.controller.api.modbus.readwrite.ControllerApiModbusRtuReadWrite", + "io.openems.edge.controller.api.Controller", + "io.openems.edge.timedata.api.TimedataProvider", + ], + }; + + export const HEAT_PUMP_SG_READY = { + id: "Controller.Io.HeatPump.SgReady", + natureIds: [ + "io.openems.edge.common.component.OpenemsComponent", + "io.openems.edge.controller.io.heatpump.sgready.ControllerIoHeatPumpSgReady", + "io.openems.edge.controller.api.Controller", + "io.openems.edge.timedata.api.TimedataProvider", + ], + }; } export namespace Component { @@ -346,6 +368,17 @@ export namespace DummyConfig { }, channels: {}, }); + + export const HEAT_PUMP_SG_READY = (id: string, alias?: string): Component => ({ + id: id, + alias: alias ?? id, + factory: Factory.HEAT_PUMP_SG_READY, + properties: { + enabled: true, + mode: "AUTOMATIC", + }, + channels: {}, + }); } } @@ -353,7 +386,7 @@ export namespace DummyConfig { * Factories. */ // identifier `Factory` is also used in namespace -// eslint-disable-next-line @typescript-eslint/no-unused-vars + type Factory = { id: string, natureIds: string[], diff --git a/ui/src/app/shared/components/edge/edgeconfig.ts b/ui/src/app/shared/components/edge/edgeconfig.ts index 0ddf42d24ca..c54e43aa049 100644 --- a/ui/src/app/shared/components/edge/edgeconfig.ts +++ b/ui/src/app/shared/components/edge/edgeconfig.ts @@ -165,6 +165,7 @@ export class EdgeConfig { "Controller.IO.ChannelSingleThreshold", "Controller.Io.FixDigitalOutput", "Controller.IO.HeatingElement", + "Controller.IO.Heating.Room", "Controller.Io.HeatPump.SgReady", ]), ].flat(2), @@ -183,6 +184,8 @@ export class EdgeConfig { "Controller.Api.ModbusTcp", "Controller.Api.ModbusTcp.ReadOnly", "Controller.Api.ModbusTcp.ReadWrite", + "Controller.Api.ModbusRtu.ReadOnly", + "Controller.Api.ModbusRtu.ReadWrite", "Controller.Api.MQTT", "Controller.Api.Rest.ReadOnly", "Controller.Api.Rest.ReadWrite", @@ -544,6 +547,7 @@ export class EdgeConfig { } switch (component.factoryId) { case "GoodWe.EmergencyPowerMeter": + case "Controller.IO.Heating.Room": return true; } const natures = this.getNatureIdsByFactoryId(component.factoryId); @@ -686,7 +690,7 @@ export class EdgeConfig { } /** - * Safely gets a property from a component if it exists, else returns null. + * Safely gets a property from a component, if it exists, else returns null. * * @param component The component from which to retrieve the property. * @param property The property name to retrieve. diff --git a/ui/src/app/shared/components/flat/abstract-flat-widget.ts b/ui/src/app/shared/components/flat/abstract-flat-widget.ts index a8a1e654f82..4a4e6131ada 100644 --- a/ui/src/app/shared/components/flat/abstract-flat-widget.ts +++ b/ui/src/app/shared/components/flat/abstract-flat-widget.ts @@ -1,5 +1,5 @@ // @ts-strict-ignore -import { Directive, Inject, Input, OnDestroy, OnInit } from "@angular/core"; +import { Directive, Input, OnDestroy, OnInit, Inject } from "@angular/core"; import { FormBuilder, FormGroup } from "@angular/forms"; import { ActivatedRoute, Router } from "@angular/router"; import { ModalController } from "@ionic/angular"; diff --git a/ui/src/app/shared/components/formly/form-field.wrapper.html b/ui/src/app/shared/components/formly/form-field.wrapper.html index 18ebda3222c..e01f45a4ce3 100644 --- a/ui/src/app/shared/components/formly/form-field.wrapper.html +++ b/ui/src/app/shared/components/formly/form-field.wrapper.html @@ -1,9 +1,4 @@ - - {{ to.label }} - * -
    {{ to.description }}
    -
    diff --git a/ui/src/app/shared/components/formly/form-field.wrapper.ts b/ui/src/app/shared/components/formly/form-field.wrapper.ts index b4bb24fc97d..94410ddbb8d 100644 --- a/ui/src/app/shared/components/formly/form-field.wrapper.ts +++ b/ui/src/app/shared/components/formly/form-field.wrapper.ts @@ -1,4 +1,4 @@ -import { ChangeDetectionStrategy, Component } from "@angular/core"; +import { ChangeDetectionStrategy, Component, ViewEncapsulation } from "@angular/core"; import { FieldWrapper } from "@ngx-formly/core"; @Component({ @@ -6,5 +6,12 @@ import { FieldWrapper } from "@ngx-formly/core"; templateUrl: "./form-field.wrapper.html", changeDetection: ChangeDetectionStrategy.OnPush, standalone: false, + encapsulation: ViewEncapsulation.None, + styles: [` + formly-field-ion-toggle, formly-field-ion-checkbox, formly-custom-select, + formly-input-serial-number { + width: 100%; + } + `], }) export class FormlyWrapperFormFieldComponent extends FieldWrapper { } diff --git a/ui/src/app/shared/components/formly/formly-select-field-modal.component.html b/ui/src/app/shared/components/formly/formly-select-field-modal.component.html index 834fbb753d5..50cab8961fa 100644 --- a/ui/src/app/shared/components/formly/formly-select-field-modal.component.html +++ b/ui/src/app/shared/components/formly/formly-select-field-modal.component.html @@ -3,7 +3,7 @@ {{ title }} - + diff --git a/ui/src/app/shared/components/formly/formly-select/formly-select.ts b/ui/src/app/shared/components/formly/formly-select/formly-select.ts new file mode 100644 index 00000000000..daf30a3f137 --- /dev/null +++ b/ui/src/app/shared/components/formly/formly-select/formly-select.ts @@ -0,0 +1,33 @@ +import { Component } from "@angular/core"; +import { FieldType } from "@ngx-formly/core"; + +@Component({ + selector: "formly-custom-select", + template: ` + + + + {{ option.label }} + + + + `, + standalone: false, + styles: [` + :host { + formly-custom-select { + width: 100%; + } + } + `], +}) +export class FormlySelectComponent extends FieldType { } diff --git a/ui/src/app/shared/components/formly/input-serial-number-wrapper.html b/ui/src/app/shared/components/formly/input-serial-number-wrapper.html index 169d30f12e8..57459c47597 100644 --- a/ui/src/app/shared/components/formly/input-serial-number-wrapper.html +++ b/ui/src/app/shared/components/formly/input-serial-number-wrapper.html @@ -1,23 +1,24 @@ - - - - - {{to.label}} - * -
    {{ to.description }}
    -
    -
    -
    - - - {{to.prefix}} - + + + + + +
    + + {{ props.label }} + * +
    {{ props.description + }}
    +
    +
    +
    - - + + diff --git a/ui/src/app/shared/components/formly/input.html b/ui/src/app/shared/components/formly/input.html index f85472cc915..5d8f34cf7e9 100644 --- a/ui/src/app/shared/components/formly/input.html +++ b/ui/src/app/shared/components/formly/input.html @@ -1,9 +1,17 @@ + [min]="props.min" [label]="props.label"> - + +
    + + {{ props.label }} + * +
    {{ props.description + }}
    +
    +
    diff --git a/ui/src/app/shared/components/formly/input.ts b/ui/src/app/shared/components/formly/input.ts index 8635fb6bc79..71642277be9 100644 --- a/ui/src/app/shared/components/formly/input.ts +++ b/ui/src/app/shared/components/formly/input.ts @@ -1,9 +1,40 @@ -import { Component } from "@angular/core"; +import { Component, ViewEncapsulation } from "@angular/core"; import { FieldType } from "@ngx-formly/core"; @Component({ selector: "formly-input-section", templateUrl: "./input.html", standalone: false, + encapsulation: ViewEncapsulation.None, + styles: [` + :host { + min-width: fit-content; + + .label-text-wrapper{ + .label-text{ + overflow: visible; + } + } + + .native-wrapper{ + max-width: max-content !important; + width: max-content; + min-width: 20%; + + @media (width <= 576px) { + text-align: right; + } + } + + ion-label{ + text-align: left; + } + + ion-label>span, + ion-label>span>small { + white-space: initial; + } +} +`], }) export class InputTypeComponent extends FieldType { } diff --git a/ui/src/app/shared/components/history-data-error/history-data-error.module.ts b/ui/src/app/shared/components/history-data-error/history-data-error.module.ts index 14a71cdd093..023a7f85d2c 100644 --- a/ui/src/app/shared/components/history-data-error/history-data-error.module.ts +++ b/ui/src/app/shared/components/history-data-error/history-data-error.module.ts @@ -1,6 +1,5 @@ import { CommonModule } from "@angular/common"; import { NgModule } from "@angular/core"; -import { BrowserAnimationsModule } from "@angular/platform-browser/animations"; import { IonicModule } from "@ionic/angular"; import { TranslateModule } from "@ngx-translate/core"; import { HistoryDataErrorComponent } from "./history-data-error.component"; @@ -8,7 +7,6 @@ import { HistoryDataErrorComponent } from "./history-data-error.component"; @NgModule({ imports: [ - BrowserAnimationsModule, CommonModule, IonicModule, TranslateModule, diff --git a/ui/src/app/shared/components/modal/modal-phases/modal-phases.ts b/ui/src/app/shared/components/modal/modal-phases/modal-phases.ts index 2a0cf4c5059..774ef47d7b1 100644 --- a/ui/src/app/shared/components/modal/modal-phases/modal-phases.ts +++ b/ui/src/app/shared/components/modal/modal-phases/modal-phases.ts @@ -1,6 +1,7 @@ import { formatNumber } from "@angular/common"; import { Component, Input } from "@angular/core"; import { ChannelAddress, CurrentData, Utils } from "src/app/shared/shared"; +import { Language } from "src/app/shared/type/language"; import { AbstractModalLine } from "../abstract-modal-line"; import { TextIndentation } from "../modal-line/modal-line"; @@ -47,8 +48,8 @@ export class ModalPhasesComponent extends AbstractModalLine { * @returns converted value */ protected CONVERT_TO_POSITIVE_WATT = (value: number | null): string => { - + const locale: string = (Language.getByKey(localStorage.LANGUAGE) ?? Language.DEFAULT).i18nLocaleKey; value = Utils.absSafely(value) ?? 0; - return formatNumber(value, "de", "1.0-0") + " W"; + return formatNumber(value, locale, "1.0-0") + " W"; }; } diff --git a/ui/src/app/shared/components/pickdate/pickdate.module.ts b/ui/src/app/shared/components/pickdate/pickdate.module.ts index a094850a04c..8970a0af5f0 100644 --- a/ui/src/app/shared/components/pickdate/pickdate.module.ts +++ b/ui/src/app/shared/components/pickdate/pickdate.module.ts @@ -1,3 +1,4 @@ +import { CommonModule } from "@angular/common"; import { NgModule } from "@angular/core"; import { ReactiveFormsModule } from "@angular/forms"; import { BrowserModule } from "@angular/platform-browser"; @@ -9,11 +10,10 @@ import { PickDatePopoverComponent } from "./popover/popover.component"; @NgModule({ imports: [ - BrowserModule, + AngularMyDatePickerModule, + CommonModule, IonicModule, - ReactiveFormsModule, TranslateModule, - AngularMyDatePickerModule, ], declarations: [ PickDateComponent, @@ -23,4 +23,17 @@ import { PickDatePopoverComponent } from "./popover/popover.component"; PickDateComponent, ], }) +export class PickdateComponentModule { } +@NgModule({ + imports: [ + BrowserModule, + IonicModule, + ReactiveFormsModule, + TranslateModule, + PickdateComponentModule, + ], + exports: [ + PickdateComponentModule, + ], +}) export class PickdateModule { } diff --git a/ui/src/app/shared/components/pickdate/popover/popover.component.ts b/ui/src/app/shared/components/pickdate/popover/popover.component.ts index 43d3f9e555a..7796d28efa3 100644 --- a/ui/src/app/shared/components/pickdate/popover/popover.component.ts +++ b/ui/src/app/shared/components/pickdate/popover/popover.component.ts @@ -57,7 +57,7 @@ export class PickDatePopoverComponent implements OnInit { .dp1 .myDpSelectedDay, .dp1 .myDpSelectedMonth, .dp1 .myDpSelectedYear { - background-color: #93c47d; + background-color: var(--ion-color-primary); } .dp1 .myDpTableSingleDay:hover, .dp1 .myDpTableSingleMonth:hover, @@ -69,10 +69,10 @@ export class PickDatePopoverComponent implements OnInit { .dp1 .myDpMarkCurrMonth, .dp1 .myDpMarkCurrYear { border-bottom: 2px solid #2d8fab; - color: #2d8fab; + color: var(--ion-color-text); } .dp1 .myDpRangeColor { - background-color: #dbeaff; + background-color: var(--ion-color-primary); } .ng-mydp * { @@ -117,8 +117,7 @@ export class PickDatePopoverComponent implements OnInit { this.locale = (Language.getByKey(localStorage.LANGUAGE) ?? Language.DEFAULT).key; // Restrict user to pick date before ibn-date - this.myDpOptions.disableUntil = { day: Utils.subtractSafely(getDate(this.edge?.firstSetupProtocol), 1) ?? 1, month: Utils.addSafely(getMonth(this.edge?.firstSetupProtocol), 1) ?? 1, year: this.edge?.firstSetupProtocol?.getFullYear() ?? 2013 }, - this.locale = this.translate.getBrowserLang(); + this.myDpOptions.disableUntil = { day: Utils.subtractSafely(getDate(this.edge?.firstSetupProtocol), 1) ?? 1, month: Utils.addSafely(getMonth(this.edge?.firstSetupProtocol), 1) ?? 1, year: this.edge?.firstSetupProtocol?.getFullYear() ?? 2013 }; // Filter out custom due to different on click event this.periods = EdgePermission.getAllowedHistoryPeriods(this.edge, this.historyPeriods).filter(period => period !== DefaultTypes.PeriodString.CUSTOM); diff --git a/ui/src/app/shared/components/shared/converter.ts b/ui/src/app/shared/components/shared/converter.ts index 16a72a5afc7..ad0b1f77b52 100644 --- a/ui/src/app/shared/components/shared/converter.ts +++ b/ui/src/app/shared/components/shared/converter.ts @@ -275,6 +275,23 @@ export namespace Converter { }; }; + export const HEAT_PUMP_STATES = (translate: TranslateService) => { + return (raw): string => { + switch (raw) { + case -1: + return translate.instant("Edge.Index.Widgets.HeatPump.undefined"); + case 0: + return translate.instant("Edge.Index.Widgets.HeatPump.lock"); + case 1: + return translate.instant("Edge.Index.Widgets.HeatPump.normalOperationShort"); + case 2: + return translate.instant("Edge.Index.Widgets.HeatPump.switchOnRecShort"); + case 3: + return translate.instant("Edge.Index.Widgets.HeatPump.switchOnComShort"); + } + }; + }; + export const FORMAT_SECONDS_TO_DURATION: any = (locale: string) => { return (raw): any => { return IF_NUMBER(raw, value => { diff --git a/ui/src/app/shared/components/shared/testing/common.ts b/ui/src/app/shared/components/shared/testing/common.ts index 737ee68587c..e6f90af2ec9 100644 --- a/ui/src/app/shared/components/shared/testing/common.ts +++ b/ui/src/app/shared/components/shared/testing/common.ts @@ -102,7 +102,7 @@ export namespace OeTester { "beginAtZero": true, ...options["left"]?.scale, ...(chartType === "line" ? { stacked: false } : {}), - "title": { "text": "kWh", "display": false, "padding": 5, "font": { "size": 11 } }, + "title": { "text": title ?? "kWh", "display": false, "padding": 5, "font": { "size": 11 } }, "position": "left", "grid": { "display": true }, "ticks": { diff --git a/ui/src/app/shared/components/shared/testing/tester.ts b/ui/src/app/shared/components/shared/testing/tester.ts index c6ed9f0bfd9..403db6b3601 100644 --- a/ui/src/app/shared/components/shared/testing/tester.ts +++ b/ui/src/app/shared/components/shared/testing/tester.ts @@ -308,7 +308,7 @@ export class OeChartTester { legendOptions.push(AbstractHistoryChart.getLegendOptions(label, displayValue)); }); - let options: Chart.ChartOptions = AbstractHistoryChart.getOptions(chartData, chartType, testContext.service, testContext.translate, legendOptions, channelData.result, locale, config, datasets, xAxisType, labels); + let options: Chart.ChartOptions = AbstractHistoryChart.getOptions(chartData, chartType, testContext.service, testContext.translate, legendOptions, channelData.result, config, datasets, xAxisType, labels); options = prepareOptionsForTesting(options, chartData); return { @@ -436,7 +436,6 @@ function prepareOptionsForTesting(options: Chart.ChartOptions, chartData: Histor options.scales[axis.yAxisId].ticks = ObjectUtils.excludeProperties(options.scales[axis.yAxisId].ticks as Chart.RadialTickOptions, ["stepSize"]); options.scales[axis.yAxisId]["title"] = ObjectUtils.excludeProperties(options.scales[axis.yAxisId]["title"] as Chart.RadialTickOptions, ["color"]); }); - console.log("options", options); return options; } diff --git a/ui/src/app/shared/pipe/formatSecondsToDuration/formatSecondsToDuration.pipe.ts b/ui/src/app/shared/pipe/formatSecondsToDuration/formatSecondsToDuration.pipe.ts index 33ff8389b7d..e9122127a9c 100644 --- a/ui/src/app/shared/pipe/formatSecondsToDuration/formatSecondsToDuration.pipe.ts +++ b/ui/src/app/shared/pipe/formatSecondsToDuration/formatSecondsToDuration.pipe.ts @@ -11,13 +11,13 @@ export class FormatSecondsToDurationPipe implements PipeTransform { constructor(private decimalPipe: DecimalPipe) { } - transform(value: number): string { + transform(value: number, showMinutes?: boolean): string { return Converter.IF_NUMBER(value, (val) => { let minutes = val / 60; const hours = Math.floor(minutes / 60); minutes -= hours * 60; - if (hours <= 23) { + if (hours <= 23 || showMinutes) { return this.decimalPipe.transform(hours, "1.0-0") + "h" + " " + this.decimalPipe.transform(minutes, "1.0-0") + "m"; } else { return this.decimalPipe.transform(hours, "1.0-0") + "h"; diff --git a/ui/src/app/shared/pipe/pipe.ts b/ui/src/app/shared/pipe/pipe.ts index dba4d592001..a11a3993ec7 100644 --- a/ui/src/app/shared/pipe/pipe.ts +++ b/ui/src/app/shared/pipe/pipe.ts @@ -10,11 +10,7 @@ import { SignPipe } from "./sign/sign.pipe"; import { TypeofPipe } from "./typeof/typeof.pipe"; import { UnitvaluePipe } from "./unitvalue/unitvalue.pipe"; import { VersionPipe } from "./version/version.pipe"; - @NgModule({ - imports: [ - BrowserModule, - ], declarations: [ UnitvaluePipe, SignPipe, @@ -44,4 +40,16 @@ import { VersionPipe } from "./version/version.pipe"; TypeofPipe, ], }) +export class PipeComponentsModule { } + +@NgModule({ + imports: [ + BrowserModule, + PipeComponentsModule, + ], + exports: [ + PipeComponentsModule, + ], +}) export class PipeModule { } + diff --git a/ui/src/app/shared/service/myerrorhandler.ts b/ui/src/app/shared/service/myerrorhandler.ts index faf283b744e..dc7bc62c00c 100644 --- a/ui/src/app/shared/service/myerrorhandler.ts +++ b/ui/src/app/shared/service/myerrorhandler.ts @@ -9,7 +9,7 @@ export class MyErrorHandler implements ErrorHandler { ) { } // https://v16.angular.io/api/core/ErrorHandler#errorhandler - // eslint-disable-next-line @typescript-eslint/no-explicit-any + handleError(error: any) { const logger = this.injector.get(Logger); console.error(error); diff --git a/ui/src/app/shared/service/service.ts b/ui/src/app/shared/service/service.ts index 73e2b1ea3d3..f0f07ca7ab0 100644 --- a/ui/src/app/shared/service/service.ts +++ b/ui/src/app/shared/service/service.ts @@ -7,7 +7,6 @@ import { LangChangeEvent, TranslateService } from "@ngx-translate/core"; import { NgxSpinnerService } from "ngx-spinner"; import { BehaviorSubject, Subject } from "rxjs"; import { filter, first, take } from "rxjs/operators"; -import { ChosenFilter } from "src/app/index/filter/filter.component"; import { environment } from "src/environments"; import { ChartConstants } from "../components/chart/chart.constants"; import { Edge } from "../components/edge/edge"; @@ -135,7 +134,7 @@ export class Service extends AbstractService { } // https://v16.angular.io/api/core/ErrorHandler#errorhandler - // eslint-disable-next-line @typescript-eslint/no-explicit-any + public override handleError(error: any) { console.error(error); // TODO: show notification @@ -314,20 +313,13 @@ export class Service extends AbstractService { /** * 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 + * @param req the get edges request + * @returns a promise with the resulting edges */ - public getEdges(page: number, query?: string, limit?: number, searchParamsObj?: { [id: string]: ChosenFilter["value"] }): Promise { + public getEdges(req: GetEdgesRequest): Promise { return new Promise((resolve, reject) => { - this.websocket.sendSafeRequest( - new GetEdgesRequest({ - page: page, - ...(query && query != "" && { query: query }), - ...(limit && { limit: limit }), - ...(searchParamsObj && { searchParams: searchParamsObj }), - })).then((response) => { + this.websocket.sendSafeRequest(req) + .then((response) => { const result = (response as GetEdgesResponse).result; diff --git a/ui/src/app/shared/service/test/dummyservice.ts b/ui/src/app/shared/service/test/dummyservice.ts index 58101b949a1..9d5a8b1845b 100644 --- a/ui/src/app/shared/service/test/dummyservice.ts +++ b/ui/src/app/shared/service/test/dummyservice.ts @@ -62,7 +62,7 @@ export class DummyService extends AbstractService { throw new Error("Method not implemented."); } // https://v16.angular.io/api/core/ErrorHandler#errorhandler - // eslint-disable-next-line @typescript-eslint/no-explicit-any + override handleError(error: any): void { throw new Error("Method not implemented."); } diff --git a/ui/src/app/shared/service/utils.ts b/ui/src/app/shared/service/utils.ts index cf1f4ec3143..f786bca3a76 100644 --- a/ui/src/app/shared/service/utils.ts +++ b/ui/src/app/shared/service/utils.ts @@ -4,6 +4,7 @@ import { TranslateService } from "@ngx-translate/core"; import { ChartDataset } from "chart.js"; import { saveAs } from "file-saver-es"; import { DefaultTypes } from "src/app/shared/service/defaulttypes"; +import { Language } from "src/app/shared/type/language"; import { JsonrpcResponseSuccess } from "../jsonrpc/base"; import { Base64PayloadResponse } from "../jsonrpc/response/base64PayloadResponse"; import { QueryHistoricTimeseriesEnergyResponse } from "../jsonrpc/response/queryHistoricTimeseriesEnergyResponse"; @@ -94,7 +95,7 @@ export class Utils { * @param v1 * @param v2 */ - public static addSafely(v1: number, v2: number): number { + public static addSafely(v1: number | null, v2: number | null): number { if (v1 == null) { return v2; } else if (v2 == null) { @@ -146,7 +147,7 @@ export class Utils { * @param v1 * @param v2 */ - public static multiplySafely(v1: number, v2: number): number { + public static multiplySafely(v1: number | null, v2: number | null): number { if (v1 == null || v2 == null) { return null; } else { @@ -214,7 +215,7 @@ export class Utils { * @param orElse the default value * @returns the value or the default value */ - public static orElse(v: number, orElse: number): number { + public static orElse(v: number | null, orElse: number): number { if (v == null) { return orElse; } else { @@ -251,10 +252,11 @@ export class Utils { * @returns converted value */ public static CONVERT_TO_WATT = (value: number | null): string => { + const locale: string = (Language.getByKey(localStorage.LANGUAGE) ?? Language.DEFAULT).i18nLocaleKey; if (value == null) { return "-"; } else if (value >= 0) { - return formatNumber(value, "de", "1.0-0") + " W"; + return formatNumber(value, locale, "1.0-0") + " W"; } else { return "0 W"; } @@ -267,13 +269,14 @@ export class Utils { * @returns converted value */ public static CONVERT_WATT_TO_KILOWATT = (value: number | null): string => { + const locale: string = (Language.getByKey(localStorage.LANGUAGE) ?? Language.DEFAULT).i18nLocaleKey; if (value == null) { return "-"; } const thisValue: number = (value / 1000); if (thisValue >= 0) { - return formatNumber(thisValue, "de", "1.0-1") + " kW"; + return formatNumber(thisValue, locale, "1.0-1") + " kW"; } else { return "0 kW"; } @@ -306,7 +309,8 @@ export class Utils { * @returns converted value */ public static CONVERT_TO_WATTHOURS = (value: number): string => { - return formatNumber(value, "de", "1.0-1") + " Wh"; + const locale: string = (Language.getByKey(localStorage.LANGUAGE) ?? Language.DEFAULT).i18nLocaleKey; + return formatNumber(value, locale, "1.0-1") + " Wh"; }; /** @@ -316,7 +320,19 @@ export class Utils { * @returns converted value */ public static CONVERT_TO_KILO_WATTHOURS = (value: number): string => { - return formatNumber(Utils.divideSafely(value, 1000), "de", "1.0-1") + " kWh"; + const locale: string = (Language.getByKey(localStorage.LANGUAGE) ?? Language.DEFAULT).i18nLocaleKey; + return formatNumber(Utils.divideSafely(value, 1000), locale, "1.0-1") + " kWh"; + }; + + /** + * Converts a value in DEZIDEGREE_CELSIUS [dC] to DEGREE_CELSIUS [°C] + * + * @param value the value from passed value in html + * @returns converted value + */ + public static CONVERT_DEZIDEGREE_CELSIUS_TO_DEGREE_CELSIUS = (value: number): string => { + const locale: string = (Language.getByKey(localStorage.LANGUAGE) ?? Language.DEFAULT).i18nLocaleKey; + return formatNumber(Utils.divideSafely(value, 10), locale, "1.0-1") + " °C"; }; /** @@ -395,8 +411,9 @@ export class Utils { * @returns converted value */ public static CONVERT_PRICE_TO_CENT_PER_KWH = (decimal: number, label: string) => { + const locale: string = (Language.getByKey(localStorage.LANGUAGE) ?? Language.DEFAULT).i18nLocaleKey; return (value: number | null | undefined): string => - (value == null ? "-" : formatNumber(value / 10, "de", "1.0-" + decimal)) + " " + label; + (value == null ? "-" : formatNumber(value / 10, locale, "1.0-" + decimal)) + " " + label; }; /** @@ -636,6 +653,8 @@ export enum YAxisType { RELAY, TIME, VOLTAGE, + HEAT_PUMP, + HEATING_ELEMENT, } export enum ChartAxis { @@ -664,15 +683,20 @@ export namespace HistoryUtils { } export type InputChannel = { - - /** Must be unique, is used as identifier in {@link ChartData.input} */ name: string, - powerChannel: ChannelAddress, - energyChannel?: ChannelAddress - /** Choose between predefined converters */ converter?: (value: number) => number | null, - }; + } & ({ + powerChannel: ChannelAddress | null, + energyChannel?: undefined + } | { + energyChannel: ChannelAddress, + powerChannel?: undefined + } | { + powerChannel: ChannelAddress | null, + energyChannel: ChannelAddress + }); + export type DisplayValue = { name: string, /** suffix to the name */ @@ -863,7 +887,7 @@ export namespace TimeOfUseTariffUtils { * @returns The formatted label, or exits if the value is not valid. */ export function getLabel(value: number, label: string, translate: TranslateService, currencyLabel?: Currency.Label): string { - + const locale: string = (Language.getByKey(localStorage.LANGUAGE) ?? Language.DEFAULT).i18nLocaleKey; // Error handling: Return undefined if value is not valid if (value === undefined || value === null || Number.isNaN(Number.parseInt(value.toString()))) { return; @@ -878,18 +902,18 @@ export namespace TimeOfUseTariffUtils { // Switch case to handle different labels switch (label) { case socLabel: - return label + ": " + formatNumber(value, "de", "1.0-0") + " %"; + return label + ": " + formatNumber(value, locale, "1.0-0") + " %"; case dischargeLabel: case chargeConsumptionLabel: case balancingLabel: // Show floating point number for values between 0 and 1 - return label + ": " + formatNumber(value, "de", "1.0-4") + " " + currencyLabel; + return label + ": " + formatNumber(value, locale, "1.0-4") + " " + currencyLabel; default: case gridBuyLabel: // Power values - return label + ": " + formatNumber(value, "de", "1.0-2") + " kW"; + return label + ": " + formatNumber(value, locale, "1.0-2") + " kW"; } } diff --git a/ui/src/app/shared/service/websocket.ts b/ui/src/app/shared/service/websocket.ts index a10012290a4..d2d7bdacaaf 100644 --- a/ui/src/app/shared/service/websocket.ts +++ b/ui/src/app/shared/service/websocket.ts @@ -1,7 +1,9 @@ // @ts-strict-ignore import { Injectable, signal, WritableSignal } from "@angular/core"; import { Router } from "@angular/router"; +import { Capacitor } from "@capacitor/core"; import { TranslateService } from "@ngx-translate/core"; +import { SavePassword } from "capacitor-ios-autofill-save-password"; import { CookieService } from "ngx-cookie-service"; import { delay, retryWhen } from "rxjs/operators"; import { webSocket, WebSocketSubject } from "rxjs/webSocket"; @@ -75,6 +77,15 @@ export class Websocket implements WebsocketInterface { this.state.set(States.AUTHENTICATED); const authenticateResponse = (r as AuthenticateResponse).result; + if (request instanceof AuthenticateWithPasswordRequest) { + if (Capacitor.getPlatform() === "ios") { + SavePassword.promptDialog({ + username: request.params.username, + password: request.params.password, + }); + } + } + const language = Language.getByKey(localStorage.DEMO_LANGUAGE ?? authenticateResponse.user.language.toLocaleLowerCase()); localStorage.LANGUAGE = language.key; this.service.setLang(language); diff --git a/ui/src/app/shared/shared.module.ts b/ui/src/app/shared/shared.module.ts index c4ac3d7797c..342bde9a381 100644 --- a/ui/src/app/shared/shared.module.ts +++ b/ui/src/app/shared/shared.module.ts @@ -20,6 +20,7 @@ import { FormlyWrapperFormFieldComponent } from "./components/formly/form-field. import { FormlyFieldCheckboxWithImageComponent } from "./components/formly/formly-field-checkbox-image/formly-field-checkbox-with-image"; import { FormlyFieldModalComponent } from "./components/formly/formly-field-modal/formlyfieldmodal"; import { FormlyFieldRadioWithImageComponent } from "./components/formly/formly-field-radio-with-image/formly-field-radio-with-image"; +import { FormlySelectComponent } from "./components/formly/formly-select/formly-select"; import { FormlySelectFieldModalComponent } from "./components/formly/formly-select-field-modal.component"; import { FormlySelectFieldExtendedWrapperComponent } from "./components/formly/formly-select-field.extended"; import { FormlyFieldWithLoadingAnimationComponent } from "./components/formly/formly-skeleton-wrapper"; @@ -59,6 +60,7 @@ export function SubnetmaskValidatorMessage(err, field: FormlyFieldConfig) { @NgModule({ imports: [ + BaseChartDirective, BrowserAnimationsModule, CommonModule, ComponentsModule, @@ -79,6 +81,7 @@ export function SubnetmaskValidatorMessage(err, field: FormlyFieldConfig) { { name: "input", component: InputTypeComponent }, { name: "repeat", component: RepeatTypeComponent }, { name: "multi-step", component: FormlyFieldMultiStepComponent }, + { name: "select", component: FormlySelectComponent }, ], validators: [ { name: "ip", validation: IpValidator }, @@ -121,6 +124,7 @@ export function SubnetmaskValidatorMessage(err, field: FormlyFieldConfig) { PanelWrapperComponent, PercentageBarComponent, RepeatTypeComponent, + FormlySelectComponent, ], exports: [ AppHeaderComponent, diff --git a/ui/src/app/shared/type/language.spec.ts b/ui/src/app/shared/type/language.spec.ts index 177daccbb97..171967beb4b 100644 --- a/ui/src/app/shared/type/language.spec.ts +++ b/ui/src/app/shared/type/language.spec.ts @@ -1,12 +1,41 @@ // @ts-strict-ignore +import { TestContext, TestingUtils } from "../components/shared/testing/utils.spec"; import { Language } from "./language"; - describe("Language", () => { + let TEST_CONTEXT: TestContext; + beforeAll(async () => { + TEST_CONTEXT = await TestingUtils.sharedSetup(); + }); + it("#geti18nLocaleByKey", () => { expect(Language.geti18nLocaleByKey("DE")).toBe("de"); expect(Language.geti18nLocaleByKey("Zz")).toBe(Language.DEFAULT.i18nLocaleKey); expect(Language.geti18nLocaleByKey(null)).toBe(Language.DEFAULT.i18nLocaleKey); expect(Language.geti18nLocaleByKey(undefined)).toBe(Language.DEFAULT.i18nLocaleKey); }); + + it("#setAdditionalTranslationFile - translation de found", async () => { + const json = { + "de": { + "key": "value", + }, + }; + TEST_CONTEXT.translate.use("de"); + + expect(await Language.setAdditionalTranslationFile(json, TEST_CONTEXT.translate)).toEqual({ lang: "de", translations: Object({ key: "value" }), shouldMerge: true }); + }); + + it("#setAdditionalTranslationFile - translation de not found - warning expected", async () => { + const json = { + "de": { + "key": "value", + }, + }; + + spyOn(console, "warn"); + TEST_CONTEXT.translate.currentLang = "cz"; + await Language.setAdditionalTranslationFile(json, TEST_CONTEXT.translate); + expect(console.warn).toHaveBeenCalledWith("No translation available for Language cz. Implemented languages are: de"); + }); }); diff --git a/ui/src/app/shared/type/language.ts b/ui/src/app/shared/type/language.ts index 693a81d2b6e..6522014a065 100644 --- a/ui/src/app/shared/type/language.ts +++ b/ui/src/app/shared/type/language.ts @@ -1,3 +1,4 @@ +import localCS from "@angular/common/locales/cs"; import localDE from "@angular/common/locales/de"; import localEN from "@angular/common/locales/en"; import localES from "@angular/common/locales/es"; @@ -5,8 +6,7 @@ import localFR from "@angular/common/locales/fr"; import localJA from "@angular/common/locales/ja"; import localNL from "@angular/common/locales/nl"; import { TranslateLoader, TranslateService } from "@ngx-translate/core"; -import { Observable, of } from "rxjs"; -import { filter, take } from "rxjs/operators"; +import { filter, Observable, of, take } from "rxjs"; import cz from "src/assets/i18n/cz.json"; import de from "src/assets/i18n/de.json"; import en from "src/assets/i18n/en.json"; @@ -35,14 +35,14 @@ export class Language { public static readonly DE: Language = new Language("German", "de", "de", de, localDE); public static readonly EN: Language = new Language("English", "en", "en", en, localEN); - public static readonly CZ: Language = new Language("Czech", "cz", "de", cz, localDE /* NOTE: there is no locale in @angular/common for Czech */); + public static readonly CS: Language = new Language("Czech", "cs", "de", cz, localCS /* NOTE: there is no locale in @angular/common for Czech */); public static readonly NL: Language = new Language("Dutch", "nl", "nl", nl, localNL); public static readonly ES: Language = new Language("Spanish", "es", "es", es, localES); public static readonly FR: Language = new Language("French", "fr", "fr", fr, localFR); public static readonly JA: Language = new Language("Japanese", "ja", "ja", ja, localJA); - public static readonly ALL = [Language.DE, Language.EN, Language.CZ, Language.NL, Language.ES, Language.FR, Language.JA]; - public static readonly DEFAULT = Language.DE; + public static readonly ALL = [Language.DE, Language.EN, Language.CS, Language.NL, Language.ES, Language.FR, Language.JA]; + public static readonly DEFAULT = Language.getByKey(environment.defaultLanguage) as Language; constructor( public readonly title: string, @@ -51,7 +51,7 @@ export class Language { public readonly json: any, // Angular is not providing common type for locale. // https://github.com/angular/angular/issues/30506 - // eslint-disable-next-line @typescript-eslint/no-explicit-any + public readonly locale: any, ) { } @@ -74,7 +74,7 @@ export class Language { return Language.EN; case "es": return Language.ES; case "nl": return Language.NL; - case "cz": return Language.CZ; + case "cs": return Language.CS; case "fr": return Language.FR; case "ja": return Language.JA; default: return null; @@ -87,7 +87,7 @@ export class Language { case Language.EN.key: return Language.EN.locale; case Language.ES.key: return Language.ES.locale; case Language.NL.key: return Language.NL.locale; - case Language.CZ.key: return Language.CZ.locale; + case Language.CS.key: return Language.CS.locale; case Language.FR.key: return Language.FR.locale; case Language.JA.key: return Language.JA.locale; default: return Language.DEFAULT.locale; @@ -119,12 +119,17 @@ export class Language { * @returns translations params */ public static async setAdditionalTranslationFile(translationFile: any, translate: TranslateService): Promise<{ lang: string; translations: {}; shouldMerge?: boolean; }> { - const lang = (await translate.onLangChange.pipe(filter(lang => !!lang), take(1)).toPromise())?.lang ?? Language.DEFAULT.key; + const lang = translate.currentLang ?? (await translate.onLangChange.pipe(filter(lang => !!lang), take(1)).toPromise())?.lang ?? Language.DEFAULT.key; let translationKey: string = lang; + + if (!(Language.DEFAULT.key in translationFile)) { + throw new Error(`Translation for fallback ${Language.DEFAULT.key} is missing`); + } + if (!(lang in translationFile)) { if (environment.debugMode) { - console.warn(`[Advert] No translation available for Language ${lang}. Implemented languages are: ${Object.keys(translationFile)}`); + console.warn(`No translation available for Language ${lang}. Implemented languages are: ${Object.keys(translationFile)}`); } translationKey = Language.EN.key; } diff --git a/ui/src/app/shared/type/widget.ts b/ui/src/app/shared/type/widget.ts index a6f73311e93..36b7677292a 100644 --- a/ui/src/app/shared/type/widget.ts +++ b/ui/src/app/shared/type/widget.ts @@ -34,6 +34,7 @@ export enum WidgetFactory { "Controller.IO.ChannelSingleThreshold", "Controller.Io.FixDigitalOutput", "Controller.IO.HeatingElement", + "Controller.IO.Heating.Room", "Controller.Io.HeatPump.SgReady", "Controller.Symmetric.PeakShaving", "Controller.TimeslotPeakshaving", diff --git a/ui/src/app/shared/utils/array/array.utils.ts b/ui/src/app/shared/utils/array/array.utils.ts index 1f00f0d723f..6b0571cb930 100644 --- a/ui/src/app/shared/utils/array/array.utils.ts +++ b/ui/src/app/shared/utils/array/array.utils.ts @@ -1,3 +1,5 @@ +import { Utils } from "../../shared"; + export namespace ArrayUtils { export function equalsCheck(a: T[], b: T[]): boolean { return a.length === b.length && @@ -28,6 +30,18 @@ export namespace ArrayUtils { return filteredArr.length > 0 ? Math.max(...filteredArr) : null; } + export function summarizeValuesByIndex(data: { [name: string]: number[] }): number[] { + const result: number[] = []; + + for (const key in data) { + data[key].forEach((value, index) => { + result[index] = Utils.addSafely(result[index], value); + }); + } + + return result; + } + /** * Sort arrays alphabetically, according to the string returned by fn. * Elements for which fn returns null or undefined are sorted to the end in an undefined order. @@ -70,4 +84,12 @@ export namespace ArrayUtils { export function containsAllStrings(strings: (number | string | null)[], arr: (number | string | null)[]): boolean { return arr.every(el => strings.includes(el)); } + + export function getArrayOfLength(length: number): number[] { + return Array.from({ length }, (_, index) => index); + } + + export function sanitize(arr: T[]): T[] { + return arr.filter(el => el != null); + } } diff --git a/ui/src/app/shared/utils/datetime/datetime-utils.ts b/ui/src/app/shared/utils/datetime/datetime-utils.ts index b008ba8e340..2449d9d85d8 100644 --- a/ui/src/app/shared/utils/datetime/datetime-utils.ts +++ b/ui/src/app/shared/utils/datetime/datetime-utils.ts @@ -1,9 +1,9 @@ // @ts-strict-ignore -/* eslint-disable import/no-duplicates */ + // cf. https://github.com/import-js/eslint-plugin-import/issues/1479 -import { differenceInMilliseconds, format, startOfMonth, startOfYear } from "date-fns"; +import { differenceInMilliseconds, format, isSameYear, startOfMonth, startOfYear } from "date-fns"; import { de } from "date-fns/locale"; -/* eslint-enable import/no-duplicates */ + import { ChronoUnit } from "src/app/edge/history/shared"; import { QueryHistoricTimeseriesDataResponse } from "../../jsonrpc/response/queryHistoricTimeseriesDataResponse"; @@ -15,6 +15,8 @@ export class DateTimeUtils { /** * Normalizes timestamps depending on chosen period * + * e.g fills up dataset with 11 months with 1 month to show full 12 months + * * @param unit the Chronounit * @param energyPerPeriodResponse the timeseries data * @returns the adjusted timestamps @@ -31,8 +33,9 @@ export class DateTimeUtils { // show 12 stacks, even if no data and timestamps const newTimestamps: string[] = []; const firstTimestamp = DateUtils.stringToDate(energyPerPeriodResponse.result.timestamps[0]); + const lastTimestamp = DateUtils.stringToDate(energyPerPeriodResponse.result.timestamps[energyPerPeriodResponse.result.timestamps.length - 1]); - if (firstTimestamp.getMonth() !== 0) { + if (firstTimestamp.getMonth() !== 0 && isSameYear(lastTimestamp, firstTimestamp)) { for (let i = 0; i <= (firstTimestamp.getMonth() - 1); i++) { newTimestamps.push(new Date(firstTimestamp.getFullYear(), i).toString()); diff --git a/ui/src/app/user/user.component.html b/ui/src/app/user/user.component.html index 7a6f64e37c4..e4ff14e18ec 100644 --- a/ui/src/app/user/user.component.html +++ b/ui/src/app/user/user.component.html @@ -166,8 +166,7 @@

    - Debug-Mode + Debug-Mode diff --git a/ui/src/environments/index.ts b/ui/src/environments/index.ts index a5790f059f5..d1505479fb6 100644 --- a/ui/src/environments/index.ts +++ b/ui/src/environments/index.ts @@ -11,6 +11,7 @@ export interface Environment { readonly uiTitle: string; readonly edgeShortName: string; readonly edgeLongName: string; + readonly defaultLanguage: string; readonly url: string; readonly backend: DefaultTypes.Backend; diff --git a/ui/src/global.scss b/ui/src/global.scss index 9e8063f82d6..d27e8c37c1c 100644 --- a/ui/src/global.scss +++ b/ui/src/global.scss @@ -47,6 +47,22 @@ ion-card-content { color: var(--ion-card-content-color); } +input:-webkit-autofill, +input:-webkit-autofill:focus { + background-color: transparent !important; + box-shadow: 0 0 0em 1000em var(--ion-background-color) inset !important; + -webkit-text-fill-color: var(--ion-text-color) !important; + margin-top: 0.1em; +} + +.custom-ion-popover { + + white-space: inherit; + + // Overwrites default width of popover + --min-width: min-content; +} + .footer-color { background-color: var(--ion-color-toolbar-secondary) !important; } @@ -82,7 +98,7 @@ formly-field-ion-radio { white-space: initial; small { - white-space: initial; + white-space: nowrap; } } diff --git a/ui/src/themes/openems/environments/theme.ts b/ui/src/themes/openems/environments/theme.ts index d771eb259d7..68374dc6273 100644 --- a/ui/src/themes/openems/environments/theme.ts +++ b/ui/src/themes/openems/environments/theme.ts @@ -6,6 +6,7 @@ export const theme = { uiTitle: "OpenEMS UI", edgeShortName: "OpenEMS", edgeLongName: "Open Energy Management System", + defaultLanguage: "de", docsUrlPrefix: "https://github.com/OpenEMS/openems/blob/develop/", links: { diff --git a/ui/src/zone-flags.ts b/ui/src/zone-flags.ts index 42fd6600d93..c214dec9fd2 100644 --- a/ui/src/zone-flags.ts +++ b/ui/src/zone-flags.ts @@ -3,6 +3,6 @@ * running with certain Web Component callbacks * https://ionicframework.com/docs/ja/troubleshooting/runtime#angular-change-detection */ -// eslint-disable-next-line no-underscore-dangle -// eslint-disable-next-line @typescript-eslint/no-explicit-any + + (window as any).__Zone_disable_customElements = true;