Finnished major refactoring of Telstick plugin

This commit is contained in:
Ziver Koc 2016-08-18 16:27:57 +02:00
parent 3bdb4ea043
commit a9b8799f21
17 changed files with 284 additions and 142 deletions

View file

@ -102,7 +102,7 @@ public class ControllerManager implements HalSensorReportListener,
} }
@Override @Override
public void reportReceived(HalSensorConfig sensorConfig, HalSensorData sensorData) { public void reportReceived(HalSensorConfig sensorConfig, HalDeviceData sensorData) {
try{ try{
DBConnection db = HalContext.getDB(); DBConnection db = HalContext.getDB();
Sensor sensor = findSensor(sensorConfig, registeredSensors); Sensor sensor = findSensor(sensorConfig, registeredSensors);
@ -191,7 +191,7 @@ public class ControllerManager implements HalSensorReportListener,
} }
@Override @Override
public void reportReceived(HalEventConfig eventConfig, HalEventData eventData) { public void reportReceived(HalEventConfig eventConfig, HalDeviceData eventData) {
try { try {
DBConnection db = HalContext.getDB(); DBConnection db = HalContext.getDB();
Event event = findEvent(eventConfig, registeredEvents); Event event = findEvent(eventConfig, registeredEvents);
@ -234,7 +234,7 @@ public class ControllerManager implements HalSensorReportListener,
public void send(Event event){ public void send(Event event){
HalEventController controller = getControllerInstance(event.getController()); HalEventController controller = getControllerInstance(event.getController());
if(controller != null) { if(controller != null) {
controller.send(event.getDeviceConfig()); controller.send(event.getDeviceConfig(), event.getDeviceData());
reportReceived(event.getDeviceConfig(), event.getDeviceData()); // save action to db reportReceived(event.getDeviceConfig(), event.getDeviceData()); // save action to db
} }
else else

View file

@ -24,9 +24,10 @@ public interface HalEventController {
void deregister(HalEventConfig event); void deregister(HalEventConfig event);
/** /**
* @param event transmit this event if possible. * @param eventConfig the event configuration to target when sending
* @param eventData the data to send
*/ */
void send(HalEventConfig event); // TODO: where to put data? void send(HalEventConfig eventConfig, HalEventData eventData);
/** /**
* @return the number of registered objects * @return the number of registered objects

View file

@ -2,6 +2,6 @@ package se.hal.intf;
public interface HalEventReportListener { public interface HalEventReportListener {
void reportReceived(HalEventConfig e, HalEventData d); void reportReceived(HalEventConfig e, HalDeviceData d);
} }

View file

@ -2,6 +2,6 @@ package se.hal.intf;
public interface HalSensorReportListener { public interface HalSensorReportListener {
void reportReceived(HalSensorConfig s, HalSensorData d); void reportReceived(HalSensorConfig s, HalDeviceData d);
} }

View file

@ -0,0 +1,13 @@
package se.hal.plugin.tellstick;
/**
* This interface represents a device configuration and links it to a protocol.
*
* Created by Ziver on 2016-08-18.
*/
public interface TellstickDevice {
String getProtocolName(); // TODO: could be implemented in a better way
String getModelName(); // TODO: could be implemented in a better way
}

View file

@ -28,16 +28,11 @@ package se.hal.plugin.tellstick;
* Indicates that the implementing class is a protocol that can have group events. * Indicates that the implementing class is a protocol that can have group events.
* More specifically that on transmission will affect multiple devices. * More specifically that on transmission will affect multiple devices.
*/ */
public interface TellstickGroupProtocol { public interface TellstickDeviceGroup {
/** /**
* Protocols should extend this method if it has group functionality. * Protocols should extend this method if it has group functionality.
* @return true if this object an the input is in the same group. * @return true if this object and the input object belongs to the same group.
*/ */
public boolean equalsGroup(TellstickGroupProtocol obj); public boolean equalsGroup(TellstickDeviceGroup obj);
/**
* Copy the state data from the group to this object.
*/
public void copyGroupData(TellstickGroupProtocol groupProtocol);
} }

View file

@ -22,12 +22,15 @@
package se.hal.plugin.tellstick; package se.hal.plugin.tellstick;
import se.hal.plugin.tellstick.TellstickProtocol.TellstickDecodedEntry;
import se.hal.plugin.tellstick.protocol.NexaSelfLearningProtocol; import se.hal.plugin.tellstick.protocol.NexaSelfLearningProtocol;
import se.hal.plugin.tellstick.protocol.Oregon0x1A2DProtocol; import se.hal.plugin.tellstick.protocol.Oregon0x1A2DProtocol;
import zutil.converter.Converter; import zutil.converter.Converter;
import zutil.log.LogUtil; import zutil.log.LogUtil;
import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
@ -38,7 +41,7 @@ import java.util.logging.Logger;
*/ */
public class TellstickParser { public class TellstickParser {
private static final Logger logger = LogUtil.getLogger(); private static final Logger logger = LogUtil.getLogger();
private static HashMap<String, Class<? extends TellstickProtocol>> protocolMap; private static HashMap<String, TellstickProtocol> protocolMap;
static { static {
registerProtocol(NexaSelfLearningProtocol.class); registerProtocol(NexaSelfLearningProtocol.class);
@ -48,8 +51,12 @@ public class TellstickParser {
private int firmwareVersion = -1; private int firmwareVersion = -1;
/**
public TellstickProtocol decode(String data) { * Will decode the given data and return a list with device and data objects
* @param data
* @return a list with decoded objects or empty list if there was an error
*/
public List<TellstickDecodedEntry> decode(String data) {
if (data.startsWith("+W")) { if (data.startsWith("+W")) {
data = data.substring(2); data = data.substring(2);
HashMap<String, String> map = new HashMap<String, String>(); HashMap<String, String> map = new HashMap<String, String>();
@ -59,19 +66,16 @@ public class TellstickParser {
map.put(keyValue[0], keyValue[1]); map.put(keyValue[0], keyValue[1]);
} }
Class<? extends TellstickProtocol> protClass = TellstickProtocol protocol =
getProtocolClass(map.get("protocol"), map.get("model")); getProtocolInstance(map.get("protocol"), map.get("model"));
if (protClass != null) { if (protocol != null) {
try { String binData = map.get("data");
TellstickProtocol protocol = protClass.newInstance();
String binData = map.get("data");
protocol.decode(Converter.hexToByte(binData)); logger.finest("Decoding: " + protocol);
logger.finest("Decoded: " + protocol); List<TellstickDecodedEntry> list = protocol.decode(Converter.hexToByte(binData));
return protocol; if (list == null)
} catch (Exception e) { list = Collections.EMPTY_LIST;
logger.log(Level.WARNING, null, e); return list;
}
} else { } else {
logger.warning("Unknown protocol: " + data); logger.warning("Unknown protocol: " + data);
} }
@ -87,9 +91,12 @@ public class TellstickParser {
logger.severe("Unknown prefix: " + data); logger.severe("Unknown prefix: " + data);
} }
return null; return Collections.EMPTY_LIST;
} }
/**
* This method blocks until a send command confirmation is received.
*/
public void waitSendConformation(){ public void waitSendConformation(){
try { try {
this.wait(); this.wait();
@ -104,20 +111,23 @@ public class TellstickParser {
} }
public static void registerProtocol(Class<? extends TellstickProtocol> protClass) { public static void registerProtocol(Class<? extends TellstickProtocol> protClass) {
try { try {
if (protocolMap == null) registerProtocol( protClass.newInstance() );
protocolMap = new HashMap<>();
TellstickProtocol tmp = protClass.newInstance();
protocolMap.put(
tmp.getProtocolName() + "-" + tmp.getModelName(),
protClass);
} catch (Exception e) { } catch (Exception e) {
logger.log(Level.SEVERE, null, e); logger.log(Level.SEVERE, null, e);
} }
} }
public static void registerProtocol(TellstickProtocol protObj) {
if (protocolMap == null)
protocolMap = new HashMap<>();
protocolMap.put(
protObj.getProtocolName() + "-" + protObj.getModelName(),
protObj);
}
public static Class<? extends TellstickProtocol> getProtocolClass(String protocol, String model) { public static TellstickProtocol getProtocolInstance(String protocol, String model) {
return protocolMap.get(protocol + "-" + model); return protocolMap.get(protocol + "-" + model);
} }
} }

View file

@ -21,9 +21,12 @@
*/ */
package se.hal.plugin.tellstick; package se.hal.plugin.tellstick;
import se.hal.intf.HalDeviceData;
import se.hal.intf.HalEventConfig; import se.hal.intf.HalEventConfig;
import se.hal.intf.HalEventData; import se.hal.intf.HalEventData;
import java.util.List;
/** /**
* Created by Ziver on 2015-02-18. * Created by Ziver on 2015-02-18.
*/ */
@ -47,6 +50,24 @@ public abstract class TellstickProtocol {
} }
public String encode(HalEventConfig deviceConfig, HalEventData deviceData){ return null; } public String encode(HalEventConfig deviceConfig, HalEventData deviceData){ return null; }
public abstract void decode(byte[] data); public abstract List<TellstickDecodedEntry> decode(byte[] data);
public static class TellstickDecodedEntry {
private TellstickDevice device;
private HalDeviceData data;
public TellstickDecodedEntry(TellstickDevice device, HalDeviceData data){
this.device = device;
this.data = data;
}
public TellstickDevice getDevice(){
return device;
}
public HalDeviceData getData(){
return data;
}
}
} }

View file

@ -25,6 +25,7 @@ package se.hal.plugin.tellstick;
import com.fazecast.jSerialComm.SerialPort; import com.fazecast.jSerialComm.SerialPort;
import se.hal.HalContext; import se.hal.HalContext;
import se.hal.intf.*; import se.hal.intf.*;
import se.hal.plugin.tellstick.TellstickProtocol.TellstickDecodedEntry;
import zutil.log.LogUtil; import zutil.log.LogUtil;
import zutil.struct.TimedHashSet; import zutil.struct.TimedHashSet;
@ -51,20 +52,20 @@ public class TellstickSerialComm implements Runnable,
private SerialPort serial; private SerialPort serial;
private InputStream in; private InputStream in;
private OutputStream out; private OutputStream out;
private TimedHashSet set; // To check for duplicate transmissions private TimedHashSet<String> set; // To check for duplicate transmissions
protected TellstickParser parser; protected TellstickParser parser;
private HalSensorReportListener sensorListener; private HalSensorReportListener sensorListener;
private HalEventReportListener eventListener; private HalEventReportListener eventListener;
private List<TellstickProtocol> registeredDevices; private List<TellstickDevice> registeredDevices;
public TellstickSerialComm() { public TellstickSerialComm() {
set = new TimedHashSet(TRANSMISSION_UNIQUENESS_TTL); set = new TimedHashSet<>(TRANSMISSION_UNIQUENESS_TTL);
parser = new TellstickParser(); parser = new TellstickParser();
registeredDevices = Collections.synchronizedList(new ArrayList<TellstickProtocol>()); registeredDevices = Collections.synchronizedList(new ArrayList<TellstickDevice>());
} }
@Override @Override
@ -122,21 +123,17 @@ public class TellstickSerialComm implements Runnable,
logger.log(Level.SEVERE, null, e); logger.log(Level.SEVERE, null, e);
} }
} }
private void reportEvent(TellstickProtocol protocol){
if (sensorListener != null && protocol instanceof HalSensorConfig)
sensorListener.reportReceived((HalSensorConfig) protocol);
else if (eventListener != null && protocol instanceof HalEventConfig)
eventListener.reportReceived((HalEventConfig) protocol);
}
/** /**
* 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);
char c = 0; int c;
while((c = (char)in.read()) >= 0){ while((c = in.read()) >= 0){
switch(c) { switch(c) {
case -1:
return null;
case '\n': case '\n':
case '\r': case '\r':
if(str.length() > 0) if(str.length() > 0)
@ -149,48 +146,58 @@ public class TellstickSerialComm implements Runnable,
return str.toString(); return str.toString();
} }
protected void handleLine(String data){ protected void handleLine(String data){
TellstickProtocol protocol = parser.decode(data); List<TellstickDecodedEntry> decodeList = parser.decode(data);
if(protocol != null) { for (TellstickDecodedEntry entry : decodeList) {
if (protocol.getTimestamp() < 0) if (entry.getData().getTimestamp() < 0)
protocol.setTimestamp(System.currentTimeMillis()); entry.getData().setTimestamp(System.currentTimeMillis());
boolean registered = registeredDevices.contains(protocol); boolean registered = registeredDevices.contains(entry.getDevice());
if(registered && !set.contains(data) || // check for duplicates transmissions of registered devices if (registered && !set.contains(data) || // check for duplicates transmissions of registered devices
!registered && set.contains(data)) { // required duplicate transmissions before reporting unregistered devices !registered && set.contains(data)) { // required duplicate transmissions before reporting unregistered devices
//Check for registered device that are in the same group //Check for registered device that are in the same group
if(protocol instanceof TellstickGroupProtocol) { if (entry.getDevice() instanceof TellstickDeviceGroup) {
TellstickGroupProtocol groupProtocol = (TellstickGroupProtocol) protocol; TellstickDeviceGroup groupProtocol = (TellstickDeviceGroup) entry.getDevice();
for (int i=0; i<registeredDevices.size(); ++i) { // Don't use foreach for concurrency reasons for (int i = 0; i < registeredDevices.size(); ++i) { // Don't use foreach for concurrency reasons
TellstickProtocol childProtocol = registeredDevices.get(i); TellstickDevice childDevice = registeredDevices.get(i);
if (childProtocol instanceof TellstickGroupProtocol && if (childDevice instanceof TellstickDeviceGroup &&
groupProtocol.equalsGroup(childProtocol) && groupProtocol.equalsGroup((TellstickDeviceGroup)childDevice) &&
!protocol.equals(childProtocol)) { !entry.getDevice().equals(childDevice)) {
((TellstickGroupProtocol) childProtocol).copyGroupData(groupProtocol); reportEvent(childDevice, entry.getData());
childProtocol.setTimestamp(protocol.getTimestamp());
reportEvent(childProtocol);
} }
} }
} }
// Report source event // Report source event
reportEvent(protocol); reportEvent(entry.getDevice(), entry.getData());
} }
set.add(data); set.add(data);
} }
} }
private void reportEvent(TellstickDevice tellstickDevice, HalDeviceData deviceData){
if (sensorListener != null) {
if (tellstickDevice instanceof HalSensorConfig)
sensorListener.reportReceived((HalSensorConfig) tellstickDevice, deviceData);
else if (tellstickDevice instanceof HalEventConfig)
eventListener.reportReceived((HalEventConfig) tellstickDevice, deviceData);
}
}
@Override @Override
public void send(HalEventConfig event) { public void send(HalEventConfig deviceConfig, HalEventData deviceData) {
if(event instanceof TellstickProtocol) if(deviceConfig instanceof TellstickDevice) {
write((TellstickProtocol) event); TellstickDevice tellstickDevice = (TellstickDevice) deviceConfig;
} TellstickProtocol prot = TellstickParser.getProtocolInstance(
public synchronized void write(TellstickProtocol prot) { tellstickDevice.getProtocolName(),
write(prot.encode()); tellstickDevice.getModelName());
parser.waitSendConformation(); write(prot.encode(deviceConfig, deviceData));
prot.setTimestamp(System.currentTimeMillis());
parser.waitSendConformation();
deviceData.setTimestamp(System.currentTimeMillis());
}
} }
private void write(String data) { private void write(String data) {
if (data == null)
return;
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));
@ -204,24 +211,24 @@ public class TellstickSerialComm implements Runnable,
@Override @Override
public void register(HalEventConfig event) { public void register(HalEventConfig event) {
if(event instanceof TellstickProtocol) if(event instanceof TellstickDevice)
registeredDevices.add((TellstickProtocol) event); registeredDevices.add((TellstickDevice) event);
} }
@Override @Override
public void register(HalSensorConfig sensor) { public void register(HalSensorConfig sensor) {
if(sensor instanceof TellstickProtocol) if(sensor instanceof TellstickDevice)
registeredDevices.add((TellstickProtocol) sensor); registeredDevices.add((TellstickDevice) sensor);
} }
@Override @Override
public void deregister(HalEventConfig event) { public void deregister(HalEventConfig event) {
if(event instanceof TellstickProtocol) if(event instanceof TellstickDevice)
registeredDevices.remove((TellstickProtocol) event); registeredDevices.remove(event);
} }
@Override @Override
public void deregister(HalSensorConfig sensor) { public void deregister(HalSensorConfig sensor) {
if(sensor instanceof TellstickProtocol) if(sensor instanceof TellstickDevice)
registeredDevices.remove((TellstickProtocol) sensor); registeredDevices.remove(sensor);
} }
@Override @Override

View file

@ -24,38 +24,37 @@ package se.hal.plugin.tellstick.device;
import se.hal.intf.HalEventConfig; import se.hal.intf.HalEventConfig;
import se.hal.intf.HalEventController; import se.hal.intf.HalEventController;
import se.hal.plugin.tellstick.TellstickGroupProtocol; import se.hal.plugin.tellstick.TellstickDevice;
import se.hal.plugin.tellstick.TellstickProtocol; import se.hal.plugin.tellstick.TellstickDeviceGroup;
import se.hal.plugin.tellstick.TellstickSerialComm; import se.hal.plugin.tellstick.TellstickSerialComm;
import zutil.ByteUtil; import se.hal.plugin.tellstick.protocol.NexaSelfLearningProtocol;
import zutil.parser.binary.BinaryStruct; import zutil.parser.binary.BinaryStruct;
import zutil.parser.binary.BinaryStructInputStream;
import zutil.parser.binary.BinaryStructOutputStream;
import zutil.ui.Configurator; import zutil.ui.Configurator;
import java.io.IOException;
/** /**
* Created by Ziver on 2015-02-18. * Created by Ziver on 2015-02-18.
*/ */
public class NexaSelfLearning implements HalEventConfig,TellstickGroupProtocol,BinaryStruct { public class NexaSelfLearning implements HalEventConfig,TellstickDevice,TellstickDeviceGroup {
@BinaryField(index=1, length=26)
@Configurator.Configurable("House code") @Configurator.Configurable("House code")
private int house = 0; private int house = 0;
@BinaryField(index=2, length=1)
@Configurator.Configurable("Group code") @Configurator.Configurable("Group code")
private boolean group = false; private boolean group = false;
@BinaryField(index=3, length=1)
private boolean enable = false;
@BinaryField(index=4, length=4)
@Configurator.Configurable("Unit code") @Configurator.Configurable("Unit code")
private int unit = 0; private int unit = 0;
public NexaSelfLearning() { }
public NexaSelfLearning(int house, boolean group, int unit) {
this.house = house;
this.group = group;
this.unit = unit;
}
public int getHouse() { public int getHouse() {
return house; return house;
} }
@ -80,8 +79,7 @@ public class NexaSelfLearning implements HalEventConfig,TellstickGroupProtocol,B
public String toString(){ public String toString(){
return "house:"+house+ return "house:"+house+
", group:"+group+ ", group:"+group+
", unit:"+unit+ ", unit:"+unit;
", method:"+enable;
} }
@Override @Override
@ -93,20 +91,21 @@ public class NexaSelfLearning implements HalEventConfig,TellstickGroupProtocol,B
return false; return false;
} }
@Override @Override
public boolean equalsGroup(TellstickGroupProtocol obj) { public boolean equalsGroup(TellstickDeviceGroup 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 );
return false; return false;
} }
@Override
public void copyGroupData(TellstickGroupProtocol group) {
if(group instanceof NexaSelfLearning)
this.enable = ((NexaSelfLearning) group).enable;
}
public Class<? extends HalEventController> getEventController() { public Class<? extends HalEventController> getEventController() {
return TellstickSerialComm.class; return TellstickSerialComm.class;
} }
@Override
public String getProtocolName() { return NexaSelfLearningProtocol.PROTOCOL; }
@Override
public String getModelName() { return NexaSelfLearningProtocol.MODEL; }
} }

View file

@ -3,8 +3,10 @@ package se.hal.plugin.tellstick.device;
import se.hal.intf.HalEventController; import se.hal.intf.HalEventController;
import se.hal.intf.HalSensorConfig; import se.hal.intf.HalSensorConfig;
import se.hal.intf.HalSensorController; import se.hal.intf.HalSensorController;
import se.hal.plugin.tellstick.TellstickDevice;
import se.hal.plugin.tellstick.TellstickProtocol; import se.hal.plugin.tellstick.TellstickProtocol;
import se.hal.plugin.tellstick.TellstickSerialComm; import se.hal.plugin.tellstick.TellstickSerialComm;
import se.hal.plugin.tellstick.protocol.Oregon0x1A2DProtocol;
import zutil.log.LogUtil; import zutil.log.LogUtil;
import zutil.ui.Configurator; import zutil.ui.Configurator;
@ -13,7 +15,7 @@ import java.util.logging.Logger;
/** /**
* Created by Ziver on 2015-11-19. * Created by Ziver on 2015-11-19.
*/ */
public class Oregon0x1A2D implements HalSensorConfig { public class Oregon0x1A2D implements HalSensorConfig,TellstickDevice {
private static final Logger logger = LogUtil.getLogger(); private static final Logger logger = LogUtil.getLogger();
@Configurator.Configurable("Address") @Configurator.Configurable("Address")
@ -23,6 +25,11 @@ public class Oregon0x1A2D implements HalSensorConfig {
public Oregon0x1A2D() { }
public Oregon0x1A2D(int address) {
this.address = address;
}
@Override @Override
public boolean equals(Object obj){ public boolean equals(Object obj){
@ -52,4 +59,9 @@ public class Oregon0x1A2D implements HalSensorConfig {
return TellstickSerialComm.class; return TellstickSerialComm.class;
} }
@Override
public String getProtocolName() { return Oregon0x1A2DProtocol.PROTOCOL; }
@Override
public String getModelName() { return Oregon0x1A2DProtocol.MODEL; }
} }

View file

@ -23,29 +23,66 @@
package se.hal.plugin.tellstick.protocol; package se.hal.plugin.tellstick.protocol;
import se.hal.intf.HalEventConfig; import se.hal.intf.HalEventConfig;
import se.hal.plugin.tellstick.TellstickGroupProtocol; import se.hal.intf.HalEventData;
import se.hal.plugin.tellstick.TellstickProtocol; import se.hal.plugin.tellstick.TellstickProtocol;
import se.hal.plugin.tellstick.device.NexaSelfLearning;
import se.hal.struct.devicedata.SwitchEventData;
import zutil.ByteUtil; import zutil.ByteUtil;
import zutil.log.LogUtil;
import zutil.parser.binary.BinaryStruct; import zutil.parser.binary.BinaryStruct;
import zutil.parser.binary.BinaryStructInputStream; import zutil.parser.binary.BinaryStructInputStream;
import zutil.parser.binary.BinaryStructOutputStream; import zutil.parser.binary.BinaryStructOutputStream;
import zutil.ui.Configurator;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
/** /**
* Created by Ziver on 2015-02-18. * Created by Ziver on 2015-02-18.
*/ */
public class NexaSelfLearningProtocol extends TellstickProtocol { public class NexaSelfLearningProtocol extends TellstickProtocol {
private static final Logger logger = LogUtil.getLogger();
public static final String PROTOCOL = "arctech";
public static final String MODEL = "selflearning";
private static class NexaSLTransmissionStruct implements BinaryStruct{
@BinaryField(index=1, length=26)
int house = 0;
@BinaryField(index=2, length=1)
boolean group = false;
@BinaryField(index=3, length=1)
boolean enable = false;
@BinaryField(index=4, length=4)
int unit = 0;
}
public NexaSelfLearningProtocol() { public NexaSelfLearningProtocol() {
super("arctech", "selflearning"); super(PROTOCOL, MODEL);
} }
@Override @Override
public String encode(){ public String encode(HalEventConfig deviceConfig, HalEventData deviceData){
if ( ! (deviceConfig instanceof NexaSelfLearning)){
logger.severe("Device config is not instance of NexaSelfLearning: "+deviceConfig.getClass());
return null;
}
if ( ! (deviceData instanceof SwitchEventData)){
logger.severe("Device data is not instance of SwitchEventData: "+deviceData.getClass());
return null;
}
NexaSLTransmissionStruct struct = new NexaSLTransmissionStruct();
struct.house = ((NexaSelfLearning) deviceConfig).getHouse();
struct.group = ((NexaSelfLearning) deviceConfig).getGroup();
struct.enable = ((SwitchEventData) deviceData).isOn();
struct.unit = ((NexaSelfLearning) deviceConfig).getUnit();
try { try {
// T[t0][t1][t2][t3][length][d1]..[dn]+ // T[t0][t1][t2][t3][length][d1]..[dn]+
StringBuilder enc = new StringBuilder(90); // Tellstick supports max 74 bytes StringBuilder enc = new StringBuilder(90); // Tellstick supports max 74 bytes
@ -54,7 +91,7 @@ public class NexaSelfLearningProtocol extends TellstickProtocol {
enc.append((char)0b0000_1001); // preamble enc.append((char)0b0000_1001); // preamble
int length = 4; int length = 4;
byte[] data = BinaryStructOutputStream.serialize(this); byte[] data = BinaryStructOutputStream.serialize(struct);
for (byte b : data){ for (byte b : data){
for (int i=7; i>=0; --i){ for (int i=7; i>=0; --i){
if (ByteUtil.getBits(b, i, 1) == 0) if (ByteUtil.getBits(b, i, 1) == 0)
@ -70,15 +107,16 @@ public class NexaSelfLearningProtocol extends TellstickProtocol {
enc.append("+"); enc.append("+");
return enc.toString(); return enc.toString();
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); logger.log(Level.SEVERE, null, e);
} }
return ""; return null;
} }
@Override @Override
public void decode(byte[] data){ public List<TellstickDecodedEntry> decode(byte[] data){
// Data positions // Data positions
// house = 0xFFFFFFC0 // house = 0xFFFFFFC0
// group = 0x00000020 // group = 0x00000020
@ -88,7 +126,15 @@ public class NexaSelfLearningProtocol extends TellstickProtocol {
// 0x2CE81990 - 00101100_11101000_00011001_10 0 1 0000 - ON // 0x2CE81990 - 00101100_11101000_00011001_10 0 1 0000 - ON
// 0x2CE81980 - 00101100_11101000_00011001_10 0 0 0000 - OFF // 0x2CE81980 - 00101100_11101000_00011001_10 0 0 0000 - OFF
BinaryStructInputStream.read(this, data); NexaSLTransmissionStruct struct = new NexaSLTransmissionStruct();
BinaryStructInputStream.read(struct, data);
ArrayList<TellstickDecodedEntry> list = new ArrayList<>();
list.add(new TellstickDecodedEntry(
new NexaSelfLearning(struct.house, struct.group, struct.unit),
new SwitchEventData(struct.enable)
));
return list;
} }

View file

@ -1,10 +1,13 @@
package se.hal.plugin.tellstick.protocol; package se.hal.plugin.tellstick.protocol;
import se.hal.intf.HalSensorConfig;
import se.hal.plugin.tellstick.TellstickProtocol; import se.hal.plugin.tellstick.TellstickProtocol;
import se.hal.plugin.tellstick.device.Oregon0x1A2D;
import se.hal.struct.devicedata.HumiditySensorData;
import se.hal.struct.devicedata.TemperatureSensorData;
import zutil.log.LogUtil; import zutil.log.LogUtil;
import zutil.ui.Configurator;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger; import java.util.logging.Logger;
/** /**
@ -12,20 +15,22 @@ import java.util.logging.Logger;
*/ */
public class Oregon0x1A2DProtocol extends TellstickProtocol { public class Oregon0x1A2DProtocol extends TellstickProtocol {
private static final Logger logger = LogUtil.getLogger(); private static final Logger logger = LogUtil.getLogger();
public static final String PROTOCOL = "oregon";
public static final String MODEL = "0x1A2D";
public Oregon0x1A2DProtocol(){ public Oregon0x1A2DProtocol(){
super("oregon", "0x1A2D"); super(PROTOCOL, MODEL);
} }
@Override @Override
public void decode(byte[] data) { public List<TellstickDecodedEntry> decode(byte[] data) {
//class:sensor;protocol:oregon;model:0x1A2D;data:20BA000000002700; //class:sensor;protocol:oregon;model:0x1A2D;data:20BA000000002700;
// int channel = (data[0] >> 4) & 0x7; // channel not used // int channel = (data[0] >> 4) & 0x7; // channel not used
address = data[1] & 0xFF; int address = data[1] & 0xFF;
int temp3 = (data[2] >> 4) & 0xF; int temp3 = (data[2] >> 4) & 0xF;
int temp1 = (data[3] >> 4) & 0xF; int temp1 = (data[3] >> 4) & 0xF;
int temp2 = data[3] & 0xF; int temp2 = data[3] & 0xF;
@ -44,14 +49,24 @@ public class Oregon0x1A2DProtocol extends TellstickProtocol {
if (calcChecksum != checksum) { if (calcChecksum != checksum) {
logger.fine("Checksum failed, address: "+address); logger.fine("Checksum failed, address: "+address);
return; return null;
} }
temperature = ((temp1 * 100) + (temp2 * 10) + temp3)/10.0; double temperature = ((temp1 * 100) + (temp2 * 10) + temp3)/10.0;
if (negative) if (negative)
temperature = -temperature; temperature = -temperature;
humidity = (hum1 * 10.0) + hum2; double humidity = (hum1 * 10.0) + hum2;
// Create return objects
ArrayList<TellstickDecodedEntry> list = new ArrayList<>();
Oregon0x1A2D device = new Oregon0x1A2D(address);
list.add(new TellstickDecodedEntry(
device, new TemperatureSensorData(temperature)
));
list.add(new TellstickDecodedEntry(
device, new HumiditySensorData(humidity)
));
return list;
} }
} }

View file

@ -11,6 +11,12 @@ public class HumiditySensorData extends HalSensorData {
private double humidity; private double humidity;
public HumiditySensorData() { }
public HumiditySensorData(double humidity) {
this.humidity = humidity;
}
@Override @Override
public double getData() { public double getData() {
return humidity; return humidity;

View file

@ -32,6 +32,11 @@ public class SwitchEventData extends HalEventData {
private boolean enabled; private boolean enabled;
public SwitchEventData() { }
public SwitchEventData(boolean enabled) {
this.enabled = enabled;
}
public void turnOn(){ public void turnOn(){
enabled = true; enabled = true;
} }

View file

@ -10,6 +10,11 @@ public class TemperatureSensorData extends HalSensorData {
private double temperature; private double temperature;
public TemperatureSensorData(){}
public TemperatureSensorData(double temperature){
this.temperature = temperature;
}
/** /**
* @param data the temperature to set in degrees C * @param data the temperature to set in degrees C
*/ */

View file

@ -22,9 +22,14 @@
package se.hal.plugin.tellstick.protocol; package se.hal.plugin.tellstick.protocol;
import se.hal.plugin.tellstick.TellstickProtocol;
import se.hal.plugin.tellstick.TellstickProtocol.TellstickDecodedEntry;
import se.hal.plugin.tellstick.device.NexaSelfLearning;
import se.hal.struct.devicedata.SwitchEventData;
import zutil.converter.Converter; import zutil.converter.Converter;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.List;
import static org.junit.Assert.*; import static org.junit.Assert.*;
@ -32,10 +37,11 @@ public class NexaSelfLearningTest {
@org.junit.Test @org.junit.Test
public void testEncode() throws Exception { public void testEncode() throws Exception {
NexaSelfLearningProtocol nexa = new NexaSelfLearningProtocol(); NexaSelfLearning nexaDevice = new NexaSelfLearning();
nexa.setHouse(11_772_006); nexaDevice.setHouse(11_772_006);
nexa.setUnit(0); nexaDevice.setUnit(0);
nexa.turnOn(); SwitchEventData nexaData = new SwitchEventData();
nexaData.turnOn();
byte[] expected = Converter.toBytes(new char[]{ byte[] expected = Converter.toBytes(new char[]{
84, // T 84, // T
@ -50,7 +56,8 @@ public class NexaSelfLearningTest {
0x00, // postemble 0x00, // postemble
43}); // + 43}); // +
byte[] actual = nexa.encode().getBytes(StandardCharsets.ISO_8859_1); NexaSelfLearningProtocol nexaProt = new NexaSelfLearningProtocol();
byte[] actual = nexaProt.encode(nexaDevice, nexaData).getBytes(StandardCharsets.ISO_8859_1);
System.out.println("Expected: "+Converter.toHexString(expected).toUpperCase()); System.out.println("Expected: "+Converter.toHexString(expected).toUpperCase());
System.out.println("Actual : "+Converter.toHexString(actual).toUpperCase()); System.out.println("Actual : "+Converter.toHexString(actual).toUpperCase());
@ -60,25 +67,25 @@ public class NexaSelfLearningTest {
@org.junit.Test @org.junit.Test
public void decode_ON() throws Exception { public void decode_ON() throws Exception {
NexaSelfLearningProtocol nexa = decode("0x2CE81990"); TellstickDecodedEntry nexa = decode("0x2CE81990");
assertEquals("House Code", 11772006, nexa.getHouse()); assertEquals("House Code", 11772006, ((NexaSelfLearning)nexa.getDevice()).getHouse());
assertEquals("Unit Code", 0, nexa.getUnit()); assertEquals("Unit Code", 0, ((NexaSelfLearning)nexa.getDevice()).getUnit());
assertTrue("Enabled", nexa.isOn()); assertTrue("Enabled", ((SwitchEventData)nexa.getData()).isOn());
} }
@org.junit.Test @org.junit.Test
public void decode_OFF() throws Exception { public void decode_OFF() throws Exception {
NexaSelfLearningProtocol nexa = decode("0x2CE81980"); TellstickDecodedEntry nexa = decode("0x2CE81980");
assertEquals("House Code", 11772006, nexa.getHouse()); assertEquals("House Code", 11772006, ((NexaSelfLearning)nexa.getDevice()).getHouse());
assertEquals("Unit Code", 0, nexa.getUnit()); assertEquals("Unit Code", 0, ((NexaSelfLearning)nexa.getDevice()).getUnit());
assertFalse("Enabled", nexa.isOn()); assertFalse("Enabled", ((SwitchEventData)nexa.getData()).isOn());
} }
private NexaSelfLearningProtocol decode(String data){ private TellstickDecodedEntry decode(String data){
NexaSelfLearningProtocol nexa = new NexaSelfLearningProtocol(); NexaSelfLearningProtocol nexaProt = new NexaSelfLearningProtocol();
nexa.decode(Converter.hexToByte(data)); List<TellstickDecodedEntry> list = nexaProt.decode(Converter.hexToByte(data));
return nexa; return list.get(0);
} }
} }