Added Junit test for Tellstick Controller and reverted equals(Hal...) as it was causing unforeseen issues.
This commit is contained in:
parent
2c1ccb8b57
commit
21ab281ec6
10 changed files with 155 additions and 86 deletions
|
|
@ -15,6 +15,6 @@ public interface HalEventData {
|
||||||
* This method needs to be implemented.
|
* This method needs to be implemented.
|
||||||
* NOTE: it should not compare data and timestamp, only static or unique data for the event type.
|
* NOTE: it should not compare data and timestamp, only static or unique data for the event type.
|
||||||
*/
|
*/
|
||||||
boolean equals(HalEventData obj);
|
boolean equals(Object obj);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -35,5 +35,5 @@ public interface HalSensorData {
|
||||||
* NOTE: it should only static or unique data for the sensor type.
|
* NOTE: it should only static or unique data for the sensor type.
|
||||||
* This method is used to associate reported data with registered sensors
|
* This method is used to associate reported data with registered sensors
|
||||||
*/
|
*/
|
||||||
boolean equals(HalSensorData obj);
|
boolean equals(Object obj);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,7 @@ public class NutUpsDevice implements PowerConsumptionSensorData{
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(HalSensorData obj){
|
public boolean equals(Object obj){
|
||||||
if (obj instanceof NutUpsDevice)
|
if (obj instanceof NutUpsDevice)
|
||||||
return deviceId != null && deviceId.equals(((NutUpsDevice)obj).deviceId);
|
return deviceId != null && deviceId.equals(((NutUpsDevice)obj).deviceId);
|
||||||
return false;
|
return false;
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,7 @@ public class RPiPowerConsumptionSensor implements PowerConsumptionSensorData {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(HalSensorData obj){
|
public boolean equals(Object obj){
|
||||||
if(!(obj instanceof RPiPowerConsumptionSensor))
|
if(!(obj instanceof RPiPowerConsumptionSensor))
|
||||||
return false;
|
return false;
|
||||||
return ((RPiPowerConsumptionSensor)obj).gpioPin == gpioPin;
|
return ((RPiPowerConsumptionSensor)obj).gpioPin == gpioPin;
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,7 @@ public class RPiTemperatureSensor implements TemperatureSensorData {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(HalSensorData obj){
|
public boolean equals(Object obj){
|
||||||
if(obj instanceof RPiTemperatureSensor)
|
if(obj instanceof RPiTemperatureSensor)
|
||||||
return obj == this;
|
return obj == this;
|
||||||
return false;
|
return false;
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,8 @@ import java.util.logging.Logger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by Ziver on 2015-02-18.
|
* Created by Ziver on 2015-02-18.
|
||||||
|
*
|
||||||
|
* Protocol Specification: http://developer.telldus.com/doxygen/TellStick.html
|
||||||
*/
|
*/
|
||||||
public class TellstickParser {
|
public class TellstickParser {
|
||||||
private static final Logger logger = LogUtil.getLogger();
|
private static final Logger logger = LogUtil.getLogger();
|
||||||
|
|
@ -43,6 +45,9 @@ public class TellstickParser {
|
||||||
registerProtocol(Oregon0x1A2D.class);
|
registerProtocol(Oregon0x1A2D.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private int firmwareVersion = -1;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public TellstickProtocol decode(String data) {
|
public TellstickProtocol decode(String data) {
|
||||||
if (data.startsWith("+W")) {
|
if (data.startsWith("+W")) {
|
||||||
|
|
@ -72,6 +77,12 @@ public class TellstickParser {
|
||||||
}
|
}
|
||||||
} else if (data.startsWith("+S") || data.startsWith("+T")) {
|
} else if (data.startsWith("+S") || data.startsWith("+T")) {
|
||||||
// This is confirmation of send commands
|
// This is confirmation of send commands
|
||||||
|
synchronized (this) {
|
||||||
|
this.notifyAll();
|
||||||
|
}
|
||||||
|
} else if (data.startsWith("+V")) {
|
||||||
|
if (data.length() > 2)
|
||||||
|
firmwareVersion = Integer.parseInt(data.substring(2));
|
||||||
}else {
|
}else {
|
||||||
logger.severe("Unknown prefix: " + data);
|
logger.severe("Unknown prefix: " + data);
|
||||||
}
|
}
|
||||||
|
|
@ -79,12 +90,24 @@ public class TellstickParser {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void waitSendConformation(){
|
||||||
|
try {
|
||||||
|
this.wait();
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
logger.log(Level.SEVERE, null, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public int getFirmwareVersion() {
|
||||||
|
return firmwareVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public static void registerProtocol(Class<? extends TellstickProtocol> protClass) {
|
public static void registerProtocol(Class<? extends TellstickProtocol> protClass) {
|
||||||
try {
|
try {
|
||||||
if (protocolMap == null)
|
if (protocolMap == null)
|
||||||
protocolMap = new HashMap<String, Class<? extends TellstickProtocol>>();
|
protocolMap = new HashMap<>();
|
||||||
TellstickProtocol tmp = protClass.newInstance();
|
TellstickProtocol tmp = protClass.newInstance();
|
||||||
protocolMap.put(
|
protocolMap.put(
|
||||||
tmp.getProtocolName() + "-" + tmp.getModelName(),
|
tmp.getProtocolName() + "-" + tmp.getModelName(),
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,7 @@ public class TellstickSerialComm implements Runnable,
|
||||||
private OutputStream out;
|
private OutputStream out;
|
||||||
private TimedHashSet set; // To check for duplicate transmissions
|
private TimedHashSet set; // To check for duplicate transmissions
|
||||||
|
|
||||||
private TellstickParser parser;
|
protected TellstickParser parser;
|
||||||
private HalSensorReportListener sensorListener;
|
private HalSensorReportListener sensorListener;
|
||||||
private HalEventReportListener eventListener;
|
private HalEventReportListener eventListener;
|
||||||
|
|
||||||
|
|
@ -115,43 +115,8 @@ public class TellstickSerialComm implements Runnable,
|
||||||
public void run() {
|
public void run() {
|
||||||
try {
|
try {
|
||||||
String data;
|
String data;
|
||||||
|
|
||||||
while (in != null && (data = readLine()) != null) {
|
while (in != null && (data = readLine()) != null) {
|
||||||
if ((data.startsWith("+S") || data.startsWith("+T"))) {
|
handleLine(data);
|
||||||
synchronized (this) {
|
|
||||||
this.notifyAll();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
TellstickProtocol protocol = parser.decode(data);
|
|
||||||
if(protocol != null) {
|
|
||||||
if (protocol.getTimestamp() < 0)
|
|
||||||
protocol.setTimestamp(System.currentTimeMillis());
|
|
||||||
|
|
||||||
boolean registered = registeredDevices.contains(protocol);
|
|
||||||
if(registered && !set.contains(data) || // check for duplicates transmissions of registered devices
|
|
||||||
!registered && set.contains(data)) { // required duplicate transmissions before reporting unregistered devices
|
|
||||||
|
|
||||||
//Check for registered device that are in the same group
|
|
||||||
if(protocol instanceof TellstickGroupProtocol) {
|
|
||||||
TellstickGroupProtocol groupProtocol = (TellstickGroupProtocol) protocol;
|
|
||||||
for (int i=0; i<registeredDevices.size(); ++i) { // Don't use foreach for concurrency reasons
|
|
||||||
TellstickProtocol childProtocol = registeredDevices.get(i);
|
|
||||||
if (childProtocol instanceof TellstickGroupProtocol &&
|
|
||||||
groupProtocol.equalsGroup(childProtocol) &&
|
|
||||||
!protocol.equals(childProtocol)) {
|
|
||||||
((TellstickGroupProtocol) childProtocol).copyGroupData(groupProtocol);
|
|
||||||
childProtocol.setTimestamp(protocol.getTimestamp());
|
|
||||||
reportEvent(childProtocol);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Report source event
|
|
||||||
reportEvent(protocol);
|
|
||||||
}
|
|
||||||
set.add(data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
logger.log(Level.SEVERE, null, e);
|
logger.log(Level.SEVERE, null, e);
|
||||||
|
|
@ -165,7 +130,7 @@ public class TellstickSerialComm implements Runnable,
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* There seems to be an issue with read(...) methods only read() is working
|
* There seems to be an issue with read(...) methods, only read() is working
|
||||||
*/
|
*/
|
||||||
private String readLine() throws IOException {
|
private String readLine() throws IOException {
|
||||||
StringBuilder str = new StringBuilder(50);
|
StringBuilder str = new StringBuilder(50);
|
||||||
|
|
@ -183,6 +148,36 @@ public class TellstickSerialComm implements Runnable,
|
||||||
}
|
}
|
||||||
return str.toString();
|
return str.toString();
|
||||||
}
|
}
|
||||||
|
protected void handleLine(String data){
|
||||||
|
TellstickProtocol protocol = parser.decode(data);
|
||||||
|
if(protocol != null) {
|
||||||
|
if (protocol.getTimestamp() < 0)
|
||||||
|
protocol.setTimestamp(System.currentTimeMillis());
|
||||||
|
|
||||||
|
boolean registered = registeredDevices.contains(protocol);
|
||||||
|
if(registered && !set.contains(data) || // check for duplicates transmissions of registered devices
|
||||||
|
!registered && set.contains(data)) { // required duplicate transmissions before reporting unregistered devices
|
||||||
|
|
||||||
|
//Check for registered device that are in the same group
|
||||||
|
if(protocol instanceof TellstickGroupProtocol) {
|
||||||
|
TellstickGroupProtocol groupProtocol = (TellstickGroupProtocol) protocol;
|
||||||
|
for (int i=0; i<registeredDevices.size(); ++i) { // Don't use foreach for concurrency reasons
|
||||||
|
TellstickProtocol childProtocol = registeredDevices.get(i);
|
||||||
|
if (childProtocol instanceof TellstickGroupProtocol &&
|
||||||
|
groupProtocol.equalsGroup(childProtocol) &&
|
||||||
|
!protocol.equals(childProtocol)) {
|
||||||
|
((TellstickGroupProtocol) childProtocol).copyGroupData(groupProtocol);
|
||||||
|
childProtocol.setTimestamp(protocol.getTimestamp());
|
||||||
|
reportEvent(childProtocol);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Report source event
|
||||||
|
reportEvent(protocol);
|
||||||
|
}
|
||||||
|
set.add(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -192,14 +187,10 @@ public class TellstickSerialComm implements Runnable,
|
||||||
}
|
}
|
||||||
public synchronized void write(TellstickProtocol prot) {
|
public synchronized void write(TellstickProtocol prot) {
|
||||||
write(prot.encode());
|
write(prot.encode());
|
||||||
try {
|
parser.waitSendConformation();
|
||||||
this.wait();
|
prot.setTimestamp(System.currentTimeMillis());
|
||||||
prot.setTimestamp(System.currentTimeMillis());
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
logger.log(Level.SEVERE, null, e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
public void write(String data) {
|
private void write(String data) {
|
||||||
try {
|
try {
|
||||||
for(int i=0; i<data.length();i++)
|
for(int i=0; i<data.length();i++)
|
||||||
out.write(0xFF & data.charAt(i));
|
out.write(0xFF & data.charAt(i));
|
||||||
|
|
|
||||||
|
|
@ -148,7 +148,7 @@ public class NexaSelfLearning extends TellstickProtocol
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(HalEventData obj){
|
public boolean equals(Object obj){
|
||||||
if(obj instanceof NexaSelfLearning)
|
if(obj instanceof NexaSelfLearning)
|
||||||
return ((NexaSelfLearning) obj).house == house &&
|
return ((NexaSelfLearning) obj).house == house &&
|
||||||
((NexaSelfLearning) obj).group == group &&
|
((NexaSelfLearning) obj).group == group &&
|
||||||
|
|
|
||||||
|
|
@ -69,7 +69,7 @@ public class Oregon0x1A2D extends TellstickProtocol implements PowerConsumptionS
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(HalSensorData obj){
|
public boolean equals(Object obj){
|
||||||
if(! (obj instanceof Oregon0x1A2D))
|
if(! (obj instanceof Oregon0x1A2D))
|
||||||
return false;
|
return false;
|
||||||
return ((Oregon0x1A2D)obj).address == this.address;
|
return ((Oregon0x1A2D)obj).address == this.address;
|
||||||
|
|
|
||||||
|
|
@ -1,59 +1,114 @@
|
||||||
package se.hal.plugin.tellstick;
|
package se.hal.plugin.tellstick;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
import se.hal.HalContext;
|
import se.hal.HalContext;
|
||||||
|
import se.hal.intf.HalEventData;
|
||||||
|
import se.hal.intf.HalEventReportListener;
|
||||||
import se.hal.intf.HalSensorData;
|
import se.hal.intf.HalSensorData;
|
||||||
import se.hal.intf.HalSensorReportListener;
|
import se.hal.intf.HalSensorReportListener;
|
||||||
import se.hal.plugin.tellstick.protocols.Oregon0x1A2D;
|
import se.hal.plugin.tellstick.protocols.Oregon0x1A2D;
|
||||||
|
import zutil.converter.Converter;
|
||||||
import zutil.db.DBConnection;
|
import zutil.db.DBConnection;
|
||||||
import zutil.log.CompactLogFormatter;
|
import zutil.log.CompactLogFormatter;
|
||||||
import zutil.log.LogUtil;
|
import zutil.log.LogUtil;
|
||||||
|
import zutil.struct.MutableInt;
|
||||||
|
|
||||||
import java.sql.PreparedStatement;
|
import java.sql.PreparedStatement;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by Ziver on 2015-11-19.
|
* Created by Ziver on 2015-11-19.
|
||||||
*/
|
*/
|
||||||
public class TelstickSerialCommTest {
|
public class TelstickSerialCommTest {
|
||||||
private static final Logger logger = LogUtil.getLogger();
|
|
||||||
|
|
||||||
public static void main(String[] args) {
|
@Before
|
||||||
try {
|
public void init(){
|
||||||
LogUtil.setGlobalFormatter(new CompactLogFormatter());
|
TellstickParser.registerProtocol(TestEvent.class);
|
||||||
LogUtil.setGlobalLevel(Level.FINEST);
|
}
|
||||||
|
|
||||||
logger.info("Initializing HalContext...");
|
|
||||||
HalContext.initialize();
|
|
||||||
final DBConnection db = HalContext.getDB();
|
|
||||||
|
|
||||||
logger.info("Setting up Tellstick listeners...");
|
//############# Non crashing TC
|
||||||
TellstickSerialComm comm = new TellstickSerialComm();
|
|
||||||
comm.setListener(new HalSensorReportListener() {
|
|
||||||
@Override
|
|
||||||
public void reportReceived(HalSensorData s) {
|
|
||||||
if(s instanceof Oregon0x1A2D){
|
|
||||||
logger.info("Power used: "+ ((Oregon0x1A2D)s).getTemperature() +" pulses");
|
|
||||||
try {
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
comm.initialize("COM5");
|
|
||||||
//comm.connect("/dev/ttyUSB1");
|
|
||||||
|
|
||||||
logger.info("Up and Running");
|
@Test
|
||||||
} catch (Exception e) {
|
public void startup(){
|
||||||
e.printStackTrace();
|
TellstickSerialComm tellstick = new TellstickSerialComm();
|
||||||
|
tellstick.handleLine("+V2");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void unregisteredListener(){
|
||||||
|
TellstickSerialComm tellstick = new TellstickSerialComm();
|
||||||
|
tellstick.handleLine("+Wclass:sensor;protocol:test-prot;model:test-model;data:1234;");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//############ Normal TCs
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void unregisteredEvent(){
|
||||||
|
// Setup
|
||||||
|
TellstickSerialComm tellstick = new TellstickSerialComm();
|
||||||
|
final ArrayList<HalEventData> list = new ArrayList<>();
|
||||||
|
tellstick.setListener(new HalEventReportListener() {
|
||||||
|
@Override
|
||||||
|
public void reportReceived(HalEventData e) {
|
||||||
|
list.add(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// Execution
|
||||||
|
tellstick.handleLine("+Wclass:sensor;protocol:test-prot;model:test-model;data:2345;");
|
||||||
|
assertEquals("Events first transmission", 0, list.size());
|
||||||
|
tellstick.handleLine("+Wclass:sensor;protocol:test-prot;model:test-model;data:2345;");
|
||||||
|
assertEquals("Events Second transmission", 1, list.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void event(){
|
||||||
|
// Setup
|
||||||
|
TellstickSerialComm tellstick = new TellstickSerialComm();
|
||||||
|
final ArrayList<HalEventData> list = new ArrayList<>();
|
||||||
|
tellstick.setListener(new HalEventReportListener() {
|
||||||
|
@Override
|
||||||
|
public void reportReceived(HalEventData e) {
|
||||||
|
list.add(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// Execution
|
||||||
|
TestEvent event = new TestEvent();
|
||||||
|
event.testData = 0xAAAA;
|
||||||
|
tellstick.register(event);
|
||||||
|
tellstick.handleLine("+Wclass:sensor;protocol:test-prot;model:test-model;data:AAAA;");
|
||||||
|
// Verification
|
||||||
|
assertEquals("Nr of received events", 1, list.size());
|
||||||
|
assertEquals("Data", event.testData, ((TestEvent)list.get(0)).testData);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private static class TestEvent extends TellstickProtocol implements HalEventData{
|
||||||
|
public int testData;
|
||||||
|
|
||||||
|
public TestEvent(){
|
||||||
|
super("test-prot", "test-model");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void decode(byte[] data) {
|
||||||
|
testData = Converter.toInt(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String encode() {return null;}
|
||||||
|
@Override
|
||||||
|
public double getData() {return 0;}
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {return testData == ((TestEvent)obj).testData;}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue