Skip to content

Commit

Permalink
Merge branch 'develop' into feature/ui-dev/unittestForFixDigitalOutput
Browse files Browse the repository at this point in the history
# Conflicts:
#	ui/src/app/shared/genericComponents/modal/modal.ts
  • Loading branch information
lukasrgr committed Aug 23, 2023
2 parents 9c766f3 + 94c7111 commit ce6255c
Show file tree
Hide file tree
Showing 258 changed files with 8,479 additions and 4,292 deletions.
4 changes: 2 additions & 2 deletions cnf/build.bnd
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,12 @@ buildpath: \
org.osgi.service.metatype;version='1.4.1',\
org.osgi.service.metatype.annotations;version='1.4.1',\
org.osgi.util.promise;version='1.2.0',\
com.google.guava;version='32.1.1.jre',\
com.google.guava;version='32.1.2.jre',\
com.google.gson;version='2.10.1',\

testpath: \
slf4j.simple,\
\${junit}
\${junit}

# OpenEMS Eclipse IDE Workingsets
-workingset = \
Expand Down
18 changes: 9 additions & 9 deletions cnf/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>32.1.1-jre</version>
<version>32.1.2-jre</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
Expand All @@ -60,7 +60,7 @@
<!-- Used by com.squareup.okhttp3: okhttp -->
<groupId>com.squareup.okio</groupId>
<artifactId>okio-jvm</artifactId>
<version>3.4.0</version>
<version>3.5.0</version>
</dependency>
<dependency>
<!-- Used by com.influxdb: influxdb-client -->
Expand Down Expand Up @@ -117,7 +117,7 @@
<!-- Changelog: https://github.com/PgBulkInsert/PgBulkInsert/blob/master/CHANGELOG.md-->
<groupId>de.bytefish</groupId>
<artifactId>pgbulkinsert</artifactId>
<version>8.1.0</version>
<version>8.1.1</version>
</dependency>
<!-- eu -->
<dependency>
Expand Down Expand Up @@ -261,7 +261,7 @@
<!-- Changelog: https://github.com/typetools/checker-framework/blob/master/docs/CHANGELOG.md -->
<groupId>org.checkerframework</groupId>
<artifactId>checker-qual</artifactId>
<version>3.36.0</version>
<version>3.37.0</version>
</dependency>
<dependency>
<groupId>org.dhatim</groupId>
Expand All @@ -277,22 +277,22 @@
<dependency>
<groupId>com.influxdb</groupId>
<artifactId>influxdb-client-java</artifactId>
<version>6.9.0</version>
<version>6.10.0</version>
</dependency>
<dependency>
<groupId>com.influxdb</groupId>
<artifactId>influxdb-client-core</artifactId>
<version>6.9.0</version>
<version>6.10.0</version>
</dependency>
<dependency>
<groupId>com.influxdb</groupId>
<artifactId>influxdb-client-utils</artifactId>
<version>6.9.0</version>
<version>6.10.0</version>
</dependency>
<dependency>
<groupId>com.influxdb</groupId>
<artifactId>flux-dsl</artifactId>
<version>6.9.0</version>
<version>6.10.0</version>
</dependency>
<dependency>
<groupId>org.java-websocket</groupId>
Expand All @@ -307,7 +307,7 @@
<dependency>
<groupId>org.jetbrains.kotlinx</groupId>
<artifactId>kotlinx-coroutines-core-jvm</artifactId>
<version>1.7.2</version>
<version>1.7.3</version>
</dependency>
<dependency>
<!-- HTML processing -->
Expand Down
2 changes: 1 addition & 1 deletion doc/modules/ROOT/pages/backend/backend-to-backend.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ https://github.com/OpenEMS/openems/blob/develop/io.openems.backend.b2bwebsocket/

=== SubscribeToChannels

Registers a subscription for regular updates of channel values. Request is acknowledged by an empty success Response and followed by regular JSON-RPC Notifications. Du stop the subscription, an empty 'subscribeEdgesChannels' Request needs to be sent.
Registers a subscription for regular updates of channel values. Request is acknowledged by an empty success Response and followed by regular JSON-RPC Notifications. To stop the subscription, an empty 'subscribeEdgesChannels' Request needs to be sent.

The parameter "count" must be increased with each new Request. Only the Request with the highest "count" value is active.

