24 June, 2013

Home automation: Raspberry Pi + Tellstick Duo ++

There are many sites that has this project in many flavors... I will just add mine.

Brief summary: Tellstick Duo is connected to Rasberry Pi (running Raspbian).  I have SE K700i GSM phone connected to RPi as well. The main features are:
  • control several radio controlled switches (Anslut)
  • monitor temperature and humidity from my wireless weather station
  • monitor for "door open event" (NEXA LMST-606)
  • monitor for commands send by SMS (gammu) Update: replaced by Android SMS Gateway. Read more...
  • report on selected events by sending SMS to predefined phone number (gammu)
  • simple web interface to control some of the features (apache + php)
  • events are logged locally in to a file and to a remote server (own twitter like)
To install telldus-core follow this guide. One can compile the GUI for RPi or use it on another computer to set the codes. I wanted to be able to repeat the original codes from the remote controls. Advanced users can use code from the examples to "learn" the codes.

Essentially, I am running a monitoring program written in python (took one of the provided examples and changed it severely). It catches signals from the remote controls and could trigger an action. In other words, I can use the remote controls to send signals to RPi. The same program monitors the GSM. It could trigger an action upon CALL or SMS. The signal from the door is logged by default but could also send an SMS - poor man's home security alarm.

I particularly like the CALL feature since you do not need to answer the call, so no cost attached. The downside is that there is only one action hooked to this event. SMS is easier but will cost you (or not - depends on the plan you have). When SMS is received from another phone (not mine) the SMS is logged and forwarded to my phone.

A cron job is running Sunwait to switch ON/OFF some night light  decoration in the house.

The data from the sensors is also logged.
There are some complications, since the signals I send over the Tellstick are also captured. In the example python code there is a solution for this as well. The problem somehow become bigger when I needed to start other programs and send SMS - I have solved this somehow.




Now for the details: (not all actually)

Learning the codes: The easiest way is to run the GUI and learn the codes. Then you can copy the tellstick.conf to /etc/tellstick.conf on theRPi. Or compile the GUI on the RPi - it takes about 20 minutes. The file looks something like this:

user = "nobody"
group = "plugdev"
deviceNode = "/dev/tellstick"
ignoreControllerConfirmation = "false"
device {
  id = 1
  name = "Window Lights"
  controller = 0
  protocol = "arctech"
  model = "selflearning-switch:proove"
  parameters {
    # devices = ""
    house = "17511102"
    unit = "16"
    code = "0000000000"
    system = "1"
    # units = ""
    fade = "false"
  }
}

...
Update: There is an newer version that simplifies a lot everything - reed my post here.

The advanced - run the example python code callbacks.py after changing this line:
#lib.tdRegisterRawDeviceEvent(cmp_funcraw, 0) #uncomment this, and comment out tdRegisterDeviceEvent, to see data for not registered devices
It will spit out the relevant information when you run it and press a button on the remote.

The monitor program: Needles to say, the program that monitors all the events and handles the GSM is a mixture from provided examples. Here, I am embarrassed to share the complete code, since many of the solutions are not pretty and clever.

Example on handling turnOn event:

def turnOn(deviceId):
        global timers, deviceIdDO
        if deviceIdDO[deviceId]:
                deviceIdDO[deviceId]= 0
                f= open('logfile', 'a')
                f.write("D_on: " + str(deviceId) + datetime.now().strftime(' %Y-%m-%d %H:%M:%S') + "\n"  )
                f.close()
        if (deviceId==9):
                tcreset(deviceId,9)
                cmd= 'weblog.sh "D_on: ' + str(deviceId) + ' " &'
                os.system(cmd)
                if (os.path.exists("/tmp/notify.gsm")):
                        tcreset(deviceId,10)
                        text='D_on: ' + str(deviceId) + datetime.now().strftime(' %Y-%m-%d %H:%M:%S')
                        sendSMSthread=  Thread(target=sendsms, args=(text,)); sendSMSthread.start()

deviceID==9 triggers on opening the door, logs the event and if /tmp/notify.gsm file exists sends SMS.

#function to be called when a GSM event occurs
def Callback(sm, type, data):
        cmd= 'weblog.sh "GSM: ' + str(type) + " : " + str(data) + ' " &'
        os.system(cmd)
        if type=='SMS':
                if not data.has_key('Number'):
                        data= sm.GetSMS(data['Folder'], data['Location'])[0]
                        text= data['Text'];
                        text= text.encode('ascii', 'replace')
                        cmd= 'weblog.sh "SMSgate From: ' + data['Number'] + ' ' + text + ' " &'
                        os.system(cmd)
                        text= 'From: ' + data['Number'] + " " + text
                        sendSMSthread=  Thread(target=sendsms, args=(text,)); sendSMSthread.start()

