Skip to content

Commit

Permalink
Merge branch 'release/2023.12.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
sfeilmeier committed Dec 4, 2023
2 parents c8a21b7 + 3131fb4 commit 9aae11e
Show file tree
Hide file tree
Showing 733 changed files with 21,611 additions and 37,414 deletions.
4 changes: 4 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*.html text eol=lf diff=html
*.java text eol=lf
*.js text eol=lf diff=javascript
*.json text eol=lf
*.lib text eol=lf
*.md text eol=lf
*.MF text eol=lf
Expand All @@ -27,9 +28,11 @@
*.properties text eol=lf
*.py text eol=lf
*.schema text eol=lf
*.scss text eol=lf
*.SF text eol=lf
*.sh text eol=lf
*.tcl text eol=lf
*.ts text eol=lf
*.txt text eol=lf
*.xml text eol=lf
*.xsd text eol=lf
Expand Down Expand Up @@ -70,6 +73,7 @@ LICENSE text eol=lf
*.otp binary
*.ots binary
*.ott binary
*.svg binary
*.key binary
*.numbers binary
*.pages binary
19 changes: 13 additions & 6 deletions cnf/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@
<!-- HikariCP A solid, high-performance, JDBC connection pool at last. -->
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>5.0.1</version>
<version>5.1.0</version>
</dependency>
<!-- commons -->
<dependency>
Expand Down Expand Up @@ -156,6 +156,13 @@
<artifactId>rxjava</artifactId>
<version>3.1.8</version>
</dependency>
<dependency>
<!-- Jenetics - Java Genetic Algorithm Library -->
<!-- Release notes: https://github.com/jenetics/jenetics/blob/master/RELEASE_NOTES.md -->
<groupId>io.jenetics</groupId>
<artifactId>jenetics</artifactId>
<version>7.2.0</version>
</dependency>
<!-- javax -->
<dependency>
<groupId>javax.jmdns</groupId>
Expand Down Expand Up @@ -208,7 +215,7 @@
<!-- Changelog: https://github.com/apache/felix-dev/commits/master/http -->
<groupId>org.apache.felix</groupId>
<artifactId>org.apache.felix.http.jetty</artifactId>
<version>5.1.2</version>
<version>5.1.4</version>
</dependency>
<dependency>
<!-- Apache Felix Servlet API -->
Expand Down Expand Up @@ -259,7 +266,7 @@
<dependency>
<groupId>org.dhatim</groupId>
<artifactId>fastexcel</artifactId>
<version>0.15.7</version>
<version>0.16.4</version>
</dependency>
<dependency>
<!-- Eclipse Paho MQTTv5 Client -->
Expand Down Expand Up @@ -295,7 +302,7 @@
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-osgi-bundle</artifactId>
<version>1.9.10</version>
<version>1.9.21</version>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlinx</groupId>
Expand All @@ -306,7 +313,7 @@
<!-- HTML processing -->
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.16.2</version>
<version>1.17.1</version>
</dependency>
<dependency>
<groupId>org.osgi</groupId>
Expand Down Expand Up @@ -393,7 +400,7 @@
<!-- Used by io.openems.backend.metadata.odoo -->
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>42.6.0</version>
<version>42.7.0</version>
</dependency>
<dependency>
<!-- Used by com.influxdb: influxdb -->
Expand Down
11 changes: 11 additions & 0 deletions doc/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
### OpenEMS Doc

