Skip to content

Commit 4a852f7

Browse files
authored
FEMS-Backports 2024-08 (2) (#2771)
* UI: fix sum chart in consumption history - Wrong variable used in consumption detail html * UI: add routing guards for settings - Introduction of [Routing Guards](https://v17.angular.io/api/router#types) - Not visible routes could be accessed through manually going there - Adding edge role check before accessing this route * UI: center refresher-spinner - Center refresh-content-spinner * Rrd4j: Fix query for custom range - fix start for timeranges with not the first day of the month - fix readonly only worked with debugmode * UI: Migration to angular 18 - Update Angular, Zone.js, Typescript * UI: Eslint: no-multiple-empty-lines * UI: fix tooltip afterTitle display bug * UI: enforce double quotes - Enforce usage of double quotes - prohibit single quotes - backticks are still usable -> [ref](https://eslint.org/docs/latest/rules/quotes#double) * UI: add exhaustive switch eslint rule - Add eslint rule [`switch-exhaustiveness-check`](https://typescript-eslint.io/rules/switch-exhaustiveness-check/) * UI: App: Update android api due to googles new policy - Updating android api level due to googles new policy, enforcing `ANDROID_API_LEVEL=34` to be minimum version * Build android app - Add CI pipeline for building Android apps * GridOptimizedCharge: avoid fail state in OFF * UI: Reduce history queries & overloading of chartData - If a history chart takes too long to load and the user switches the timerange, the old timerange will be shown instead of the actual one (at least for a few seconds, until the new chart is finished) * UI: Replace `setCurrentComponent` with `getCurrentEdge` - Replace `setCurrentComponent` with `getCurrentEdge`, setCurrentComponent is already deprecated and shouldnt be used anymore * UI: Unify fixDigitalOutput & singlethreshold history (#1315) - Unify and refactor all FixDigitalOutputControllers and SingleThresholds in one widget in history - Refactoring them and using the new `CumulatedLevelActiveTime`-Channel * UI: fix TimeOfUseTariff powerSocChart - Fix `TypeError: this.options.plugins is undefined` - To reproduce the error see "live" screen and open the modal for Time-of-Use with ADMIN role. --------- Co-authored-by: Lukas Rieger <[email protected]> Co-authored-by: Michael Grill <[email protected]> Co-authored-by: Kai Jeschek <[email protected]> Co-authored-by: Johann Kaufmann <[email protected]> Co-authored-by: Fabian Brandtner <[email protected]> Co-authored-by: Sebastian Asen <[email protected]> Reviewed-by: Sagar Venu <[email protected]> Reviewed-by: Lukas Rieger <[email protected]> Reviewed-by: Sebastian Asen <[email protected]> Reviewed-by: Stefan Feilmeier <[email protected]> Reviewed-by: Hueseyin Sahutoglu <[email protected]>
1 parent 31e7c78 commit 4a852f7

File tree

426 files changed

+17338
-17185
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

426 files changed

+17338
-17185
lines changed

.woodpecker/ui-build.yml

+80
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
variables:
2+
- &sftp-settings
3+
server: ${CACHE_SERVER}
4+
username: user
5+
password: pass
6+
ignore_branch: true
7+
port: 2222
8+
path: /cache
9+
mount:
10+
- cache
11+
12+
- &rsync-settings
13+
user: fenecon-docs
14+
hosts:
15+
- ${ARTIFACT_SERVER}
16+
port: 22
17+
key:
18+
from_secret: ssh_key_intranet
19+
args: '-v'
20+
21+
- &main-build
22+
- branch: [main, develop]
23+
- evaluate: 'CI_COMMIT_MESSAGE contains "[APP]"'
24+
- path:
25+
include: ['.woodpecker/ui-build.yml']
26+
on_empty: false
27+
28+
when:
29+
event:
30+
- push
31+
32+
matrix:
33+
THEME:
34+
- fenecon
35+
- heckert
36+
37+
clone:
38+
git:
39+
when: *main-build
40+
image: woodpeckerci/plugin-git
41+
42+
steps:
43+
restore-cache:
44+
when: *main-build
45+
image: appleboy/drone-sftp-cache
46+
settings:
47+
restore: true
48+
<<: *sftp-settings
49+
50+
prepare-environment:
51+
when: *main-build
52+
image: openems-bash
53+
commands:
54+
- export CACHE=$CI_WORKSPACE/cache
55+
- mkdir -p $CI_WORKSPACE/cache build/target
56+
- source tools/common.sh
57+
- common_initialize_environment
58+
- common_build_snapshot_version
59+
- common_save_environment $CI_WORKSPACE/.openems-env
60+
depends_on: [restore-cache]
61+
62+
build-android-app:
63+
when: *main-build
64+
image: openems-android:20.32
65+
environment:
66+
- THEME=${THEME}
67+
commands:
68+
- source $CI_WORKSPACE/.openems-env
69+
- source tools/common.sh
70+
- common_build_android_app
71+
depends_on: [prepare-environment]
72+
73+
refresh-dev-android:
74+
when: *main-build
75+
image: woodpeckerci/rsync:latest
76+
settings:
77+
<<: *rsync-settings
78+
source: $CI_WORKSPACE/ui/android/target/
79+
target: /var/opt/develop/fems-artifacts/html/${CI_COMMIT_BRANCH}
80+
depends_on: [build-android-app]

io.openems.edge.controller.ess.gridoptimizedcharge/src/io/openems/edge/controller/ess/gridoptimizedcharge/ControllerEssGridOptimizedChargeImpl.java

+1-2
Original file line numberDiff line numberDiff line change
@@ -145,8 +145,7 @@ private void updateConfig(Config config) {
145145

146146
@Override
147147
public void run() throws OpenemsNamedException {
148-
149-
if (!this.ess.isManaged()) {
148+
if (!this.ess.isManaged() && this.config.mode() != Mode.OFF) {
150149
this._setConfiguredEssIsNotManaged(true);
151150
return;
152151
}

io.openems.edge.timedata.rrd4j/src/io/openems/edge/timedata/rrd4j/RecordWorker.java

+4-2
Original file line numberDiff line numberDiff line change
@@ -202,8 +202,10 @@ public void collectData() {
202202
protected void forever() throws InterruptedException {
203203
final var record = this.records.take();
204204

205-
if (this.config.readOnly() && this.config.debugMode()) {
206-
this.log.info("Read-Only-Mode is activated. Not writing record: " + record.toString());
205+
if (this.config.readOnly()) {
206+
if (this.config.debugMode()) {
207+
this.log.info("Read-Only-Mode is activated. Not writing record: " + record.toString());
208+
}
207209
return;
208210
}
209211

io.openems.edge.timedata.rrd4j/src/io/openems/edge/timedata/rrd4j/Rrd4jReadHandler.java

+18-4
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import java.time.Instant;
55
import java.time.ZoneOffset;
66
import java.time.ZonedDateTime;
7+
import java.time.temporal.ChronoUnit;
78
import java.util.List;
89
import java.util.Optional;
910
import java.util.Set;
@@ -479,10 +480,10 @@ public SortedMap<ZonedDateTime, SortedMap<ChannelAddress, JsonElement>> queryHis
479480
}, (t, u) -> t, TreeMap::new));
480481
}
481482

482-
private static record Range(ZonedDateTime from, ZonedDateTime to) {
483+
protected static record Range(ZonedDateTime from, ZonedDateTime to) {
483484
}
484485

485-
private static Stream<Range> streamRanges(//
486+
protected static Stream<Range> streamRanges(//
486487
final ZonedDateTime from, //
487488
final ZonedDateTime to, //
488489
final Resolution resolution //
@@ -493,15 +494,16 @@ private static Stream<Range> streamRanges(//
493494
final var builder = Stream.<Range>builder();
494495

495496
var fromRange = from;
496-
var toRange = increase(from, resolution);
497+
498+
var toRange = truncate(increase(from, resolution), resolution);
497499
if (toRange.isAfter(to)) {
498500
toRange = to;
499501
}
500502

501503
while (!fromRange.equals(toRange)) {
502504
builder.accept(new Range(fromRange, toRange));
503505
fromRange = toRange;
504-
toRange = increase(toRange, resolution);
506+
toRange = truncate(increase(fromRange, resolution), resolution);
505507
if (toRange.isAfter(to)) {
506508
toRange = to;
507509
}
@@ -510,6 +512,18 @@ private static Stream<Range> streamRanges(//
510512
return builder.build();
511513
}
512514

515+
private static ZonedDateTime truncate(ZonedDateTime date, Resolution resolution) {
516+
return switch (resolution.getUnit()) {
517+
case DAYS, HALF_DAYS, HOURS, SECONDS, MINUTES, MILLIS, NANOS, MICROS -> {
518+
yield date.truncatedTo(resolution.getUnit());
519+
}
520+
case CENTURIES, DECADES, ERAS, FOREVER, MILLENNIA, YEARS, WEEKS -> {
521+
throw new UnsupportedOperationException();
522+
}
523+
case MONTHS -> date.withDayOfMonth(1).truncatedTo(ChronoUnit.DAYS);
524+
};
525+
}
526+
513527
private static ZonedDateTime increase(ZonedDateTime date, Resolution resolution) {
514528
return switch (resolution.getUnit()) {
515529
case DAYS, HALF_DAYS, HOURS, SECONDS, MINUTES, MILLIS, NANOS, MICROS -> {

io.openems.edge.timedata.rrd4j/test/io/openems/edge/timedata/rrd4j/Rrd4jReadHandlerTest.java

+15
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,21 @@ public void testQueryHistoricDataWithResolution15minutes() throws Exception {
163163
), this.query(new Resolution(15, ChronoUnit.MINUTES)));
164164
}
165165

166+
@Test
167+
public void testStreamRanges() throws Exception {
168+
final var utc = ZoneId.of("UTC");
169+
final var from = ZonedDateTime.of(2023, 12, 26, 0, 0, 0, 0, utc);
170+
final var to = ZonedDateTime.of(2024, 3, 8, 0, 0, 0, 0, utc);
171+
final var result = Rrd4jReadHandler.streamRanges(from, to, new Resolution(1, ChronoUnit.MONTHS)).toList();
172+
assertEquals(4, result.size());
173+
assertEquals(new Rrd4jReadHandler.Range(from, ZonedDateTime.of(2024, 1, 1, 0, 0, 0, 0, utc)), result.get(0));
174+
assertEquals(new Rrd4jReadHandler.Range(ZonedDateTime.of(2024, 1, 1, 0, 0, 0, 0, utc),
175+
ZonedDateTime.of(2024, 2, 1, 0, 0, 0, 0, utc)), result.get(1));
176+
assertEquals(new Rrd4jReadHandler.Range(ZonedDateTime.of(2024, 2, 1, 0, 0, 0, 0, utc),
177+
ZonedDateTime.of(2024, 3, 1, 0, 0, 0, 0, utc)), result.get(2));
178+
assertEquals(new Rrd4jReadHandler.Range(ZonedDateTime.of(2024, 3, 1, 0, 0, 0, 0, utc), to), result.get(3));
179+
}
180+
166181
private SortedMap<ZonedDateTime, SortedMap<ChannelAddress, JsonElement>> query(Resolution resolution)
167182
throws IllegalArgumentException, OpenemsNamedException {
168183
return this.readHandler.queryHistoricData(this.rrdbId, //

tools/common.sh

+33-2
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,9 @@ common_initialize_environment() {
1111
SRC_ANDROID_GRADLE="ui/android/app/build.gradle"
1212

1313
# Set environment variables
14-
THEME="openems"
14+
THEME="${THEME:-openems}"
1515
PACKAGE_NAME="openems-edge"
16+
1617
VERSION_STRING=""
1718
VERSION="$(cd ui && node -p "require('./package.json').version" && cd ..)"
1819
local tmp_version=$(echo $VERSION | cut -d'-' -f1)
@@ -120,6 +121,36 @@ common_build_ui() {
120121
fi
121122
}
122123

124+
common_build_android_app() {
125+
echo "# Build OpenEMS Android APP"
126+
if [ "${NODE_MODULES_CACHE}" != "" -a -d "$NODE_MODULES_CACHE" ]; then
127+
echo "## Use cached node_modules"
128+
mv -f "${NODE_MODULES_CACHE}" "ui/node_modules"
129+
fi
130+
cd ui
131+
132+
# Install dependencies from package.json
133+
npm ci
134+
if [ "${NG_CLI_CACHE_PATH}" != "" ]; then
135+
echo "## Angular Cache: $NG_CLI_CACHE_PATH"
136+
node_modules/.bin/ng config cli.cache.path "$NG_CLI_CACHE_PATH"
137+
fi
138+
139+
case "${THEME^^}" in
140+
"FENECON") NODE_ENV="FENECON";;
141+
"HECKERT") NODE_ENV="Heckert";;
142+
esac
143+
144+
# Install depencencies for capacitor
145+
NODE_ENV=${NODE_ENV} ionic cap build android -c "${THEME},${THEME}-backend-deploy-app"
146+
147+
# Build App
148+
cd android
149+
THEME=${THEME} ./gradlew buildThemeRelease
150+
151+
cd ../..
152+
}
153+
123154
common_save_environment() {
124155
local file=${1:-build.environment}
125156
echo "
@@ -132,4 +163,4 @@ common_save_environment() {
132163
export VERSION_DEV_COMMIT=\"$VERSION_DEV_COMMIT\"
133164
export VERSION_DEV_BUILD_TIME=\"$VERSION_DEV_BUILD_TIME\"
134165
" | tee $file
135-
}
166+
}

tools/drone/openems-android.sh

+5-3
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@
22

33
NODE_MAJOR=20
44

5-
ANDROID_SDK_VERSION=9477386
5+
ANDROID_SDK_VERSION=11076708
66
ANDROID_HOME="/opt/android-sdk"
7-
ANDROID_BUILD_TOOLS_VERSION=32.0.0
8-
ANDROID_PLATFORMS_VERSION=32
7+
ANDROID_BUILD_TOOLS_VERSION=34.0.0
8+
ANDROID_PLATFORMS_VERSION=34
99

1010
# Build/Update 'openems-android' Container for Drone/Woodpecker CI
1111

@@ -14,6 +14,8 @@ docker pull node:${NODE_MAJOR}
1414
docker build -t openems-android:${NODE_MAJOR}.${ANDROID_PLATFORMS_VERSION} -f - . <<EOF
1515
FROM node:${NODE_MAJOR}
1616
17+
SHELL ["/bin/bash", "-c"]
18+
1719
RUN apt-get update \
1820
&& apt-get install --no-install-recommends -y git nodejs wget unzip android-sdk;
1921

ui/.eslintrc.json

+12-1
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,18 @@
8888
}
8989
}
9090
],
91-
"@typescript-eslint/member-ordering": "error"
91+
"@typescript-eslint/member-ordering": "error",
92+
"no-multiple-empty-lines": "error",
93+
"quotes": [
94+
"error",
95+
"double"
96+
],
97+
"@typescript-eslint/switch-exhaustiveness-check": [
98+
"error",
99+
{
100+
"allowDefaultCaseForExhaustiveSwitch": false
101+
}
102+
]
92103
}
93104
},
94105
{

ui/.vscode/settings.json

+3-2
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@
1818
"editor.codeActionsOnSave": {
1919
"source.organizeImports": "explicit",
2020
"source.removeUnusedImports": "explicit"
21-
}
21+
},
22+
"typescript.preferences.quoteStyle": "double"
2223
},
2324
"[jsonc]": {
2425
"editor.defaultFormatter": "vscode.json-language-features"
@@ -46,5 +47,5 @@
4647
"**/node_modules",
4748
"*.svg",
4849
"*.scss"
49-
]
50+
],
5051
}

0 commit comments

Comments
 (0)