= 2.6.7
*
* Version 3.2, 03/02/2008: Added a filter for control and scene names beginning
* with a double-underscore, (like __name) to exclude them from the display.
*
* Version 3.1, 03/02/2008: At the suggestion of a reader who has dimmers, changed
* regex to accommodate intermediate "percent" states between on and off,
* translating them all into "On".
*
*/
// BEGIN user definitions
// Show controls table
$show_controls = true;
// Show scenes table
$show_scenes = true;
// ISY-26 access name or IP
$isy26_address = "pl-isy26";
// ISY-26 logon name
$logon_name="admin";
// ISY-26 access password
$password="(your password)";
// Specify a convenient font size
$font_size = "12pt";
// Specify how many cells in table rows
$control_row_length = 4;
$scene_row_length = 4;
// Specify seconds between page refreshes
$refresh_interval = 5;
// END user definitions
$controls_path = "/devices";
$scenes_path = "/scenes";
$change_path = "/change";
function wrap_tag($tag,$content,$extension = "") {
return "<$tag $extension>$content$tag>";
}
function fetch_http($host,$port,$method,$path,$args = null)
{
global $logon_name,$password;
$buf = "";
$auth = base64_encode("$logon_name:$password");
try {
$fp = fsockopen($host, $port);
if ($args && $method == 'GET') {
$path .= '?' . $args;
}
$content = "$method $path HTTP/1.1\r\n";
$content .= "Host: $host\r\n";
$content .= "Authorization: Basic $auth\r\n";
$content .= "Content-type: application/x-www-form-urlencoded\r\n";
$content .= "Content-length: " . strlen($args) . "\r\n";
$content .= "Connection: close\r\n\r\n";
if ($args && $method == 'POST') {
$content .= $args;
}
fputs($fp, $content);
while (!feof($fp)) {
$buf .= fgets($fp,1024);
}
fclose($fp);
}
catch(Exception $e) {
echo 'Error: ', $e->getMessage(), "
\n";
}
return $buf;
}
// fetch ISY-26 data page
function fetch_table_data($path) {
global $isy26_address;
global $control_row_length,$scene_row_length,$controls_path;
$result = "";
// Fetch a page using GET method
$data = fetch_http($isy26_address,80,"GET",$path);
// Did the page load fail (sometimes happens)?
if(!preg_match("%%ism",$data)) {
$result = $data;
}
else {
// isolate the data table
$data = preg_replace("%^.*
(.*).*%is","$1",$data);
// make an array of row contents
$n = preg_match_all("%(.*?)
%is",$data,$matches,PREG_PATTERN_ORDER);
$row_array = $matches[1];
// drop header row
array_shift($row_array);
if($path == $controls_path) {
$row_length = $control_row_length;
// create an array of device data: name,address,state (on/off)
$device_array = preg_replace("%.*?node=(.*?)\">(.*?).*?(\d+ percent|On|Off).*$%","$2,$1,$3",$row_array);
}
else {
$row_length = $scene_row_length;
// create an array of scene data: name,address,-
$device_array = preg_replace("%.*?node=(.*?)\">(.*?).*$%","$2,$1,-",$row_array);
}
// sort controls and scenes by name
sort($device_array);
// build the display Web page
$pa = array();
$n = 0;
$row = "";
foreach ($device_array as $record) {
list($name,$address,$action) = split(",",$record);
// To exclude a control or scene from the display,
// prefix its name with a double-underscore
if(!preg_match("/^__/",$name)) {
$n++;
// all percentage values count as "On"
$on_state = ($action != "Off" && $action != "-");
$class = ($on_state && !preg_match("/All/",$name))?"spy":"spn";
$next_state = $on_state?"Off":"On";
if($path == $controls_path) {
$arg = $address . "," . $next_state . ",d";
$title = "Turn " . $next_state . " control '" . $name . "'";
$span = wrap_tag("span",$name,"class=\"$class\" title=\"$title\" onClick=\"clicked('$arg');\"");
$row .= wrap_tag("td",$span);
}
else {
$arg = $address . ",On,s";
$title = "Turn On scene '" . $name . "'";
$span = wrap_tag("span",$name . " On","class=\"$class\" title=\"$title\" onClick=\"clicked('$arg');\"");
$row .= wrap_tag("td",$span);
$arg = $address . ",Off,s";
$title = "Turn Off scene '" . $name . "'";
$span = wrap_tag("span",$name . " Off","class=\"$class\" title=\"$title\" onClick=\"clicked('$arg');\"");
$row .= wrap_tag("td",$span);
$n++;
}
}
// Test for row length
if(!($n % $row_length)) {
$pa[] = wrap_tag("tr",$row);
$row = "";
}
}
// Add possible incomplete row
if(strlen($row) > 0) {
while($n % $row_length) {
$row .= wrap_tag("td"," ");
$len = strlen($row);
$n++;
}
$pa[] = wrap_tag("tr",$row);
}
$result = join("\n",$pa);
$result = wrap_tag("table", "\n" . $result . "\n","class=\"bordered\" cellpadding=\"0\" cellspacing=\"0\"");
$title = ($path == $controls_path)?"Controls":"Scenes";
$title = wrap_tag("b",$title . ":");
$title = wrap_tag("p",$title);
$result = $title . $result;
}
return $result;
}
// if there is POST data from a prior control input, then submit it to the ISY-26.
// The POST info has this form: node (address), action:On or Off, type: [d]evice or [s]cene
if(array_key_exists('info',$_POST)) {
list($node,$action,$type) = split(",",$_POST['info']);
$out = "node=$node&submit=$action";
$result = fetch_http($isy26_address,80,"POST",$change_path,$out);
// If this was a scene command, delay for ISY-26 to update its state
if($type == "s") {
usleep(250000);
}
}
$page = "";
if($show_scenes) {
$page .= fetch_table_data($scenes_path);
}
if($show_controls) {
$page .= fetch_table_data($controls_path);
}
?>
Lighting Controls