Difference between revisions of "Install HTML"
(→Install a web server) |
(→Prepare a home control page) |
||
Line 36: | Line 36: | ||
wget http://code.jquery.com/jquery-2.1.4.min.js | 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/\<br \/\> /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); | ||
+ | |||
+ | |||
+ | In this directory, create a <code>simple.html</code> control page: | ||
+ | <pre> | ||
+ | <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> | ||
+ | </pre> | ||
+ | Navigate to the control page: <code>http://harmonia.local/homeControl/simple.html</code> | ||
= Prepare a home control page = | = Prepare a home control page = | ||
Revision as of 14:40, 24 June 2015
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
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);
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
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