Expand Down
8 changes: 5 additions & 3 deletions io.openems.backend.application/BackendApp.bndrun
Original file line number Diff line number Diff line change
Expand Up @@ -51,18 +51,19 @@
bnd.identity;id='io.openems.backend.metadata.dummy',\
bnd.identity;id='io.openems.backend.metadata.file',\
bnd.identity;id='io.openems.backend.metadata.odoo',\
bnd.identity;id='io.openems.backend.timedata.aggregatedinflux',\
bnd.identity;id='io.openems.backend.timedata.dummy',\
bnd.identity;id='io.openems.backend.timedata.influx',\
bnd.identity;id='io.openems.backend.timedata.timescaledb',\
bnd.identity;id='io.openems.backend.uiwebsocket',\

-runbundles: \
Java-WebSocket;version='[1.5.4,1.5.5)',\
checker-qual;version='[3.36.0,3.36.1)',\
checker-qual;version='[3.37.0,3.37.1)',\
com.google.gson;version='[2.10.1,2.10.2)',\
com.google.guava;version='[32.1.1,32.1.2)',\
com.google.guava;version='[32.1.2,32.1.3)',\
com.google.guava.failureaccess;version='[1.0.1,1.0.2)',\
com.squareup.okio;version='[3.4.0,3.4.1)',\
com.squareup.okio;version='[3.5.0,3.5.1)',\
com.zaxxer.HikariCP;version='[5.0.1,5.0.2)',\
io.openems.backend.alerting;version=snapshot,\
io.openems.backend.application;version=snapshot,\
Expand All @@ -74,6 +75,7 @@
io.openems.backend.metadata.dummy;version=snapshot,\
io.openems.backend.metadata.file;version=snapshot,\
io.openems.backend.metadata.odoo;version=snapshot,\
io.openems.backend.timedata.aggregatedinflux;version=snapshot,\
io.openems.backend.timedata.dummy;version=snapshot,\
io.openems.backend.timedata.influx;version=snapshot,\
io.openems.backend.timedata.timescaledb;version=snapshot,\
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,75 @@

import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.TreeSet;

import com.google.gson.JsonElement;
import com.google.gson.JsonNull;

import io.openems.common.jsonrpc.notification.AggregatedDataNotification;
import io.openems.common.jsonrpc.notification.TimestampedDataNotification;

