Browse Source

Merge pull request #164 from kanoi/master

miner.php optionally support multiple rigs
Con Kolivas 14 years ago
parent
commit
381107cc7b
2 changed files with 342 additions and 51 deletions
  1. 2 3
      README
  2. 340 48
      miner.php

+ 2 - 3
README

@@ -794,9 +794,8 @@ api-example.c - a 'C' program to access the API (with source code)
 
 
 miner.php - an example web page to access the API
 miner.php - an example web page to access the API
  This includes buttons and inputs to attempt access to the privileged commands
  This includes buttons and inputs to attempt access to the privileged commands
- You must modify the 2 lines near the top to change where it looks for cgminer
-  $miner = '127.0.0.1'; # hostname or IP address
-  $port = 4028;
+ Read the top of the file (miner.php) for details of how to tune the display
+ and also to use the option to display a multi-rig summary
 
 
 ---
 ---
 
 

+ 340 - 48
miner.php

@@ -1,9 +1,11 @@
 <?php
 <?php
 session_start();
 session_start();
 #
 #
-global $miner, $port, $readonly, $notify;
-$miner = '127.0.0.1'; # hostname or IP address
-$port = 4028;
+global $miner, $port, $readonly, $notify, $rigs;
+#
+# Don't touch these 2 - see $rigs below
+$miner = null;
+$port = null;
 #
 #
 # Set $readonly to true to force miner.php to be readonly
 # Set $readonly to true to force miner.php to be readonly
 # Set $readonly to false then it will check cgminer 'privileged'
 # Set $readonly to false then it will check cgminer 'privileged'
@@ -15,12 +17,27 @@ $readonly = false;
 #  coz it doesn't have notify - it just shows the error status table
 #  coz it doesn't have notify - it just shows the error status table
 $notify = true;
 $notify = true;
 #
 #
+# Set $rigs to an array of your cgminer rigs that are running
+#  format: 'IP:Port' or 'Host:Port'
+# If you only have one rig, it will just show the detail of that rig
+# If you have more than one rig it will show a summary of all the rigs
+#  with buttons to show the details of each rig
+# e.g. $rigs = array('127.0.0.1:4028','myrig.com:4028');
+$rigs = array('127.0.0.1:4028');
+#
 $here = $_SERVER['PHP_SELF'];
 $here = $_SERVER['PHP_SELF'];
 #
 #