This project was generated with [antora](https://antora.org/)

### Building pages

Use the package-manager of your choice to install and generate the [uibundle_openems.zip](./build/uibundle_openems.zip).

`$ npx antora ./build/site.yml`

Open the index.html inside it.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 5 additions & 1 deletion doc/modules/ROOT/nav.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,11 @@
** xref:ui/setup-ide.adoc[Setup IDE]
** xref:ui/architecture.adoc[Architecture]
** xref:ui/build.adoc[Build OpenEMS UI]
** xref:ui/implementing-a-widget.adoc[Implementing a UI Widget]
*** xref:ui/implementing-a-widget/introduction.adoc[Implementing a UI Widget]
**** xref:ui/implementing-a-widget/components/flat.adoc[Flat-Widget]
**** xref:ui/implementing-a-widget/components/modal.adoc[Modal-Widget]
**** xref:ui/implementing-a-widget/components/chart.adoc[Chart]
* OpenEMS Backend
** xref:backend/architecture.adoc[Architecture]
** xref:backend/backend-to-backend.adoc[Backend-to-Backend]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
=== Creating a Chart

This chapter assumes that you already completed link:../introduction.html#_create_a_new_module_history_view[this].

image::ui-history-energy-monitor.png[Energy Monitor]

Charts are mainly used in the History-View and should be acting like the `modal` in the live-view. This means they shouldn't be apparent in the history-view directly, but should open when clicking on a `flat-widget`.

Creating or updating charts has been very difficult, but if you use the recommended and new way of creating them, its much easier and can be done fast. Furthermore they are unittestable now.

If we take a look at a link:src\app\edge\history\common\autarchy\chart\chart.ts[Working Example], we will see, that the chart directory includes not only the chart.ts but also the corresponding .spec-file. If you are not familiar with angulars unit testing, check it out link:https://angular.io/guide/testing#test-file-name-and-location[here].

NOTE: It is recommended to have the `component.ts` and `component.spec.ts` files in the same folder.

==== General

To understand how data is queried from the timeseries database, you need to know that there are some predefined time ranges link:https://github.com/OpenEMS/openems/blob/d6291452f01c2a370d722a50c884706c3121c529/ui/src/app/shared/service/defaulttypes.ts#L94[modes] for the chart.

If you used the charts from time to time, you will notice that there are two visualisations. Bar and line chart. Line charts are used for day and week periods while bar charts are used for months and year. The custom period shows both, dependent on the selected period link:https://github.com/OpenEMS/openems/blob/d6291452f01c2a370d722a50c884706c3121c529/ui/src/app/edge/history/shared.ts#L290[(view resolution)]. The resolution, returned from this method is also used in the corresponding `Timeseries-Request`.

When using the link:https://github.com/OpenEMS/openems/blob/develop/ui/src/app/shared/jsonrpc/request/queryHistoricTimeseriesDataRequest.ts[QueryHistoricTimeseriesDataRequest], you should use the power-channels and for the link:https://github.com/OpenEMS/openems/blob/develop/ui/src/app/shared/jsonrpc/request/queryHistoricTimeseriesEnergyPerPeriodRequest.ts[QueryHistoricTimeseriesEnergyPerPeriodRequest] the energy-channels. You can read more about that link:https://openems.github.io/openems.io/openems/latest/backend/service.html#_timedata_aggregated_influxdb[here].


If you take a look link:ui\src\app\edge\history\common\autarchy\chart\chart.ts[here] you will notice that creating charts can be broken down to 2 main parts. The link:https://github.com/OpenEMS/openems/blob/develop/ui/src/app/shared/service/utils.ts#L646[input] and link:https://github.com/OpenEMS/openems/blob/d6291452f01c2a370d722a50c884706c3121c529/ui/src/app/shared/service/utils.ts#L648[output].

The input consists of this:

[source, js]
----
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,
};
----


Here you define the channels that should be subscribed, it is mandatory to use a power channel, if no energy channel provided, you won't see the energy-value next to the legend-label. If no valid datapoint in the resulting data or no response exists, the link:https://openems.github.io/openems.io/openems/latest/backend/service.html#_timedata_aggregated_influxdb[dataset] won't be shown. You can also pass a converter. This enables mutating the data right away. For this you should either use one of the predefined link:https://github.com/OpenEMS/openems/blob/develop/ui/src/app/shared/genericComponents/shared/converter.ts[converters] or create your own.

The output callback gets this data and with it, you can define the link:https://github.com/OpenEMS/openems/blob/d6291452f01c2a370d722a50c884706c3121c529/ui/src/app/shared/service/utils.ts#L604[datasets]:

Lets get back to the link:src\app\edge\history\common\autarchy\chart\chart.ts[example].

TIP: When looking at the example when reading the following, it will be easier to follow.

For the `input` there are two channel-pairs used, additionally to the second, the data gets filter through a `converter` which filters in this case all null or negative values.
The `name` property is used to have a ID for using the data later.

The `output` is then defining the dataset, with the `nameSuffix` callback having the data of the `QueryHistoricTimeseriesEnergyRequest`, that has been called for the whole period, this means only one datapoint for the chosen period. If month or year are used as periods, there are always two of these requests. One for the `legend label` and the other for being displayed in the chart.

The second one is passed with the output callback, and has to be used for the converter callback-function.

