How to use Tellstick with VSCP

telldus_tellstick-gammal.jpg telldus_tellstick-ny.jpg

This page will show how you can use a Tellstick USB adapter with VSCP. The instruction should work well on all Linux boxes including Raspberry Pi and Beaglebone. Credits to this Swedish page. from which most of the information is fetched from.

Only version 2.1.1 appears to work with olders sticks.

Two general setup instruction are here http://forum.telldus.com/viewtopic.php?f=15&t=4366 and here http://raspberry.arctics.se/2015/05/03/uppdaterad-artikel-om-tellstick-pa-raspberry-pi

Setup the Telldus subsystem

Step 1

Install the ftdi libraries.

sudo apt-get install libftdi1 libftdi-dev

may already be installed on some machines.

Step 2

Install som elibs used by the Tellstick software

sudo apt-get install libconfuse0 libconfuse-dev
Step 3

Check if your Tellstick has been found by the OS with

lsusb

if you see a line that looks like

Bus 001 Device 004: ID 1781:0c30 Multiple Vendors Telldus TellStick

the adapter is found and everything is OK

Step 4

Now load the kernel module with

sudo modprobe ftdi_sio vendor=0x1781 product=0x0c30

check that it has been loaded with

lsmod | grep ftdi

you should see a line

usbserial              27365  1 ftdi_sio

if it is loaded. To have the driver start automagically when you restart the system add

ftdi_sio vendor=0x1781 product=0x0c30

into /etc/modules

Step 5

The Tellstick software needs cmake so install it

sudo apt-get install cmake             

and fetch the Tellstick software

wget http://download.telldus.se/TellStick/Software/telldus-core/telldus-core-2.1.1.tar.gz

You can check here to see if any later version is available. If it is use that version instead.

Step 6

Unpack it

tar xfz telldus-core-2.1.1.tar.gz
Step 7

Go into the folder

cd telldus-core-2.1.1

generate makefiles

cmake .

then run

make

if all goes well and you don't see any error messages install the software with

sudo make install

on a Linux box issue

sudo ldconfig

to configure installed libraries.

On mu Debian system I got the error

/root/telldus-core-2.1.1/common/Socket_unix.cpp:44:18: error: ‘close’ was not declared in this scope

when I built the package. I solved this by adding

#include <unistd.h>

to the

common/Socket_unix.cpp

file as of below

#include <stdio.h>
#include <sys/socket.h>
#include <unistd.h>
#include <sys/un.h>
#include <math.h>        
    
Step 8

Now create a startup script /etc/init.d/telldusd with the following content

#! /bin/sh
### BEGIN INIT INFO
# Provides:          telldusd
# Required-Start:    $remote_fs $syslog
# Required-Stop:     $remote_fs $syslog
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Tellstick service daemon
# Description:       Tellstick service daemon controlling remove switches
### END INIT INFO

# Author: Kjell Haveskold (nimmis) <kjell.havneskold@gmail.com>

# Do NOT "set -e"

# PATH should only include /usr/* if it runs after the mountnfs.sh script
PATH=/sbin:/usr/sbin:/bin:/usr/bin:/usr/local/sbin
DESC="Tellstick service daemon"
NAME=telldusd
DAEMON=/usr/local/sbin/$NAME
DAEMON_ARGS=""
PIDFILE=/var/run/$NAME.pid
SCRIPTNAME=/etc/init.d/$NAME

# Exit if the package is not installed
[ -x "$DAEMON" ] || exit 0

# Read configuration variable file if it is present
[ -r /etc/default/$NAME ] && . /etc/default/$NAME

# Load the VERBOSE setting and other rcS variables
. /lib/init/vars.sh

# Define LSB log_* functions.
# Depend on lsb-base (>= 3.2-14) to ensure that this file is present
# and status_of_proc is working.
. /lib/lsb/init-functions

#
# Function that starts the daemon/service
#
do_start()
{
        # Return
        #   0 if daemon has been started
        #   1 if daemon was already running
        #   2 if daemon could not be started
        start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \
                || return 1
        start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON -- \
                $DAEMON_ARGS \
                || return 2
        # Add code here, if necessary, that waits for the process to be ready
        # to handle requests from services started subsequently which depend
        # on this one.  As a last resort, sleep for some time.
}

#
# Function that stops the daemon/service
#
do_stop()
{
        # Return
        #   0 if daemon has been stopped
        #   1 if daemon was already stopped
        #   2 if daemon could not be stopped
        #   other if a failure occurred
        start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE --name $NAME
        RETVAL="$?"
        [ "$RETVAL" = 2 ] && return 2
        # Wait for children to finish too if this is a daemon that forks
        # and if the daemon is only ever run from this initscript.
        # If the above conditions are not satisfied then add some other code
        # that waits for the process to drop all resources that could be
        # needed by services started subsequently.  A last resort is to
        # sleep for some time.
        start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON
        [ "$?" = 2 ] && return 2
        # Many daemons don't delete their pidfiles when they exit.
        rm -f $PIDFILE
        return "$RETVAL"
}