-function htmlhead()
+global $tablebegin, $tableend, $warnfont, $warnoff;
+$tablebegin = '<tr><td><table border=1 cellpadding=5 cellspacing=0>';
+$tableend = '</table></td></tr>';
+$warnfont = '<font color=red><b>';
+$warnoff = '</b></font>';
+
+#
+function htmlhead($checkapi)
 {
 {
  global $error, $readonly, $here;
  global $error, $readonly, $here;
- if ($readonly === false)
+ if ($readonly === false && $checkapi === true)
  {
  {
 	$access = api('privileged');
 	$access = api('privileged');
 	if ($error != null
 	if ($error != null
@@ -36,17 +53,18 @@ td.h { color:blue; font-family:verdana,arial,sans; font-size:13pt; background:#d
 td.err { color:black; font-family:verdana,arial,sans; font-size:13pt; background:#ff3050 }
 td.err { color:black; font-family:verdana,arial,sans; font-size:13pt; background:#ff3050 }
 td.warn { color:black; font-family:verdana,arial,sans; font-size:13pt; background:#ffb050 }
 td.warn { color:black; font-family:verdana,arial,sans; font-size:13pt; background:#ffb050 }
 td.sta { color:green; font-family:verdana,arial,sans; font-size:13pt; }
 td.sta { color:green; font-family:verdana,arial,sans; font-size:13pt; }
+td.tot { color:blue; font-family:verdana,arial,sans; font-size:13pt; background:#fff8f2 }
 </style>
 </style>
 </head><body bgcolor=#ecffff>
 </head><body bgcolor=#ecffff>
 <script type='text/javascript'>
 <script type='text/javascript'>
 function pr(a,m){if(m!=null){if(!confirm(m+'?'))return}window.location="<?php echo $here ?>"+a}
 function pr(a,m){if(m!=null){if(!confirm(m+'?'))return}window.location="<?php echo $here ?>"+a}
 <?php
 <?php
- if ($readonly === false)
+ if ($readonly === false && $checkapi === true)
  {
  {
 ?>
 ?>
 function prc(a,m){pr('?arg='+a,m)}
 function prc(a,m){pr('?arg='+a,m)}
-function prs(a){var c=a.substr(3);var z=c.split('|',2);var m=z[0].substr(0,1).toUpperCase()+z[0].substr(1)+' GPU '+z[1];prc(a,m)}
-function prs2(a,n){var v=document.getElementById('gi'+n).value;var c=a.substr(3);var z=c.split('|',2);var m='Set GPU '+z[1]+' '+z[0].substr(0,1).toUpperCase()+z[0].substr(1)+' to '+v;prc(a+','+v,m)}
+function prs(a,r){var c=a.substr(3);var z=c.split('|',2);var m=z[0].substr(0,1).toUpperCase()+z[0].substr(1)+' GPU '+z[1];prc(a+'&rig='+r,m)}
+function prs2(a,n,r){var v=document.getElementById('gi'+n).value;var c=a.substr(3);var z=c.split('|',2);var m='Set GPU '+z[1]+' '+z[0].substr(0,1).toUpperCase()+z[0].substr(1)+' to '+v;prc(a+','+v+'&rig='+r,m)}
 <?php
 <?php
  }
  }
 ?>
 ?>
@@ -219,7 +237,14 @@ function fmt($section, $name, $value)
 			if ($value == 0)
 			if ($value == 0)
 				$ret = sprintf("%dh$b%02dm$b%02ds", $h, $m, $s);
 				$ret = sprintf("%dh$b%02dm$b%02ds", $h, $m, $s);
 			else
 			else
-				$ret = sprintf("%ddays$b%02dh$b%02dm$b%02ds", $value, $h, $m, $s);
+			{
+				if ($value == 1)
+					$days = '';
+				else
+					$days = 's';
+
+				$ret = sprintf("%dday$days$b%02dh$b%02dm$b%02ds", $value, $h, $m, $s);
+			}
 		}
 		}
 	}
 	}
 	break;
 	break;
@@ -250,10 +275,56 @@ function fmt($section, $name, $value)
  case 'SUMMARY.Utility':
  case 'SUMMARY.Utility':
 	$ret = $value.'/m';
 	$ret = $value.'/m';
 	break;
 	break;
- case 'GPU.Temperature':
  case 'PGA.Temperature':
  case 'PGA.Temperature':
 	$ret = $value.'&deg;C';
 	$ret = $value.'&deg;C';
 	break;
 	break;
+ case 'GPU.Temperature':
+	$ret = $value.'&deg;C';
+ case 'GPU.Fan Speed':
+ case 'GPU.Fan Percent':
+ case 'GPU.GPU Clock':
+ case 'GPU.Memory Clock':
+ case 'GPU.GPU Voltage':
+ case 'GPU.GPU Activity':
+	if ($value == 0)
+		$class = $warnclass;
+	break;
+ case 'GPU.MHS av':
+ case 'PGA.MHS av':
+ case 'SUMMARY.MHS av':
+ case 'GPU.Total MH':
+ case 'PGA.Total MH':
+ case 'SUMMARY.Total MH':
+ case 'SUMMARY.Getworks':
+ case 'GPU.Accepted':
+ case 'PGA.Accepted':
+ case 'SUMMARY.Accepted':
+ case 'GPU.Rejected':
+ case 'PGA.Rejected':
+ case 'SUMMARY.Rejected':
+ case 'SUMMARY.Local Work':
+ case 'POOL.Getworks':
+ case 'POOL.Accepted':
+ case 'POOL.Rejected':
+ case 'POOL.Discarded':
+	$parts = explode('.', $value, 2);
+	if (count($parts) == 1)
+		$dec = '';
+	else
+		$dec = '.'.$parts[1];
+	$ret = number_format($parts[0]).$dec;
+	break;
+ case 'GPU.Status':
+ case 'PGA.Status':
+ case 'POOL.Status':
+	if ($value != 'Alive')
+		$class = $errorclass;
+	break;
+ case 'GPU.Enabled':
+ case 'PGA.Enabled':
+	if ($value != 'Y')
+		$class = $warnclass;
+	break;
  }
  }
 
 
  if ($section == 'NOTIFY' && substr($name, 0, 1) == '*' && $value != '0')
  if ($section == 'NOTIFY' && substr($name, 0, 1) == '*' && $value != '0')
@@ -287,22 +358,20 @@ function showhead($cmd, $item, $values)
  echo '</tr>';
  echo '</tr>';
 }
 }
 #
 #
-function details($cmd, $list)
+function details($cmd, $list, $rig)
 {
 {
+ global $tablebegin, $tableend;
  global $poolcmd, $readonly;
  global $poolcmd, $readonly;
 
 
  $dfmt = 'H:i:s j-M-Y \U\T\CP';
  $dfmt = 'H:i:s j-M-Y \U\T\CP';
 
 
  $stas = array('S' => 'Success', 'W' => 'Warning', 'I' => 'Informational', 'E' => 'Error', 'F' => 'Fatal');
  $stas = array('S' => 'Success', 'W' => 'Warning', 'I' => 'Informational', 'E' => 'Error', 'F' => 'Fatal');
 
 
- $tb = '<tr><td><table border=1 cellpadding=5 cellspacing=0>';
- $te = '</table></td></tr>';
-
- echo $tb;
+ echo $tablebegin;
 
 
  echo '<tr><td class=sta>Date: '.date($dfmt).'</td></tr>';
  echo '<tr><td class=sta>Date: '.date($dfmt).'</td></tr>';
 
 
- echo $te.$tb;
+ echo $tableend.$tablebegin;
 
 
  if (isset($list['STATUS']))
  if (isset($list['STATUS']))
  {
  {
@@ -328,7 +397,7 @@ function details($cmd, $list)
 
 
 	if ($sectionname != $section)
 	if ($sectionname != $section)
 	{
 	{
-		echo $te.$tb;
+		echo $tableend.$tablebegin;
 		showhead($cmd, $item, $values);
 		showhead($cmd, $item, $values);
 		$section = $sectionname;
 		$section = $sectionname;
 	}
 	}
@@ -353,7 +422,7 @@ function details($cmd, $list)
 			else
 			else
 			{
 			{
 				echo "<input type=button value='Pool $pool'";
 				echo "<input type=button value='Pool $pool'";
-				echo " onclick='prc(\"$pcmd|$pool\",\"$name Pool $pool\")'>";
+				echo " onclick='prc(\"$pcmd|$pool&rig=$rig\",\"$name Pool $pool\")'>";
 			}
 			}
 			echo '</td>';
 			echo '</td>';
 		}
 		}
@@ -361,14 +430,16 @@ function details($cmd, $list)
 
 
 	echo '</tr>';
 	echo '</tr>';
  }
  }
- echo $te;
+
+ echo $tableend;
 }
 }
 #
 #
 global $devs;
 global $devs;
 $devs = null;
 $devs = null;
 #
 #
-function gpubuttons($count)
+function gpubuttons($count, $rig)
 {
 {
+ global $tablebegin, $tableend;
  global $devs;
  global $devs;
 
 
  $basic = array( 'GPU', 'Enable', 'Disable', 'Restart' );
  $basic = array( 'GPU', 'Enable', 'Disable', 'Restart' );
@@ -379,10 +450,7 @@ function gpubuttons($count)
 			'mem' => 'Memory Clock',
 			'mem' => 'Memory Clock',
 			'vddc' => 'GPU Voltage' );
 			'vddc' => 'GPU Voltage' );
 
 
- $tb = '<tr><td><table border=1 cellpadding=5 cellspacing=0>';
- $te = '</table></td></tr>';
-
- echo $tb.'<tr>';
+ echo $tablebegin.'<tr>';
 
 
  foreach ($basic as $head)
  foreach ($basic as $head)
 	echo "<td>$head</td>";
 	echo "<td>$head</td>";
@@ -405,7 +473,7 @@ function gpubuttons($count)
 		{
 		{
 			echo "<input type=button value='$name $c' onclick='prs(\"gpu";
 			echo "<input type=button value='$name $c' onclick='prs(\"gpu";
 			echo strtolower($name);
 			echo strtolower($name);
-			echo "|$c\")'>";
+			echo "|$c\",$rig)'>";
 		}
 		}
 
 
 		echo '</td>';
 		echo '</td>';
@@ -419,7 +487,7 @@ function gpubuttons($count)
 		else
 		else
 		{
 		{
 			$value = $devs["GPU$c"][$des];
 			$value = $devs["GPU$c"][$des];
-			echo "<input type=button value='Set $c:' onclick='prs2(\"gpu$name|$c\",$n)'>";
+			echo "<input type=button value='Set $c:' onclick='prs2(\"gpu$name|$c\",$n,$rig)'>";
 			echo "<input size=7 type=text name=gi$n value='$value' id=gi$n>";
 			echo "<input size=7 type=text name=gi$n value='$value' id=gi$n>";
 			$n++;
 			$n++;
 		}
 		}
@@ -429,35 +497,37 @@ function gpubuttons($count)
 
 
  }
  }
 
 
