Moved find device to its own utility method, and added a specific equals method and reworked some test.

This commit is contained in:
Ziver Koc 2021-03-23 01:57:12 +01:00
parent 7e8938c38c
commit c7e286f51e
166 changed files with 618 additions and 374 deletions

View file

@ -2,6 +2,7 @@ package se.hal;
import se.hal.intf.*;
import se.hal.struct.Event;
import se.hal.util.HalDeviceUtil;
import zutil.db.DBConnection;
import zutil.log.LogUtil;
import zutil.plugin.PluginManager;
@ -35,6 +36,25 @@ public class EventControllerManager extends HalAbstractControllerManager<HalEven
private List<Event> limboEvents = Collections.synchronizedList(new LinkedList<>());
public void initialize(PluginManager pluginManager) {
super.initialize(pluginManager);
instance = this;
// Read in existing devices
try {
DBConnection db = HalContext.getDB();
logger.info("Reading in existing events.");
for (Event event : Event.getLocalEvents(db)) {
EventControllerManager.getInstance().register(event);
}
} catch (SQLException e) {
logger.log(Level.SEVERE, "Unable to read in existing events.", e);
}
}
// ----------------------------------------------------
// EVENTS
// ----------------------------------------------------
@ -61,7 +81,7 @@ public class EventControllerManager extends HalAbstractControllerManager<HalEven
if(controller != null)
controller.register(event.getDeviceConfig());
registeredEvents.add(event);
detectedEvents.remove(findEvent(event.getDeviceConfig(), detectedEvents)); // Remove if this device was detected
detectedEvents.remove(HalDeviceUtil.findDevice(event.getDeviceConfig(), detectedEvents)); // Remove if this device was detected
}
/**
@ -136,7 +156,7 @@ public class EventControllerManager extends HalAbstractControllerManager<HalEven
public void reportReceived(HalEventConfig eventConfig, HalEventData eventData) {
try {
DBConnection db = HalContext.getDB();
Event event = findEvent(eventConfig, registeredEvents);
Event event = HalDeviceUtil.findDevice(eventConfig, registeredEvents);
if (event != null) {
logger.finest("Received report from event(" + eventConfig.getClass().getSimpleName() + "): " + eventConfig);
@ -150,7 +170,7 @@ public class EventControllerManager extends HalAbstractControllerManager<HalEven
else { // unknown sensor
logger.info("Received report from unregistered event" +
"(" + eventConfig.getClass().getSimpleName() + "): " + eventConfig);
event = findEvent(eventConfig, detectedEvents);
event = HalDeviceUtil.findDevice(eventConfig, detectedEvents);
if(event == null) {
event = new Event();
detectedEvents.add(event);
@ -167,16 +187,6 @@ public class EventControllerManager extends HalAbstractControllerManager<HalEven
}
}
private static Event findEvent(HalEventConfig eventData, List<Event> list){
for (int i=0; i<list.size(); ++i) { // Don't use foreach for concurrency reasons
Event e = list.get(i);
if (eventData.equals(e.getDeviceConfig())) {
return e;
}
}
return null;
}
public void send(Event event){
HalEventController controller = getControllerInstance(event.getController());
if(controller != null) {
@ -198,7 +208,7 @@ public class EventControllerManager extends HalAbstractControllerManager<HalEven
@Override
public void preConfigurationAction(Configurator configurator, Object obj) {
if(obj instanceof HalEventConfig) {
Event event = findEvent((HalEventConfig) obj, registeredEvents);
Event event = HalDeviceUtil.findDevice((HalEventConfig) obj, registeredEvents);
if(event != null){
deregister(event);
limboEvents.add(event);
@ -209,7 +219,7 @@ public class EventControllerManager extends HalAbstractControllerManager<HalEven
@Override
public void postConfigurationAction(Configurator configurator, Object obj) {
if (obj instanceof HalEventConfig) {
Event event = findEvent((HalEventConfig) obj, limboEvents);
Event event = HalDeviceUtil.findDevice((HalEventConfig) obj, limboEvents);
if(event != null){
register(event);
limboEvents.remove(event);
@ -217,11 +227,6 @@ public class EventControllerManager extends HalAbstractControllerManager<HalEven
}
}
public void initialize(PluginManager pluginManager){
super.initialize(pluginManager);
instance = this;
}
public static EventControllerManager getInstance(){
return instance;

View file

@ -32,6 +32,8 @@ import java.util.logging.Logger;
public class HalServer {
private static final Logger logger = LogUtil.getLogger();
private static List<HalAbstractControllerManager> controllerManagers = new ArrayList<>();
private static ScheduledExecutorService daemonExecutor;
private static List<HalDaemon> daemons = new ArrayList<>();
@ -91,23 +93,7 @@ public class HalServer {
for (Iterator<HalAbstractControllerManager> it = pluginManager.getSingletonIterator(HalAbstractControllerManager.class); it.hasNext(); ) {
HalAbstractControllerManager manager = it.next();
manager.initialize(pluginManager);
}
// ------------------------------------
// Import sensors,events and triggers
// ------------------------------------
logger.info("Initializing Sensors and Events.");
for (Sensor sensor : Sensor.getLocalSensors(db)) {
SensorControllerManager.getInstance().register(sensor);
}
for (Event event : Event.getLocalEvents(db)) {
EventControllerManager.getInstance().register(event);
}
// Import triggers
for (TriggerFlow flow : TriggerFlow.getTriggerFlows(db)) {
TriggerManager.getInstance().register(flow);
controllerManagers.add(manager);
}
// ------------------------------------
@ -183,4 +169,9 @@ public class HalServer {
pages.add(page);
http.setPage(page.getId(), page);
}
public static List<HalAbstractControllerManager> getControllerManagers() {
return controllerManagers;
}
}

View file

@ -2,6 +2,7 @@ package se.hal;
import se.hal.intf.*;
import se.hal.struct.Sensor;
import se.hal.util.HalDeviceUtil;
import zutil.db.DBConnection;
import zutil.log.LogUtil;
import zutil.plugin.PluginManager;
@ -35,6 +36,27 @@ public class SensorControllerManager extends HalAbstractControllerManager<HalAbs
/** List of sensors that are currently being reconfigured **/
private List<Sensor> limboSensors = Collections.synchronizedList(new LinkedList<>());
@Override
public void initialize(PluginManager pluginManager){
super.initialize(pluginManager);
instance = this;
// Read in existing devices
try {
DBConnection db = HalContext.getDB();
logger.info("Reading in existing sensors.");
for (Sensor sensor : Sensor.getLocalSensors(db)) {
SensorControllerManager.getInstance().register(sensor);
}
} catch (SQLException e) {
logger.log(Level.SEVERE, "Unable to read in existing sensors.", e);
}
}
// ----------------------------------------------------
// SENSORS
// ----------------------------------------------------
@ -61,7 +83,8 @@ public class SensorControllerManager extends HalAbstractControllerManager<HalAbs
if(controller != null)
controller.register(sensor.getDeviceConfig());
registeredSensors.add(sensor);
detectedSensors.remove(findSensor(sensor.getDeviceConfig(), detectedSensors)); // Remove if this device was detected
detectedSensors.remove(
HalDeviceUtil.findDevice(sensor.getDeviceConfig(), detectedSensors)); // Remove if this device was detected
}
/**
@ -137,7 +160,7 @@ public class SensorControllerManager extends HalAbstractControllerManager<HalAbs
public void reportReceived(HalSensorConfig sensorConfig, HalSensorData sensorData) {
try{
DBConnection db = HalContext.getDB();
Sensor sensor = findSensor(sensorConfig, registeredSensors);
Sensor sensor = HalDeviceUtil.findDevice(sensorConfig, registeredSensors);
if (sensor != null) {
logger.finest("Received report from sensor(" + sensorConfig.getClass().getSimpleName() + "): " + sensorConfig);
@ -151,7 +174,7 @@ public class SensorControllerManager extends HalAbstractControllerManager<HalAbs
else { // unknown sensor
logger.finest("Received report from unregistered sensor" +
"(" + sensorConfig.getClass().getSimpleName() + "): " + sensorConfig);
sensor = findSensor(sensorConfig, detectedSensors);
sensor = HalDeviceUtil.findDevice(sensorConfig, detectedSensors);
if(sensor == null) {
sensor = new Sensor();
detectedSensors.add(sensor);
@ -168,20 +191,11 @@ public class SensorControllerManager extends HalAbstractControllerManager<HalAbs
}
}
private static Sensor findSensor(HalSensorConfig sensorData, List<Sensor> list){
for (int i=0; i<list.size(); ++i) { // Don't use foreach for concurrency reasons
Sensor s = list.get(i);
if (sensorData.equals(s.getDeviceConfig())) {
return s;
}
}
return null;
}
@Override
public void preConfigurationAction(Configurator configurator, Object obj) {
if (obj instanceof HalSensorConfig) {
Sensor sensor = findSensor((HalSensorConfig) obj, registeredSensors);
Sensor sensor = HalDeviceUtil.findDevice((HalSensorConfig) obj, registeredSensors);
if (sensor != null){
deregister(sensor);
limboSensors.add(sensor);
@ -192,7 +206,7 @@ public class SensorControllerManager extends HalAbstractControllerManager<HalAbs
@Override
public void postConfigurationAction(Configurator configurator, Object obj) {
if (obj instanceof HalSensorConfig) {
Sensor sensor = findSensor((HalSensorConfig) obj, limboSensors);
Sensor sensor = HalDeviceUtil.findDevice((HalSensorConfig) obj, limboSensors);
if (sensor != null){
register(sensor);
limboSensors.remove(sensor);
@ -201,12 +215,6 @@ public class SensorControllerManager extends HalAbstractControllerManager<HalAbs
}
@Override
public void initialize(PluginManager pluginManager){
super.initialize(pluginManager);
instance = this;
}
public static SensorControllerManager getInstance(){
return instance;
}

View file

@ -3,9 +3,11 @@ package se.hal;
import se.hal.intf.HalAction;
import se.hal.intf.HalTrigger;
import se.hal.struct.TriggerFlow;
import zutil.db.DBConnection;
import zutil.log.LogUtil;
import zutil.plugin.PluginManager;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
@ -31,6 +33,37 @@ public class TriggerManager {
private ScheduledExecutorService executor;
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());
}
manager.setEvaluationInterval(EVALUATION_INTERVAL);
instance = manager;
try {
// Import triggers
DBConnection db = HalContext.getDB();
logger.info("Reading in existing sensors.");
for (TriggerFlow flow : TriggerFlow.getTriggerFlows(db)) {
TriggerManager.getInstance().register(flow);
}
} catch (SQLException e) {
logger.log(Level.SEVERE, "Unable to read in existing triggers.", e);
}
}
public void setEvaluationInterval(long interval) {
if (executor != null)
@ -86,23 +119,6 @@ public class TriggerManager {
}
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());
}
manager.setEvaluationInterval(EVALUATION_INTERVAL);
instance = manager;
}
public static TriggerManager getInstance(){
return instance;
}

View file

@ -20,6 +20,28 @@ public abstract class HalAbstractControllerManager<T extends HalAbstractControll
protected HashMap<Class, T> controllerMap = new HashMap<>();
/**
* Will instantiate a generic ControllerManager.
*
* @param pluginManager a PluginManager instance that will be used to find Controller plugins.
*/
public void initialize(PluginManager pluginManager) {
Class[] genericClasses = ClassUtil.getGenericClasses(HalAbstractControllerManager.class);
if (genericClasses.length >= 1 && genericClasses[0] != null) {
for (Iterator<Class<C>> it = pluginManager.getClassIterator(genericClasses[0]); it.hasNext(); ) {
addAvailableDevice(it.next());
}
} else {
logger.severe("Unable to retrieve Controller class from generics.");
}
for (Iterator<Class<? extends HalAutoScannableController>> it = pluginManager.getClassIterator(HalAutoScannableController.class); it.hasNext(); ){
Class controller = it.next();
getControllerInstance(controller); // Instantiate controller
}
}
// ----------------------------------------------------
// Abstract methods
// ----------------------------------------------------
@ -131,26 +153,4 @@ public abstract class HalAbstractControllerManager<T extends HalAbstractControll
controller.close();
}
}
/**
* Will instantiate a generic ControllerManager.
*
* @param pluginManager a PluginManager instance that will be used to find Controller plugins.
*/
public void initialize(PluginManager pluginManager) {
Class[] genericClasses = ClassUtil.getGenericClasses(HalAbstractControllerManager.class);
if (genericClasses.length >= 1 && genericClasses[0] != null) {
for (Iterator<Class<C>> it = pluginManager.getClassIterator(genericClasses[0]); it.hasNext(); ) {
addAvailableDevice(it.next());
}
} else {
logger.severe("Unable to retrieve Controller class from generics.");
}
for (Iterator<Class<? extends HalAutoScannableController>> it = pluginManager.getClassIterator(HalAutoScannableController.class); it.hasNext(); ){
Class controller = it.next();
getControllerInstance(controller); // Instantiate controller
}
}
}

