Skip to content

Commit

Permalink
Merge branch 'release/2022.5.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
sfeilmeier committed May 1, 2022
2 parents 3be6a88 + 40e9625 commit a45ce89
Show file tree
Hide file tree
Showing 260 changed files with 13,753 additions and 2,180 deletions.
8 changes: 4 additions & 4 deletions cnf/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@
<!-- Used by SDNotify -->
<groupId>net.java.dev.jna</groupId>
<artifactId>jna</artifactId>
<version>5.10.0</version>
<version>5.11.0</version>
</dependency>
<!-- org -->
<dependency>
Expand All @@ -164,7 +164,7 @@
<!-- Changelog: https://github.com/apache/felix-dev/blob/master/configadmin/changelog.txt -->
<groupId>org.apache.felix</groupId>
<artifactId>org.apache.felix.configadmin</artifactId>
<version>1.9.22</version>
<version>1.9.24</version>
</dependency>
<dependency>
<!-- Apache Felix EventAdmin -->
Expand Down Expand Up @@ -254,7 +254,7 @@
<dependency>
<groupId>org.java-websocket</groupId>
<artifactId>Java-WebSocket</artifactId>
<version>1.5.2</version>
<version>1.5.3</version>
</dependency>
<dependency>
<!-- HTML processing -->
Expand Down Expand Up @@ -306,7 +306,7 @@
<!-- Used by io.openems.backend.metadata.odoo -->
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>42.3.3</version>
<version>42.3.4</version>
</dependency>
<dependency>
<!-- Used by io.openems.edge.timedata.rrd4j -->
Expand Down
2 changes: 1 addition & 1 deletion doc/modules/ROOT/pages/single_document.adoc
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
= OpenEMS - Open Energy Management System
ifndef::toc[]
(c) 2022 OpenEMS Association e.V.
Version 2022.4.0
Version 2022.5.0
:sectnums:
:sectnumlevels: 4
:toc:
Expand Down
12 changes: 12 additions & 0 deletions io.openems.backend.alerting/.classpath
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="con" path="aQute.bnd.classpath.container"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11"/>
<classpathentry kind="src" output="bin" path="src"/>
<classpathentry kind="src" output="bin_test" path="test">
<attributes>
<attribute name="test" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="output" path="bin"/>
</classpath>
3 changes: 3 additions & 0 deletions io.openems.backend.alerting/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
/bin/
/bin_test/
/generated/
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>io.openems.edge.controller.ess.onefullcycle</name>
<name>io.openems.backend.alerting</name>
<comment></comment>
<projects>
</projects>
Expand Down
12 changes: 12 additions & 0 deletions io.openems.backend.alerting/bnd.bnd
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
Bundle-Name: OpenEMS Backend Alerting
Bundle-Vendor: FENECON GmbH
Bundle-License: https://opensource.org/licenses/EPL-2.0
Bundle-Version: 1.0.0.${tstamp}

-buildpath: \
${buildpath},\
io.openems.backend.common,\
io.openems.common,\

-testpath: \
${testpath}
Original file line number Diff line number Diff line change
@@ -0,0 +1,224 @@
package io.openems.backend.alerting;

import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.TreeMap;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;

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.event.Event;
import org.osgi.service.event.EventAdmin;
import org.osgi.service.event.EventHandler;
import org.osgi.service.event.propertytypes.EventTopics;
import org.osgi.service.metatype.annotations.Designate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import io.openems.backend.common.component.AbstractOpenemsBackendComponent;
import io.openems.backend.common.metadata.Edge;
import io.openems.backend.common.metadata.EdgeUser;
import io.openems.backend.common.metadata.Mailer;
import io.openems.backend.common.metadata.Metadata;
import io.openems.common.event.EventReader;

