/**
* Copyright (c) 2010-2016 by the respective copyright holders.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.openhab.binding.tellstick.internal.device;
import java.util.ArrayList;
import org.openhab.binding.tellstick.internal.JNA;
/**
* Any tellstick device.
*
* @author jarlebh
* @since 1.5.0
*/
public class TellstickDevice implements Comparable<TellstickDevice> {
/**
* Holds the device ID.
*/
protected int deviceId;
/**
* Holds the device Name.
*/
protected String name;
/**
* Holds the device model
*/
protected String model;
/**
* Holds the device protocol.
*/
protected String protocol;
/**
* Holds the current Device Status.
*/
protected int status;
/**
* Holds the device type.
*/
protected int deviceType;
/**
* Holds the last send data
*/
protected String data;
/**
* Holds all the supported methods! Must be set with setSupportedMethods.
*/
static protected int supportedMethods = -1;
/**
* Tellstick success flag from C Lib.
*/
static final public int TELLSTICK_SUCCESS = 0;
/**
* This is a must to set for all applications that is getting developed! If
* not set SupportedMethodsException will get thrown whenever you try to get
* / create devices. Usage: // Set supported methods for this app.
* TellstickDevice.setSupportedMethods( JNA.CLibrary.TELLSTICK_BELL |
* JNA.CLibrary.TELLSTICK_TURNOFF | JNA.CLibrary.TELLSTICK_TURNON |
* JNA.CLibrary.TELLSTICK_DIM | JNA.CLibrary.TELLSTICK_LEARN |
* JNA.CLibrary.TELLSTICK_EXECUTE | JNA.CLibrary.TELLSTICK_STOP );
*
* @param supportedM
*/
static public void setSupportedMethods(int supportedM) {
supportedMethods = supportedM;
}
/**
* Checks if supported methods is set. This is required for this lib to
* work.
*
* @throws SupportedMethodsException
*/
static public void supportedMethodsCheck() throws SupportedMethodsException {
if (supportedMethods == -1) {
throw new SupportedMethodsException(
"You must set supported methods with TellstickDevice.setSupportedMethods( ... ) to define what methods your application supports.");
}
}
/**
* Constuctor of the device.
*
* @param deviceId
* @throws SupportedMethodsException
*/
public TellstickDevice(int deviceId) throws SupportedMethodsException {
supportedMethodsCheck();
this.deviceId = deviceId;
// Get name
this.name = JNA.getPointerValue(JNA.CLibrary.INSTANCE.tdGetName(deviceId));
// JNA.CLibrary.INSTANCE.tdReleaseString(name);
// Get model
this.model = JNA.getPointerValue(JNA.CLibrary.INSTANCE.tdGetModel(deviceId));
// JNA.CLibrary.INSTANCE.tdReleaseString(model);
// Get protocol
this.protocol = JNA.getPointerValue(JNA.CLibrary.INSTANCE.tdGetProtocol(deviceId));
// JNA.CLibrary.INSTANCE.tdReleaseString(protocol);
// Get last status ( EMULATED 2 way communication ) Works with TS DUO
this.status = JNA.CLibrary.INSTANCE.tdLastSentCommand(deviceId, getSupportedMethods());
if (this.status == JNA.CLibrary.TELLSTICK_DIM) {
this.data = JNA.getPointerValue(JNA.CLibrary.INSTANCE.tdLastSentValue(deviceId));
}
// Get the device type.
this.deviceType = JNA.CLibrary.INSTANCE.tdGetDeviceType(deviceId);
}
/**
* Creates a new device. Can throw exception if failure to create new
* device.
*
*/
public TellstickDevice(String name, String protocol, String model) throws Exception {
supportedMethodsCheck();
int id = JNA.CLibrary.INSTANCE.tdAddDevice();
if (id < 0) {
throw new Exception("Unknown error creating a new device.");
}
this.deviceId = id;
if (!setName(name)) {
remove();
throw new Exception("Error creating device, could not set name.");
}
if (!setProtocol(protocol)) {
remove();
throw new Exception("Error creating device, could not set protocol.");
}
if (!setModel(model)) {
remove();
throw new Exception("Error creating device, could not set protocol.");
}
}
/**
* Gets parameter from device.
*
* @param attribute
* @param defaultVal
*/
public String getParameter(String attribute, String defaultVal) {
return JNA.getPointerValue(JNA.CLibrary.INSTANCE.tdGetDeviceParameter(getId(), attribute, defaultVal));
}
/**
* Sets parameter to device.
*
* @param attribute
* @param value
*/
public boolean setParameter(String attribute, String value) {
return JNA.CLibrary.INSTANCE.tdSetDeviceParameter(getId(), attribute, value);
}
/**
* Returns The right object for this device. Can be: - GroupDevice ( Can
* have methods from bell, dim and on/off) - SceneDevice ( Contains execute
* ) - BellDevice - DimmableDevice - Device
*
* @param TS
* @param deviceId
* TellstickDevice , Either BellDevice, DimmableDevice or Device.
* @throws SupportedMethodsException
* Exception is thrown if accepted methods is not defined.
* @throws DeviceNotSupportedException
* Exception is thrown if application does not support this
* device type.
*/
static public TellstickDevice getDevice(int deviceId)
throws SupportedMethodsException, DeviceNotSupportedException {
supportedMethodsCheck();
int methods = JNA.CLibrary.INSTANCE.tdMethods(deviceId, getSupportedMethods());
// Is this device a group or scene ? In this case, we must return either
// GroupDevice or SceneDevice.
int type = JNA.CLibrary.INSTANCE.tdGetDeviceType(deviceId);
if (type == JNA.CLibrary.TELLSTICK_TYPE_GROUP) {
return new GroupDevice(deviceId);
}
// Now single action based.
if (type == JNA.CLibrary.TELLSTICK_TYPE_SCENE) {
return new SceneDevice(deviceId);
} else if ((methods & JNA.CLibrary.TELLSTICK_BELL) > 0) {
return new BellDevice(deviceId);
} else if ((methods & JNA.CLibrary.TELLSTICK_DIM) > 0) {
return new DimmableDevice(deviceId);
} else if ((methods & JNA.CLibrary.TELLSTICK_UP) > 0 && (methods & JNA.CLibrary.TELLSTICK_DOWN) > 0
&& (methods & JNA.CLibrary.TELLSTICK_STOP) > 0) {
return new UpDownDevice(deviceId);
} else if ((methods & JNA.CLibrary.TELLSTICK_TURNON) > 0 && (methods & JNA.CLibrary.TELLSTICK_TURNOFF) > 0) {
return new Device(deviceId);
} else if ((methods & JNA.CLibrary.TELLSTICK_EXECUTE) > 0) {
return new SceneDevice(deviceId);
}
throw new DeviceNotSupportedException("The device properties seems not to be supported by this application");
}
/**
* Gets a list of all the devices. Created using ArrayList.
*
* @throws SupportedMethodsException
* @throws DeviceNotSupportedException
*/
static public ArrayList<TellstickDevice> getDevices() throws SupportedMethodsException {
int nbrDevices = JNA.CLibrary.INSTANCE.tdGetNumberOfDevices();
ArrayList<TellstickDevice> devices = new ArrayList<TellstickDevice>();
for (int i = 0; i < nbrDevices; i++) {
try {
TellstickDevice dev = TellstickDevice.getDevice(JNA.CLibrary.INSTANCE.tdGetDeviceId(i));
devices.add(dev);
} catch (DeviceNotSupportedException e) {
// Device not supported. Do not add to list.
}
}
return devices;
}
/**
* Gets all devices with a filter of instances. Usage:
* ArrayList<TellstickDevice> devices2 =
* TellstickDevice.getDevices(Device.class, DimmableDevice.class,
* ...etc...);
*
* @param type
*
* @throws SupportedMethodsException
*/
static public ArrayList<TellstickDevice> getDevices(Class<? extends TellstickDevice>... types)
throws SupportedMethodsException {
return filterDevices(getDevices(), types);
}
/**
* Filters devices into a new list. Usage: ArrayList<TellstickDevice>
* devices2 = TellstickDevice.getDevices(devices, Device.class,
* DimmableDevice.class, ...etc...);
*
* @param allDevices
* ArrayList of devices for input.
* @param type
* The types , eg DimmableDevice.class , Device.class,
* BellDevice.class, GroupDevice.class ... etc ..
*
* @throws SupportedMethodsException
*/
static public ArrayList<TellstickDevice> filterDevices(ArrayList<TellstickDevice> allDevices,
Class<? extends TellstickDevice>... types) throws SupportedMethodsException {
ArrayList<TellstickDevice> newList = new ArrayList<TellstickDevice>();
for (TellstickDevice dev : allDevices) {
boolean added = false;
for (Class<? extends TellstickDevice> t : types) {
if (!added && t.isInstance(dev)) {
newList.add(dev);
added = true;
}
}
}
return newList;
}
/**
* Gets a list of TellstickDevice with a supplied list of device Ids in
* int..
*
* @param deviceIds
*
* @throws SupportedMethodsException
* @throws DeviceNotSupportedException
*/
static public ArrayList<TellstickDevice> getDevices(int... deviceIds) throws SupportedMethodsException {
ArrayList<TellstickDevice> devices = getDevices();
ArrayList<TellstickDevice> retDevices = new ArrayList<TellstickDevice>();
for (TellstickDevice td : devices) {
for (int devid : deviceIds) {
if (td.getId() == devid) {
retDevices.add(td);
}
}
}
return devices;
}
/**
* Gets a list of TellstickDevice with a supplied list of device Ids in
* String.
*
* @param deviceIds
*
* @throws SupportedMethodsException
* @throws DeviceNotSupportedException
*/
static public ArrayList<TellstickDevice> getDevices(String... deviceIds) throws SupportedMethodsException {
int[] parsedIds = new int[deviceIds.length];
int a = 0;
for (String i : deviceIds) {
int parsedI = Integer.parseInt(i.trim());
if (parsedI > 0) {
parsedIds[a] = parsedI;
a++;
}
}
return getDevices(parsedIds);
}
/**
* Gets the ID of the device.
*/
public int getId() {
return deviceId;
}
/**
* Gets the name of the device.
*/
public String getName() {
return name;
}
/**
* Gets the device type. Can return JNA.CLibrary.TELLSTICK_TYPE_GROUP
* JNA.CLibrary.TELLSTICK_TYPE_SCENE JNA.CLibrary.TELLSTICK_TYPE_DEVICE
*/
public int getDeviceType() {
return deviceType;
}
/**
* Gets the status of the last action """ CURRENT STATE """ that this device
* has. Must be in supported methods.
*
* Available statuses: See setSupportedMethods( ... ), this depends on what
* the application supports!
*
*/
public int getStatus() {
return status;
}
/**
* Gets the protocol
*/
public String getProtocol() {
return protocol;
}
/**
* Sets the protocol of the device.
*
* @param name
*/
public boolean setProtocol(String protocol) {
this.protocol = protocol;
return JNA.CLibrary.INSTANCE.tdSetProtocol(getId(), protocol);
}
/**
* Gets the model name of the device.
*/
public String getModel() {
return model;
}
/**
* Removes this device totally and deletes it. Note that the object will
* still be there in JAVA while in runtime.
*/
public boolean remove() {
return JNA.CLibrary.INSTANCE.tdRemoveDevice(getId());
}
/**
* Tries to learn the device. Note, must have flag in methods:
* JNA.CLibrary.INSTANCE.TELLSTICK_LEARN
*
* @throws TellstickException
*/
public void learn() throws TellstickException {
int status = JNA.CLibrary.INSTANCE.tdLearn(getId());
if (status != TELLSTICK_SUCCESS) {
throw new TellstickException(this, status);
}
}
/**
* Returns true if this device is learnable.
*/
public boolean isLearnable() {
int methods = JNA.CLibrary.INSTANCE.tdMethods(deviceId, JNA.CLibrary.TELLSTICK_LEARN);
return (JNA.CLibrary.TELLSTICK_LEARN & methods) > 0;
}
/**
* Sets the name of the device.
*
* @param name
*/
public boolean setName(String name) {
this.name = name;
return JNA.CLibrary.INSTANCE.tdSetName(getId(), name);
}
/**
* Sets the name of the model of the device. WARNING; Careful using this!
*
* @param model
*/
public boolean setModel(String model) {
this.model = model;
return JNA.CLibrary.INSTANCE.tdSetModel(getId(), model);
}
/**
* Gets the type of the device. Override this when creating new devices.
*/
public String getType() {
return "Unknown";
}
/**
* These are supported by the API. Returns all the action methods that are
* implemented in tellstick. Check like: int methods =
* JNA.CLibrary.INSTANCE.tdMethods(deviceId, allMethods()); if ((methods &
* JNA.CLibrary.TELLSTICK_BELL) > 0) // IT HAS BELL ACTION
*/
public static int getSupportedMethods() {
return supportedMethods;
}
/**
* Compares to tellstick devices. They are equal if they have the same id.
*/
@Override
public int compareTo(TellstickDevice dev) {
return this.getId() - dev.getId();
}
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
@Override
public String toString() {
return "TellstickDevice [deviceId=" + deviceId + ", name=" + name + ", status=" + status + ", deviceType="
+ deviceType + ", data=" + data + "]";
}
}