View file

@ -5,6 +5,9 @@ package se.hal.intf;
*/
public interface HalDeviceConfig {
/**
* @return the controller class that is responsible to track this configuration
*/
Class<? extends HalAbstractController> getDeviceControllerClass();
/**
@ -13,9 +16,11 @@ public interface HalDeviceConfig {
Class<? extends HalDeviceData> getDeviceDataClass();
/**
* This method needs to be implemented.
* NOTE: it should not compare data and timestamp, only static or unique data for the event type.
* This method is required to be implemented.
* This method compares two configuration objects static or unique configuration. it should not compare data and timestamp type dynamic values.
*
* @param obj is the target object to compare to.
* @return true if the configuration of the two objects are same, false if the objects are not of same type or configuration does not match.
*/
boolean equals(Object obj);
}

View file

@ -0,0 +1,29 @@
package se.hal.util;
import se.hal.intf.HalAbstractDevice;
import se.hal.intf.HalDeviceConfig;
import java.util.List;
/**
* A class containing utility methods for HalDevice objects.
*/
public class HalDeviceUtil {
/**
* Method will search a list for a device matching the given configuration object.
*
* @param deviceConfig the configuration object to identify the device by.
* @param list the list to search through.
* @return a HalAbstractDevice object matching the configuration object, null if no device was found.
*/
public static <D extends HalAbstractDevice> D findDevice(HalDeviceConfig deviceConfig, List<D> list){
for (int i=0; i<list.size(); ++i) { // Don't use foreach for concurrency reasons
D e = list.get(i);
if (deviceConfig.equals(e.getDeviceConfig())) {
return e;
}
}
return null;
}
}