- echo '</tr>'.$te;
+ echo '</tr>'.$tableend;
 }
 }
 #
 #
-function processgpus($rd, $ro)
+function processgpus($rig)
 {
 {
  global $error;
  global $error;
+ global $warnfont, $warnoff;
 
 
  $gpus = api('gpucount');
  $gpus = api('gpucount');
 
 
  if ($error != null)
  if ($error != null)
-	echo '<tr><td>Error getting GPU count: '.$rd.$error.$ro.'</td></tr>';
+	echo '<tr><td>Error getting GPU count: '.$warnfont.$error.$warnoff.'</td></tr>';
  else
  else
  {
  {
 	if (!isset($gpus['GPUS']['Count']))
 	if (!isset($gpus['GPUS']['Count']))
-		echo '<tr><td>No GPU count returned: '.$rd.$gpus['STATUS']['STATUS'].' '.$gpus['STATUS']['Msg'].$ro.'</td></tr>';
+		echo '<tr><td>No GPU count returned: '.$warnfont.$gpus['STATUS']['STATUS'].' '.$gpus['STATUS']['Msg'].$ro.'</td></tr>';
 	else
 	else
 	{
 	{
 		$count = $gpus['GPUS']['Count'];
 		$count = $gpus['GPUS']['Count'];
 		if ($count == 0)
 		if ($count == 0)
 			echo '<tr><td>No GPUs</td></tr>';
 			echo '<tr><td>No GPUs</td></tr>';
 		else
 		else
-			gpubuttons($count);
+			gpubuttons($count, $rig);
 	}
 	}
  }
  }
 }
 }
 #
 #
