Home Automation - Control via SSH


14 posts
by armyofme » Wed Feb 13, 2013 11:26 am
I'm loving my raspberry pi and have so far managed to set up wireless and infrared transmitters with it (Tellstick and Iguanaworks). At the moment I can control them via ssh and have found the sshmote andorid app which seems very good. I would however like to find another option. Under Windows I used Eventghost and the Webserver addon - I designed my own webpage that contained links to the commands.

I really would like a to design a simple interface for sending the ssh commands back to the raspberry pi. This could be a html page containing the commands. I was thinking down this line because then it could be accessed on a Windows laptop or Android phone. Any ideas how I could approach this?
Posts: 12
Joined: Sat Jan 12, 2013 11:28 am
by Hoagie » Wed Feb 13, 2013 12:46 pm
Here's how I do it. This is for the switch control system in MagPi issue 8, but it gives an idea how to make just about anything happen with a web based interface.

Set up a small web server on the Pi. I use mini-httpd, which you can get with apt-get.
Host the web pages on the Pi and have the controls on them get something from a CGI.
The CGI can be a simple script containing commands as you would type them in ssh.

Here's my config for mini-httpd
Code: Select all
# Example config for mini_httpd.
# Author: Marvin Stark <marv@der-marv.de>

# Uncomment this line for turning on ssl support.
#ssl

# On which host mini_httpd should bind?
host=0.0.0.0

# On which port mini_httpd should listen?
port=80

# Which user mini_httpd should use?
user=nobody

# Run in chroot mode?
#chroot # yes
nochroot # no

# Working directory of mini_httpd.
dir=/var/www

# We are the web files stored?
# Please change this to your needs.
data_dir=/var/www
# data_dir=/usr/share/mini-httpd/html

