Install HTML
Controlling the home from distance is made via a web access.
In this example, the server is harmonia.local
: evidently, this has to be replaced by your local server name.
Contents
[hide]Install a web server
Install the web server:
su apt-get update apt-get install lighttpd apt-get install php5-cgi lighttpd-enable-mod fastcgi fastcgi-php lighty-enable-mod cgi service lighttpd reload service lighttpd status
Configure the base directory and modify the line with server.document-root
:
WWW_ROOT=/mnt/storage/www/ nano /etc/lighttpd/lighttpd.conf service lighttpd reload cp /var/www/index.lighttpd.html $WWW_ROOT
Edit /etc/lighttpd/conf-enabled/10-cgi.conf
to allow CGI script execution:
# /usr/share/doc/lighttpd/cgi.txt server.modules += ( "mod_cgi" ) $HTTP["url"] =~ "^/homeControl/" { cgi.assign = ( ".cgi" => "/usr/bin/perl" ) }
Navigate to your server within a web browser. You should discover the default lighttpd placeholder page.
Install jQuery
Download the latest compressed, production jQuery version.
wget http://code.jquery.com/jquery-2.1.4.min.js
CGI control script
The following script can be run either from a terminal or as a CGI:
#!/usr/bin/perl use IO::Socket; use CGI; my $cgi = CGI->new; #------------------------------------------------------------------------------- # constants # my $portId = 3865; my $messageType = 'xpl-cmnd'; my $source = 'sendstate.harmonia'; my $target = 'dspc-state.home'; my $scheme = 'state.basic'; $separator = '-' x 80; $indent = ' ' x 2; #------------------------------------------------------------------------------- # Input arguments # my $verbose = 1; my ($room, $kind, $object, $value); my $broadcastAddress = '255.255.255.255'; my $timeout = -1; my $logFilespec = '/tmp/sendState.log'; if ($ENV{'REQUEST_METHOD'}) { # get parameters from URL $room = $cgi->param('room'); $kind = $cgi->param('kind'); $object = $cgi->param('object'); $value = $cgi->param('value'); } else { # get parameters from command line use Getopt::Std; my %opts; getopts('hvb:t:l:', \%opts); die("\n". "Usage: $0 [-hv] [-b address] [-t timeout] room kind object value\n". "\n". "Parameters:\n". "${indent}-h display this help message\n". "${indent}-v verbose\n". "${indent}-b addr broadcast address\n". "${indent}-t time timeout\n". "${indent}-l file log filespec\n". "\n". "The message is sent to machine <server>, UDP port <portId>.\n". "\n". "More information with: perldoc $0\n". "\n". "" ) if ($opts{h}); $verbose = $opts{v}; ($room, $kind, $object, $value) = @ARGV; $broadcastAddress = $opts{'b'} || $broadcastAddress; $timeout = $opts{'t'} || $timeout; $logFilespec = $opts{'l'} || $logFilespec; } ################################################################################ # Subroutines # #------------------------------------------------------------------------------- # send UDP frame # sub sendUDP { my ($broadcastAddress, $portId, $command) = @_; my $reply = ; # open UDP socket my $socket = IO::Socket::INET->new( Proto => 'udp', Broadcast => 1) or return('Socket open failed.'); my $ipAddress = inet_aton($broadcastAddress); my $portAddress = sockaddr_in($portId, $ipAddress); # send command send($socket, $command, 0, $portAddress); # close socket close($socket); return($reply); } ################################################################################ # Main program # # log command my $text = "In $room $kind, setting $object to \"$value\"."; open(my $LOG_FILE, '>', $logFilespec) or die "Could not open file '$logFilespec' $!"; print $LOG_FILE "$text\n"; close $LOG_FILE; chmod(oct('0666'), $logFilespec); # display xPL frame info if ($verbose > 0) { $text .= "\n"; $text .= "${indent}broadcast address is \"$broadcastAddress\"\n"; $text .= "${indent}message type is \"$messageType\"\n"; $text .= "${indent}source is \"$source\"\n"; $text .= "${indent}target is \"$target\"\n"; $text .= "${indent}scheme is \"$scheme\"\n"; if ($ENV{'REQUEST_METHOD'}) { $text =~ s/\n$indent/\
/g; print $cgi->header; print $cgi->start_html; print("$text\n"); print $cgi->end_html; } else { print("$separator\n"); print("$text\n"); } } # send xPL frame my $message = "$messageType\n"; $message .= "{\n"; $message .= "hop=1\n"; $message .= "source=$source\n"; $message .= "target=$target\n"; $message .= "}\n"; $message .= "$scheme\n"; $message .= "{\n"; $message .= "room=$room\n"; $message .= "kind=$kind\n"; $message .= "object=$object\n"; $message .= "value=$value\n"; $message .= "command=set\n"; $message .= "}\n"; sendUDP($broadcastAddress, $portId, $message);
Save it as /homeControl/sendState.cgi
in the web pages directory.
Test it in a terminal window:
./sendState.cgi -v study lights ceiling on
Navigate to the control page: http://harmonia.local/homeControl/simple.html
Prepare a home control page
Create the home control directory:
WWW_CONTROL=$WWW_ROOT/homeControl mkdir -p $WWW_CONTROL chmod -R 775 $WWW_CONTROL chown -R control:users $WWW_CONTROL cd $WWW_CONTROL
In this directory, create a simple.html
control page:
<html> <head> <script src="//code.jquery.com/jquery-1.11.0.min.js"> </script> </head> <body> <!-- Light controls .................................................... --> <br /> <table align="center" border='0px' cellpadding='12px' cellspacing='0px' bgcolor="#CCCCCC"> <tr> <th width="240px">ceiling</th> <th width="240px">stand</th> </tr> <tr> <td align="center"><input id="ceiling" type="checkbox" /></td> <td align="center"><input id="stand" type="checkbox" /></td> </tr> </table> <!-- Websocket java script ............................................. --> <script> $().ready(function() { var ws = new WebSocket('ws://harmonia.local:8080/'); ws.onopen = function() { console.log("Web socket started"); } // outgoing messages $('#ceiling').on('change', function() { ws.send('ceiling ' + $(this).is(':checked')); }); $('#stand').on('change', function() { ws.send('stand ' + $(this).is(':checked')); }); // polling message window.setInterval( function() { ws.send('poll request'); } , 100 ); // incoming messages ws.onmessage = function(message) { console.log(message.data); var words = message.data.split(' '); if (words[0] === 'ceiling') { $('#ceiling').prop('checked', words[1] == 'true'); } if (words[0] === 'stand') { $('#stand').prop('checked', words[1] == 'true'); } } }); </script> </body> </html>
Navigate to the control page: http://harmonia.local/homeControl/simple.html