Telldus Core API

Introduction

This is the guide to Telldus TellStick SDK. Even though all examples are written in C/C++ most of the code has a direct eqvivalent function in the other languages. See Notes using other languages than C/C++ how to use the library in one of the supported languages by Telldus.

Idea

All of the devices used by TellStick must be predefined before they can be used in any software. Under all platforms this can be done with the software TelldusCenter but under Linux this can also be done by editing the file /etc/tellstick.conf with your favorite text editor.

Having the devices preconfigured is an advantage to both the developer and the end user.

  • The end user might use more then one program for controlling his/her TellStick. By having the devices preconfigured he/she does not have to reconfigure the same devices twice. If some settings change in one of the devices, this change will affect all softwares using Telldus TellStick SDK.
  • Telldus continuously adds support for new devices. If a software defines it's own devices, the developer will have to keep the software up to date with new devices and settings implemented by Telldus. By querying Telldus Tellstick SDK all the new devices will be available automaticly to the end user.

Basic usage (telldus-core)

Telldus provides a non-gui library to list, query and control the devices called telldus-core. To initiate the library a call to tdInit() must be made. This call will open up all controllers (e.g. a TellStick) and start listening for events from them. When you are done with telldus-core, call tdClose() to allow the library to clean up after itself.

Listing devices

To list all of the configured devices, look at the following example:

 int intNumberOfDevices = tdGetNumberOfDevices();
 for (int i = 0; i < intNumberOfDevices; i++) {
   int id = tdGetDeviceId( i );
   char *name = tdGetName( id );
   printf("%d\t%s\n", id, name);
   tdReleaseString(name);
 }

First, we call tdGetNumberOfDevices(). This returnes the total number of devices configured. We then iterate over all of the devices with the index in the variable i. Since the devices could change between runs of the program we can not be sure that the index points to the same device between two runs of the program. That is why every device has it's own unique id that is safe to store in a configuration file. Two different devices can never share the same device id.

The call to tdGetDeviceId() returns the id for a specific index. This function should only be called in a loop iterating over all of the devices. After we have found the id for a device it is safe to store this or use it in the rest of the program.

The next two lines of code queries the device for it's name with a call to tdGetName() and then displays it to stdout. Finally we must release the resource after we are done with it by calling tdReleaseString() on any char pointer returned by telldus-core.

Sending commands to TellStick

Device features

TellStick can control many different types of devices that support different features. For example, a bell does not support turning the on-signal and not all lamp switches support dimming. Call tdMethods() to find out what a specific device supports:

 function checkFeatures( int id ) {
   int supportedMethods = TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_BELL;
   int methods = tdMethods( id, supportedMethods );
   if ( methods & TELLSTICK_TURNON ) {
     printf( "The device %d support tdTurnOn()\n", id );
   }
   if ( methods & TELLSTICK_TURNOFF ) {
     printf( "The device %d support tdTurnOff()\n", id );
   }
   if ( methods & TELLSTICK_BELL ) {
     printf( "The device %d support tdBell()\n", id );
   }
 }

By supplying the methods your application supports, the library can return customized methods for your application, even if your application doesn't support the same methods as the device accepts. One example is if your application only supports ON and OFF, you can control a device that needs UP and DOWN anyway by using just ON and OFF. Let's say that the client application only supports turning on and off. The call to query a device for it's methods should be:

 int methods = tdMethods( id, TELLSTICK_TURNON | TELLSTICK_TURNOFF );

If the device in the above example is a device only supporing TELLSTICK_BELL, the library will instead return TELLSTICK_TURNON, making the client application still able to control the device. When you know which features a device supports it is safe to call the controlling functions described in Controlling functions.

When calling tdMethods() all of the supported methods should be passed in one call. Do not call tdMethods() for each of the supported methods. Look at the following example:

 //Correct
 int methods = tdMethods( id, TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_BELL );
 //Wrong
 int turnOn = tdMethods( id, TELLSTICK_TURNON );
 int turnOff = tdMethods( id, TELLSTICK_TURNOFF );
 int bell = tdMethods( id, TELLSTICK_BELL );

Another thing to note is if you are developing a library intended for thirdparty use. You should not hardcode which methods are supported by the library. It is always up to the application implementing the methods to supply the methods it supports.

Controlling functions

TellStick has a couple of functions for controlling devices. Each of them should only be called if the device support the feature.

These functions all return zero if the call was successful and non-zero otherwise.

tdTurnOn()

Devices supporting TELLSTICK_TURNON. Most of the normal switches (for lamp etc.) support this.

tdTurnOff()

Devices supporting TELLSTICK_TURNOFF. Almost all of the devices supporting TELLSTICK_TURNON also support this.

tdDim()

Devices supporting TELLSTICK_DIM. This is a quite unusual feature for dimmers. Many dimmers on the market that are dimmable have no way for sending a specific level which means it does not support this feature.

tdBell()

Devices supporting TELLSTICK_BELL. This is mostly wireless doorbells.

Error codes

If any of the calls in Controlling functions fails it returns a non-zero error code. This values is one of the TELLSTICK_ERROR_* defines. To translate the error code to a human readable string call the function tdGetErrorString(). Example:

 printf("Error: %s\n", tdGetErrorString( TELLSTICK_METHOD_NOT_SUPPORTED ) );
 //Error: The method you tried to use is not supported by the device
 int retval = tdTurnOn( deviceID );
 if (retval != TELLSTICK_SUCCESS ) {
   char *errorString = tdGetErrorString( retval );
   printf("Error: %s\n", errorString );
   tdReleaseString(errorString);
 }

Device states