# CGI path
cgipat=cgi-bin/*

# Which certificate to use?
#certfile=<certfile>

# Which logfile to use?
logfile=/var/log/mini-httpd.log

# Which pidfile to use?
pidfile=/var/run/mini-httpd.pid

# Which charset to use?
charset=iso-8859-1

This assumes you'll keep your web pages under /var/www


Here's my very simple web page, I call it in /var/www/switch.html
Code: Select all
<html>
<head>
<title>Switch Control Page</title>
</head>
<script language="javascript">
var m_XML = false;

function ProcessResponse()
{
        if (m_XML.readyState == 4)
        {
                if (m_XML.status == 200)
                {
                }
        }
}

function Doxml(chan,state)
{
        try
        {
                if (! m_XML)
                {
                        if (window.XMLHttpRequest)
                        {
                                m_XML = new XMLHttpRequest();
                        }
                        else if (window.ActiveXObject)
                        {
                                m_XML = new ActiveXObject("Microsoft.XMLHTTP");
                        }
                }

                if (m_XML)
                {
                        m_XML.open("GET","cgi-bin/switch_cgi?"+chan+"&"+state);
                        m_XML.onreadystatechange = ProcessResponse ;
                        m_XML.send(null);
                }
        }
        catch (e)
        {
        }
}
</script>

<body>
<table>
<tr>
<td>Channel 1</td>
<td><button type="button" onclick="Doxml('1','on')">ON</button></td>
<td><button type="button" onclick="Doxml('1','off')">OFF</button></td>
</tr>
<tr>
<td>Channel 2</td>
<td><button type="button" onclick="Doxml('2','on')">ON</button></td>
<td><button type="button" onclick="Doxml('2','off')">OFF</button></td>
</tr>
<tr>
<td>Channel 3</td>
<td><button type="button" onclick="Doxml('3','on')">ON</button></td>
<td><button type="button" onclick="Doxml('3','off')">OFF</button></td>
</tr>
<tr>
<td>Channel 4</td>
<td><button type="button" onclick="Doxml('4','on')">ON</button></td>
<td><button type="button" onclick="Doxml('4','off')">OFF</button></td>
</tr>
</table>
</html>


And here's the cgi script it calls /var/www/cgi-bin/switch_cgi
Code: Select all
#!/bin/bash

echo Content-type: text/plain
echo

cd /var/www/cgi-bin

PARAMS=`echo $QUERY_STRING | cut -d\? -f 2`

CHAN=`echo $PARAMS | cut -d\& -f 1`
ACT=`echo $PARAMS | cut -d\& -f 2`

echo $QUERY_STRING
echo $PARAMS
echo $CHAN
echo $ACT

switch $CHAN $ACT


The DoXML function in the page does a background GET operation to the web server which calls the CGI script. CGI is great because of it's sheer simplicity, your program gets run and there's a variable called $QUERY_STRING that contains the URL parameters. The parameters can be anything you can put in a web URL, though http://cgi-bin/page.cgi?something=1&somethingelse=2 is the generally accepted format. In the example above, I cheated and just passed the parameters as 1&on with no something= parts.

Hope that gets you going.

Geoff.
Posts: 94
Joined: Sun Sep 23, 2012 7:19 pm
by armyofme » Thu Feb 14, 2013 8:08 am
Thanks for your reply Geoff. Looks like a great idea. I will try it out at the weekend :)
Posts: 12
Joined: Sat Jan 12, 2013 11:28 am
by armyofme » Fri Feb 15, 2013 3:02 pm
Hey Geoff,

I've now set up the httpd web server as you've suggested. How do I know input my commands into the page....I assume I have to change the switch.html file somewhere in the line:
Code: Select all
<td><button type="button" onclick="Doxml('1','on')">ON</button></td>

So I tried this:
Code: Select all
<td><button type="button" onclick="tdtool -n1">ON</button></td>

But it did not work :( How do I include my commands into the page? Apologies, I am new to this.

Many thanks,

Andrew.
Posts: 12
Joined: Sat Jan 12, 2013 11:28 am
by simonpb1 » Fri Feb 15, 2013 6:47 pm
Hi
I have created a simple HA system which uses 6LoWPAN. At the moment it is some evaluation boards with LEDs. I have a mysql database and a webserver(apache) The mysql database is queried every 1 minute by some php scripts and cron. Each device can be scheduled at specific intervals and with groups and scenes.

For example you could turn the landing light on at 8pm and turn it off at 10pm with cron like scheduling using 0 8 1-5 * * which would turn the light on at 8am on monday to friday.

It will work with groups and scenes. You could fire a scene which turns off the main lights, turns on the lamp closes the curtains. All the devices are wireless so the pi sends out the signal wirelessly to control the devices.

It is still work in progress but when it is complete I will be looking make it available as a download.
I will be making lots of notes on my progress at http://www.raspberry-pie.co.uk
Posts: 25
Joined: Thu Sep 13, 2012 11:25 am
by armyofme » Fri Feb 15, 2013 11:19 pm
Thanks for the info Simonpb1 :)

To be honest I'm quite happy with the control I have...it's the interface I want to improve on.

I have Tellstick and Iguanaworks wireless and infrared transceivers connected to my pi, so via cron, I already have lights, radio etc coming on using crontab and sunwait.

I'm very interested in the httpd interface Geoff is recommending but think I need to learn a bit more about how to edit the cgi script file.

Any other ideas on developing an interface that can send commands to the pi via ssh are welcome :)
Posts: 12
Joined: Sat Jan 12, 2013 11:28 am
by simonpb1 » Sun Feb 17, 2013 12:01 pm
It depends on what you want to control and when. If you want devices to operate at specified intervals then the most obvious thing is to use cron. I want to control lots of devices with the pi so I use a mysql database to store the scheduled events and then I have a php script that is called from cron each minute this is what pulls the events from the database and then sends the relevant command to my wireless network.

I can use any internet connected device to control the devices in real time and the scheduler takes care of everything else.
Posts: 25
Joined: Thu Sep 13, 2012 11:25 am
by Hoagie » Mon Feb 18, 2013 1:16 pm
armyofme wrote:Hey Geoff,

I've now set up the httpd web server as you've suggested. How do I know input my commands into the page....I assume I have to change the switch.html file somewhere in the line:
Code: Select all
<td><button type="button" onclick="Doxml('1','on')">ON</button></td>

So I tried this:
Code: Select all
<td><button type="button" onclick="tdtool -n1">ON</button></td>

But it did not work :( How do I include my commands into the page? Apologies, I am new to this.

Many thanks,

Andrew.


I assume from that "tdtool -n1" is the command you'd use at the command prompt.

I'd leave most of DoXML in place, maybe just change the URL in the m_XML.open line. DoXML handles the cross browser compatibility (makes it work on IE) for you. My implementation just passes on the parameters to a fixed CGI script, you may want different parameters for your script, like n1 for instance.

Keep the CGI on the server end, but put any calls to your control program in there. So maybe call it tdtool_cgi and make it call tdtool with a parameter taken from the QUERY_STRING variable.

You can also test my CGI script by typing http://YOUR_IP/cgi-bin/switch_cgi?1&on into the address bar of a browser. Debugging CGIs is a bit tricky but one way is to log lots of things to a file and have "tail -f logfile" running in an SSH window.

Hope that gets you going.
Geoff.
Posts: 94
Joined: Sun Sep 23, 2012 7:19 pm
by armyofme » Mon Feb 18, 2013 9:58 pm
Thanks for your reply.

So maybe call it tdtool_cgi and make it call tdtool with a parameter taken from the QUERY_STRING variable.


How would I go about doing this bit...What would I need to write in the cgi script to call the tdtool command? I take it the QUERY_STRING is only for the parameters?
Posts: 12
Joined: Sat Jan 12, 2013 11:28 am
by armyofme » Tue Feb 19, 2013 4:35 pm
Basically I'm trying to control the lights in my house with the tellstick. For this I need to use the 'tdtool', to turn the living room lights on I type tdtool -n1 and to turn them off I type tdtool -f1, 1 being the livingroom lights ID.

So I would like to use your html control page. In your code it says:

Code: Select all
m_XML.open("GET","cgi-bin/switch_cgi?"+chan+"&"+state);


So from what you said in your last message I have created a tdtool_cgi, although I'm not confident I've written it correctly. So I've changed the above to say tdtool_cgi. But what about the chan and state parts...how do I get these to correspond to my devices (numbers 1-4) and the states (-n and -f).

Really appreciate your help! Thanks.

Code: Select all
<td>Channel 1</td>
<td><button type="button" onclick="Doxml('1','on')">ON</button></td>
<td><button type="button" onclick="Doxml('1','off')">OFF</button></td>
</tr>
Posts: 12
Joined: Sat Jan 12, 2013 11:28 am
by Hoagie » Tue Feb 19, 2013 9:36 pm
Firstly, you could pass 1-4 and f or o as the parameters to doxml from the button clicks. They would then get passed to the cgi script.

The script would then be something like this...
cd /var/www/cgi-bin

PARAMS=`echo $QUERY_STRING | cut -d\? -f 2`

CHAN=`echo $PARAMS | cut -d\& -f 1`
ACT=`echo $PARAMS | cut -d\& -f 2`

echo $QUERY_STRING
echo $PARAMS
echo $CHAN
echo $ACT

tdtool $ACT$CHAN


Oops, forgot the code markers.
The only change there is the last line, now it calls tdtool with the parameters the other way around, and no space between them.

Note. Tdtool must be runnable by the user the http server is using. There's info in my MagPi article on how i made switch work for any user.

Cheers,
Geoff.
Posts: 94
Joined: Sun Sep 23, 2012 7:19 pm
by armyofme » Wed Feb 20, 2013 4:23 pm
That's brilliant! Thank you!

I now can control my lights. Next step...my amplifiers! So in the same html page I want to be able to turn my amps on, off, volume up and down - is this possible?

To turn my cambridge amp on I send the following lirc command 'irsend send_once cambridge on' and if I want to turn off my mission amp it would be 'irsend send_once mission off'. Can I call different cgi scripts in the same page?
Posts: 12
Joined: Sat Jan 12, 2013 11:28 am
by armyofme » Wed Feb 20, 2013 7:24 pm
In the html page can I have this bit:
Code: Select all
    function Doxml(act,chan)
    {
            try
            {
                    if (! m_XML)
                    {
                            if (window.XMLHttpRequest)
                            {
                                    m_XML = new XMLHttpRequest();
                            }
                            else if (window.ActiveXObject)
                            {
                                    m_XML = new ActiveXObject("Microsoft.XMLHTTP");
                            }
                    }

                    if (m_XML)
                    {
                            m_XML.open("GET","cgi-bin/tdtool_cgi?"+act+"&"+chan);
                            m_XML.onreadystatechange = ProcessResponse ;
                            m_XML.send(null);
                    }
            }
            catch (e)
            {
            }
    }


Can I repeat this but call another script? If so, can I call it 'Doxml2'? Like so...
Code: Select all
    function Doxml2(act,chan)
Posts: 12
Joined: Sat Jan 12, 2013 11:28 am
by armyofme » Wed Feb 20, 2013 8:19 pm
That worked too :)

How come in the html they are called state and chan but in the script $ACT and $CHAN?
Posts: 12
Joined: Sat Jan 12, 2013 11:28 am