#
# Function that sends a SIGHUP to the daemon/service
#
do_reload() {
        #
        # If the daemon can reload its configuration without
        # restarting (for example, when it is sent a SIGHUP),
        # then implement that here.
        #
        start-stop-daemon --stop --signal 1 --quiet --pidfile $PIDFILE --name $NAME
        return 0
}

case "$1" in
  start)
        [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME"
        do_start
        case "$?" in
                0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
                2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
        esac
        ;;
  stop)
        [ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
        do_stop
        case "$?" in
                0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
                2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
        esac
        ;;
  status)
        status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $?
        ;;
  #reload|force-reload)
        #
        # If do_reload() is not implemented then leave this commented out
        # and leave 'force-reload' as an alias for 'restart'.
        #
        #log_daemon_msg "Reloading $DESC" "$NAME"
        #do_reload
        #log_end_msg $?
        #;;
  restart|force-reload)
        #
        # If the "reload" option is implemented then remove the
        # 'force-reload' alias
        #
        log_daemon_msg "Restarting $DESC" "$NAME"
        do_stop
        case "$?" in
          0|1)
                do_start
                case "$?" in
                        0) log_end_msg 0 ;;
                        1) log_end_msg 1 ;; # Old process is still running
                        *) log_end_msg 1 ;; # Failed to start
                esac
                ;;
          *)
                # Failed to stop
                log_end_msg 1
                ;;
        esac
        ;;
  *)
        #echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2
        echo "Usage: $SCRIPTNAME {start|stop|status|restart|force-reload}" >&2
        exit 3
        ;;
esac

Make the file executable with

sudo chmod +x /etc/init.d/telldusd

install the startup script with

sudo update-rc.d telldusd defaults

Start the Telldus service with

/etc/init.d/telldusd start
Step 9

Now the Telldus subsystem is in place. To make it do something one have to put some info intio the configuration file /etc/tellstick.conf Remember to restart the Telldus daemon with

/etc/init.d/telldusd restart

every time you make changes into this file. You can find documentation for the configuration file here.

My testfile looks like this

user = "nobody"
group = "plugdev"
ignoreControllerConfirmation = "false"
device {
  id = 1
  name = "switch1"
  protocol = "arctech"
  model = "codeswitch:nexa"
  parameters {
    house = "A"
    unit = "1"
  }
}
device {
  id = 2
  name = "switch2"
  protocol = "arctech"
  model = "codeswitch:nexa"
  parameters {
    house = "A"
    unit = "2"
  }
}
device {
  id = 3
  name = "switch3"
  protocol = "arctech"
  model = "codeswitch:nexa"
  parameters {
    house = "A"
    unit = "3"
  }
}

as I use Nexa devices bur as a lot of other protocols such as X10 is supported you can use that instead for your setup.

Step 10

To turn on one of the devices use

tdtool --on switch1

or

tdtool --on 1

To turn off one of the devices use

tdtool --off switch1

or

tdtool --off 1

Using the VSCP decision matrix to control Tellstick connected devices

The decision matrix of the VSCP daemon is a powerful tool and can among other things be used as a scheduler to turn on/off devices at certain times. To use it first follow the instructions here Setup your system on Linux or Setup your system on Raspberry Pi or some of the other getting started descriptions that describes your system, to install and get VSCP & Friends ready for use on your system.

First suppose that we want switch1 to come on in the evening and off in the morning. Typical scenario in a home or in an office for windows lamps or similar. We can do this in two ways. Either we edit the dm configuration file directly in its default location /etc/vscp/dm.xml) or we can use the build in web interface of the VSCP daemon to do the same thing. We do it the hard way first.

How tough girls do it

Suppose we want switch1 to be turned on at 07:00 and be turned of at 03:00. To turn it on we add this code to the decision matrix configuration file

    <row enabled="true" groupid="nightlight">
        <!-- Mask - We just care for class and type -->
        <mask priority="0" class="0xffff" type="0xff"
            guid="00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00"></mask>

        <!-- Event we are interested in is internal minute event -->
        <filter priority="0" class="0xffff" type="6"
            guid="00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00"></filter>

        <!-- Allowed historical -->
        <allowed_from>1977-01-01 00:00:00</allowed_from>

        <!-- Allowed also far into the future -->
        <allowed_to>2099-12-31 23:59:59</allowed_to>

        <!-- Allowed every day in the week -->
        <allowed_weekdays>mtwtfss</allowed_weekdays>

        <!-- Execute command at 20:00 -->
        <allowed_time>*-*-* 20:00:*</allowed_time>

        <!-- Control code -  -->
        <control>0x80000000</control>

        <!-- Action code == Execute command  -->
        <action>0x00000010</action>

        <!-- Action parameter -->
        <param>/usr/local/bin/tdtool --on switch1</param>

         <!-- Comment for decision matrix row -->
        <comment>Turn on night lamp(s)</comment>
    </row>