View file

@ -92,6 +92,11 @@ public class EventControllerManagerTest {
public Class<? extends HalEventData> getDeviceDataClass() {
return OnOffEventData.class;
}
@Override
public boolean equals(Object obj) {
return this.equals(obj);
}
}
public static class TestEvent2 implements HalEventConfig {
@ -105,6 +110,11 @@ public class EventControllerManagerTest {
public Class<? extends HalEventData> getDeviceDataClass() {
return OnOffEventData.class;
}
@Override
public boolean equals(Object obj) {
return this.equals(obj);
}
}
public static class TestController implements HalEventController {

View file

@ -104,6 +104,11 @@ public class SensorControllerManagerTest {
public Class<? extends HalSensorData> getDeviceDataClass() {
return TemperatureSensorData.class;
}
@Override
public boolean equals(Object obj) {
return this.equals(obj);
}
}
public static class TestSensor2 implements HalSensorConfig {
@ -127,6 +132,11 @@ public class SensorControllerManagerTest {
public Class<? extends HalSensorData> getDeviceDataClass() {
return HumiditySensorData.class;
}
@Override
public boolean equals(Object obj) {
return this.equals(obj);
}
}
public static class TestController implements HalSensorController {

View file

@ -0,0 +1,45 @@
package se.hal.test;
import se.hal.intf.*;
import se.hal.struct.devicedata.TemperatureSensorData;
/**
* A dymmy device config class
*/
public class TestDeviceConfig implements HalSensorConfig, HalEventConfig {
private String id;
public TestDeviceConfig(String id) {
this.id = id;
}
@Override
public long getDataInterval() {
return 60 * 1000; // 1 min
}
@Override
public AggregationMethod getAggregationMethod() {
return AggregationMethod.AVERAGE;
}
@Override
public Class<? extends HalSensorController> getDeviceControllerClass() {
return null;
}
@Override
public Class<? extends HalSensorData> getDeviceDataClass() {
return TemperatureSensorData.class;
}
@Override
public boolean equals(Object obj) {
if (obj instanceof TestDeviceConfig)
return id.equals(((TestDeviceConfig) obj).id);
return false;
}
}

View file

@ -0,0 +1,31 @@
package se.hal.util;
import junit.framework.TestCase;
import org.junit.Test;
import se.hal.struct.Event;
import se.hal.test.TestDeviceConfig;
import java.util.ArrayList;
import java.util.List;
public class HalDeviceUtilTest extends TestCase {
@Test
public void testFindDevice() {
List<Event> eventList = new ArrayList<>();
Event device = new Event();
device.setDeviceConfig(new TestDeviceConfig("not test"));
eventList.add(device);
Event device2 = new Event();
device2.setDeviceConfig(new TestDeviceConfig("not test"));
eventList.add(device2);
Event expectedDevice = new Event();
expectedDevice.setDeviceConfig(new TestDeviceConfig("test"));
eventList.add(expectedDevice);
assertEquals(expectedDevice, HalDeviceUtil.findDevice(new TestDeviceConfig("test"), eventList));
}
}