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 13: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