-function process($cmds, $rd, $ro)
+function process($cmds, $rig)
 {
 {
  global $error, $devs;
  global $error, $devs;
+ global $warnfont, $warnoff;
 
 
  foreach ($cmds as $cmd => $des)
  foreach ($cmds as $cmd => $des)
  {
  {
@@ -465,13 +535,13 @@ function process($cmds, $rd, $ro)
 
 
 	if ($error != null)
 	if ($error != null)
 	{
 	{
-		echo "<tr><td>Error getting $des: ";
-		echo $rd.$error.$ro.'</td></tr>';
+		echo "<tr><td colspan=100>Error getting $des: ";
+		echo $warnfont.$error.$warnoff.'</td></tr>';
 		break;
 		break;
 	}
 	}
 	else
 	else
 	{
 	{
-		details($cmd, $process);
+		details($cmd, $process, $rig);
 		echo '<tr><td><br><br></td></tr>';
 		echo '<tr><td><br><br></td></tr>';
 		if ($cmd == 'devs')
 		if ($cmd == 'devs')
 			$devs = $process;
 			$devs = $process;
@@ -479,25 +549,152 @@ function process($cmds, $rd, $ro)
  }
  }
 }
 }
 #
 #
-function display()
+# $head is a hack but this is just a demo anyway :)
+function doforeach($cmd, $des, $sum, $head)
+{
+ global $miner, $port;
+ global $error, $readonly, $notify, $rigs;
+ global $tablebegin, $tableend, $warnfont, $warnoff;
+
+ $header = $head;
+ $anss = array();
+
+ $count = 0;
+ foreach ($rigs as $rig)
+ {
+	$parts = explode(':', $rig, 2);
+	if (count($parts) == 2)
+	{
+		$miner = $parts[0];
+		$port = $parts[1];
+
+		$ans = api($cmd);
+
+		if ($error != null)
+		{
+			echo "<tr><td colspan=100>Error on rig $count getting $des: ";
+			echo $warnfont.$error.$warnoff.'</td></tr>';
+			$error = null;
+		}
+		else
+			$anss[$count] = $ans;
+	}
+	$count++;
+ }
+
+ if (count($anss) == 0)
+ {
+	echo "<tr><td>Failed to access any rigs successfully</td></tr>";
+	return;
+ }
+
+ $total = array();
+
+ foreach ($anss as $rig => $ans)
+ {
+	foreach ($ans as $item => $row)
+	{
+		if ($item == 'STATUS')
+			continue;
+
+		if (count($row) > count($header))
+		{
+			$header = $head;
+			foreach ($row as $name => $value)
+				if (!isset($header[$name]))
+					$header[$name] = '';
+		}
+
+		if ($sum != null)
+			foreach ($sum as $name)
+			{
+				if (isset($row[$name]))
+				{
+					if (isset($total[$name]))
+						$total[$name] += $row[$name];
+					else
+						$total[$name] = $row[$name];
+				}
+			}
+	}
+ }
+
+ if ($sum != null)
+	$anss['total']['total'] = $total;
+
+ showhead('', null, $header);
+
+ $section = '';
+
+ foreach ($anss as $rig => $ans)
+ {
+	foreach ($ans as $item => $row)
+	{
+		if ($item == 'STATUS')
+			continue;
+
+		echo '<tr>';
+
+		$newsection = preg_replace('/\d/', '', $item);
+		if ($newsection != 'total')
+			$section = $newsection;
+
+		foreach ($header as $name => $x)
+		{
+			if ($name == '')
+			{
+				if ($rig === 'total')
+					echo "<td align=right class=tot>Total:</td>";
+				else
+					echo "<td align=right><input type=button value='Rig $rig' onclick='pr(\"?rig=$rig\",null)'></td>";
+			}
+			else
+			{
+				if (isset($row[$name]))
+					list($showvalue, $class) = fmt($section, $name, $row[$name]);
+				else
+				{
+					$class = '';
+					$showvalue = '&nbsp;';
+				}
+
+				if ($rig === 'total' and $class == '')
+					$class = ' class=tot';
+
+				echo "<td$class align=right>$showvalue</td>";
+			}
+		}
+
+		echo '</tr>';
+	}
+ }
+}
+#
+function doOne($rig, $preprocess)
 {
 {
  global $error, $readonly, $notify;
  global $error, $readonly, $notify;
+ global $rigs;
 
 
- $error = null;
+ htmlhead(true);
 
 
- $rd = '<font color=red><b>';
- $ro = '</b></font>';
+ $error = null;
 
 
  echo "<tr><td><table cellpadding=0 cellspacing=0 border=0><tr><td>";
  echo "<tr><td><table cellpadding=0 cellspacing=0 border=0><tr><td>";
- echo "<input type=button value='Refresh' onclick='pr(\"\",null)'>";
- echo "</td><td width=100%>&nbsp;</td><td>";
+ echo "<input type=button value='Refresh' onclick='pr(\"?rig=$rig\",null)'></td>";
+ if (count($rigs) > 1)
+	echo "<td><input type=button value='Summary' onclick='pr(\"\",null)'></td>";
+ echo "<td width=100%>&nbsp;</td><td>";
  if ($readonly === false)
  if ($readonly === false)
-	echo "<input type=button value='Quit' onclick='prc(\"quit\",\"Quit CGMiner\")'>";
+ {
+	$msg = 'Quit CGMiner';
+	if (count($rigs) > 1)
+		$msg .= " Rig $rig";
+	echo "<input type=button value='Quit' onclick='prc(\"quit&rig=$rig\",\"$msg\")'>";
+ }
  echo "</td></tr></table></td></tr>";
  echo "</td></tr></table></td></tr>";
 
 
- $arg = trim(getparam('arg', true));
- if ($arg != null and $arg != '')
-	process(array($arg => $arg), $rd, $ro);
+ if ($preprocess != null)
+	process(array($preprocess => $preprocess), $rig);
 
 
  $cmds = array(	'devs'    => 'device list',
  $cmds = array(	'devs'    => 'device list',
 		'summary' => 'summary information',
 		'summary' => 'summary information',
@@ -508,13 +705,108 @@ function display()
 
 
  $cmds['config'] = 'cgminer config';
  $cmds['config'] = 'cgminer config';
 
 
- process($cmds, $rd, $ro);
+ process($cmds, $rig);
 
 
  if ($error == null && $readonly === false)
  if ($error == null && $readonly === false)
-	processgpus($rd, $ro);
+	processgpus($rig);
+}
+#
+function display()
+{
+ global $tablebegin, $tableend;
+ global $miner, $port;
+ global $error, $readonly, $notify, $rigs;
+
+ $rig = trim(getparam('rig', true));
+
+ $arg = trim(getparam('arg', true));
+ $preprocess = null;
+ if ($arg != null and $arg != '')
+ {
+	$num = null;
+	if ($rig != null and $rig != '')
+	{
+		if ($rig >= 0 and $rig < count($rigs))
+			$num = $rig;
+	}
+	else
+		if (count($rigs) == 0)
+			$num = 0;
+
+	if ($num != null)
+	{
+		$parts = explode(':', $rigs[$num], 2);
+		if (count($parts) == 2)
+		{
+			$miner = $parts[0];
+			$port = $parts[1];
+
+			$preprocess = $arg;
+		}
+	}
+ }
+
+ if ($rigs == null or count($rigs) == 0)
+ {
+	echo "<tr><td>No rigs defined</td></tr>";
+	return;
+ }
+
+ if (count($rigs) == 1)
+ {
+	$parts = explode(':', $rigs[0], 2);
+	if (count($parts) == 2)
+	{
+		$miner = $parts[0];
+		$port = $parts[1];
+
+		doOne(0, $preprocess);
+	}
+	else
+		echo '<tr><td>Invalid "$rigs" array</td></tr>';
+
+	return;
+ }
+
+ if ($rig != null and $rig != '' and $rig >= 0 and $rig < count($rigs))
+ {
+	$parts = explode(':', $rigs[$rig], 2);
+	if (count($parts) == 2)
+	{
+		$miner = $parts[0];
+		$port = $parts[1];
+
+		doOne($rig, $preprocess);
+	}
+	else
+		echo '<tr><td>Invalid "$rigs" array</td></tr>';
+
+	return;
+ }
+
+ htmlhead(false);
+
+ echo "<tr><td><table cellpadding=0 cellspacing=0 border=0><tr><td>";
+ echo "<input type=button value='Refresh' onclick='pr(\"\",null)'>";
+ echo "</td></tr></table></td></tr>";
+
+ if ($preprocess != null)
+	process(array($preprocess => $preprocess), $rig);
+
+ echo $tablebegin;
+ $sum = array('MHS av', 'Getworks', 'Found Blocks', 'Accepted', 'Rejected', 'Discarded', 'Stale', 'Utility', 'Local Work', 'Total MH');
+ doforeach('summary', 'summary information', $sum, array());
+ echo $tableend;
+ echo '<tr><td><br><br></td></tr>';
+ echo $tablebegin;
+ doforeach('devs', 'device list', $sum, array(''=>'','ID'=>'','Name'=>''));
+ echo $tableend;
+ echo '<tr><td><br><br></td></tr>';
+ echo $tablebegin;
+ doforeach('pools', 'pool list', $sum, array(''=>''));
+ echo $tableend;
 }
 }
 #
 #
-htmlhead();
 display();
 display();
 #
 #
 ?>
 ?>