initial implementation of triggers. issue 6

This commit is contained in:
Ziver Koc 2017-01-11 17:31:00 +01:00
parent 6a8040b529
commit dd1bb75192
8 changed files with 283 additions and 11 deletions

View file

@ -32,16 +32,17 @@ public class HalServer {
// init logging
LogUtil.readConfiguration("logging.properties");
// init DB and other configurations
DBConnection db = HalContext.getDB();
// init Managers
PluginManager pluginManager = new PluginManager("./");
HalContext.initialize();
ControllerManager.initialize(pluginManager);
HalAlertManager.initialize();
ControllerManager.initialize(pluginManager);
TriggerManager.initialize(pluginManager);
// init DB and other configurations
DBConnection db = HalContext.getDB();
// Init sensors,events and controllers
for(Sensor sensor : Sensor.getLocalSensors(db)){
ControllerManager.getInstance().register(sensor);

90
src/se/hal/TriggerManager.java Executable file
View file

@ -0,0 +1,90 @@
package se.hal;
import se.hal.intf.HalAction;
import se.hal.intf.HalTrigger;
import se.hal.struct.TriggerFlow;
import zutil.log.LogUtil;
import zutil.plugin.PluginManager;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.logging.Logger;
/**
* Handles all triggers registered on Hal
*/
public class TriggerManager {
private static final Logger logger = LogUtil.getLogger();
private static TriggerManager instance;
private ArrayList<Class<? extends HalTrigger>> availableTriggers = new ArrayList<>();
private ArrayList<Class<? extends HalAction>> availableActions = new ArrayList<>();
private ArrayList<TriggerFlow> triggerFlows = new ArrayList<>();
public void addAvailableTrigger(Class<? extends HalTrigger> clazz) {
if ( ! availableTriggers.contains(clazz))
availableTriggers.add(clazz);
}
public List<Class<? extends HalTrigger>> getAvailableTriggers() {
return availableTriggers;
}
public void addAvailableAction(Class<? extends HalAction> clazz) {
if ( ! availableActions.contains(clazz))
availableActions.add(clazz);
}
public List<Class<? extends HalAction>> getAvailableActions() {
return availableActions;
}
public void register(TriggerFlow flow){
if ( ! triggerFlows.contains(flow))
triggerFlows.add(flow);
}
/**
* Main execution method.
* This method will go through all flows and evaluate them. If the
* evaluation of a trigger returns true then its execute method will be called.
*/
public synchronized void evaluateAndExecute() {
for (int i = 0; i < triggerFlows.size(); i++) { // avoid foreach as triggerFlow can change while we are running
TriggerFlow flow = triggerFlows.get(i);
if (flow.evaluate()) {
logger.fine("Flow "+ flow.getId() +" evaluated true, executing actions");
flow.execute();
flow.reset();
}
}
}
public static void initialize(PluginManager pluginManager){
TriggerManager manager = new TriggerManager();
for (Iterator<Class<? extends HalTrigger>> it = pluginManager.getClassIterator(HalTrigger.class);
it.hasNext(); ){
manager.addAvailableTrigger(it.next());
}
for (Iterator<Class<? extends HalAction>> it = pluginManager.getClassIterator(HalAction.class);
it.hasNext(); ){
manager.addAvailableAction(it.next());
}
instance = manager;
}
public static TriggerManager getInstance(){
return instance;
}
}

9
src/se/hal/intf/HalAction.java Executable file
View file

@ -0,0 +1,9 @@
package se.hal.intf;
/**
* Defines a action that will be executed
*/
public interface HalAction {
void execute();
}

20
src/se/hal/intf/HalTrigger.java Executable file
View file

@ -0,0 +1,20 @@
package se.hal.intf;
/**
* A interfaces that declares a trigger/condition that
* needs to be validated before an action can be run
*/
public interface HalTrigger {
/**
* Evaluates if this trigger has passed. If the trigger is
* true then this method will return true until the {@link #reset()}
* method is called.
*/
boolean evaluate();
/**
* Reset the evaluation to false.
*/
void reset();
}

View file

@ -68,14 +68,16 @@ public class NetScanController implements HalEventController, HalAutoScannableCo
public void run() {
try(MultiCommandExecutor executor = new MultiCommandExecutor();){
for (Map.Entry<LocalNetworkDevice,SwitchEventData> entry : devices.entrySet()) {
LocalNetworkDevice device = entry.getKey();
SwitchEventData data = entry.getValue();
if (listener != null) {
//logger.finest("Pinging IP "+entry.getKey().getHost());
boolean online = InetScanner.isReachable(entry.getKey().getHost(), executor);
if (entry.getValue() == null || entry.getValue().isOn() != online) {
//logger.finest("Pinging IP "+ device.getHost());
boolean online = InetScanner.isReachable(device.getHost(), executor);
if (data == null || data.isOn() != online) {
entry.setValue(
new SwitchEventData(online, System.currentTimeMillis()));
logger.fine("IP "+entry.getKey().getHost() +" state has changed to "+ entry.getValue());
listener.reportReceived(entry.getKey(), entry.getValue());
logger.fine("IP "+device.getHost() +" state has changed to "+ data);
listener.reportReceived(device, data);
}
}
}

View file

@ -5,7 +5,7 @@
{"se.hal.intf.HalHttpPage": "se.hal.page.PCOverviewHttpPage"},
{"se.hal.intf.HalHttpPage": "se.hal.page.PCHeatMapHttpPage"},
{"se.hal.intf.HalDaemon": "se.hal.deamon.PCDataSynchronizationClient"},
{"se.hal.intf.HalDaemon": "se.hal.deamon.PCDataSynchronizationDaemon"}
{"se.hal.intf.HalDaemon": "se.hal.daemon.PCDataSynchronizationClient"},
{"se.hal.intf.HalDaemon": "se.hal.daemon.PCDataSynchronizationDaemon"}
]
}

View file

@ -0,0 +1,55 @@
package se.hal.struct;
import se.hal.intf.HalAction;
import se.hal.intf.HalTrigger;
import zutil.db.bean.DBBean;
import java.util.ArrayList;
/**
* A class that encapsulates triggers and their actions.
* TODO: Bad class name, should be renamed when we come up with a better one
*/
public class TriggerFlow extends DBBean {
private ArrayList<HalTrigger> triggers = new ArrayList<>();
private ArrayList<HalAction> actions = new ArrayList<>();
public void addTrigger(HalTrigger trigger) {
triggers.add(trigger);
}
public void addAction(HalAction action) {
actions.add(action);
}
/**
* @return true if any one of the triggers evaluate to true,
* false if there are no triggers added.
* Note: this method will not execute any actions
*/
public boolean evaluate(){
for(HalTrigger trigger : triggers){
if (trigger.evaluate())
return true;
}
return false;
}
/**
* Executes the associated actions in this flow
*/
public void execute(){
for(HalAction action : actions){
action.execute();
}
}
/**
* Resets all trigger evaluations
*/
public void reset() {
for(HalTrigger trigger : triggers){
trigger.reset();
}
}
}

View file

@ -0,0 +1,95 @@
package se.hal;
import org.junit.Test;
import se.hal.intf.HalAction;
import se.hal.intf.HalTrigger;
import se.hal.struct.TriggerFlow;
import java.util.Collections;
import static org.junit.Assert.*;
/**
*
*/
public class TriggerManagerTest {
private TriggerManager manager = new TriggerManager();
@Test
public void registerAvailableTrigger(){
assertEquals(Collections.EMPTY_LIST, manager.getAvailableTriggers());
manager.addAvailableTrigger(TestTrigger.class);
manager.addAvailableTrigger(TestTrigger.class);
assertEquals(1, manager.getAvailableTriggers().size());
assertTrue(manager.getAvailableTriggers().contains(TestTrigger.class));
}
@Test
public void registerAvailableAction(){
assertEquals(Collections.EMPTY_LIST, manager.getAvailableActions());
manager.addAvailableAction(TestAction.class);
manager.addAvailableAction(TestAction.class);
assertEquals(1, manager.getAvailableActions().size());
assertTrue(manager.getAvailableActions().contains(TestAction.class));
}
@Test
public void register(){
registerAvailableTrigger();
TriggerFlow flow = new TriggerFlow();
flow.addTrigger(new TestTrigger(true));
TestAction action = new TestAction();
flow.addAction(action);
manager.register(flow);
manager.evaluateAndExecute();
assertEquals(1, action.nrOfExecutions);
}
@Test
public void evaluateAndExecute(){
registerAvailableTrigger();
TriggerFlow flow = new TriggerFlow();
TestTrigger trigger = new TestTrigger(true);
flow.addTrigger(trigger);
TestAction action = new TestAction();
flow.addAction(action);
manager.register(flow);
manager.evaluateAndExecute();
assertEquals("Action executed nr of times",
1, action.nrOfExecutions);
manager.evaluateAndExecute();
assertEquals("Action executed nr of times",
1, action.nrOfExecutions);
}
/////////////////////////////////////////////////////////////////////////////
private static class TestTrigger implements HalTrigger {
boolean evaluation;
TestTrigger(boolean b){ evaluation = b; }
@Override
public boolean evaluate() { return evaluation; }
@Override
public void reset() { evaluation = false; }
}
private class TestAction implements HalAction {
int nrOfExecutions;
@Override
public void execute() { nrOfExecutions++; }
}
}