From 9af96a7cb2cc5c4390d99c2760ae3881d2011e3e Mon Sep 17 00:00:00 2001 From: Ziver Koc Date: Fri, 10 Mar 2017 16:59:07 +0100 Subject: [PATCH] Implementation of Event based triggering. issue 51 --- build.xml | 1 - resource/web/trigger.tmpl | 4 +- src/se/hal/ControllerManager.java | 6 ++ src/se/hal/action/SendEventAction.java | 4 +- src/se/hal/intf/HalDeviceReportListener.java | 14 ++++ src/se/hal/plugin.json | 1 + src/se/hal/struct/AbstractDevice.java | 41 +++++++--- src/se/hal/struct/Event.java | 4 +- src/se/hal/struct/Sensor.java | 5 +- src/se/hal/trigger/EventTrigger.java | 84 ++++++++++++++++++++ 10 files changed, 144 insertions(+), 20 deletions(-) create mode 100755 src/se/hal/intf/HalDeviceReportListener.java create mode 100755 src/se/hal/trigger/EventTrigger.java diff --git a/build.xml b/build.xml index 88337c2a..d2047cc6 100755 --- a/build.xml +++ b/build.xml @@ -103,7 +103,6 @@ -
- {{.getClass().getName()}} + {{.getObjectClass()}}
@@ -95,7 +95,7 @@
- {{.getClass().getName()}} + {{.getObjectClass()}} diff --git a/src/se/hal/ControllerManager.java b/src/se/hal/ControllerManager.java index 6685a2a1..adafa0bb 100755 --- a/src/se/hal/ControllerManager.java +++ b/src/se/hal/ControllerManager.java @@ -161,6 +161,9 @@ public class ControllerManager implements HalSensorReportListener, sensor.setDeviceConfig(sensorConfig); } sensor.setDeviceData(sensorData); + // call listeners + for(HalDeviceReportListener listener : sensor.getReportListeners()) + listener.receivedReport(sensor); }catch (SQLException e){ logger.log(Level.WARNING, "Unable to store sensor report", e); @@ -284,6 +287,9 @@ public class ControllerManager implements HalSensorReportListener, event.setDeviceConfig(eventConfig); } event.setDeviceData(eventData); + // call listeners + for(HalDeviceReportListener listener : event.getReportListeners()) + listener.receivedReport(event); }catch (SQLException e){ logger.log(Level.WARNING, "Unable to store event report", e); diff --git a/src/se/hal/action/SendEventAction.java b/src/se/hal/action/SendEventAction.java index 3698ccb5..4b8b422d 100755 --- a/src/se/hal/action/SendEventAction.java +++ b/src/se/hal/action/SendEventAction.java @@ -18,9 +18,9 @@ import java.util.logging.Logger; public class SendEventAction implements HalAction { private static final Logger logger = LogUtil.getLogger(); - @Configurator.Configurable(order = 1, value = "Event Device ID") + @Configurator.Configurable("Event Device ID") private int eventId; - @Configurator.Configurable(order = 1, value = "Data to Send") + @Configurator.Configurable("Data to Send") private double data; diff --git a/src/se/hal/intf/HalDeviceReportListener.java b/src/se/hal/intf/HalDeviceReportListener.java new file mode 100755 index 00000000..5083b76d --- /dev/null +++ b/src/se/hal/intf/HalDeviceReportListener.java @@ -0,0 +1,14 @@ +package se.hal.intf; + +import se.hal.struct.AbstractDevice; + +/** + * A listener interface that will be called when the + * Event or Sensor that it is registered to receives a report + * + * @param is the device type + */ +public interface HalDeviceReportListener { + + void receivedReport(T device); +} diff --git a/src/se/hal/plugin.json b/src/se/hal/plugin.json index 4b6d6752..0fe86c7c 100755 --- a/src/se/hal/plugin.json +++ b/src/se/hal/plugin.json @@ -20,6 +20,7 @@ {"se.hal.intf.HalTrigger": "se.hal.trigger.DateTimeTrigger"}, + {"se.hal.intf.HalTrigger": "se.hal.trigger.EventTrigger"}, {"se.hal.intf.HalTrigger": "se.hal.trigger.TimerTrigger"}, {"se.hal.intf.HalAction": "se.hal.action.SendEventAction"} ] diff --git a/src/se/hal/struct/AbstractDevice.java b/src/se/hal/struct/AbstractDevice.java index 8302bbd0..b3573d78 100755 --- a/src/se/hal/struct/AbstractDevice.java +++ b/src/se/hal/struct/AbstractDevice.java @@ -2,6 +2,7 @@ package se.hal.struct; import se.hal.ControllerManager; import se.hal.HalContext; +import se.hal.intf.HalDeviceReportListener; import zutil.db.DBConnection; import zutil.db.bean.DBBean; import zutil.log.LogUtil; @@ -10,13 +11,19 @@ import zutil.parser.json.JSONWriter; import zutil.ui.Configurator; import java.sql.SQLException; +import java.util.LinkedList; +import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; /** - * Created by Ziver on 2016-01-15. + * Contains logic and data common to devices (Events and Sensors) + * + * @param is the device type + * @param is the device configuration class + * @param is the device data class */ -public abstract class AbstractDevice extends DBBean { +public abstract class AbstractDevice extends DBBean { private static final Logger logger = LogUtil.getLogger(); // Sensor specific data @@ -25,7 +32,7 @@ public abstract class AbstractDevice extends DBBean { private String config; // only used to store the deviceConfig configuration in DB /** Sensor specific configuration **/ - private transient T deviceConfig; + private transient C deviceConfig; /** latest device data received **/ private transient D deviceData; @@ -39,24 +46,26 @@ public abstract class AbstractDevice extends DBBean { @DBColumn("map_y") private double y; + protected transient List> listeners = new LinkedList<>(); + /**************** DEVICE CONFIG ******************/ - public Configurator getDeviceConfigurator() { - T obj = getDeviceConfig(); + public Configurator getDeviceConfigurator() { + C obj = getDeviceConfig(); if (obj != null) { - Configurator configurator = new Configurator<>(obj); + Configurator configurator = new Configurator<>(obj); configurator.setPreConfigurationListener(ControllerManager.getInstance()); configurator.setPostConfigurationListener(ControllerManager.getInstance()); return configurator; } return null; } - public T getDeviceConfig() { + public C getDeviceConfig() { if (deviceConfig == null || !deviceConfig.getClass().getName().equals(type)) { try { Class c = Class.forName(type); - deviceConfig = (T) c.newInstance(); + deviceConfig = (C) c.newInstance(); applyConfig(); deviceData = getLatestDeviceData(HalContext.getDB()); @@ -72,7 +81,7 @@ public abstract class AbstractDevice extends DBBean { * And the current config will be applied on the new DeviceData. * DeviceData will be reset if the input is set as null. */ - public void setDeviceConfig(T data) { + public void setDeviceConfig(C data) { if(data != null) { type = data.getClass().getName(); deviceConfig = data; @@ -98,7 +107,7 @@ public abstract class AbstractDevice extends DBBean { * Will update the config String that will be stored in DB. */ private void updateConfigString() { - Configurator configurator = getDeviceConfigurator(); + Configurator configurator = getDeviceConfigurator(); this.config = JSONWriter.toString(configurator.getValuesAsNode()); } /** @@ -107,12 +116,13 @@ public abstract class AbstractDevice extends DBBean { */ private void applyConfig(){ if (config != null && !config.isEmpty()) { - Configurator configurator = getDeviceConfigurator(); + Configurator configurator = getDeviceConfigurator(); configurator.setValues(JSONParser.read(config)); configurator.applyConfiguration(); } } + public abstract Class getController(); /**************** DEVICE DATA ******************/ @@ -180,4 +190,13 @@ public abstract class AbstractDevice extends DBBean { this.y = y; } + public void addReportListener(HalDeviceReportListener listener){ + listeners.add(listener); + } + public void removeReportListener(HalDeviceReportListener listener){ + listeners.remove(listener); + } + public List> getReportListeners(){ + return listeners; + } } diff --git a/src/se/hal/struct/Event.java b/src/se/hal/struct/Event.java index 82c5dbf6..17f2fa7a 100755 --- a/src/se/hal/struct/Event.java +++ b/src/se/hal/struct/Event.java @@ -24,7 +24,7 @@ import java.util.logging.Logger; * Created by Ziver on 2015-12-15. */ @DBBean.DBTable(value="event", superBean=true) -public class Event extends AbstractDevice{ +public class Event extends AbstractDevice{ private static final Logger logger = LogUtil.getLogger(); @@ -40,7 +40,7 @@ public class Event extends AbstractDevice{ - + @Override public Class getController(){ return getDeviceConfig().getEventControllerClass(); } diff --git a/src/se/hal/struct/Sensor.java b/src/se/hal/struct/Sensor.java index 7b1611fd..f79e4e49 100755 --- a/src/se/hal/struct/Sensor.java +++ b/src/se/hal/struct/Sensor.java @@ -1,6 +1,7 @@ package se.hal.struct; import se.hal.HalContext; +import se.hal.intf.HalDeviceReportListener; import se.hal.intf.HalSensorController; import se.hal.intf.HalSensorConfig; import se.hal.intf.HalSensorData; @@ -19,7 +20,7 @@ import java.util.logging.Logger; @DBBean.DBTable(value="sensor", superBean=true) -public class Sensor extends AbstractDevice{ +public class Sensor extends AbstractDevice{ private static final Logger logger = LogUtil.getLogger(); private long external_id = -1; @@ -109,7 +110,7 @@ public class Sensor extends AbstractDevice{ } - + @Override public Class getController(){ return getDeviceConfig().getSensorControllerClass(); } diff --git a/src/se/hal/trigger/EventTrigger.java b/src/se/hal/trigger/EventTrigger.java new file mode 100755 index 00000000..60405e82 --- /dev/null +++ b/src/se/hal/trigger/EventTrigger.java @@ -0,0 +1,84 @@ +package se.hal.trigger; + +import se.hal.HalContext; +import se.hal.TriggerManager; +import se.hal.intf.HalDeviceReportListener; +import se.hal.intf.HalEventData; +import se.hal.intf.HalTrigger; +import se.hal.struct.Event; +import zutil.db.DBConnection; +import zutil.log.LogUtil; +import zutil.ui.Configurator; +import zutil.ui.Configurator.PostConfigurationActionListener; +import zutil.ui.Configurator.PreConfigurationActionListener; + +import java.sql.SQLException; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * + */ +public class EventTrigger implements HalTrigger, + PreConfigurationActionListener, + PostConfigurationActionListener, HalDeviceReportListener { + + private static final Logger logger = LogUtil.getLogger(); + + @Configurator.Configurable("Event Device ID") + private int eventId = -1; + @Configurator.Configurable("Data to compare to") + private double expectedData; + + private transient HalEventData receivedData; + + + private Event getEvent(long id){ + try { + if (eventId >= 0) + return Event.getEvent(HalContext.getDB(), eventId); + } catch (SQLException e){ logger.log(Level.SEVERE, null, e);} + return null; + } + @Override + public void preConfigurationAction(Configurator configurator, Object obj) { + Event event = getEvent(eventId); + if (event != null) + event.removeReportListener(this); + reset(); + } + @Override + public void postConfigurationAction(Configurator configurator, Object obj) { + Event event = getEvent(eventId); + if (event != null) + event.addReportListener(this); + } + + @Override + public void receivedReport(Event device) { + receivedData = device.getDeviceData(); + // Instant trigger evaluation + TriggerManager.getInstance().evaluateAndExecute(); + } + + + @Override + public boolean evaluate() { + if (receivedData != null) + return expectedData == receivedData.getData(); + return false; + } + + @Override + public void reset() { + receivedData = null; + } + + + @Override + public String toString(){ + Event event = getEvent(eventId); + return (event != null ? event.getName() : null) + " == "+ expectedData; + } + +}