Difference between revisions of "Install HTML"

From xPL
Jump to: navigation, search
(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 \/\>&nbsp;&nbsp;/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.

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

Implement a WebSocket server