Difference between revisions of "Install HTML"

From xPL
Jump to: navigation, search
(Install a web server)
(CGI control script)
 
(22 intermediate revisions by one user not shown)
Line 7: Line 7:
 
Install the [http://www.lighttpd.net web server]:
 
Install the [http://www.lighttpd.net web server]:
 
  su
 
  su
  apt-get update
+
  apt update
  apt-get install lighttpd
+
  apt install -y lighttpd
  apt-get install php5-cgi
+
# apt install -y php5-cgi
 +
  apt-get install -y php7.0-fpm php-cgi
 
  lighttpd-enable-mod fastcgi fastcgi-php
 
  lighttpd-enable-mod fastcgi fastcgi-php
lighty-enable-mod cgi
 
 
  service lighttpd reload
 
  service lighttpd reload
 
  service lighttpd status
 
  service lighttpd status
Line 21: Line 21:
 
  cp /var/www/index.lighttpd.html $WWW_ROOT
 
  cp /var/www/index.lighttpd.html $WWW_ROOT
  
Edit <code>/etc/lighttpd/conf-enabled/10-cgi.conf</code> to allow CGI script execution:
+
Edit <code>/etc/lighttpd/conf-enabled/10-cgi.conf</code> to allow [https://en.wikipedia.org/wiki/Common_Gateway_Interface CGI] scripts execution:
 
  # /usr/share/doc/lighttpd/cgi.txt
 
  # /usr/share/doc/lighttpd/cgi.txt
 
  server.modules += ( "mod_cgi" )
 
  server.modules += ( "mod_cgi" )
Line 31: Line 31:
 
You should discover the default [http://www.lighttpd.net lighttpd] placeholder page.
 
You should discover the default [http://www.lighttpd.net lighttpd] placeholder page.
  
= Install jQuery =
+
= Install libraries =
  
Download the [http://jquery.com/download/ latest compressed, production jQuery version].
+
== Install jQuery ==
wget http://code.jquery.com/jquery-2.1.4.min.js
+
  
= Prepare a home control page =
+
[https://jquery.com jQuery] is a fast, small, and feature-rich JavaScript library for HTML event handling and animation.
  
 
Create the home control directory:
 
Create the home control directory:
Line 45: Line 44:
 
  cd $WWW_CONTROL
 
  cd $WWW_CONTROL
  
In this directory, create a <code>simple.html</code> control page:
+
Download the [http://jquery.com/download/ latest compressed, production jQuery version].
 +
wget http://code.jquery.com/jquery-2.1.4.min.js
 +
 
 +
== Install Perl libraries ==
 +
 
 +
[https://en.wikipedia.org/wiki/Common_Gateway_Interface Common Gateway Interface] (CGI)
 +
allows to run scripts which create HTML pages.
 +
 
 +
Install it:
 +
perl -MFile::Find=find -MFile::Spec::Functions -Tlw -e 'find { wanted => sub { print canonpath $_ if /\.pm\z/ }, no_chdir => 1 }, @INC' 2> /dev/null | grep -i cgi
 +
su
 +
perl -MCPAN -e "install 'CGI'"
 +
exit
 +
or
 +
apt-cache search CGI-pm
 +
apt install libcgi-pm-perl
 +
 
 +
[http://search.cpan.org/~grantm/XML-Simple-2.24/lib/XML/Simple.pm XML::Simple] allows to easily read and write XML files.
 +
 
 +
Install it:
 +
perl -MFile::Find=find -MFile::Spec::Functions -Tlw -e 'find { wanted => sub { print canonpath $_ if /\.pm\z/ }, no_chdir => 1 }, @INC' 2> /dev/null | grep -i xml/simple
 +
su
 +
apt install libxml-sax-expat-incremental-perl
 +
perl -MCPAN -e "install 'XML::Simple'"
 +
exit
 +
or
 +
apt-cache search XML::Simple | grep simple
 +
apt-get install libxml-simple-perl
 +
 
 +
[http://www.blackperl.com/Image::Size/ Image::Size] allows to find height and width information of an image.
 +
It can be handy for displaying buttons.
 +
 
 +
Install it:
 +
perl -MFile::Find=find -MFile::Spec::Functions -Tlw -e 'find { wanted => sub { print canonpath $_ if /\.pm\z/ }, no_chdir => 1 }, @INC' 2> /dev/null | grep -i image/size
 +
su
 +
perl -MCPAN -e "install 'Image::Size'"
 +
exit
 +
or
 +
apt-cache search Image::Size
 +
apt install libimage-size-perl
 +
 
 +
= CGI control script =
 +
 
 +
The following <code>sendState.cgi</code> script can be run either from a terminal
 +
or as a [https://en.wikipedia.org/wiki/Common_Gateway_Interface Common Gateway Interface] (CGI) script:
 +
<pre>
 +
#!/usr/bin/perl
 +
use IO::Socket;
 +
use CGI;
 +
my $cgi = CGI->new;
 +
 
 +
#-------------------------------------------------------------------------------
 +
# constants
 +
#
 +
my $portId = 3865;
 +
my $messageType = 'xpl-cmnd';
 +
my $source = 'sendstate.metis';
 +
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);
 +
</pre>
 +
 
 +
The idea of working both in terminal and in [https://en.wikipedia.org/wiki/Common_Gateway_Interface CGI] mode came from John Bent's [http://johnb.xplproject.org.uk/info/perl/ xPL ToolKit for Perl].
 +
 
 +
Save the script as <code>/homeControl/sendState.cgi</code> in the web pages directory.
 +
 
 +
Test it in a terminal window:
 +
WWW_CONTROL='/mnt/storage/www/homeControl'
 +
cd $WWW_CONTROL/
 +
./sendState.cgi -v study lights ceiling on
 +
The terminal should display information about what is being sent,
 +
an [[Install xpl hub#Test the hub|xPL monitor]] should show the corresponding frame
 +
and the [[Install state|home state]] xPL device should turn the corresponding light on.
 +
 
 +
Test it as a CGI by navigating to the control page:
 +
http://hades.local/homeControl/sendState.cgi?room=study&kind=lights&object=ceiling&value=off
 +
The browser shoud display the same info as the terminal,
 +
the monitor should show the frame
 +
and the home state device shoiud turn the light off.
 +
 
 +
= Home control page =
 +
 
 +
== Static HTML page ==
 +
 
 +
In the www home control directory, create a <code>simple.html</code> control page:
 
<pre>
 
<pre>
 
<html>
 
<html>
 
   <head>
 
   <head>
     <script src="//code.jquery.com/jquery-1.11.0.min.js">
+
    <!--
     </script>
+
     <script src="//code.jquery.com/jquery-2.1.4.min.js"></script>
 +
     -->
 +
    <script src="jquery-2.1.4.min.js"></script>
 
   </head>
 
   </head>
 
   <body>
 
   <body>
Line 66: Line 268:
 
     </table>
 
     </table>
  
     <!-- Websocket java script ............................................. -->
+
     <!-- Button handling javascript ........................................ -->
 
     <script>
 
     <script>
 
       $().ready(function() {
 
       $().ready(function() {
         var ws = new WebSocket('ws://harmonia.local:8080/');
+
         var room = 'study';
 
+
         var kind = 'lights';
         ws.onopen = function() {
+
        var object = '';
          console.log("Web socket started");
+
         var value = '';
         }
+
 
                                                             // outgoing messages
 
                                                             // outgoing messages
 
         $('#ceiling').on('change', function() {
 
         $('#ceiling').on('change', function() {
           ws.send('ceiling ' + $(this).is(':checked'));
+
           object = 'ceiling';
 +
          value = ($(this).is(':checked') == true ? 'on' : 'off');
 +
          $.post('sendState.cgi', {room: room, kind: kind, object: object, value: value})
 +
          console.log('sending ' + room + ' ' + kind + ' ' + object + ' "' + value + '"');
 
         });
 
         });
 
         $('#stand').on('change', function() {
 
         $('#stand').on('change', function() {
           ws.send('stand ' + $(this).is(':checked'));
+
           object = 'stand';
 +
          value = ($(this).is(':checked') == true ? 'on' : 'off');
 +
          $.post('sendState.cgi', {room: room, kind: kind, object: object, value: value})
 +
          console.log('sending ' + room + ' ' + kind + ' ' + object + ' "' + value + '"');
 
         });
 
         });
                                                              // 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>
 
     </script>
Line 108: Line 296:
 
Navigate to the control page: <code>http://harmonia.local/homeControl/simple.html</code>
 
Navigate to the control page: <code>http://harmonia.local/homeControl/simple.html</code>
  
= Implement a WebSocket server =
+
The web browser should show two buttons.
 +
Clicking on them should launch the CGI script and turn the lights on or off.
 +
 
 +
== Dynamic HTML pages ==
 +
 
 +
Adding further buttons to the preceeding HTML page is a tedious task consisting on repeating a regular pattern.
 +
Obviously, the HTML rendering should be scripted.
 +
 
 +
The [http://www.dspc.ch/xPL/Downloads/buildControlPage.zip build control page ZIP file] contains:
 +
* <code>buildControlPage.cgi</code>, the script generating the HTML pages
 +
* <code>pages.xml</code>, an [https://en.wikipedia.org/wiki/XML XML] file defining the layout of the HTML control pages for my apartment
 +
* <code>Icons</code>, a directory containing the buton icons
 +
 
 +
The pages are specified by two identifiers: <code>room</code> and <code>level</code>.
 +
Navigation buttons, with attribute <code>type='navigation'</code>, allow to jump to another control page by specifying these two identifiers.
 +
The other buttons, with attribute <code>type='press'</code>, <code>type='slider'</code> or <code>type='on_off'</code> (toggle), allow to send xPL commands via the [[#CGI_control_script|<code> sendState.cgi</code>]] script.
 +
 
 +
The <code>pages.xml</code> description allows to define the background color of the generated HTML page.
 +
Additionally to that, it can add [https://en.wikipedia.org/wiki/Scalable_Vector_Graphics Scalable Vector Graphics] (SVG) drawings such as the rectangles in the ''apartment/rooms'' page.
  
 
[[Category: all]] [[Category: install]] [[Category: web]]
 
[[Category: all]] [[Category: install]] [[Category: web]]

Latest revision as of 16:48, 19 March 2019

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 update
apt install -y lighttpd
# apt install -y php5-cgi
apt-get install -y php7.0-fpm php-cgi
lighttpd-enable-mod fastcgi fastcgi-php
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 scripts 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 libraries

Install jQuery

jQuery is a fast, small, and feature-rich JavaScript library for HTML event handling and animation.

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

Download the latest compressed, production jQuery version.

wget http://code.jquery.com/jquery-2.1.4.min.js

Install Perl libraries

Common Gateway Interface (CGI) allows to run scripts which create HTML pages.

Install it:

perl -MFile::Find=find -MFile::Spec::Functions -Tlw -e 'find { wanted => sub { print canonpath $_ if /\.pm\z/ }, no_chdir => 1 }, @INC' 2> /dev/null | grep -i cgi
su
perl -MCPAN -e "install 'CGI'"
exit

or

apt-cache search CGI-pm
apt install libcgi-pm-perl

XML::Simple allows to easily read and write XML files.

Install it:

perl -MFile::Find=find -MFile::Spec::Functions -Tlw -e 'find { wanted => sub { print canonpath $_ if /\.pm\z/ }, no_chdir => 1 }, @INC' 2> /dev/null | grep -i xml/simple
su
apt install libxml-sax-expat-incremental-perl
perl -MCPAN -e "install 'XML::Simple'"
exit

or

apt-cache search XML::Simple | grep simple
apt-get install libxml-simple-perl

Image::Size allows to find height and width information of an image. It can be handy for displaying buttons.

Install it:

perl -MFile::Find=find -MFile::Spec::Functions -Tlw -e 'find { wanted => sub { print canonpath $_ if /\.pm\z/ }, no_chdir => 1 }, @INC' 2> /dev/null | grep -i image/size
su
perl -MCPAN -e "install 'Image::Size'"
exit

or

apt-cache search Image::Size
apt install libimage-size-perl

CGI control script

The following sendState.cgi script can be run either from a terminal or as a Common Gateway Interface (CGI) script:

#!/usr/bin/perl
use IO::Socket;
use CGI;
my $cgi = CGI->new;

#-------------------------------------------------------------------------------
# constants
#
my $portId = 3865;
my $messageType = 'xpl-cmnd';
my $source = 'sendstate.metis';
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);

The idea of working both in terminal and in CGI mode came from John Bent's xPL ToolKit for Perl.

Save the script as /homeControl/sendState.cgi in the web pages directory.

Test it in a terminal window:

WWW_CONTROL='/mnt/storage/www/homeControl'
cd $WWW_CONTROL/
./sendState.cgi -v study lights ceiling on

The terminal should display information about what is being sent, an xPL monitor should show the corresponding frame and the home state xPL device should turn the corresponding light on.

Test it as a CGI by navigating to the control page:

http://hades.local/homeControl/sendState.cgi?room=study&kind=lights&object=ceiling&value=off

The browser shoud display the same info as the terminal, the monitor should show the frame and the home state device shoiud turn the light off.

Home control page

Static HTML page

In the www home control directory, create a simple.html control page:

<html>
  <head>
    <!--
    <script src="//code.jquery.com/jquery-2.1.4.min.js"></script>
    -->
    <script src="jquery-2.1.4.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>

    <!-- Button handling javascript ........................................ -->
    <script>
      $().ready(function() {
        var room = 'study';
        var kind = 'lights';
        var object = '';
        var value = '';
                                                            // outgoing messages
        $('#ceiling').on('change', function() {
          object = 'ceiling';
          value = ($(this).is(':checked') == true ? 'on' : 'off');
          $.post('sendState.cgi', {room: room, kind: kind, object: object, value: value})
          console.log('sending ' + room + ' ' + kind + ' ' + object + ' "' + value + '"');
        });
        $('#stand').on('change', function() {
          object = 'stand';
          value = ($(this).is(':checked') == true ? 'on' : 'off');
          $.post('sendState.cgi', {room: room, kind: kind, object: object, value: value})
          console.log('sending ' + room + ' ' + kind + ' ' + object + ' "' + value + '"');
        });
      });
    </script>

  </body>
</html>

Navigate to the control page: http://harmonia.local/homeControl/simple.html

The web browser should show two buttons. Clicking on them should launch the CGI script and turn the lights on or off.

Dynamic HTML pages

Adding further buttons to the preceeding HTML page is a tedious task consisting on repeating a regular pattern. Obviously, the HTML rendering should be scripted.

The build control page ZIP file contains:

  • buildControlPage.cgi, the script generating the HTML pages
  • pages.xml, an XML file defining the layout of the HTML control pages for my apartment
  • Icons, a directory containing the buton icons

The pages are specified by two identifiers: room and level. Navigation buttons, with attribute type='navigation', allow to jump to another control page by specifying these two identifiers. The other buttons, with attribute type='press', type='slider' or type='on_off' (toggle), allow to send xPL commands via the sendState.cgi script.

The pages.xml description allows to define the background color of the generated HTML page. Additionally to that, it can add Scalable Vector Graphics (SVG) drawings such as the rectangles in the apartment/rooms page.