@Designate(ocd = Config.class, factory = false)
@Component(//
name = "Alerting", //
configurationPolicy = ConfigurationPolicy.REQUIRE, //
immediate = true //
)
@EventTopics({ //
Edge.Events.ON_SET_ONLINE, //
Metadata.Events.AFTER_IS_INITIALIZED //
})
public class Alerting extends AbstractOpenemsBackendComponent implements EventHandler {

public static final int INITIAL_DELAY = 15; // Minutes

private final Logger log = LoggerFactory.getLogger(Alerting.class);
protected final ScheduleMessageService tasks;

@Reference
protected Metadata metadata;

@Reference
protected EventAdmin eventAdmin;

@Reference
protected Mailer notifier;

public Alerting() {
super("Alerting");

this.tasks = new ScheduleMessageService(this, this.actionTimeout);
}

/**
* executed action after waiting time ends.
*/
private Consumer<Message> actionTimeout = (message) -> {
var timeStamp = message.getTimeStamp();
var listUser = message.getUser();

this.sendEmails(timeStamp, listUser);
};

@Activate
private void activate(Config config) {
this.logInfo(this.log, "Activate");

this.tasks.start();

/* load all cached edges */
if (this.metadata.isInitialized()) {
this.checkMetadata();
}
}

@Deactivate
private void deactivate() {
this.logInfo(this.log, "Deactivate");

this.tasks.stop();
}

private void checkMetadata() {
this.metadata.getAllEdges().forEach(edge -> {
if (!edge.isOnline()) {
this.tryAddEdge(edge);
}
});
}

/**
* add Edge to list, with calculated TimeStamp (at which to notify).
*
* @param edge to add
*/
private void tryAddEdge(Edge edge) {
if (edge.getUser().isEmpty()) {
return;
}

ZonedDateTime now = ZonedDateTime.now();
Map<ZonedDateTime, List<EdgeUser>> edgeUsers = new TreeMap<>();
edge.getUser().forEach(user -> {
this.getNotifyStamp(edge, user).ifPresent(notifyStamp -> {
if (notifyStamp.isBefore(now)) {
notifyStamp = now;
}

edgeUsers.putIfAbsent(notifyStamp, new ArrayList<>());
edgeUsers.get(notifyStamp).add(user);
});
});
if (!edgeUsers.isEmpty()) {
this.tasks.createTask(edgeUsers, edge.getId());
}
}

/**
* send e-mail via notifier service.
*
* @param stamp at with mail send was initialized
* @param user list of recipents
*/
private void sendEmails(ZonedDateTime stamp, List<EdgeUser> user) {
// log to Console
this.logInfo(this.log, "send Email - to " + user.size() + " user");
this.notifier.sendAlertingMail(stamp, user);
}

/**
* get TimeStamp of next notification or null if no notification is needed.
*
* @param edge thats involved
* @param user that will recieve the mail
* @return Optional of ZonedDateTime
*/
private Optional<ZonedDateTime> getNotifyStamp(Edge edge, EdgeUser user) {
ZonedDateTime lastStamp = user.getLastNotification(ZoneId.systemDefault());
ZonedDateTime lastOnline = edge.getLastMessageTimestamp();

ZonedDateTime notifyStamp = null;
if (lastOnline == null) {
this.logDebug(this.log, "[" + edge.getId() + "] has no TimeStamp");
} else {
int timeToWait = user.getTimeToWait();

// tmeToWait <= 0 equals OFF
if (timeToWait > 0) {
notifyStamp = lastOnline.withZoneSameInstant(ZoneId.systemDefault()) //
.plus(timeToWait, ChronoUnit.MINUTES);

if (lastStamp != null && !notifyStamp.isAfter(lastStamp)) {
notifyStamp = null;
}
}
}
return Optional.ofNullable(notifyStamp);
}

private void handleEdgeOnSetOnline(EventReader reader) {
boolean isOnline = reader.getBoolean(Edge.Events.OnSetOnline.IS_ONLINE);
Edge edge = reader.getProperty(Edge.Events.OnSetOnline.EDGE);

if (isOnline) {
this.tasks.removeAll(edge.getId());
} else {
this.tryAddEdge(edge);
}
}

private void handleMetadataAfterInitialize(EventReader reader) {
Executors.newSingleThreadScheduledExecutor().schedule(() -> {
this.checkMetadata();
}, Alerting.INITIAL_DELAY, TimeUnit.MINUTES);
}

@Override
public void handleEvent(Event event) {
EventReader reader = new EventReader(event);

switch (event.getTopic()) {
case Edge.Events.ON_SET_ONLINE:
this.handleEdgeOnSetOnline(reader);
break;

case Metadata.Events.AFTER_IS_INITIALIZED:
this.handleMetadataAfterInitialize(reader);
break;
}
}

@Override
protected void logInfo(Logger log, String message) {
super.logInfo(log, message);
}

@Override
protected void logError(Logger log, String message) {
super.logError(log, message);
}

@Override
protected void logWarn(Logger log, String message) {
super.logWarn(log, message);
}

@Override
protected void logDebug(Logger log, String message) {
super.logDebug(log, message);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package io.openems.backend.alerting;

import org.osgi.service.metatype.annotations.ObjectClassDefinition;

@ObjectClassDefinition(//
name = "Alerting", //
description = "Configures the Notification Service")
public @interface Config {

String webconsole_configurationFactory_nameHint() default "Alerting";

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package io.openems.backend.alerting;

import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

import io.openems.backend.common.metadata.EdgeUser;

/**
* Properties for one notification.
*/
public class Message implements Comparable<Message> {
private final List<EdgeUser> userList;
private final ZonedDateTime notifyStamp;

public Message(ZonedDateTime notifyStamp) {
this(notifyStamp, new ArrayList<>());
}

public Message(ZonedDateTime notifyStamp, List<EdgeUser> users) {
this.userList = users;
this.notifyStamp = notifyStamp;
}

public ZonedDateTime getTimeStamp() {
return this.notifyStamp.withZoneSameInstant(ZoneId.systemDefault());
}

@Override
public int compareTo(Message o) {
return this.notifyStamp.compareTo(o.notifyStamp);
}

@Override
public int hashCode() {
return Objects.hash(this.notifyStamp);
}

@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if ((obj == null) || (getClass() != obj.getClass())) {
return false;
}
Message other = (Message) obj;
return Objects.equals(this.notifyStamp, other.notifyStamp);
}

/**
* Add User to UserList.
*
* @param user to add
*/
public void addUser(EdgeUser user) {
this.userList.add(user);
}

public List<EdgeUser> getUser() {
return this.userList;
}

public ZonedDateTime getNotifyStamp() {
return this.notifyStamp;
}
}
Loading

0 comments on commit a45ce89

Please sign in to comment.