diff --git a/src/se/hal/intf/HalDeviceData.java b/src/se/hal/intf/HalDeviceData.java index 02c47987..321ec366 100755 --- a/src/se/hal/intf/HalDeviceData.java +++ b/src/se/hal/intf/HalDeviceData.java @@ -22,4 +22,6 @@ public abstract class HalDeviceData { * @return serialized event data converted to double that will be saved in DB. */ public abstract double getData(); + + public abstract void setData(double data); } diff --git a/src/se/hal/intf/HalEventConfig.java b/src/se/hal/intf/HalEventConfig.java index 4edcade7..40bb524c 100755 --- a/src/se/hal/intf/HalEventConfig.java +++ b/src/se/hal/intf/HalEventConfig.java @@ -7,7 +7,12 @@ package se.hal.intf; */ public interface HalEventConfig { - Class getEventController(); + Class getEventControllerClass(); + + /** + * @return the class that should be instantiated and used for data received from this event + */ + Class getEventDataClass(); /** * This method needs to be implemented. diff --git a/src/se/hal/intf/HalSensorConfig.java b/src/se/hal/intf/HalSensorConfig.java index 2fb9befb..3f0c95fb 100755 --- a/src/se/hal/intf/HalSensorConfig.java +++ b/src/se/hal/intf/HalSensorConfig.java @@ -26,7 +26,12 @@ public interface HalSensorConfig { /** * @return the Controller class where SensorData should be registered on */ - Class getSensorController(); + Class getSensorControllerClass(); + + /** + * @return the class that should be instantiated and used for data received from this sensor + */ + Class getSensorDataClass(); /** * NOTE: it should only static or unique data for the sensor type. diff --git a/src/se/hal/plugin/nutups/NutUpsDevice.java b/src/se/hal/plugin/nutups/NutUpsDevice.java index 39d0c427..f83c6d5a 100755 --- a/src/se/hal/plugin/nutups/NutUpsDevice.java +++ b/src/se/hal/plugin/nutups/NutUpsDevice.java @@ -26,7 +26,7 @@ public class NutUpsDevice implements HalSensorConfig{ protected HalSensorData read(NutUPSClient.UPSDevice ups){ PowerConsumptionSensorData data = new PowerConsumptionSensorData(); data.setTimestamp(System.currentTimeMillis()); - data.setConsumption(ups.getPowerUsage() * 1/60.0); // convert watt min to watt hour + data.setData(ups.getPowerUsage() * 1/60.0); // convert watt min to watt hour return data; } @@ -57,7 +57,11 @@ public class NutUpsDevice implements HalSensorConfig{ return AggregationMethod.SUM; } @Override - public Class getSensorController() { + public Class getSensorControllerClass() { return NutUpsController.class; } + @Override + public Class getSensorDataClass() { + return PowerConsumptionSensorData.class; + } } diff --git a/src/se/hal/plugin/raspberry/RPiPowerConsumptionSensor.java b/src/se/hal/plugin/raspberry/RPiPowerConsumptionSensor.java index c88e31fa..da0cdb50 100755 --- a/src/se/hal/plugin/raspberry/RPiPowerConsumptionSensor.java +++ b/src/se/hal/plugin/raspberry/RPiPowerConsumptionSensor.java @@ -2,6 +2,7 @@ package se.hal.plugin.raspberry; import se.hal.intf.HalSensorConfig; import se.hal.intf.HalSensorController; +import se.hal.intf.HalSensorData; import se.hal.struct.devicedata.PowerConsumptionSensorData; import zutil.ui.Configurator; @@ -29,10 +30,15 @@ public class RPiPowerConsumptionSensor implements HalSensorConfig { } @Override - public Class getSensorController() { + public Class getSensorControllerClass() { return RPiController.class; } + @Override + public Class getSensorDataClass() { + return PowerConsumptionSensorData.class; + } + @Override public boolean equals(Object obj){ if(obj instanceof RPiPowerConsumptionSensor) diff --git a/src/se/hal/plugin/raspberry/RPiTemperatureSensor.java b/src/se/hal/plugin/raspberry/RPiTemperatureSensor.java index 4d7bf698..1bcdaef1 100755 --- a/src/se/hal/plugin/raspberry/RPiTemperatureSensor.java +++ b/src/se/hal/plugin/raspberry/RPiTemperatureSensor.java @@ -2,6 +2,7 @@ package se.hal.plugin.raspberry; import se.hal.intf.HalSensorConfig; import se.hal.intf.HalSensorController; +import se.hal.intf.HalSensorData; import se.hal.struct.devicedata.TemperatureSensorData; import zutil.ui.Configurator; @@ -29,10 +30,15 @@ public class RPiTemperatureSensor implements HalSensorConfig { } @Override - public Class getSensorController() { + public Class getSensorControllerClass() { return RPiController.class; } + @Override + public Class getSensorDataClass() { + return TemperatureSensorData.class; + } + @Override public boolean equals(Object obj){ if(obj instanceof RPiTemperatureSensor && w1Address != null) diff --git a/src/se/hal/plugin/tellstick/device/NexaSelfLearning.java b/src/se/hal/plugin/tellstick/device/NexaSelfLearning.java index 2428c7fb..dde999e1 100755 --- a/src/se/hal/plugin/tellstick/device/NexaSelfLearning.java +++ b/src/se/hal/plugin/tellstick/device/NexaSelfLearning.java @@ -24,10 +24,14 @@ package se.hal.plugin.tellstick.device; import se.hal.intf.HalEventConfig; import se.hal.intf.HalEventController; +import se.hal.intf.HalEventData; +import se.hal.intf.HalSensorData; import se.hal.plugin.tellstick.TellstickDevice; import se.hal.plugin.tellstick.TellstickDeviceGroup; import se.hal.plugin.tellstick.TellstickSerialComm; import se.hal.plugin.tellstick.protocol.NexaSelfLearningProtocol; +import se.hal.struct.devicedata.SwitchEventData; +import se.hal.struct.devicedata.TemperatureSensorData; import zutil.parser.binary.BinaryStruct; import zutil.ui.Configurator; @@ -99,11 +103,16 @@ public class NexaSelfLearning implements HalEventConfig,TellstickDevice,Tellstic } - - public Class getEventController() { + @Override + public Class getEventControllerClass() { return TellstickSerialComm.class; } + @Override + public Class getEventDataClass() { + return SwitchEventData.class; + } + @Override public String getProtocolName() { return NexaSelfLearningProtocol.PROTOCOL; } @Override diff --git a/src/se/hal/plugin/tellstick/device/Oregon0x1A2D.java b/src/se/hal/plugin/tellstick/device/Oregon0x1A2D.java index db2bbabb..4f888eb2 100755 --- a/src/se/hal/plugin/tellstick/device/Oregon0x1A2D.java +++ b/src/se/hal/plugin/tellstick/device/Oregon0x1A2D.java @@ -3,10 +3,12 @@ package se.hal.plugin.tellstick.device; import se.hal.intf.HalEventController; import se.hal.intf.HalSensorConfig; import se.hal.intf.HalSensorController; +import se.hal.intf.HalSensorData; import se.hal.plugin.tellstick.TellstickDevice; import se.hal.plugin.tellstick.TellstickProtocol; import se.hal.plugin.tellstick.TellstickSerialComm; import se.hal.plugin.tellstick.protocol.Oregon0x1A2DProtocol; +import se.hal.struct.devicedata.PowerConsumptionSensorData; import zutil.log.LogUtil; import zutil.ui.Configurator; @@ -55,10 +57,14 @@ public class Oregon0x1A2D implements HalSensorConfig,TellstickDevice { } @Override - public Class getSensorController() { + public Class getSensorControllerClass() { return TellstickSerialComm.class; } + @Override + public Class getSensorDataClass() { + return PowerConsumptionSensorData.class; // TODO: needs to support all data, add enum? + } @Override public String getProtocolName() { return Oregon0x1A2DProtocol.PROTOCOL; } diff --git a/src/se/hal/struct/AbstractDevice.java b/src/se/hal/struct/AbstractDevice.java index 3be520a8..475a789a 100755 --- a/src/se/hal/struct/AbstractDevice.java +++ b/src/se/hal/struct/AbstractDevice.java @@ -1,6 +1,7 @@ package se.hal.struct; import se.hal.ControllerManager; +import se.hal.HalContext; import zutil.db.DBConnection; import zutil.db.bean.DBBean; import zutil.log.LogUtil; @@ -74,7 +75,7 @@ public abstract class AbstractDevice extends DBBean { if(data != null) { type = data.getClass().getName(); deviceConfig = data; - deviceData = readDeviceData(); + deviceData = getLatestDeviceData(HalContext.getDB()); } else { deviceConfig = null; deviceData = null; @@ -127,9 +128,7 @@ public abstract class AbstractDevice extends DBBean { /** * Reads latest device data from DB */ - private D readDeviceData(){ - return null; // TODO: how to do this in a good way? - } + protected abstract D getLatestDeviceData(DBConnection db); /**************** OTHER ******************/ diff --git a/src/se/hal/struct/Event.java b/src/se/hal/struct/Event.java index 608f25e3..f7b40daa 100755 --- a/src/se/hal/struct/Event.java +++ b/src/se/hal/struct/Event.java @@ -1,16 +1,23 @@ package se.hal.struct; +import se.hal.intf.HalDeviceData; import se.hal.intf.HalEventController; import se.hal.intf.HalEventConfig; import se.hal.intf.HalEventData; +import se.hal.util.DeviceDataSqlResult; import zutil.db.DBConnection; +import zutil.db.SQLResultHandler; import zutil.db.bean.DBBean; import zutil.db.bean.DBBeanSQLResultHandler; +import zutil.db.handler.SimpleSQLResult; import zutil.log.LogUtil; import java.sql.PreparedStatement; +import java.sql.ResultSet; import java.sql.SQLException; +import java.sql.Statement; import java.util.List; +import java.util.logging.Level; import java.util.logging.Logger; /** @@ -26,13 +33,33 @@ public class Event extends AbstractDevice{ } public static List getLocalEvents(DBConnection db) throws SQLException { - PreparedStatement stmt = db.getPreparedStatement( "SELECT event.* FROM event,user WHERE user.external == 0 AND user.id == event.user_id" ); - return DBConnection.exec(stmt, DBBeanSQLResultHandler.createList(Event.class, db) ); + PreparedStatement stmt = db.getPreparedStatement( + "SELECT event.* FROM event,user WHERE user.external == 0 AND user.id == event.user_id"); + return DBConnection.exec(stmt, DBBeanSQLResultHandler.createList(Event.class, db)); } + public Class getController(){ - return getDeviceConfig().getEventController(); + return getDeviceConfig().getEventControllerClass(); + } + + @Override + protected HalEventData getLatestDeviceData(DBConnection db) { + try { + Class deviceDataClass = getDeviceConfig().getEventDataClass(); + if (deviceDataClass == null) + throw new ClassNotFoundException("Unknown device data class for: " + getDeviceConfig().getClass()); + + PreparedStatement stmt = db.getPreparedStatement( + "SELECT data FROM event_data_raw WHERE event_id == ? ORDER BY timestamp DESC LIMIT 1"); + stmt.setLong(1, getId()); + return (HalEventData) + DBConnection.exec(stmt, new DeviceDataSqlResult(deviceDataClass)); + } catch (Exception e){ + logger.log(Level.WARNING, null, e); + } + return null; } } diff --git a/src/se/hal/struct/Sensor.java b/src/se/hal/struct/Sensor.java index dc9998cc..50aedc28 100755 --- a/src/se/hal/struct/Sensor.java +++ b/src/se/hal/struct/Sensor.java @@ -4,6 +4,7 @@ import se.hal.HalContext; import se.hal.intf.HalSensorController; import se.hal.intf.HalSensorConfig; import se.hal.intf.HalSensorData; +import se.hal.util.DeviceDataSqlResult; import zutil.db.DBConnection; import zutil.db.bean.DBBean; import zutil.db.bean.DBBeanSQLResultHandler; @@ -13,6 +14,7 @@ import zutil.log.LogUtil; import java.sql.PreparedStatement; import java.sql.SQLException; import java.util.List; +import java.util.logging.Level; import java.util.logging.Logger; @@ -109,6 +111,24 @@ public class Sensor extends AbstractDevice{ public Class getController(){ - return getDeviceConfig().getSensorController(); + return getDeviceConfig().getSensorControllerClass(); + } + + @Override + protected HalSensorData getLatestDeviceData(DBConnection db) { + try { + Class deviceDataClass = getDeviceConfig().getSensorDataClass(); + if (deviceDataClass == null) + throw new ClassNotFoundException("Unknown device data class for: " + getDeviceConfig().getClass()); + + PreparedStatement stmt = db.getPreparedStatement( + "SELECT data FROM event_data_raw WHERE event_id == ? ORDER BY timestamp DESC LIMIT 1"); + stmt.setLong(1, getId()); + return (HalSensorData) + DBConnection.exec(stmt, new DeviceDataSqlResult(deviceDataClass)); + } catch (Exception e){ + logger.log(Level.WARNING, null, e); + } + return null; } } diff --git a/src/se/hal/struct/devicedata/DimmerEventData.java b/src/se/hal/struct/devicedata/DimmerEventData.java index 4b60fd0c..2c996169 100755 --- a/src/se/hal/struct/devicedata/DimmerEventData.java +++ b/src/se/hal/struct/devicedata/DimmerEventData.java @@ -42,4 +42,8 @@ public class DimmerEventData extends HalEventData { public double getData() { return dimmValue; } + @Override + public void setData(double dimmValue) { + this.dimmValue = dimmValue; + } } diff --git a/src/se/hal/struct/devicedata/HumiditySensorData.java b/src/se/hal/struct/devicedata/HumiditySensorData.java index 5c224427..d5c9f55b 100755 --- a/src/se/hal/struct/devicedata/HumiditySensorData.java +++ b/src/se/hal/struct/devicedata/HumiditySensorData.java @@ -21,4 +21,8 @@ public class HumiditySensorData extends HalSensorData { public double getData() { return humidity; } + @Override + public void setData(double humidity) { + this.humidity = humidity; + } } diff --git a/src/se/hal/struct/devicedata/PowerConsumptionSensorData.java b/src/se/hal/struct/devicedata/PowerConsumptionSensorData.java index b23aba27..814a2f04 100755 --- a/src/se/hal/struct/devicedata/PowerConsumptionSensorData.java +++ b/src/se/hal/struct/devicedata/PowerConsumptionSensorData.java @@ -21,11 +21,6 @@ public class PowerConsumptionSensorData extends HalSensorData { } - - public void setConsumption(double wattHours){ - this.wattHours = wattHours; - } - /** * @return int representing Watt/Hour */ @@ -33,4 +28,9 @@ public class PowerConsumptionSensorData extends HalSensorData { public double getData() { return wattHours; } + @Override + public void setData(double wattHours){ + this.wattHours = wattHours; + } + } diff --git a/src/se/hal/struct/devicedata/SwitchEventData.java b/src/se/hal/struct/devicedata/SwitchEventData.java index bbdbae1b..64db9eab 100755 --- a/src/se/hal/struct/devicedata/SwitchEventData.java +++ b/src/se/hal/struct/devicedata/SwitchEventData.java @@ -47,8 +47,13 @@ public class SwitchEventData extends HalEventData { public boolean isOn(){ return enabled; } + @Override public double getData() { return (enabled ? 1.0 : 0.0); } + @Override + public void setData(double enabled) { + this.enabled = enabled > 0; + } } diff --git a/src/se/hal/struct/devicedata/TemperatureSensorData.java b/src/se/hal/struct/devicedata/TemperatureSensorData.java index 507c36fa..595be88e 100755 --- a/src/se/hal/struct/devicedata/TemperatureSensorData.java +++ b/src/se/hal/struct/devicedata/TemperatureSensorData.java @@ -33,5 +33,9 @@ public class TemperatureSensorData extends HalSensorData { public double getData() { return temperature; } + @Override + public void setData(double temperature) { + this.temperature = temperature; + } } diff --git a/src/se/hal/util/DeviceDataSqlResult.java b/src/se/hal/util/DeviceDataSqlResult.java new file mode 100755 index 00000000..9b91de6a --- /dev/null +++ b/src/se/hal/util/DeviceDataSqlResult.java @@ -0,0 +1,37 @@ +package se.hal.util; + +import se.hal.intf.HalDeviceData; +import zutil.ClassUtil; +import zutil.db.SQLResultHandler; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; + +/** + * Created by Ziver on 2016-08-22. + */ +public class DeviceDataSqlResult implements SQLResultHandler { + + private Class clazz; + + + public DeviceDataSqlResult(Class clazz){ + this.clazz = clazz; + } + + + @Override + public HalDeviceData handleQueryResult(Statement stmt, ResultSet result) throws SQLException { + try { + HalDeviceData dataObj = clazz.newInstance(); + dataObj.setData(result.getDouble("data")); + dataObj.setTimestamp(result.getLong("timestamp")); + return dataObj; + } catch (SQLException e){ + throw e; + } catch (Exception e){ + throw new SQLException(e); + } + } +} diff --git a/test/se/hal/plugin/tellstick/TelstickSerialCommEventTest.java b/test/se/hal/plugin/tellstick/TelstickSerialCommEventTest.java index 0bbc09ae..1ed4c2ae 100755 --- a/test/se/hal/plugin/tellstick/TelstickSerialCommEventTest.java +++ b/test/se/hal/plugin/tellstick/TelstickSerialCommEventTest.java @@ -3,6 +3,7 @@ package se.hal.plugin.tellstick; import org.junit.Before; import org.junit.Test; import se.hal.intf.*; +import se.hal.struct.devicedata.DimmerEventData; import se.hal.struct.devicedata.SwitchEventData; import se.hal.struct.devicedata.TemperatureSensorData; import zutil.converter.Converter; @@ -95,14 +96,18 @@ public class TelstickSerialCommEventTest { ArrayList list = new ArrayList<>(); list.add(new TellstickDecodedEntry( - this, new TemperatureSensorData(testData) + this, new DimmerEventData(testData) )); return list; } @Override - public Class getEventController() { return null; } + public Class getEventControllerClass() { return null; } + @Override + public Class getEventDataClass() { + return null; + } @Override public boolean equals(Object obj) {return testData == ((TestEvent)obj).testData;} diff --git a/test/se/hal/plugin/tellstick/TelstickSerialCommSensorTest.java b/test/se/hal/plugin/tellstick/TelstickSerialCommSensorTest.java index 1a5a53b4..c1812aa3 100755 --- a/test/se/hal/plugin/tellstick/TelstickSerialCommSensorTest.java +++ b/test/se/hal/plugin/tellstick/TelstickSerialCommSensorTest.java @@ -2,10 +2,8 @@ package se.hal.plugin.tellstick; import org.junit.Before; import org.junit.Test; -import se.hal.intf.HalSensorConfig; -import se.hal.intf.HalSensorController; -import se.hal.intf.HalSensorData; -import se.hal.intf.HalSensorReportListener; +import se.hal.intf.*; +import se.hal.struct.devicedata.SwitchEventData; import se.hal.struct.devicedata.TemperatureSensorData; import zutil.converter.Converter; @@ -97,6 +95,10 @@ public class TelstickSerialCommSensorTest { @Override public AggregationMethod getAggregationMethod() { return null; } @Override - public Class getSensorController() { return null; } + public Class getSensorControllerClass() { return null; } + @Override + public Class getSensorDataClass() { + return null; + } } }