Additionally we define the formatting of the data in the tooltip and the yAxes.
Original file line number Diff line number Diff line change
@@ -1,58 +1,3 @@
= Implementing a UI-Widget
:sectnums:
:sectnumlevels: 4
:toc:
:toclevels: 4
:experimental:
:keywords: AsciiDoc
:source-highlighter: highlight.js
:icons: font
:imagesdir: ../../assets/images

== Step-by-step guide

This chapter explains the steps required to implement a UI Widget for OpenEMS UI. There are many examples of how ui widgets are created and used in
link:https://github.com/OpenEMS/openems/blob/develop/ui/src/app/edge/live/live.component.html[LiveComponent, window="_blank"] and link:https://github.com/OpenEMS/openems/blob/develop/ui/src/app/edge/history/history.component.html[HistoryComponent, window="_blank"].


UI-Modules mainly consist of these components:

Module:: Modules should always be used to import and export all of the components, relevant to this Widget. The following components could be part of it:

FlatWidget::: directly visible in Live-View.
ModalComponent::: Popover, that can be opened when clicking on a `FlatWidget`, used in Live-View.
Chart::: Chart that is shown instead of a modal, used in History-View

=== Create a new module [Live-View]

. Copy an existing Module e.g. link:https://github.com/OpenEMS/openems/blob/develop/ui/src/app/edge/live/Controller/Ess/FixActivePower/Ess_FixActivePower.ts[FixActivePower, window="_blank"] and paste it inside the Live-View.

. Change the `@Component` link:https://github.com/OpenEMS/openems/blob/develop/ui/src/app/edge/live/Controller/Ess/FixActivePower/flat/flat.ts[selector, window="_blank"] and use it inside link:file:ui/src/app/edge/live/live.component.html#L135[LiveComponent, window="_blank"].

. Rename the link:https://github.com/OpenEMS/openems/blob/develop/ui/src/app/edge/live/Controller/Ess/FixActivePower/Ess_FixActivePower.ts[Module, window="_blank"] and import it in link:https://github.com/OpenEMS/openems/blob/develop/ui/src/app/edge/live/live.module.ts[LiveModule, window="_blank"] under imports.
To be able to see the module in action, you need to create a new switchCase Statement with your controllers factoryId.

[source,html]
----
<ion-col size="12" *ngSwitchCase="'Controller.Ess.FixActivePower'"
size-lg="6" class="ion-no-padding">
<Controller_Ess_FixActivePower [componentId]="widget.componentId">
</Controller_Ess_FixActivePower>
</ion-col>
----



NOTE: The Live and History View are designed to show UI-Widgets dependent on the `EdgeConfig`, except of widgets listed in link:https://github.com/OpenEMS/openems/blob/develop/ui/src/app/edge/live/common/[Common, window="_blank"].
If you implemented a controller or component, that is part of an `EdgeConfig`, you have to use the factoryId as a switchCase statement.
If thats not the case, go into link:https://github.com/OpenEMS/openems/blob/develop/ui/src/app/shared/type/widget.ts[widget.ts, window="_blank"] and add a identifier to the classes array inside `parseWidgets()`.



The FlatWidget should now be visible in the Live-View and could be looking like this.

image::ui-flat-widget-fixactivepower.png[FlatWidget FixActivePower]

=== Creating a FlatWidget

Data Visualisation in the Live-View is enabled with the link:https://github.com/OpenEMS/openems/tree/develop/ui/src/app/shared/genericComponents/flat[flat, window="_blank"] and https://github.com/OpenEMS/openems/tree/develop/ui/src/app/shared/genericComponents/modal[modal, window="_blank"]-widgets.
Expand Down Expand Up @@ -177,4 +122,4 @@ NOTE: Lines should always present one line of data visualisation. It could be co
This line will be looking like this:
image::modal-line-example-consumption.png[]
image::modal-line-example-consumption.png[]
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
### Creating a modal

Creating a `modal-widget` is pretty similar to creating a `flat-widget`.
The model should act as the detailed view of a `flat-widget` and can also fit the purpose of user interaction.

There are multiple implementations of `modals` at the creation time of this page, but the one thats considered best practice is the unit-testable version.

#### Creating a Line

Lets take a look at one link:https://github.com/OpenEMS/openems/blob/develop/ui/src/app/edge/live/common/consumption/modal/modal.ts[example].

[source, html]
----
public static generateView(
config: EdgeConfig, role: Role, translate: TranslateService)
:OeFormlyView {
// Total
lines.push({
type: 'channel-line',
name: translate.instant('General.TOTAL'),
channel: '_sum/ConsumptionActivePower',
converter: Converter.ONLY_POSITIVE_POWER_AND_NEGATIVE_AS_ZERO
});
return {
title: translate.instant('General.grid'),
lines: lines
};
}
----