This simply forwards SMS that has arriwed on the GSM to my phone. Note that this version does not check if I have sent the SMS. I needed to remove some non ascii characters the brute way, since that was causing crashes to the program. I spent too much time on this without success, so if you know a solution - just let me know. And yes, having "# -*- coding: UTF-8 -*-" does not solve the problem. Sending SMS also turned out to be quite slow routine. Since I am monitoring the phone, I can't send SMS with the command line tool in background... I have used threads in python to run the routine in separate thread. This trick is so nice that I have started to use threads for everything...

Web interface: perhaps it is better to use python server as it is done here, but I had web server running anyway... so, here is how my web interface looks like (it fits on the screen on my mobile).

There is no authentication, but the server is not exposed to the world as well. I use VPN on my phone or computer to access the web page. I use exec in php to send commands to tdtool - not very clever but it works. It is easy to implement the current status to change the color of the buttons accordingly but I found that the states are often wrong - the button that acts on the 3 receivers simultaneously is not detected properly...

Night lights: here is what i have in the crontab:
1    2 * * * /home/pi/opt/src/sunwait-20041208/sunwait sun up   +0:10:00 59.xxN 1x.xxE; /usr/local/bin/tdtool -f 7
1   14 * * * /home/pi/opt/src/sunwait-20041208/sunwait sun down -0:10:00 59.xxN 1x.xxE; /usr/local/bin/tdtool -n 7
I need to start sunwait at 2:01 during the night and 14:01 in the afternoon to make sure I cover the whole year variation - I live north enough... The other inconvenience ;-) is that restarting the RPi during the sunwait will cancel the scheduled command... so it requires manual switch some time...

Just to summarize in few words. This illustrates the basic ideas, so the project itself is far from complete solution. It is developed on "personal demand and needs" base, so it is very patchy and disperse. Anyway, any ideas will be gratefully appreciated!

Update: Here is the code anyway. I have new version that I will post soon
Update: I have some major upgrade of the "system" - here is the post about it.

7 comments:

Anonymous said...

Hey im trying to get the (NEXA LMST-606) to work here as well.
and your code helped me alot.. thru the py callback raw. i get turn on and off from the magnet sensor.

but I get it from diffrent units and house codes. its consistent so i think i have it right.

but then i added them both to my devices in the .conf file. and then i just dont get any data. when switching back to the normal callback.. which i figure is because i still need to use it as raw and code my way from here.

but what i want is to get on off of this (NEXA LMST-606) i tried to check your turnOn(deviceid) function but that dident help as much. is there a way you could share your callback.py?

//MP
thx in advance.

Uncle Scrooge said...

Hej,

I have added the code at the end of the post. The magnet triggers deviceID=9 on open and deviceID=10 on close.

Cheers

Unknown said...

Tjo jag fick det att fungera bra med rawCallbacks och sen plockade jag upp dom id som magnetsensorn skickar via on och off sen plockar jag ut en lista från mina devices i dbn och matchar mot och ser då om dom är öppna eller inte.

Det jag nu skulle vilja försöka lösa är att skicka raw direkt och kringgå själva .conf filen då de känns som ett dumt steg.

dock så lyckas jag inte mot selflearning utan bara vanliga codeswitch. troligen jag som inte riktigt fattar hur raw är uppbyggd då man tycks kunna skicka både binärt och hex och ansi. wierd

Anonymous said...

Hi
I also try to use NEXA LMST-606, but my callback.py doesn't put out any raw information.
Any suggestions? I thought just open/close the sensor would result in some output from callback.py?
Thanks

//Sven

Uncle Scrooge said...

Sorry for the late answer, I was away and could not test it on my setup. It actually spits quite some output (the following 2 lines about 20 times) from my "callbacks.py":

class:command;protocol:arctech;model:selflearning;house:50576774;unit:2;group:0;method:turnon;
class:command;protocol:sartano;model:codeswitch;code:0111011001;method:turnon;

Make sure that you do not have some other callbacks.py process running loose...

Uncle Scrooge said...

Probably it is worth mentioning, that I flashed my Tellstick Duo with the latest firmware when I bought it. I think there were some signal stability improvements and more protocols but I can't say for sure.

Elizabeth J. Neal said...

Nice to be visiting your blog once more, it has been months for me. Well this article that ive been waited for therefore long. i want this article to finish my assignment within the faculty, and it has same topic together with your article. Thanks, nice share. local alarm companies laredo