and to turn off we add this row

    <row enabled="true" groupid="nightlight">
        <!-- Mask - We just care for class and type -->
        <mask priority="0" class="0xffff" type="0xff"
            guid="00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00"></mask>

        <!-- Event we are interested in is internal minute event -->
        <filter priority="0" class="0xffff" type="6"
            guid="00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00"></filter>

        <!-- Allowed historical -->
        <allowed_from>1977-01-01 00:00:00</allowed_from>

        <!-- Allowed also far into the future -->
        <allowed_to>2099-12-31 23:59:59</allowed_to>

        <!-- Allowed every day in the week -->
        <allowed_weekdays>mtwtfss</allowed_weekdays>

        <!-- Execute command at 03:00 -->
        <allowed_time>*-*-* 03:00:*</allowed_time>

        <!-- Control code -  -->
        <control>0x80000000</control>

        <!-- Action code == Execute command  -->
        <action>0x00000010</action>

        <!-- Action parameter -->
        <param>/usr/local/bin/tdtool --off switch1</param>

         <!-- Comment for decision matrix row -->
        <comment>Turn off night lamp(s)</comment>
    </row>

OK lets look at what this means.

First we have the group which i set to nightlight. This is a way to group rows that belong to each other together. We also have enable which is set to true which means the row will be active. Just set to false to inactivate a row.

Then we have the mask and the filter. In short they say we are interested in a VSCP daemon event that is feed to the decision matrix every minute (CLASS2.VSCPD, Type=6). The event is guarantied to be feed to the dm once each minute.There are plenty of other events, seconds/hour/week/random etc that can be used. See the VSCP specification document 13.8. How filter/mask works is explained here How filter/masks work and what they are.

Next we have allowed_from which is set to a date far back in history and allowed_to which is set to a date far in the future meaning this should be done “always”. This is a perfect place to handle summer/winter time scenarios and/or when different settings are needed between different dates.

allowed_weekdays says which weekdays the the action is allowed. Perfect if you want different scenarios for different days. Replace the day with a dash for a non allowed day.

In allowed_time we set the time we want the action to occur. Notice the setting for switch1 turnon *-*-* 20:00:* which means any year, any month, any day, at hour=20, at minute=0, any second. Any second is important here as we don't know this value when the minute event is feed to the decision matrix. The same is used for switch1 turn off

control is not needed here but is here to make the sample complete.

Then we have action which tells which action that should be done if the criterias above are fulfilled. In this case 0x10 = 16 meaning execute external program is used.

param is the the program we should execute and possibly any parameters needed.IN our case /usr/local/bin/tdtool –on switch1 and /usr/local/bin/tdtool –off switch1

Then last is the comment which is is a description of what we do.

The decision matrix and all its parameters, actions etc is described in the VSCP specification document section 14.7

How smart girls do it

A much easier way to add/edit/delet DM entries is to use the built in web interface of the VSCP daemon. Just point your browser at

http://host:8080/vscp

where host is the host where you have the VSCP daemon installed. Change 8080 to another port if you have changed this in the configuration file.

Now to add a new dm entry go to menu

/Configuration/DM - New element

and input the information as of above. To turn on at 21:30

and to turn off at 03:00

when save you have them in the list

Just click on one of the rows to edit it's content. There is no need to restart the VSCP daemon after you change a value.

Turn on/off a device with a button

The typical command that is sent to turn on a something in VSCP is CLASS1.CONTROL, Type=5, TurnOn (Specifiation 12.7.6) and to turn off something CLASS1.CONTROL, Type=6, TurnOff (Specifiation 12.7.67). Both use zone/subzone to tell what should be turned on/off. So if we also want to handle these buttons we can add a decision matrix entry for each just as above. One for class=30, Type=5 and one for Class=30, Type=6

In VSCP all devices that do something should report back that they have done what was requested from them. For this CLASS1.INFORMATION, Type=2, ON and CLASS1.INFORMATION, Type=3, OFF should be sent in this case for switch1 on and switch1 off respectively. But Tellstick does not return this information so we need to add decision matrix entries for this to.

One extra thing you should do here is to also check zone and subzone so check these values and also enter valid values.

Control Tellstick devices from the web

See the Websockets guide and the vscpws_stateButton. All you have to do is to program a button to send the CLASS1.CONTROL, TurnOn/TurnOff event to the zone/subzone you have set up in the decision matrix as described above.

 
howto/how_to_tellstick.txt · Last modified: 2016/12/12 16:19 by akhe
[unknown button type]
 
Except where otherwise noted, content on this wiki is licensed under the following license: Public Domain
Recent changes RSS feed Donate Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki