-
Notifications
You must be signed in to change notification settings - Fork 403
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
260 changed files
with
13,753 additions
and
2,180 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
/bin/ | ||
/bin_test/ | ||
/generated/ |
2 changes: 1 addition & 1 deletion
2
...edge.controller.ess.onefullcycle/.project → io.openems.backend.alerting/.project
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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} |
224 changes: 224 additions & 0 deletions
224
io.openems.backend.alerting/src/io/openems/backend/alerting/Alerting.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | ||
} | ||
} |
12 changes: 12 additions & 0 deletions
12
io.openems.backend.alerting/src/io/openems/backend/alerting/Config.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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"; | ||
|
||
} |
69 changes: 69 additions & 0 deletions
69
io.openems.backend.alerting/src/io/openems/backend/alerting/Message.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} | ||
} |
Oops, something went wrong.