Predefined fields in link:https://github.com/OpenEMS/openems/blob/develop/ui/src/app/shared/genericComponents/shared/oe-formly-component.ts[OeFormlyField] can be used here.

For this line we use the type 'channel-line'. This represents a line, where a channel has to be subscribed. You also need to specify the link:https://github.com/OpenEMS/openems/blob/develop/ui/src/app/shared/genericComponents/shared/converter.ts[converter], that uses the data coming from this channel and mutates it. A link:https://github.com/OpenEMS/openems/blob/develop/ui/src/app/shared/genericComponents/shared/filter.ts[filter], which has to return a boolean, decides if the line will be shown or not.

NOTE: Lines should always present one line of data visualisation. It could be consisting of a identifier and a value or just a value. The value or channel will be shown at the end of the line, the name, if provided, at the start.

This line will be looking like this:

image::modal-line-example-consumption.png[]
57 changes: 57 additions & 0 deletions doc/modules/ROOT/pages/ui/implementing-a-widget/introduction.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
= Implementing a UI-Widget
:sectnums:
:sectnumlevels: 4
:toc:
:toclevels: 4
:experimental:
:keywords: AsciiDoc
:source-highlighter: highlight.js
:icons: font
:imagesdir: ../../assets/images

== Step-by-step guide

This chapter explains the steps required to implement a UI Widget for OpenEMS UI. There are many examples of how ui widgets are created and used in
link:https://github.com/OpenEMS/openems/blob/develop/ui/src/app/edge/live/live.component.html[LiveComponent, window="_blank"] and link:https://github.com/OpenEMS/openems/blob/develop/ui/src/app/edge/history/history.component.html[HistoryComponent, window="_blank"].


UI-Modules mainly consist of these components:

Module:: Modules should always be used to import and export all of the components, relevant to this Widget. The following components could be part of it:

FlatWidget::: directly visible in Live-View.
ModalComponent::: Popover, that can be opened when clicking on a `FlatWidget`, used in Live-View.
Chart::: Chart that is shown instead of a modal, used in History-View

== Create a new module [Live-View]

. Copy an existing Module e.g. link:https://github.com/OpenEMS/openems/blob/develop/ui/src/app/edge/live/Controller/Ess/FixActivePower/Ess_FixActivePower.ts[FixActivePower, window="_blank"] and paste it inside the Live-View.

. Change the `@Component` link:https://github.com/OpenEMS/openems/blob/develop/ui/src/app/edge/live/Controller/Ess/FixActivePower/flat/flat.ts[selector, window="_blank"] and use it inside link:file:ui/src/app/edge/live/live.component.html#L135[LiveComponent, window="_blank"].

. Rename the link:https://github.com/OpenEMS/openems/blob/develop/ui/src/app/edge/live/Controller/Ess/FixActivePower/Ess_FixActivePower.ts[Module, window="_blank"] and import it in link:https://github.com/OpenEMS/openems/blob/develop/ui/src/app/edge/live/live.module.ts[LiveModule, window="_blank"] under imports.
To be able to see the module in action, you need to create a new switchCase Statement with your controllers factoryId.

[source,html]
----
<ion-col size="12" *ngSwitchCase="'Controller.Ess.FixActivePower'"
size-lg="6" class="ion-no-padding">
<Controller_Ess_FixActivePower [componentId]="widget.componentId">
</Controller_Ess_FixActivePower>
</ion-col>
----



NOTE: The Live and History View are designed to show UI-Widgets dependent on the `EdgeConfig`, except of widgets listed in link:https://github.com/OpenEMS/openems/blob/develop/ui/src/app/edge/live/common/[Common, window="_blank"].
If you implemented a controller or component, that is part of an `EdgeConfig`, you have to use the factoryId as a switchCase statement.
If thats not the case, go into link:https://github.com/OpenEMS/openems/blob/develop/ui/src/app/shared/type/widget.ts[widget.ts, window="_blank"] and add a identifier to the classes array inside `parseWidgets()`.


The FlatWidget should now be visible in the Live-View and could be looking like this.

image::ui-flat-widget-fixactivepower.png[FlatWidget FixActivePower]

== Create a new module [History-View]

For creating a module in the history-view, you can follow the same steps as for the live-view.
Loading

0 comments on commit 9aae11e

Please sign in to comment.