The Tellstick from Telldus is a small little USB dongle that lets you communicate with remote receivers such as wireless power outlets. Even though the Telldus company release their own software for controlling the Tellstick they are really open with their product and lets users access the Tellstick pretty much any way they want.
When interfacing the Tellstick in Java on Mac OS X there is at least three ways of doing this:
1. RXTXcomm, this way you access the device directly. You’ll need to download Virtual COM Port drivers. On the downside you’ll have to implement support for the different receiver protocols on your own.
2. JNI bindings, using Telldus tellstick library. The bindings are very old and haven’t kept up with the development of the Telldus tellstick library.
3. JNA, using Telldus tellstick library but without the need for the JNI bindings.
This post will focus on the third alternative. When using Telldus own library (TelldusCore) you don’t have to deal with the different kinds of protocols used by the receivers. You’ll automatically have access to every protocol supported by Telldus.
As of writing this post, the current Telldus Center 2 release does only come with a 32-bit version of the TelldusCore library. If you’re running a 32-bit version of Java you only have to download and install Telldus Center 2 to get the TelldusCore library. But if you’re like me, running a 64-bit version of Java you need to recompile TelldusCore.
$ java -version java version "1.6.0_17" Java(TM) SE Runtime Environment (build 1.6.0_17-b04-248-10M3025) Java HotSpot(TM) 64-Bit Server VM (build 14.3-b01-101, mixed mode)
Now Download TelldusCore 2.0.2.
In order to compile TelldusCore 2.0.2 you’ll also need:
- cmake – used to configure the sources.
- D2XX Direct Drivers – download the latest version (currently 0.1.7). Read the readme file on how to install it properly. It’s fairly simple, especially if you have som terminal knowledge. Be sure to copy from the bin/10.6 directory which contains a 64-bit version of the library.
Untar the TelldusCore sources and (inside telldus-core-2.0.2) run
$ cmake -DBUILD_RFCMD=0 -DSUPPORT_USB=1 -DFTD2XX_LIBRARY=/usr/local/lib/libftd2xx.dylib
This will configure the sources for building TelldusCore without rfcmd. Make sure that FTD2XX_LIBRARY actually points to the library that you copied when installing the D2XX Direct Drivers.
Anyway, your output should look something like this:
$ cmake -DBUILD_RFCMD=0 -DSUPPORT_USB=1 -DFTD2XX_LIBRARY=/usr/local/lib/libftd2xx.dylib -- The C compiler identification is GNU -- The CXX compiler identification is GNU -- Checking whether C compiler has -isysroot -- Checking whether C compiler has -isysroot - yes -- Check for working C compiler: /usr/bin/gcc -- Check for working C compiler: /usr/bin/gcc -- works -- Detecting C compiler ABI info -- Detecting C compiler ABI info - done -- Checking whether CXX compiler has -isysroot -- Checking whether CXX compiler has -isysroot - yes -- Check for working CXX compiler: /usr/bin/c++ -- Check for working CXX compiler: /usr/bin/c++ -- works -- Detecting CXX compiler ABI info -- Detecting CXX compiler ABI info - done -- Looking for Q_WS_X11 -- Looking for Q_WS_X11 - not found. -- Looking for Q_WS_WIN -- Looking for Q_WS_WIN - not found. -- Looking for Q_WS_QWS -- Looking for Q_WS_QWS - not found. -- Looking for Q_WS_MAC -- Looking for Q_WS_MAC - found -- Looking for QT_MAC_USE_COCOA -- Looking for QT_MAC_USE_COCOA - found -- Found Qt-Version 4.6.1 (using /usr/bin/qmake) -- Configuring done -- Generating done -- Build files have been written to: /Users/pakerfeldt/telldus-core-2.0.2
Now build TelldusCore by running make:
$ make Scanning dependencies of target TelldusCore [ 5%] Building CXX object driver/libtelldus-core/CMakeFiles/TelldusCore.dir/Device.cpp.o [ 10%] Building CXX object driver/libtelldus-core/CMakeFiles/TelldusCore.dir/DeviceBrateck.cpp.o [ 15%] Building CXX object driver/libtelldus-core/CMakeFiles/TelldusCore.dir/DeviceEverflourish.cpp.o [ 21%] Building CXX object driver/libtelldus-core/CMakeFiles/TelldusCore.dir/DeviceGroup.cpp.o [ 26%] Building CXX object driver/libtelldus-core/CMakeFiles/TelldusCore.dir/DeviceIkea.cpp.o [ 31%] Building CXX object driver/libtelldus-core/CMakeFiles/TelldusCore.dir/DeviceNexa.cpp.o [ 36%] Building CXX object driver/libtelldus-core/CMakeFiles/TelldusCore.dir/DeviceRisingSun.cpp.o [ 42%] Building CXX object driver/libtelldus-core/CMakeFiles/TelldusCore.dir/DeviceSartano.cpp.o [ 47%] Building CXX object driver/libtelldus-core/CMakeFiles/TelldusCore.dir/DeviceUndefined.cpp.o [ 52%] Building CXX object driver/libtelldus-core/CMakeFiles/TelldusCore.dir/DeviceUpm.cpp.o [ 57%] Building CXX object driver/libtelldus-core/CMakeFiles/TelldusCore.dir/DeviceWaveman.cpp.o [ 63%] Building CXX object driver/libtelldus-core/CMakeFiles/TelldusCore.dir/DeviceX10.cpp.o [ 68%] Building CXX object driver/libtelldus-core/CMakeFiles/TelldusCore.dir/Controller.cpp.o [ 73%] Building CXX object driver/libtelldus-core/CMakeFiles/TelldusCore.dir/Manager.cpp.o [ 78%] Building CXX object driver/libtelldus-core/CMakeFiles/TelldusCore.dir/Settings.cpp.o [ 84%] Building CXX object driver/libtelldus-core/CMakeFiles/TelldusCore.dir/telldus-core.cpp.o [ 89%] Building CXX object driver/libtelldus-core/CMakeFiles/TelldusCore.dir/SettingsCoreFoundationPreferences.cpp.o [ 94%] Building CXX object driver/libtelldus-core/CMakeFiles/TelldusCore.dir/win/Device.cpp.o Linking CXX shared library TelldusCore.framework/Versions/2.0.2/TelldusCore Copying OS X content driver/libtelldus-core/TelldusCore.framework/Versions/2.0.2/Headers/telldus-core.h [ 94%] Built target TelldusCore Scanning dependencies of target tdtool [100%] Building CXX object tdtool/CMakeFiles/tdtool.dir/main.cpp.o Linking CXX executable tdtool [100%] Built target tdtool
The result is placed in telldus-core-2.0.2/driver/libtelldus-core/TelldusCore.framework/.
Create the directory /Library/Frameworks/TelldusCore.framework/Versions/2.0.2/
$ mkdir -p /Library/Frameworks/TelldusCore.framework/Versions/2.0.2/
And copy the result to this directory:
$ cp -Rp driver/libtelldus-core/TelldusCore.framework/* /Library/Frameworks/TelldusCore.framework/Versions/2.0.2/
Also, add a symbolic link named libTelldusCore.dylib in that directory:
$ ln -s /Library/Frameworks/TelldusCore.framework/Versions/2.0.2/TelldusCore /Library/Frameworks/TelldusCore.framework/Versions/2.0.2/libTelldusCore.dylib
You should now be able to access you’re newly built 64-bit TelldusCore using JNA. This is actually quite easy. A JNA binding to TelldusCore could look something like this:
package se.akerfeldt.code.tellstick;
import com.sun.jna.Library;
import com.sun.jna.Native;
public interface TellstickBinding extends Library {
TellstickBinding INSTANCE = (TellstickBinding) Native.loadLibrary(("TelldusCore"), TellstickBinding.class);
int tdAddDevice();
int tdTurnOn(int intDeviceId);
int tdTurnOff(int intDeviceId);
int tdGetNumberOfDevices();
int tdGetDeviceId(int deviceIndex);
boolean tdSetName(int deviceId, String name);
String tdGetName(int deviceId);
boolean tdSetProtocol(int deviceId, String protocol);
String tdGetProtocol(int deviceId);
boolean tdSetModel(int deviceId, String model);
String tdGetModel(int deviceId);
boolean tdSetDeviceParameter(int deviceId, String name, String value);
String tdGetDeviceParameter(int deviceId, String name, String defaultValue);
String tdGetErrorString(int errorNo);
}
Please refer to telldus-core.h for a complete list of native methods. I haven’t paid much attention to the Java class above.
Now, before running your application add -Djna.library.path=/Library/Frameworks/TelldusCore.framework/Versions/2.0.2 to your VM arguments.
In order to turn something on/off you’ll have to add a device for it, just use the JNA binding for that!
int deviceId = TellstickBinding.INSTANCE.tdAddDevice(); TellstickBinding.INSTANCE.tdSetName(deviceId, "Outdoor light"); TellstickBinding.INSTANCE.tdSetProtocol(deviceId, "arctech"); TellstickBinding.INSTANCE.tdSetModel(deviceId, "codeswitch"); TellstickBinding.INSTANCE.tdSetDeviceParameter(deviceId, "house", "A"); TellstickBinding.INSTANCE.tdSetDeviceParameter(deviceId, "unit", "1"); TellstickBinding.INSTANCE.tdTurnOn(deviceId);
I’m still looking for a better source of information regarding the different kinds of protocols and models. In the meantime this Telldus wiki page might give some more information for you.
