diff --git a/lib/globals.php b/lib/globals.php
index 0e39739..95b28ce 100644
--- a/lib/globals.php
+++ b/lib/globals.php
@@ -45,8 +45,9 @@
define("ACTION","686400176463");
define("ON" ,"0000000001");
define("OFF","0000000000");
-define("MAX_RETRIES",30);
-
+define("MAX_RETRIES",10);
+define("TIMEOUT",0.3); // Max time to wait for a reply from S20, in seconds
+define("DEBUG",0);
?>
diff --git a/lib/orvfms.php b/lib/orvfms.php
index 2fd9932..87a481c 100644
--- a/lib/orvfms.php
+++ b/lib/orvfms.php
@@ -51,17 +51,36 @@ function createSocketAndSendMsg($msg,$addr){
echo "
Error opening socket
";
exit(0);
}
-
- if(!socket_bind($s,"0.0.0.0",PORT)){
- echo "Error binding socket
";
- exit(0);
+
+ $loop_count = 0;
+ $stay = 1;
+ while($stay){
+ if(!socket_bind($s,"0.0.0.0",PORT)){
+ if(++$loop_count > MAX_RETRIES){
+ error_log("Fatal error binding to socket\n");
+ echo "Error binding socket
";
+ exit(0);
+ }
+ usleep(300000);
+ }
+ else{
+ $stay = 0;
+ }
}
+ if(DEBUG)
+ error_log("Bind loop count = ".$loop_count);
+
if(!socket_set_option($s,SOL_SOCKET,SO_BROADCAST,1)){
echo "Error setting socket options
";
exit(0);
}
- // Set the timeout to 300ms; seems enough.
- $timeout = array('sec' => 0,'usec'=> 300000);
+ //
+ // Set the timeout. Default set in globals.php
+ // to 300ms; seems enough.
+ //
+ $sec = (int) TIMEOUT;
+ $usec = (int) ((TIMEOUT - $sec) * 1000000.0);
+ $timeout = array('sec' => $sec,'usec'=> $usec);
socket_set_option($s,SOL_SOCKET,SO_RCVTIMEO,$timeout);
sendByteMsg($s,$msg,$addr);
return $s;
@@ -72,30 +91,30 @@ function searchS20(){
//
// This function searchs for all S20 in a local network
// through a broadcast call
- // and returns an associative array $allS20Data indexed
+ // and returns an associative array $s20Table indexed
// by each S20 mac adress. Each array position is itself
// an associative array which contains
//
- // $allS20Data[$mac)['ip'] - IP adresss
- // $allS20Data[$mac)['st'] - current S20 status (ON=1,OFF=0)
- // $allS20Data[$mac)['imac'] - Inverted mac,not strictly required,
+ // $s20Table[$mac)['ip'] - IP adresss
+ // $s20Table[$mac)['st'] - current S20 status (ON=1,OFF=0)
+ // $s20Table[$mac)['imac'] - Inverted mac,not strictly required,
// computed just once for sake of efficiency.
//
// Note that $mac and is represented as a sequence of hexadecimals
// without the usual separators; for example, ac:cf:23:34:e2:b8 is represented
// as "accf2334e2b8".
//
- // An additional field $allS20Data[$mac]['name'] is later added
+ // An additional field $s20Table[$mac]['name'] is later added
// to each entry with the name assigned to each device.
// This is done in a specific function since it requires a separate
// request to each S20 (see function getName() and fillNames below).
//
- // Returns the $allS20Data array
+ // Returns the $s20Table array
//
$s = createSocketAndSendMsg(DISCOVERY_MSG,IP_BROADCAST);
$recIP="";
$recPort=0;
- $allS20Data=array();
+ $s20Table=array();
while ( 1 ){
$n=@socket_recvfrom($s,$bytesRecMsg,42,0,$recIP,$recPort);
if(!$n)
@@ -105,26 +124,26 @@ function searchS20(){
if(substr($recMsg,0,4) == "6864"){
$mac = substr($recMsg,14,12);
$status = (int) substr($recMsg,-1);
- $allS20Data[$mac]=array();
- $allS20Data[$mac]['ip']=$recIP;
- $allS20Data[$mac]['st']=$status;
- $allS20Data[$mac]['imac']=invMac($mac);
+ $s20Table[$mac]=array();
+ $s20Table[$mac]['ip']=$recIP;
+ $s20Table[$mac]['st']=$status;
+ $s20Table[$mac]['imac']=invMac($mac);
}
}
}
socket_close($s);
- return $allS20Data;
+ return $s20Table;
}
-function subscribe($mac,$allS20Data){
+function subscribe($mac,$s20Table){
//
// Sends a subscribe message to S20 specified by mac address
- // $mac, using global device information im $allS20Data.
+ // $mac, using global device information im $s20Table.
//
// Returns the socket status
//
- $imac = $allS20Data[$mac]['imac'];
- $ip = $allS20Data[$mac]['ip'];
+ $imac = $s20Table[$mac]['imac'];
+ $ip = $s20Table[$mac]['ip'];
$msg = SUBSCRIBE.$mac.TWENTIES.$imac.TWENTIES;
$s = createSocketAndSendMsg($msg,$ip);
$stay=1;
@@ -137,7 +156,8 @@ function subscribe($mac,$allS20Data){
$n=@socket_recvfrom($s,$bytesRecMsg,24,0,$recIP,$recPort);
if($n == 0){
// This is probably due to timeout; retry...
- // echo "retrying on update\n";
+ if(DEBUG)
+ error_log( "retrying on update\n");
sendByteMsg($s,$msg,$ip);
}
else{
@@ -153,17 +173,19 @@ function subscribe($mac,$allS20Data){
}
}
}
+ if(DEBUG)
+ error_log("Number of retries subscribe = ".$loop_count."\n");
socket_close($s);
return $status;
}
-function getName($mac,$allS20Data){
+function getName($mac,$s20Table){
//
// Returns the registered name in S20 specified by the mac $mac.
- // Uses previous device information available in $allS20Data.
+ // Uses previous device information available in $s20Table.
//
- $ip = $allS20Data[$mac]['ip'];
- subscribe($mac,$allS20Data);
+ $ip = $s20Table[$mac]['ip'];
+ subscribe($mac,$s20Table);
$getSocketData = "6864001D7274".$mac.TWENTIES."0000000004001700000000";
$s = createSocketAndSendMsg($getSocketData,$ip);
$recIp = ""; $recPort=0;
@@ -177,8 +199,9 @@ function getName($mac,$allS20Data){
$n=@socket_recvfrom($s,$bytesRecMsg,168,0,$recIP,$recPort);
if($n == 0){
// This is probably due to timeout; retry...
+ if(DEBUG)
+ error_log("retrying in getName()".$loop_count);
sendByteMsg($s,$getSocketData,$ip);
- // echo "retrying\n";
}
else{
$recMsg = hex_byte2str($bytesRecMsg,$n);
@@ -195,21 +218,23 @@ function getName($mac,$allS20Data){
}
// ob_flush();
}
+ if(DEBUG)
+ error_log("Number of retries getName = ".$loop_count."\n");
socket_close($s);
return trim($name);
}
-function fillNames($allS20Data){
+function fillNames($s20Table){
//
- // Loos through all S20 regiestered in $allS20Data and
+ // Loos through all S20 regiestered in $s20Table and
// fills the name in each entry
//
//
- foreach($allS20Data as $mac => $devData){
- $name = getName($mac,$allS20Data);
- $allS20Data[$mac]['name'] = $name;
+ foreach($s20Table as $mac => $devData){
+ $name = getName($mac,$s20Table);
+ $s20Table[$mac]['name'] = $name;
}
- return $allS20Data;
+ return $s20Table;
}
function initS20Data(){
@@ -218,37 +243,37 @@ function initS20Data(){
// an associative array with all collected data,
// including names
//
- $allS20Data = searchS20();
- $allS20Data = fillNames($allS20Data);
- return $allS20Data;
+ $s20Table = searchS20();
+ $s20Table = fillNames($s20Table);
+ return $s20Table;
}
-function checkStatus($mac,$allS20Data){
+function checkStatus($mac,$s20Table){
//
// Checks the power status of the S20 speciifed by
// mac adresss $mac using available information in
- // $allS20Data. This is basically done with a subscribe
+ // $s20Table. This is basically done with a subscribe
// function (see above)
//
- return subscribe($mac,$allS20Data);
+ return subscribe($mac,$s20Table);
}
-function updateAllStatus($allS20Data){
+function updateAllStatus($s20Table){
//
// This function updates the power status of all S20 in $allAllS20Data.
//
// InitS20Data also fills the power status when it is called.
- // However, this function is more efficient when $allS20Data
+ // However, this function is more efficient when $s20Table
// was already initialized and relevant available
// and one just wants to update the power status of all S20s
//
- foreach($allS20Data as $mac => $devData){
- $allS20Data[$mac]['st'] = checkStatus($mac,$allS20Data);
+ foreach($s20Table as $mac => $devData){
+ $s20Table[$mac]['st'] = checkStatus($mac,$s20Table);
}
- return $allS20Data;
+ return $s20Table;
}
-function sendAction($mac,$allS20Data,$action){
+function sendAction($mac,$s20Table,$action){
//
// Sends an $action (ON=1, OFF = 0) to S20 specified by $mac
// It retries until a proper reply is received with the desired
@@ -258,13 +283,13 @@ function sendAction($mac,$allS20Data,$action){
// use this function alone. Prefer switchAndCheck() below, which
// performs a double check of the final state.
//
- subscribe($mac,$allS20Data);
+ subscribe($mac,$s20Table);
$msg = ACTION.$mac.TWENTIES;
if($action)
$msg .= ON;
else
$msg .= OFF;
- $ip = $allS20Data[$mac]['ip'];
+ $ip = $s20Table[$mac]['ip'];
$s = createSocketAndSendMsg($msg,$ip);
$stay=1;
$loop_count = 0;
@@ -276,7 +301,8 @@ function sendAction($mac,$allS20Data,$action){
$n=@socket_recvfrom($s,$bytesRecMsg,23,0,$recIP,$recPort);
if($n == 0){
// This is probably due to timeout; retry...
- // echo "retrying on switch\n";
+ if(DEBUG)
+ error_log("retrying on switch\n");
sendByteMsg($s,$msg,$ip);
}
else{
@@ -295,10 +321,13 @@ function sendAction($mac,$allS20Data,$action){
}
}
}
+ if(DEBUG)
+ error_log("Number of retries sendAction() = ".$loop_count."\n");
+
socket_close($s);
}
-function actionAndCheck($mac,$allS20Data,$action){
+function actionAndCheck($mac,$s20Table,$action){
/*
This function implements a switch and check satus.
The check is in fact a double check and should not
@@ -317,8 +346,8 @@ function actionAndCheck($mac,$allS20Data,$action){
echo " Error: too many retries without successfull action in actionAndCheck ()
\n";
exit(0);
}
- sendAction($mac,$allS20Data,$action);
- $st = checkStatus($mac,$allS20Data);
+ sendAction($mac,$s20Table,$action);
+ $st = checkStatus($mac,$s20Table);
if($st == $action){
$stay = 0;
}
@@ -328,15 +357,17 @@ function actionAndCheck($mac,$allS20Data,$action){
error_log($logmsg);
}
}
+ if(DEBUG)
+ error_log("Number of retries actionAndCheck() = ".$loop_count."\n");
return $st;
}
-function getMacFromName($name,$allS20Data){
+function getMacFromName($name,$s20Table){
//
// Returns the $mac address of the S20 with name $name
//
$count = 0;
- foreach($allS20Data as $imac => $devData){
+ foreach($s20Table as $imac => $devData){
if($devData['name'] == $name){
$mac = $imac;
$count++;
@@ -349,16 +380,16 @@ function getMacFromName($name,$allS20Data){
if($count > 1){
echo "Ambiguous: more than one S20 found with same name ".$name." result may be incorrect
\n";
}
- // echo "Found mac for ".$name." = ".$mac."\n";
+
return $mac;
}
-function sendActionByDeviceName($name,$allS20Data,$action){
+function sendActionByDeviceName($name,$s20Table,$action){
//
// Sends an action to device designates with $name
//
- $mac = getMacFromName($name,$allS20Data);
- return actionAndCheck($mac,$allS20Data,$action);
+ $mac = getMacFromName($name,$s20Table);
+ return actionAndCheck($mac,$s20Table,$action);
}
?>
diff --git a/lib/test.php b/lib/test.php
index 019ad87..4c0f093 100644
--- a/lib/test.php
+++ b/lib/test.php
@@ -37,32 +37,33 @@
include("orvfms.php");
-$allS20Data = initS20Data();
+$s20Table = initS20Data();
-$allS20Data = updateAllStatus($allS20Data); // Update all status (not required, just for test,
+$s20Table = updateAllStatus($s20Table); // Update all status (not required, just for test,
//since immediately after init they
// are already uptodate)
// Print the full array
-print_r($allS20Data);
+print_r($s20Table);
//
// Loop over all switch and toggle twice the status
//
for($i = 0; $i < 2; $i++){
- foreach($allS20Data as $mac => $devData){
+ foreach($s20Table as $mac => $devData){
$name = $devData['name'];
$ip = $devData['ip'];
- $st = checkStatus($mac,$allS20Data);
+ $st = checkStatus($mac,$s20Table);
echo "Status of S20 named >".$name. "< (mac=".$mac.", IP=".$ip.") is ".($st ? "ON" : "OFF")."\n";
echo " ...Turning it ".($st ? "OFF" : "ON")."\n";
- sendActionByDeviceName($name,$allS20Data,($st ? 0 : 1));
- $st = checkStatus($mac,$allS20Data);
+ sendActionByDeviceName($name,$s20Table,($st ? 0 : 1));
+ $st = checkStatus($mac,$s20Table);
echo " ...new status is ".($st ? "ON" : "OFF")."\n\n";
ob_flush();
}
+ sleep(2);
}
diff --git a/s20/index.php b/s20/index.php
index 71588d4..1d6c564 100644
--- a/s20/index.php
+++ b/s20/index.php
@@ -57,30 +57,35 @@
$myUrl = htmlspecialchars($_SERVER["PHP_SELF"]);
#print_r($_SESSION);
-
-if(isset($_SESSION["allS20Data"]) && isset($_SESSION["devNumber"]) &&
- (count($allS20Data) == $_SESSION["devNumber"])){
- $allS20Data = $_SESSION["allS20Data"];
- $allS20Data = updateAllStatus($allS20Data);
+if(isset($_SESSION["s20Table"]))
+ $s20Table = $_SESSION["s20Table"];
+
+if(isset($_SESSION["s20Table"]) && isset($_SESSION["devNumber"]) &&
+ (count($s20Table) == $_SESSION["devNumber"])){
+ $s20Table = updateAllStatus($s20Table);
+ if(DEBUG)
+ error_log("Session restarted; only status update\n");
}
else{
- $allS20Data=initS20Data();
- $ndev=count($allS20Data);
+ $s20Table=initS20Data();
+ $ndev=count($s20Table);
$_SESSION["devNumber"]=$ndev;
+ if(DEBUG)
+ error_log("New session: S20 data initialized\n");
}
if ($_SERVER["REQUEST_METHOD"] == "POST") {
$location = $_POST['selected'];
- $mac = getMacFromName($location,$allS20Data);
- $st = $allS20Data[$mac]['st'];
- $newSt = actionAndCheck($mac,$allS20Data,($st==0 ? 1 : 0));
- $allS20Data[$mac]['st']=$newSt;
+ $mac = getMacFromName($location,$s20Table);
+ $st = $s20Table[$mac]['st'];
+ $newSt = actionAndCheck($mac,$s20Table,($st==0 ? 1 : 0));
+ $s20Table[$mac]['st']=$newSt;
}
-$_SESSION["allS20Data"]=$allS20Data;
+$_SESSION["s20Table"]=$s20Table;
-$ndevs = count($allS20Data);
+$ndevs = count($s20Table);
?>
@@ -93,14 +98,14 @@
//
// Sort array (in this case, by mac address), such that data is displayed in a deterministic sequence
//
-$macs = array_keys($allS20Data);
+$macs = array_keys($s20Table);
sort($macs);
//
// Loop on all devices and display each button, coloured according to
// current S20 state.
//
foreach ($macs as $mac){
- $devData = $allS20Data[$mac];
+ $devData = $s20Table[$mac];
$st = $devData['st'];
$name = $devData['name'];
$type = ($st == 0 ? "redbutton" : "greenbutton");