Since controllable devices only have a receiver and not a transmitter the communication is one-way. This means that telldus-core will never know for sure which state a reciever has. Instead, the library remembers which command was last sent. Either sent from the TellStick itself, or sent from another controller (e.g. a remote control) captured by the Tellstick Duo. In this way it "emulates" a two-way communication.

To query the device state, use the function tdLastSentCommand()

Example:

 char *name = tdGetName( id );
 int state = tdLastSentCommand( id );
 if (state == TELLSTICK_TURNON) {
   printf("%s is on\n", name);
 } else if (state == TELLSTICK_TURNOFF) {
   printf("%s is off\n", name);
 } else {
   printf("%s is in an unknown state\n", name);
 }
 tdReleaseString(name);

Sensors

Retrieving sensor values can be done in two ways. Either by a polling interface or by callbacks. The client application can implement one or both of these interfaces. For callbacks, read more under Events.

Each of the sensors can have one or several value types. Currently only temperature and humidity are implemented.

There is no API to add, remove or edit sensors. Each sensor that TellStick Duo has got any data from is added to an internal list. It is up to the client application to filter and only show the sensors your are interested in.

To iterate over the list of sensors, call tdSensor() repeatedly as long as it returns TELLSTICK_SUCCESS. The parameters protocol, model, sensorId, and dataTypes are sent by reference and will be filled with the values.

Example:

 char protocol[DATA_LENGTH], model[DATA_LENGTH];
 int sensorId = 0, dataTypes = 0;
 while(tdSensor(protocol, DATA_LENGTH, model, DATA_LENGTH, &sensorId, &dataTypes) == TELLSTICK_SUCCESS) {
   //Print the sensor
   printf("%s,\t%s,\t%i\n", protocol, model, sensorId);
 }

The type of sensor values the sensor supports are stored as flags in the parameter sensorId. Call tdSensorValue() for each type.

Example:

 char value[DATA_LENGTH];
 char timeBuf[80];
 time_t timestamp = 0;
 if (dataTypes & TELLSTICK_TEMPERATURE) {
   tdSensorValue(protocol, model, sensorId, TELLSTICK_TEMPERATURE, value, DATA_LENGTH, (int *)&timestamp);
   strftime(timeBuf, sizeof(timeBuf), "%Y-%m-%d %H:%M:%S", localtime(&timestamp));
   printf("Temperature:\t%sº\t(%s)\n", value, timeBuf);
 }

Events

To get events from either a TellStick Duo, another software changes the status of a device, or new sensors values you have to register for a callback.

Registering for callbacks

For each callback there is a corresponding register function:

These all work in the same way. The first parameter is a function-pointer to the callback function. The second parameter is an optional void pointer. This can be anything and is dependent on the implementation. This object will be sent back to each call to the callback function. The functions return an integer which is an id to the specific callback. This is is sent as a parameter in each call and should also be used for unregister the callback.

Please note that the callback will be called by another thread than the thread used by the application and some measures must be taken to synchronize it with the main thread.

Many devices (for example motion detectors) resends their messages many times to ensure that they are received correctly. If a deviceeventcallback or rawdeviceeventcallback in turn is calling a controlling function, for example tdTurnOn, it may be neccessary to implement some solution to wait for the device to finish its resending, before executing the controlling function. See how this can be done in the python example.

Callbacks

telldus-core currently implements four different callback function for different purposes.

DeviceEvent

This event is fired when the state of a device changes. This can either occur via a remote control, but can as well occur via another software on the computer.

Parameters:

  • int deviceId - The device id of the device that changed.
  • int method - The new state. Can be TELLSTICK_TURNON, TELLSTICK_TURNOFF etc.
  • const char *data - For some methods this contains data. For TELLSTICK_DIM this hold the current value.
  • int callbackId - id of callback
  • void *context - see Registering for callbacks for description

DeviceChangeEvent

This event is fired when the data around a device is changed. It can only be triggered by another software. Use this callback to keep your list of devices in sync.

Parameters:

  • int deviceId - The device id of the device that changed.
  • int changeEvent - What was changed. This can be:
    • TELLSTICK_DEVICE_ADDED - A new device was added. The parameter deviceId holds the id of the new device.
    • TELLSTICK_DEVICE_REMOVED - A device was removed, the parameter deviceId holds the id of the removed device.
    • TELLSTICK_DEVICE_CHANGED - The settings of a device changed. The next parameter holds what was changed.
  • int changeType - If changeEvent is TELLSTICK_DEVICE_CHANGED this parameter holds what was changed. It can be one of the following:
    • TELLSTICK_CHANGE_NAME - Use tdGetName() to read the new name.
    • TELLSTICK_CHANGE_PROTOCOL - Use tdGetProtocol() to read the new value.
    • TELLSTICK_CHANGE_MODEL - Use tdGetModel() to read the new value.
  • int callbackId - id of callback
  • void *context - see Registering for callbacks for description

RawDeviceEvent

Use this callback with caution. It outputs everything from a TellStick Duo without any preprocessing. This can be used to get events from devices not already configured.

Parameters:

  • const char *data - raw device data
  • int controllerId - id of receiving controller, can identify the TellStick if several exists in the system
  • int callbackId - id of callback
  • void *context - see Registering for callbacks for description

SensorEvent

This event is fired when a new sensor value is retrieved.

Parameters:

  • const char *protocol - The sensors protocol
  • const char *model - The model of the sensor
  • int id - The unique id for the sensor.
  • int dataType - Flags for which types of data the sensor supports
  • const char *value - A human readable string of the data
  • int timestamp - The timestamp when the latest value was received
  • int callbackId - id of callback
  • void *context - See Registering for callbacks for description

Example

Notes using other languages than C/C++

Python

There is no native Python support for TellStick yet. To use telldus-core in Python, please have look at the ctypes library. It contains cdll and windll to load any dynamic link libraries.