diff --git a/.gitignore b/.gitignore index bb0f511d..ec0cf5ed 100755 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ /hal.db* /build/ /lib/Zutil.jar +/tellstick.conf diff --git a/src/se/koc/hal/ControllerManager.java b/src/se/koc/hal/ControllerManager.java index a632053a..07b2a323 100755 --- a/src/se/koc/hal/ControllerManager.java +++ b/src/se/koc/hal/ControllerManager.java @@ -1,15 +1,16 @@ package se.koc.hal; -import se.koc.hal.intf.HalEvent; -import se.koc.hal.intf.HalEventController; -import se.koc.hal.intf.HalSensor; -import se.koc.hal.intf.HalSensorController; +import se.koc.hal.intf.*; +import se.koc.hal.plugin.tellstick.protocols.Oregon0x1A2D; import se.koc.hal.struct.Event; import se.koc.hal.struct.Sensor; +import zutil.db.DBConnection; import zutil.log.LogUtil; import zutil.plugin.PluginData; import zutil.plugin.PluginManager; +import java.sql.PreparedStatement; +import java.sql.SQLException; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; @@ -20,7 +21,7 @@ import java.util.logging.Logger; /** * This class manages all SensorController and EventController objects */ -public class ControllerManager { +public class ControllerManager implements HalSensorReportListener, HalEventReportListener { private static final Logger logger = LogUtil.getLogger(); private static ControllerManager instance; @@ -75,6 +76,38 @@ public class ControllerManager { return detectedSensors; } + @Override + public void reportReceived(HalSensor sensorData) { + try{ + DBConnection db = HalContext.getDB(); + Sensor sensor = null; + for (Sensor s : registeredSensors) { + if (sensorData.equals(s.getSensorData())) { + sensor = s; + sensor.setSensorData(sensorData); // Set the latest data + break; + } + } + + if (sensor != null) { + PreparedStatement stmt = + db.getPreparedStatement("INSERT INTO sensor_data_raw (timestamp, event_id, data) VALUES(?, ?, ?)"); + stmt.setLong(1, sensorData.getTimestamp()); + stmt.setLong(2, sensor.getId()); + stmt.setDouble(3, sensorData.getData()); + db.exec(stmt); + logger.finest("Received report from sensor: "+ sensorData); + } + else { // unknown sensor + if(!detectedSensors.contains(sensorData)) { + logger.finest("Received report from unregistered sensor: "+ sensorData); + detectedSensors.add(sensorData); + } + } + }catch (SQLException e){ + logger.log(Level.WARNING, "Unable to store sensor report", e); + } + } //////////////////////////////// EVENTS /////////////////////////////////// @@ -105,6 +138,38 @@ public class ControllerManager { return detectedEvents; } + @Override + public void reportReceived(HalEvent eventData) { + try { + DBConnection db = HalContext.getDB(); + Event event = null; + for (Event e : registeredEvents) { + if (eventData.equals(e.getEventData())) { + event = e; + event.setEventData(eventData); // Set the latest data + break; + } + } + + if (event != null) { + PreparedStatement stmt = + db.getPreparedStatement("INSERT INTO event_data_raw (timestamp, event_id, data) VALUES(?, ?, ?)"); + stmt.setLong(1, eventData.getTimestamp()); + stmt.setLong(2, event.getId()); + stmt.setDouble(3, eventData.getData()); + db.exec(stmt); + logger.finest("Received report from event: "+ eventData); + } + else { // unknown sensor + if(!detectedEvents.contains(eventData)) { + logger.finest("Received report from unregistered event: "+ eventData); + detectedEvents.add(eventData); + } + } + }catch (SQLException e){ + logger.log(Level.WARNING, "Unable to store event report", e); + } + } /////////////////////////////// GENERAL /////////////////////////////////// @@ -117,6 +182,11 @@ public class ControllerManager { logger.fine("Instantiating new controller: " + c.getName()); try { controller = c.newInstance(); + if(controller instanceof HalSensorController) + ((HalSensorController) controller).setListener(this); + if(controller instanceof HalEventController) + ((HalEventController) controller).setListener(this); + controllerMap.put(c, controller); } catch (Exception e){ logger.log(Level.SEVERE, "Unable to instantiate controller: "+c.getName(), e); @@ -169,4 +239,5 @@ public class ControllerManager { public static ControllerManager getInstance(){ return instance; } + } diff --git a/src/se/koc/hal/HALClient.java b/src/se/koc/hal/HALClient.java index 86c12d4c..2149c513 100755 --- a/src/se/koc/hal/HALClient.java +++ b/src/se/koc/hal/HALClient.java @@ -4,10 +4,6 @@ import se.koc.hal.bot.AliceBot; import se.koc.hal.intf.HalBot; import se.koc.hal.intf.HalSpeachToText; import se.koc.hal.intf.HalTextToSpeach; -import se.koc.hal.plugin.tellstick.TellstickChangeListener; -import se.koc.hal.plugin.tellstick.TellstickProtocol; -import se.koc.hal.plugin.tellstick.TellstickSerialComm; -import se.koc.hal.plugin.tellstick.protocols.NexaSelfLearning; import se.koc.hal.struct.SwitchEvent; import se.koc.hal.stt.ManualSTTClient; import se.koc.hal.tts.MaryRemoteTTSClient; diff --git a/src/se/koc/hal/HalContext.java b/src/se/koc/hal/HalContext.java index 25129a96..6066b088 100755 --- a/src/se/koc/hal/HalContext.java +++ b/src/se/koc/hal/HalContext.java @@ -27,7 +27,7 @@ public class HalContext { private static final String DEFAULT_DB_FILE = "hal-default.db"; // Variables - private static DBConnection db; + private static DBConnection db; // TODO: Should probably be a db pool as we have multiple threads accessing the DB private static Properties defaultFileConf; private static Properties fileConf; diff --git a/src/se/koc/hal/intf/HalEvent.java b/src/se/koc/hal/intf/HalEvent.java index 4e06fc66..1f05f7ce 100755 --- a/src/se/koc/hal/intf/HalEvent.java +++ b/src/se/koc/hal/intf/HalEvent.java @@ -7,6 +7,16 @@ import zutil.parser.DataNode; */ public interface HalEvent { - public Class getController(); + long getTimestamp(); + + double getData(); + + Class getEventController(); + + /** + * This method needs to be implemented. + * NOTE: it should not compare data and timestamp, only static or unique data for the event type. + */ + boolean equals(Object obj); } diff --git a/src/se/koc/hal/intf/HalEventController.java b/src/se/koc/hal/intf/HalEventController.java index 179759b3..6cabf031 100755 --- a/src/se/koc/hal/intf/HalEventController.java +++ b/src/se/koc/hal/intf/HalEventController.java @@ -1,7 +1,5 @@ package se.koc.hal.intf; -import se.koc.hal.struct.Event; - /** * Created by Ziver on 2015-12-15. */ @@ -30,11 +28,7 @@ public interface HalEventController { /** * Set a listener that will receive all reports from the the registered Events */ - void setListener(EventReportListener listener); - - interface EventReportListener{ - void reportReceived(HalEvent s); //TODO: rename, use a better name - } + void setListener(HalEventReportListener listener); /** diff --git a/src/se/koc/hal/intf/HalEventReportListener.java b/src/se/koc/hal/intf/HalEventReportListener.java new file mode 100755 index 00000000..0d2f6f01 --- /dev/null +++ b/src/se/koc/hal/intf/HalEventReportListener.java @@ -0,0 +1,7 @@ +package se.koc.hal.intf; + +public interface HalEventReportListener { + + void reportReceived(HalEvent e); + +} \ No newline at end of file diff --git a/src/se/koc/hal/intf/HalSensor.java b/src/se/koc/hal/intf/HalSensor.java index 2a070ddc..ef03e10b 100755 --- a/src/se/koc/hal/intf/HalSensor.java +++ b/src/se/koc/hal/intf/HalSensor.java @@ -12,10 +12,17 @@ public interface HalSensor { } + long getTimestamp(); + + double getData(); AggregationMethod getAggregationMethod(); - Class getController(); - + Class getSensorController(); + /** + * This method needs to be implemented. + * NOTE: it should not compare data and timestamp, only static or unique data for the event type. + */ + boolean equals(Object obj); } diff --git a/src/se/koc/hal/intf/HalSensorController.java b/src/se/koc/hal/intf/HalSensorController.java index 9367cadb..6dec2389 100755 --- a/src/se/koc/hal/intf/HalSensorController.java +++ b/src/se/koc/hal/intf/HalSensorController.java @@ -1,7 +1,5 @@ package se.koc.hal.intf; -import se.koc.hal.struct.Sensor; - /** * Created by Ziver on 2015-12-15. */ @@ -26,11 +24,7 @@ public interface HalSensorController { /** * Set a listener that will receive all reports from the the registered Sensors */ - void setListener(SensorReportListener listener); - - interface SensorReportListener{ - void reportReceived(HalSensor s); - } + void setListener(HalSensorReportListener listener); /** diff --git a/src/se/koc/hal/intf/HalSensorReportListener.java b/src/se/koc/hal/intf/HalSensorReportListener.java new file mode 100755 index 00000000..00421a59 --- /dev/null +++ b/src/se/koc/hal/intf/HalSensorReportListener.java @@ -0,0 +1,7 @@ +package se.koc.hal.intf; + +public interface HalSensorReportListener { + + void reportReceived(HalSensor s); + +} \ No newline at end of file diff --git a/src/se/koc/hal/page/PCConfigureHttpPage.java b/src/se/koc/hal/page/PCConfigureHttpPage.java index 43ea2848..c81b1144 100755 --- a/src/se/koc/hal/page/PCConfigureHttpPage.java +++ b/src/se/koc/hal/page/PCConfigureHttpPage.java @@ -58,7 +58,7 @@ public class PCConfigureHttpPage extends HalHttpPage { sensor = new Sensor(); sensor.setName(request.get("name")); sensor.setType(request.get("type")); - sensor.setConfig(request.get("config")); + //sensor.setConfig(request.get("config")); sensor.setUser(localUser); sensor.setSynced(true); sensor.save(db); @@ -67,7 +67,7 @@ public class PCConfigureHttpPage extends HalHttpPage { if(sensor != null){ sensor.setName(request.get("name")); sensor.setType(request.get("type")); - sensor.setConfig(request.get("config")); + //sensor.setConfig(request.get("config")); sensor.save(db); } break; diff --git a/src/se/koc/hal/plugin/tellstick/TellstickChangeListener.java b/src/se/koc/hal/plugin/tellstick/TellstickChangeListener.java deleted file mode 100755 index 8b7ab481..00000000 --- a/src/se/koc/hal/plugin/tellstick/TellstickChangeListener.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (c) 2015 Ziver - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -package se.koc.hal.plugin.tellstick; - -/** - * Created by Ziver on 2015-05-08. - */ -public interface TellstickChangeListener { - - public void stateChange(TellstickProtocol protocol); -} diff --git a/src/se/koc/hal/plugin/tellstick/TellstickProtocol.java b/src/se/koc/hal/plugin/tellstick/TellstickProtocol.java index b8ddb121..4deb1e82 100755 --- a/src/se/koc/hal/plugin/tellstick/TellstickProtocol.java +++ b/src/se/koc/hal/plugin/tellstick/TellstickProtocol.java @@ -22,14 +22,47 @@ package se.koc.hal.plugin.tellstick; +import se.koc.hal.intf.HalEventController; +import se.koc.hal.intf.HalSensorController; + /** * Created by Ziver on 2015-02-18. */ -public interface TellstickProtocol { +public abstract class TellstickProtocol { - public String encode(); - public void decode(byte[] data); + private String protocol; + private String model; + private long timestamp = -1; - public String getProtocolName(); - public String getModelName(); + + public TellstickProtocol(String protocol, String model){ + this.protocol = protocol; + this.model = model; + } + + + public String getProtocolName(){ + return protocol; + } + public String getModelName(){ + return model; + } + + public long getTimestamp() { + return timestamp; + } + public void setTimestamp(long timestamp) { + this.timestamp = timestamp; + } + + + public Class getEventController() { + return TellstickSerialComm.class; + } + public Class getSensorController() { + return TellstickSerialComm.class; + } + + public abstract String encode(); + public abstract void decode(byte[] data); } diff --git a/src/se/koc/hal/plugin/tellstick/TellstickSerialComm.java b/src/se/koc/hal/plugin/tellstick/TellstickSerialComm.java index 0819f3dc..a1412b9d 100755 --- a/src/se/koc/hal/plugin/tellstick/TellstickSerialComm.java +++ b/src/se/koc/hal/plugin/tellstick/TellstickSerialComm.java @@ -23,14 +23,15 @@ package se.koc.hal.plugin.tellstick; import com.fazecast.jSerialComm.SerialPort; -import se.koc.hal.intf.HalSensor; -import se.koc.hal.intf.HalSensorController; +import se.koc.hal.intf.*; +import zutil.io.file.FileUtil; import zutil.log.InputStreamLogger; import zutil.log.LogUtil; import zutil.log.OutputStreamLogger; import zutil.struct.TimedHashSet; import java.io.*; +import java.util.Properties; import java.util.concurrent.Executors; import java.util.logging.Level; import java.util.logging.Logger; @@ -40,7 +41,7 @@ import java.util.logging.Logger; * This version of the TwoWaySerialComm example makes use of the * SerialPortEventListener to avoid polling. */ -public class TellstickSerialComm implements Runnable, HalSensorController { +public class TellstickSerialComm implements Runnable, HalSensorController, HalEventController { private static final long TRANSMISSION_UNIQUENESS_TTL = 300; // milliseconds private static final Logger logger = LogUtil.getLogger(); @@ -50,13 +51,27 @@ public class TellstickSerialComm implements Runnable, HalSensorController { private TimedHashSet set; // To check for retransmissions private TellstickParser parser; - private TellstickChangeListener listener; + private HalSensorReportListener sensorListener; + private HalEventReportListener eventListener; + + private int registeredObjects; + public TellstickSerialComm() throws Exception { set = new TimedHashSet(TRANSMISSION_UNIQUENESS_TTL); parser = new TellstickParser(); - connect("COM6"); + registeredObjects = 0; + + // Read properties + Properties prop = new Properties(); + prop.setProperty("com_port", "COM6"); // defaults + if(FileUtil.find("tellstick.conf") != null) { + Reader reader = new FileReader("tellstick.conf"); + prop.load(reader); + reader.close(); + } + connect(prop.getProperty("com_port")); } public void connect(String portName) throws Exception { @@ -100,10 +115,14 @@ public class TellstickSerialComm implements Runnable, HalSensorController { else { if(!set.contains(data)) { TellstickProtocol protocol = parser.decode(data); + if(protocol.getTimestamp() < 0) + protocol.setTimestamp(System.currentTimeMillis()); set.add(data); - if (listener != null) { - listener.stateChange(protocol); - } + + if (sensorListener != null && protocol instanceof HalSensor) + sensorListener.reportReceived((HalSensor)protocol); + else if (eventListener != null && protocol instanceof HalEvent) + eventListener.reportReceived((HalEvent)protocol); } } } @@ -112,6 +131,12 @@ public class TellstickSerialComm implements Runnable, HalSensorController { } } + + @Override + public void send(HalEvent event) { + if(event instanceof TellstickProtocol) + write((TellstickProtocol) event); + } public synchronized void write(TellstickProtocol prot) { write(prot.encode()); try { @@ -120,7 +145,6 @@ public class TellstickSerialComm implements Runnable, HalSensorController { logger.log(Level.SEVERE, null, e); } } - public void write(String data) { try { for(int i=0; i getController() { - return TellstickSerialComm.class; - } } diff --git a/src/se/koc/hal/struct/DimmerEvent.java b/src/se/koc/hal/struct/DimmerEvent.java index a1a6e3b7..b303730c 100755 --- a/src/se/koc/hal/struct/DimmerEvent.java +++ b/src/se/koc/hal/struct/DimmerEvent.java @@ -28,4 +28,5 @@ import se.koc.hal.intf.HalEvent; * Created by Ziver on 2015-05-07. */ public abstract class DimmerEvent implements HalEvent { + } diff --git a/src/se/koc/hal/struct/Event.java b/src/se/koc/hal/struct/Event.java index cdb6ede3..841745e7 100755 --- a/src/se/koc/hal/struct/Event.java +++ b/src/se/koc/hal/struct/Event.java @@ -45,6 +45,9 @@ public class Event extends DBBean{ } + public void setEventData(HalEvent eventData){ + this.eventData = eventData; + } public HalEvent getEventData(){ if(eventData == null) { try { @@ -80,6 +83,6 @@ public class Event extends DBBean{ public Class getController(){ - return getEventData().getController(); + return getEventData().getEventController(); } } diff --git a/src/se/koc/hal/struct/Sensor.java b/src/se/koc/hal/struct/Sensor.java index 54881160..514d2d91 100755 --- a/src/se/koc/hal/struct/Sensor.java +++ b/src/se/koc/hal/struct/Sensor.java @@ -79,6 +79,9 @@ public class Sensor extends DBBean{ } + public void setSensorData(HalSensor sensorData){ + this.sensorData = sensorData; + } public HalSensor getSensorData(){ if(sensorData == null) { try { @@ -125,12 +128,6 @@ public class Sensor extends DBBean{ public void setType(String type) { this.type = type; } - public String getConfig() { - return config; - } - public void setConfig(String config) { - this.config = config; - } public User getUser() { return user; @@ -157,6 +154,6 @@ public class Sensor extends DBBean{ } public Class getController(){ - return getSensorData().getController(); + return getSensorData().getSensorController(); } } diff --git a/src/se/koc/hal/struct/SwitchEvent.java b/src/se/koc/hal/struct/SwitchEvent.java index aaf317df..31a709fa 100755 --- a/src/se/koc/hal/struct/SwitchEvent.java +++ b/src/se/koc/hal/struct/SwitchEvent.java @@ -31,7 +31,8 @@ import se.koc.hal.plugin.tellstick.protocols.NexaSelfLearning; */ public interface SwitchEvent extends HalEvent { - public boolean isOn(); - public void turnOn(); - public void turnOff(); + boolean isOn(); + + void turnOn(); + void turnOff(); } diff --git a/src/se/koc/hal/struct/TemperatureSensor.java b/src/se/koc/hal/struct/TemperatureSensor.java index 47376954..f33cbe50 100755 --- a/src/se/koc/hal/struct/TemperatureSensor.java +++ b/src/se/koc/hal/struct/TemperatureSensor.java @@ -7,7 +7,7 @@ import se.koc.hal.intf.HalSensor; */ public interface TemperatureSensor extends HalSensor { - public double getTemperature(); + double getTemperature(); - public double getHumidity(); + double getHumidity(); } diff --git a/test/se/koc/hal/plugin/tellstick/TelstickSerialCommNexaOnOffTest.java b/test/se/koc/hal/plugin/tellstick/TelstickSerialCommNexaOnOffTest.java index f4e79433..f0685606 100755 --- a/test/se/koc/hal/plugin/tellstick/TelstickSerialCommNexaOnOffTest.java +++ b/test/se/koc/hal/plugin/tellstick/TelstickSerialCommNexaOnOffTest.java @@ -27,7 +27,7 @@ public class TelstickSerialCommNexaOnOffTest { System.out.println("Up and Running"); while(true) { Thread.sleep(2000); - nexa.setEnable(true); + nexa.turnOn(); nexa.setUnit(0); comm.write(nexa); Thread.sleep(2000); @@ -36,7 +36,7 @@ public class TelstickSerialCommNexaOnOffTest { Thread.sleep(2000); - nexa.setEnable(false); + nexa.turnOff(); nexa.setUnit(0); comm.write(nexa); Thread.sleep(2000); diff --git a/test/se/koc/hal/plugin/tellstick/TelstickSerialCommTest.java b/test/se/koc/hal/plugin/tellstick/TelstickSerialCommTest.java index 95982469..e13715c1 100755 --- a/test/se/koc/hal/plugin/tellstick/TelstickSerialCommTest.java +++ b/test/se/koc/hal/plugin/tellstick/TelstickSerialCommTest.java @@ -1,10 +1,14 @@ package se.koc.hal.plugin.tellstick; +import se.koc.hal.intf.HalSensor; +import se.koc.hal.intf.HalSensorController; +import se.koc.hal.intf.HalSensorReportListener; import se.koc.hal.plugin.tellstick.protocols.Oregon0x1A2D; import zutil.db.DBConnection; import zutil.log.CompactLogFormatter; import zutil.log.LogUtil; +import java.sql.PreparedStatement; import java.sql.SQLException; import java.util.logging.Level; import java.util.logging.Logger; @@ -25,17 +29,18 @@ public class TelstickSerialCommTest { logger.info("Setting up Tellstick listeners..."); TellstickSerialComm comm = new TellstickSerialComm(); - comm.setListener(new TellstickChangeListener() { + comm.setListener(new HalSensorReportListener() { @Override - public void stateChange(TellstickProtocol protocol) { - if(protocol instanceof Oregon0x1A2D){ - logger.info("Power used: "+ ((Oregon0x1A2D)protocol).getTemperature() +" pulses"); + public void reportReceived(HalSensor s) { + if(s instanceof Oregon0x1A2D){ + logger.info("Power used: "+ ((Oregon0x1A2D)s).getTemperature() +" pulses"); try { - db.exec("INSERT INTO sensor_data_raw (timestamp, sensor_id, data) VALUES("+ - System.currentTimeMillis() + "," + - "1," + - (int)((Oregon0x1A2D)protocol).getTemperature() - +")"); + PreparedStatement stmt = + db.getPreparedStatement("INSERT INTO sensor_data_raw (timestamp, event_id, data) VALUES(?, ?, ?)"); + stmt.setLong(1, s.getTimestamp()); + stmt.setLong(2, 1); + stmt.setDouble(3, ((Oregon0x1A2D)s).getTemperature()); + db.exec(stmt); } catch (SQLException e) { e.printStackTrace(); } diff --git a/test/se/koc/hal/plugin/tellstick/protocols/NexaSelfLearningTest.java b/test/se/koc/hal/plugin/tellstick/protocols/NexaSelfLearningTest.java index a8638c0e..e128f56c 100755 --- a/test/se/koc/hal/plugin/tellstick/protocols/NexaSelfLearningTest.java +++ b/test/se/koc/hal/plugin/tellstick/protocols/NexaSelfLearningTest.java @@ -33,7 +33,7 @@ public class NexaSelfLearningTest { NexaSelfLearning nexa = new NexaSelfLearning(); nexa.setHouse(11772006); nexa.setUnit(3); - nexa.setEnable(true); + nexa.turnOn(); assertArrayEquals( new char[]{ @@ -53,7 +53,7 @@ public class NexaSelfLearningTest { assertEquals("House Code", 11772006, nexa.getHouse()); assertEquals("Unit Code", 1, nexa.getUnit()); - assertTrue("Enabled", nexa.isEnabled()); + assertTrue("Enabled", nexa.isOn()); } @org.junit.Test public void decode_OFF() throws Exception { @@ -62,6 +62,6 @@ public class NexaSelfLearningTest { assertEquals("House Code", 11772006, nexa.getHouse()); assertEquals("Unit Code", 1, nexa.getUnit()); - assertFalse("Enabled", nexa.isEnabled()); + assertFalse("Enabled", nexa.isOn()); } } \ No newline at end of file