public class EdgeCache {

/**
* The Timestamp of the data in the Cache.
*/
private long timestamp = 0L;
private final ChannelDataCache current = new ChannelDataCache();
private final ChannelDataCache aggregated = new ChannelDataCache();

public static record Pair<A, B>(A a, B b) {

}

private static class ChannelDataCache {
private long timestamp = 0L;
private final HashMap<String, JsonElement> data = new HashMap<>();

/**
* Gets the channel value from cache.
*
* @param address the Channel-Address of the channel
* @return the value; {@link JsonNull} if it is not in cache
*/
public final JsonElement getChannelValue(String address) {
synchronized (this) {
return this.data.get(address);
}
}

/**
* Updates the Cache.
*
* @param incomingDatas the incoming data
*/
public void update(SortedMap<Long, Map<String, JsonElement>> incomingDatas) {
for (var entry : incomingDatas.entrySet()) {
var incomingTimestamp = entry.getKey();
var incomingData = entry.getValue();

private final HashMap<String, JsonElement> data = new HashMap<>();
// Check if cache should be applied
if (incomingTimestamp < this.timestamp) {
// Incoming data is older than cache -> do not apply cache

} else {
// Incoming data is more recent than cache

if (incomingTimestamp > this.timestamp + 15 * 60 * 1000) {
// Cache is not anymore valid (elder than 15 minutes) -> clear Cache
synchronized (this) {
this.data.clear();
}
}

// update cache
this.timestamp = incomingTimestamp;
synchronized (this) {
this.data.putAll(incomingData);
}
}
}
}
}

/**
* Gets the channel value from cache.
Expand All @@ -24,46 +79,61 @@ public class EdgeCache {
* @return the value; {@link JsonNull} if it is not in cache
*/
public final JsonElement getChannelValue(String address) {
synchronized (this) {
var result = this.data.get(address);
if (result == null) {
return JsonNull.INSTANCE;
}
final var result = this.current.getChannelValue(address);
if (result != null) {
return result;
}
final var aggregatedResult = this.aggregated.getChannelValue(address);
if (aggregatedResult != null) {
return aggregatedResult;
}
return JsonNull.INSTANCE;
}

/**
* Updates the Cache.
* Gets the channel values from cache.
*
* @param incomingDatas the incoming data
* @param addresses the Channel-Addresses of the channels
* @return a) Map of Channel-Address to values ({@link JsonNull} if not in
* cache); b) Set of Channel-Addresses that are only available as
* aggregated data
*/
public void update(SortedMap<Long, Map<String, JsonElement>> incomingDatas) {
for (Entry<Long, Map<String, JsonElement>> entry : incomingDatas.entrySet()) {
var incomingTimestamp = entry.getKey();
var incomingData = entry.getValue();

// Check if cache should be applied
if (incomingTimestamp < this.timestamp) {
// Incoming data is older than cache -> do not apply cache

} else {
// Incoming data is more recent than cache

if (incomingTimestamp > this.timestamp + 15 * 60 * 1000) {
// Cache is not anymore valid (elder than 15 minutes) -> clear Cache
synchronized (this) {
this.data.clear();
}
}

// update cache
this.timestamp = incomingTimestamp;
synchronized (this) {
this.data.putAll(incomingData);
}
public final Pair<Map<String, JsonElement>, Set<String>> getChannelValues(Set<String> addresses) {
final var result = new TreeMap<String, JsonElement>();
final var aggregatedChannelValues = new TreeSet<String>();
for (var address : addresses) {
final var value = this.current.getChannelValue(address);
if (value != null) {
result.put(address, value);
continue;
}
final var aggregatedValue = this.aggregated.getChannelValue(address);
if (aggregatedValue != null) {
result.put(address, aggregatedValue);
aggregatedChannelValues.add(address);
continue;
}
result.put(address, JsonNull.INSTANCE);
}
return new Pair<>(result, aggregatedChannelValues);
}

/**
* Updates the Cache.
*
* @param notification the incoming data
*/
public void updateCurrentData(TimestampedDataNotification notification) {
this.current.update(notification.getData().rowMap());
}

/**
* Updates the aggregated data cache.
*
* @param notification the incoming data
*/
public void updateAggregatedData(AggregatedDataNotification notification) {
this.aggregated.update(notification.getData().rowMap());
}

}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package io.openems.backend.common.edgewebsocket;

import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.concurrent.CompletableFuture;

import org.osgi.annotation.versioning.ProviderType;
Expand Down Expand Up @@ -62,6 +62,6 @@ public CompletableFuture<JsonrpcResponseSuccess> handleSubscribeSystemLogRequest
* @param channelAddresses The {@link ChannelAddress}es
* @return the values; possibly {@link JsonNull}
*/
public Map<ChannelAddress, JsonElement> getChannelValues(String edgeId, Set<ChannelAddress> channelAddresses);
public SortedMap<ChannelAddress, JsonElement> getChannelValues(String edgeId, Set<ChannelAddress> channelAddresses);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package io.openems.backend.common.timedata;

import java.time.ZonedDateTime;
import java.util.Set;
import java.util.SortedMap;

import org.osgi.annotation.versioning.ProviderType;

import com.google.gson.JsonElement;

import io.openems.common.exceptions.OpenemsError.OpenemsNamedException;
import io.openems.common.jsonrpc.notification.AggregatedDataNotification;
import io.openems.common.jsonrpc.notification.ResendDataNotification;
import io.openems.common.jsonrpc.notification.TimestampedDataNotification;
import io.openems.common.timedata.CommonTimedataService;
import io.openems.common.types.ChannelAddress;

@ProviderType
public interface BackendTimedata extends CommonTimedataService {

/**
* Sends the data points to the Timedata service.
*
* @param edgeId The unique Edge-ID
* @param data Table of timestamp (epoch in milliseconds), Channel-Address and
* the Channel value as JsonElement. Sorted by timestamp.
*/
public void write(String edgeId, TimestampedDataNotification data);

/**
* Sends the data points to the Timedata service.
*
* @param edgeId The unique Edge-ID
* @param data Table of timestamp (epoch in milliseconds), Channel-Address and
* the Channel value as AggregatedData. Sorted by timestamp.
*/
public void write(String edgeId, AggregatedDataNotification data);

/**
* Sends the data points to the Timedata service.
*
* @param edgeId The unique Edge-ID
* @param data Table of timestamp (epoch in milliseconds), Channel-Address and
* the Channel value as ResendData. Sorted by timestamp.
*/
public void write(String edgeId, ResendDataNotification data);

/**
* Queries the latest values which are before the given {@link ZonedDateTime}.
*
* @param edgeId the id of the edge
* @param date the bounding date exclusive
* @param channels the channels
* @return the channel values
* @throws OpenemsNamedException on error
*/
public default SortedMap<ChannelAddress, JsonElement> queryFirstValueBefore(//
final String edgeId, //
final ZonedDateTime date, //
final Set<ChannelAddress> channels //
) throws OpenemsNamedException {
return null;
}

}
Loading

0 comments on commit ce6255c

Please sign in to comment.