PageRenderTime 25ms CodeModel.GetById 3ms app.highlight 11ms RepoModel.GetById 1ms app.codeStats 0ms

/miner.php

https://github.com/bkkcoins/cgminer-klondike
PHP | 2750 lines | 2292 code | 279 blank | 179 comment | 513 complexity | a95946abbb43fb51168419987f6fdd9b MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1<?php
   2session_start();
   3#
   4global $title, $miner, $port, $readonly, $notify, $rigs;
   5global $rigipsecurity, $rigtotals, $forcerigtotals;
   6global $socksndtimeoutsec, $sockrcvtimeoutsec;
   7global $checklastshare, $poolinputs, $hidefields;
   8global $ignorerefresh, $changerefresh, $autorefresh;
   9global $allowcustompages, $customsummarypages;
  10global $miner_font_family, $miner_font_size;
  11global $colouroverride, $placebuttons, $userlist;
  12#
  13# See API-README for more details of these variables and how
  14# to configure miner.php
  15#
  16# Web page title
  17$title = 'Mine';
  18#
  19# Set $readonly to true to force miner.php to be readonly
  20# Set $readonly to false then it will check cgminer 'privileged'
  21$readonly = false;
  22#
  23# Set $userlist to null to allow anyone access or read API-README
  24$userlist = null;
  25#
  26# Set $notify to false to NOT attempt to display the notify command
  27# Set $notify to true to attempt to display the notify command
  28$notify = true;
  29#
  30# Set $checklastshare to true to do the following checks:
  31# If a device's last share is 12x expected ago then display as an error
  32# If a device's last share is 8x expected ago then display as a warning
  33# If either of the above is true, also display the whole line highlighted
  34# This assumes shares are 1 difficulty shares
  35$checklastshare = true;
  36#
  37# Set $poolinputs to true to show the input fields for adding a pool
  38# and changing the pool priorities
  39# N.B. also if $readonly is true, it will not display the fields
  40$poolinputs = false;
  41#
  42# Set $rigs to an array of your cgminer rigs that are running
  43#  format: 'IP:Port' or 'Host:Port' or 'Host:Port:Name'
  44$rigs = array('127.0.0.1:4028');
  45#
  46# Set $rigipsecurity to false to show the IP/Port of the rig
  47# in the socket error messages and also show the full socket message
  48$rigipsecurity = true;
  49#
  50# Set $rigtotals to true to display totals on the single rig page
  51# 'false' means no totals (and ignores $forcerigtotals)
  52# You can force it to always show rig totals when there is only
  53# one line by setting $forcerigtotals = true;
  54$rigtotals = true;
  55$forcerigtotals = false;
  56#
  57# These should be OK for most cases
  58$socksndtimeoutsec = 10;
  59$sockrcvtimeoutsec = 40;
  60#
  61# List of fields NOT to be displayed
  62# This example would hide the slightly more sensitive pool information
  63#$hidefields = array('POOL.URL' => 1, 'POOL.User' => 1);
  64$hidefields = array();
  65#
  66# Auto-refresh of the page (in seconds) - integers only
  67# $ignorerefresh = true/false always ignore refresh parameters
  68# $changerefresh = true/false show buttons to change the value
  69# $autorefresh = default value, 0 means dont auto-refresh
  70$ignorerefresh = false;
  71$changerefresh = true;
  72$autorefresh = 0;
  73#
  74# Should we allow custom pages?
  75# (or just completely ignore them and don't display the buttons)
  76$allowcustompages = true;
  77#
  78# OK this is a bit more complex item: Custom Summary Pages
  79# As mentioned above, see API-README
  80# see the example below (if there is no matching data, no total will show)
  81$mobilepage = array(
  82 'DATE' => null,
  83 'RIGS' => null,
  84 'SUMMARY' => array('Elapsed', 'MHS av', 'Found Blocks=Blks', 'Accepted', 'Rejected=Rej', 'Utility'),
  85 'DEVS+NOTIFY' => array('DEVS.Name=Name', 'DEVS.ID=ID', 'DEVS.Status=Status', 'DEVS.Temperature=Temp',
  86			'DEVS.MHS av=MHS av', 'DEVS.Accepted=Accept', 'DEVS.Rejected=Rej',
  87			'DEVS.Utility=Utility', 'NOTIFY.Last Not Well=Not Well'),
  88 'POOL' => array('POOL', 'Status', 'Accepted', 'Rejected=Rej', 'Last Share Time'));
  89$mobilesum = array(
  90 'SUMMARY' => array('MHS av', 'Found Blocks', 'Accepted', 'Rejected', 'Utility'),
  91 'DEVS+NOTIFY' => array('DEVS.MHS av', 'DEVS.Accepted', 'DEVS.Rejected', 'DEVS.Utility'),
  92 'POOL' => array('Accepted', 'Rejected'));
  93#
  94$statspage = array(
  95 'DATE' => null,
  96 'RIGS' => null,
  97 'SUMMARY' => array('Elapsed', 'MHS av', 'Found Blocks=Blks',
  98			'Accepted', 'Rejected=Rej', 'Utility',
  99			'Hardware Errors=HW Errs', 'Network Blocks=Net Blks',
 100			'Work Utility'),
 101 'COIN' => array('*'),
 102 'STATS' => array('*'));
 103#
 104$statssum = array(
 105 'SUMMARY' => array('MHS av', 'Found Blocks', 'Accepted',
 106			'Rejected', 'Utility', 'Hardware Errors',
 107			'Work Utility'));
 108#
 109$poolspage = array(
 110 'DATE' => null,
 111 'RIGS' => null,
 112 'SUMMARY' => array('Elapsed', 'MHS av', 'Found Blocks=Blks', 'Accepted', 'Rejected=Rej',
 113			'Utility', 'Hardware Errors=HW Errs', 'Network Blocks=Net Blks',
 114			'Work Utility'),
 115 'POOL+STATS' => array('STATS.ID=ID', 'POOL.URL=URL', 'POOL.Difficulty Accepted=Diff Acc',
 116			'POOL.Difficulty Rejected=Diff Rej',
 117			'POOL.Has Stratum=Stratum', 'POOL.Stratum Active=StrAct',
 118			'POOL.Has GBT=GBT', 'STATS.Times Sent=TSent',
 119			'STATS.Bytes Sent=BSent', 'STATS.Net Bytes Sent=NSent',
 120			'STATS.Times Recv=TRecv', 'STATS.Bytes Recv=BRecv',
 121			'STATS.Net Bytes Recv=NRecv'));
 122#
 123$poolssum = array(
 124 'SUMMARY' => array('MHS av', 'Found Blocks', 'Accepted',
 125			'Rejected', 'Utility', 'Hardware Errors',
 126			'Work Utility'),
 127 'POOL+STATS' => array('POOL.Difficulty Accepted', 'POOL.Difficulty Rejected',
 128			'STATS.Times Sent', 'STATS.Bytes Sent', 'STATS.Net Bytes Sent',
 129			'STATS.Times Recv', 'STATS.Bytes Recv', 'STATS.Net Bytes Recv'));
 130#
 131$poolsext = array(
 132 'POOL+STATS' => array(
 133	'where' => null,
 134	'group' => array('POOL.URL', 'POOL.Has Stratum', 'POOL.Stratum Active', 'POOL.Has GBT'),
 135	'calc' => array('POOL.Difficulty Accepted' => 'sum', 'POOL.Difficulty Rejected' => 'sum',
 136			'STATS.Times Sent' => 'sum', 'STATS.Bytes Sent' => 'sum',
 137			'STATS.Net Bytes Sent' => 'sum', 'STATS.Times Recv' => 'sum',
 138			'STATS.Bytes Recv' => 'sum', 'STATS.Net Bytes Recv' => 'sum'),
 139	'having' => array(array('STATS.Bytes Recv', '>', 0)))
 140);
 141
 142#
 143# customsummarypages is an array of these Custom Summary Pages
 144$customsummarypages = array('Mobile' => array($mobilepage, $mobilesum),
 145 'Stats' => array($statspage, $statssum),
 146 'Pools' => array($poolspage, $poolssum, $poolsext));
 147#
 148$here = $_SERVER['PHP_SELF'];
 149#
 150global $tablebegin, $tableend, $warnfont, $warnoff, $dfmt;
 151#
 152$tablebegin = '<tr><td><table border=1 cellpadding=5 cellspacing=0>';
 153$tableend = '</table></td></tr>';
 154$warnfont = '<font color=red><b>';
 155$warnoff = '</b></font>';
 156$dfmt = 'H:i:s j-M-Y \U\T\CP';
 157#
 158$miner_font_family = 'verdana,arial,sans';
 159$miner_font_size = '13pt';
 160#
 161# Edit this or redefine it in myminer.php to change the colour scheme
 162# See $colourtable below for the list of names
 163$colouroverride = array();
 164#
 165# Where to place the buttons: 'top' 'bot' 'both'
 166#  anything else means don't show them - case sensitive
 167$placebuttons = 'top';
 168#
 169# This below allows you to put your own settings into a seperate file
 170# so you don't need to update miner.php with your preferred settings
 171# every time a new version is released
 172# Just create the file 'myminer.php' in the same directory as
 173# 'miner.php' - and put your own settings in there
 174if (file_exists('myminer.php'))
 175 include_once('myminer.php');
 176#
 177# This is the system default that must always contain all necessary
 178# colours so it must be a constant
 179# You can override these values with $colouroverride
 180# The only one missing is in $warnfont
 181# - which you can override directly anyway
 182global $colourtable;
 183$colourtable = array(
 184	'body bgcolor'		=> '#ecffff',
 185	'td color'		=> 'blue',
 186	'td.two color'		=> 'blue',
 187	'td.two background'	=> '#ecffff',
 188	'td.h color'		=> 'blue',
 189	'td.h background'	=> '#c4ffff',
 190	'td.err color'		=> 'black',
 191	'td.err background'	=> '#ff3050',
 192	'td.warn color'		=> 'black',
 193	'td.warn background'	=> '#ffb050',
 194	'td.sta color'		=> 'green',
 195	'td.tot color'		=> 'blue',
 196	'td.tot background'	=> '#fff8f2',
 197	'td.lst color'		=> 'blue',
 198	'td.lst background'	=> '#ffffdd',
 199	'td.hi color'		=> 'blue',
 200	'td.hi background'	=> '#f6ffff',
 201	'td.lo color'		=> 'blue',
 202	'td.lo background'	=> '#deffff'
 203);
 204#
 205# Don't touch these 2
 206$miner = null;
 207$port = null;
 208#
 209# Ensure it is only ever shown once
 210global $showndate;
 211$showndate = false;
 212#
 213# For summary page to stop retrying failed rigs
 214global $rigerror;
 215$rigerror = array();
 216#
 217global $rownum;
 218$rownum = 0;
 219#
 220// Login
 221global $ses;
 222$ses = 'rutroh';
 223#
 224function getcss($cssname, $dom = false)
 225{
 226 global $colourtable, $colouroverride;
 227
 228 $css = '';
 229 foreach ($colourtable as $cssdata => $value)
 230 {
 231	$cssobj = explode(' ', $cssdata, 2);
 232	if ($cssobj[0] == $cssname)
 233	{
 234		if (isset($colouroverride[$cssdata]))
 235			$value = $colouroverride[$cssdata];
 236
 237		if ($dom == true)
 238			$css .= ' '.$cssobj[1].'='.$value;
 239		else
 240			$css .= $cssobj[1].':'.$value.'; ';
 241	}
 242 }
 243 return $css;
 244}
 245#
 246function getdom($domname)
 247{
 248 return getcss($domname, true);
 249}
 250#
 251function htmlhead($checkapi, $rig, $pg = null, $noscript = false)
 252{
 253 global $title, $miner_font_family, $miner_font_size;
 254 global $error, $readonly, $poolinputs, $here;
 255 global $ignorerefresh, $autorefresh;
 256
 257 $extraparams = '';
 258 if ($rig != null && $rig != '')
 259	$extraparams = "&rig=$rig";
 260 else
 261	if ($pg != null && $pg != '')
 262		$extraparams = "&pg=$pg";
 263
 264 if ($ignorerefresh == true || $autorefresh == 0)
 265	$refreshmeta = '';
 266 else
 267 {
 268	$url = "$here?ref=$autorefresh$extraparams";
 269	$refreshmeta = "\n<meta http-equiv='refresh' content='$autorefresh;url=$url'>";
 270 }
 271
 272 if ($readonly === false && $checkapi === true)
 273 {
 274	$error = null;
 275	$access = api($rig, 'privileged');
 276	if ($error != null
 277	||  !isset($access['STATUS']['STATUS'])
 278	||  $access['STATUS']['STATUS'] != 'S')
 279		$readonly = true;
 280 }
 281 $miner_font = "font-family:$miner_font_family; font-size:$miner_font_size;";
 282
 283 echo "<html><head>$refreshmeta
 284<title>$title</title>
 285<style type='text/css'>
 286td { $miner_font ".getcss('td')."}
 287td.two { $miner_font ".getcss('td.two')."}
 288td.h { $miner_font ".getcss('td.h')."}
 289td.err { $miner_font ".getcss('td.err')."}
 290td.warn { $miner_font ".getcss('td.warn')."}
 291td.sta { $miner_font ".getcss('td.sta')."}
 292td.tot { $miner_font ".getcss('td.tot')."}
 293td.lst { $miner_font ".getcss('td.lst')."}
 294td.hi { $miner_font ".getcss('td.hi')."}
 295td.lo { $miner_font ".getcss('td.lo')."}
 296</style>
 297</head><body".getdom('body').">\n";
 298if ($noscript === false)
 299{
 300echo "<script type='text/javascript'>
 301function pr(a,m){if(m!=null){if(!confirm(m+'?'))return}window.location='$here?ref=$autorefresh'+a}\n";
 302
 303if ($ignorerefresh == false)
 304 echo "function prr(a){if(a){v=document.getElementById('refval').value}else{v=0}window.location='$here?ref='+v+'$extraparams'}\n";
 305
 306 if ($readonly === false && $checkapi === true)
 307 {
 308echo "function prc(a,m){pr('&arg='+a,m)}
 309function 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)}
 310function 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)}\n";
 311	if ($poolinputs === true)
 312		echo "function cbs(s){var t=s.replace(/\\\\/g,'\\\\\\\\'); return t.replace(/,/g, '\\\\,')}\nfunction pla(r){var u=document.getElementById('purl').value;var w=document.getElementById('pwork').value;var p=document.getElementById('ppass').value;pr('&rig='+r+'&arg=addpool|'+cbs(u)+','+cbs(w)+','+cbs(p),'Add Pool '+u)}\nfunction psp(r){var p=document.getElementById('prio').value;pr('&rig='+r+'&arg=poolpriority|'+p,'Set Pool Priorities to '+p)}\n";
 313 }
 314echo "</script>\n";
 315}
 316?>
 317<table width=100% height=100% border=0 cellpadding=0 cellspacing=0 summary='Mine'>
 318<tr><td align=center valign=top>
 319<table border=0 cellpadding=4 cellspacing=0 summary='Mine'>
 320<?php
 321}
 322#
 323global $haderror, $error;
 324$haderror = false;
 325$error = null;
 326#
 327function getsock($rig, $addr, $port)
 328{
 329 global $rigipsecurity;
 330 global $haderror, $error, $socksndtimeoutsec, $sockrcvtimeoutsec;
 331
 332 $error = null;
 333 $socket = null;
 334 $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
 335 if ($socket === false || $socket === null)
 336 {
 337	$haderror = true;
 338	if ($rigipsecurity === false)
 339	{
 340		$error = socket_strerror(socket_last_error());
 341		$msg = "socket create(TCP) failed";
 342		$error = "ERR: $msg '$error'\n";
 343	}
 344	else
 345		$error = "ERR: socket create(TCP) failed\n";
 346
 347	return null;
 348 }
 349
 350 // Ignore if this fails since the socket connect may work anyway
 351 //  and nothing is gained by aborting if the option cannot be set
 352 //  since we don't know in advance if it can connect
 353 socket_set_option($socket, SOL_SOCKET, SO_SNDTIMEO, array('sec' => $socksndtimeoutsec, 'usec' => 0));
 354 socket_set_option($socket, SOL_SOCKET, SO_RCVTIMEO, array('sec' => $sockrcvtimeoutsec, 'usec' => 0));
 355
 356 $res = socket_connect($socket, $addr, $port);
 357 if ($res === false)
 358 {
 359	$haderror = true;
 360	if ($rigipsecurity === false)
 361	{
 362		$error = socket_strerror(socket_last_error());
 363		$msg = "socket connect($addr,$port) failed";
 364		$error = "ERR: $msg '$error'\n";
 365	}
 366	else
 367		$error = "ERR: socket connect($rig) failed\n";
 368
 369	socket_close($socket);
 370	return null;
 371 }
 372 return $socket;
 373}
 374#
 375function readsockline($socket)
 376{
 377 $line = '';
 378 while (true)
 379 {
 380	$byte = socket_read($socket, 1);
 381	if ($byte === false || $byte === '')
 382		break;
 383	if ($byte === "\0")
 384		break;
 385	$line .= $byte;
 386 }
 387 return $line;
 388}
 389#
 390function api_convert_escape($str)
 391{
 392 $res = '';
 393 $len = strlen($str);
 394 for ($i = 0; $i < $len; $i++)
 395 {
 396	$ch = substr($str, $i, 1);
 397	if ($ch != '\\' || $i == ($len-1))
 398		$res .= $ch;
 399	else
 400	{
 401		$i++;
 402		$ch = substr($str, $i, 1);
 403		switch ($ch)
 404		{
 405		case '|':
 406			$res .= "\1";
 407			break;
 408		case '\\':
 409			$res .= "\2";
 410			break;
 411		case '=':
 412			$res .= "\3";
 413			break;
 414		case ',':
 415			$res .= "\4";
 416			break;
 417		default:
 418			$res .= $ch;
 419		}
 420	}
 421 }
 422 return $res;
 423}
 424#
 425function revert($str)
 426{
 427 return str_replace(array("\1", "\2", "\3", "\4"), array("|", "\\", "=", ","), $str);
 428}
 429#
 430function api($rig, $cmd)
 431{
 432 global $haderror, $error;
 433 global $miner, $port, $hidefields;
 434
 435 $socket = getsock($rig, $miner, $port);
 436 if ($socket != null)
 437 {
 438	socket_write($socket, $cmd, strlen($cmd));
 439	$line = readsockline($socket);
 440	socket_close($socket);
 441
 442	if (strlen($line) == 0)
 443	{
 444		$haderror = true;
 445		$error = "WARN: '$cmd' returned nothing\n";
 446		return $line;
 447	}
 448
 449#	print "$cmd returned '$line'\n";
 450
 451	$line = api_convert_escape($line);
 452
 453	$data = array();
 454
 455	$objs = explode('|', $line);
 456	foreach ($objs as $obj)
 457	{
 458		if (strlen($obj) > 0)
 459		{
 460			$items = explode(',', $obj);
 461			$item = $items[0];
 462			$id = explode('=', $items[0], 2);
 463			if (count($id) == 1 or !ctype_digit($id[1]))
 464				$name = $id[0];
 465			else
 466				$name = $id[0].$id[1];
 467
 468			if (strlen($name) == 0)
 469				$name = 'null';
 470
 471			$sectionname = preg_replace('/\d/', '', $name);
 472
 473			if (isset($data[$name]))
 474			{
 475				$num = 1;
 476				while (isset($data[$name.$num]))
 477					$num++;
 478				$name .= $num;
 479			}
 480
 481			$counter = 0;
 482			foreach ($items as $item)
 483			{
 484				$id = explode('=', $item, 2);
 485
 486				if (isset($hidefields[$sectionname.'.'.$id[0]]))
 487					continue;
 488
 489				if (count($id) == 2)
 490					$data[$name][$id[0]] = revert($id[1]);
 491				else
 492					$data[$name][$counter] = $id[0];
 493
 494				$counter++;
 495			}
 496		}
 497	}
 498	return $data;
 499 }
 500 return null;
 501}
 502#
 503function getparam($name, $both = false)
 504{
 505 $a = null;
 506 if (isset($_POST[$name]))
 507	$a = $_POST[$name];
 508
 509 if (($both === true) and ($a === null))
 510 {
 511	if (isset($_GET[$name]))
 512		$a = $_GET[$name];
 513 }
 514
 515 if ($a == '' || $a == null)
 516	return null;
 517
 518 // limit to 1K just to be safe
 519 return substr($a, 0, 1024);
 520}
 521#
 522function newtable()
 523{
 524 global $tablebegin, $rownum;
 525 echo $tablebegin;
 526 $rownum = 0;
 527}
 528#
 529function newrow()
 530{
 531 echo '<tr>';
 532}
 533#
 534function otherrow($row)
 535{
 536 echo "<tr>$row</tr>";
 537}
 538#
 539function endrow()
 540{
 541 global $rownum;
 542 echo '</tr>';
 543 $rownum++;
 544}
 545#
 546function endtable()
 547{
 548 global $tableend;
 549 echo $tableend;
 550}
 551#
 552function classlastshare($when, $alldata, $warnclass, $errorclass)
 553{
 554 global $checklastshare;
 555
 556 if ($checklastshare === false)
 557	return '';
 558
 559 if ($when == 0)
 560	return '';
 561
 562 if (!isset($alldata['MHS av']))
 563	return '';
 564
 565 if ($alldata['MHS av'] == 0)
 566	return '';
 567
 568 if (!isset($alldata['Last Share Time']))
 569	return '';
 570
 571 if (!isset($alldata['Last Share Difficulty']))
 572	return '';
 573
 574 $expected = pow(2, 32) / ($alldata['MHS av'] * pow(10, 6));
 575
 576 // If the share difficulty changes while waiting on a share,
 577 // this calculation will of course be incorrect
 578 $expected *= $alldata['Last Share Difficulty'];
 579
 580 $howlong = $when - $alldata['Last Share Time'];
 581 if ($howlong < 1)
 582	$howlong = 1;
 583
 584 if ($howlong > ($expected * 12))
 585	return $errorclass;
 586
 587 if ($howlong > ($expected * 8))
 588	return $warnclass;
 589
 590 return '';
 591}
 592#
 593function endzero($num)
 594{
 595 $rep = preg_replace('/0*$/', '', $num);
 596 if ($rep === '')
 597	$rep = '0';
 598 return $rep;
 599}
 600#
 601function fmt($section, $name, $value, $when, $alldata)
 602{
 603 global $dfmt, $rownum;
 604
 605 if ($alldata == null)
 606	$alldata = array();
 607
 608 $errorclass = ' class=err';
 609 $warnclass = ' class=warn';
 610 $lstclass = ' class=lst';
 611 $hiclass = ' class=hi';
 612 $loclass = ' class=lo';
 613 $c2class = ' class=two';
 614 $totclass = ' class=tot';
 615 $b = '&nbsp;';
 616
 617 $ret = $value;
 618 $class = '';
 619
 620 $nams = explode('.', $name);
 621 if (count($nams) > 1)
 622	$name = $nams[count($nams)-1];
 623
 624 if ($value === null)
 625	$ret = $b;
 626 else
 627	switch ($section.'.'.$name)
 628	{
 629	case 'GPU.Last Share Time':
 630	case 'PGA.Last Share Time':
 631	case 'ASC.Last Share Time':
 632	case 'DEVS.Last Share Time':
 633		if ($value == 0
 634		||  (isset($alldata['Last Share Pool']) && $alldata['Last Share Pool'] == -1))
 635		{
 636			$ret = 'Never';
 637			$class = $warnclass;
 638		}
 639		else
 640		{
 641			$ret = date('H:i:s', $value);
 642			$class = classlastshare($when, $alldata, $warnclass, $errorclass);
 643		}
 644		break;
 645	case 'GPU.Last Valid Work':
 646	case 'PGA.Last Valid Work':
 647	case 'ASC.Last Valid Work':
 648	case 'DEVS.Last Valid Work':
 649		if ($value == 0)
 650			$ret = 'Never';
 651		else
 652			$ret = ($value - $when) . 's';
 653		break;
 654	case 'POOL.Last Share Time':
 655		if ($value == 0)
 656			$ret = 'Never';
 657		else
 658			$ret = date('H:i:s d-M', $value);
 659		break;
 660	case 'GPU.Last Share Pool':
 661	case 'PGA.Last Share Pool':
 662	case 'ASC.Last Share Pool':
 663	case 'DEVS.Last Share Pool':
 664		if ($value == -1)
 665		{
 666			$ret = 'None';
 667			$class = $warnclass;
 668		}
 669		break;
 670	case 'SUMMARY.Elapsed':
 671	case 'STATS.Elapsed':
 672		$s = $value % 60;
 673		$value -= $s;
 674		$value /= 60;
 675		if ($value == 0)
 676			$ret = $s.'s';
 677		else
 678		{
 679			$m = $value % 60;
 680			$value -= $m;
 681			$value /= 60;
 682			if ($value == 0)
 683				$ret = sprintf("%dm$b%02ds", $m, $s);
 684			else
 685			{
 686				$h = $value % 24;
 687				$value -= $h;
 688				$value /= 24;
 689				if ($value == 0)
 690					$ret = sprintf("%dh$b%02dm$b%02ds", $h, $m, $s);
 691				else
 692				{
 693					if ($value == 1)
 694						$days = '';
 695					else
 696						$days = 's';
 697	
 698					$ret = sprintf("%dday$days$b%02dh$b%02dm$b%02ds", $value, $h, $m, $s);
 699				}
 700			}
 701		}
 702		break;
 703	case 'NOTIFY.Last Well':
 704		if ($value == '0')
 705		{
 706			$ret = 'Never';
 707			$class = $warnclass;
 708		}
 709		else
 710			$ret = date('H:i:s', $value);
 711		break;
 712	case 'NOTIFY.Last Not Well':
 713		if ($value == '0')
 714			$ret = 'Never';
 715		else
 716		{
 717			$ret = date('H:i:s', $value);
 718			$class = $errorclass;
 719		}
 720		break;
 721	case 'NOTIFY.Reason Not Well':
 722		if ($value != 'None')
 723			$class = $errorclass;
 724		break;
 725	case 'GPU.Utility':
 726	case 'PGA.Utility':
 727	case 'ASC.Utility':
 728	case 'DEVS.Utility':
 729	case 'SUMMARY.Utility':
 730	case 'total.Utility':
 731		$ret = $value.'/m';
 732		if ($value == 0)
 733			$class = $errorclass;
 734		else
 735			if (isset($alldata['Difficulty Accepted'])
 736			&&  isset($alldata['Accepted'])
 737			&&  isset($alldata['MHS av'])
 738			&&  ($alldata['Difficulty Accepted'] > 0)
 739			&&  ($alldata['Accepted'] > 0))
 740			{
 741				$expected = 60 * $alldata['MHS av'] * (pow(10, 6) / pow(2, 32));
 742				if ($expected == 0)
 743					$expected = 0.000001; // 1 H/s
 744
 745				$da = $alldata['Difficulty Accepted'];
 746				$a = $alldata['Accepted'];
 747				$expected /= ($da / $a);
 748
 749				$ratio = $value / $expected;
 750				if ($ratio < 0.9)
 751					$class = $loclass;
 752				else
 753					if ($ratio > 1.1)
 754						$class = $hiclass;
 755			}
 756		break;
 757	case 'SUMMARY.Work Utility':
 758	case 'total.Work Utility':
 759		$ret = $value.'/m';
 760		break;
 761	case 'GPU.Temperature':
 762	case 'PGA.Temperature':
 763	case 'ASC.Temperature':
 764	case 'DEVS.Temperature':
 765		$ret = $value.'&deg;C';
 766		if (!isset($alldata['GPU']))
 767			break;
 768	case 'GPU.GPU Clock':
 769	case 'DEVS.GPU Clock':
 770	case 'GPU.Memory Clock':
 771	case 'DEVS.Memory Clock':
 772	case 'GPU.GPU Voltage':
 773	case 'DEVS.GPU Voltage':
 774	case 'GPU.GPU Activity':
 775	case 'DEVS.GPU Activity':
 776		if ($value == 0)
 777			$class = $warnclass;
 778		break;
 779	case 'GPU.Fan Percent':
 780	case 'DEVS.Fan Percent':
 781		if ($value == 0)
 782			$class = $warnclass;
 783		else
 784		{
 785			if ($value == 100)
 786				$class = $errorclass;
 787			else
 788				if ($value > 85)
 789					$class = $warnclass;
 790		}
 791		break;
 792	case 'GPU.Fan Speed':
 793	case 'DEVS.Fan Speed':
 794		if ($value == 0)
 795			$class = $warnclass;
 796		else
 797			if (isset($alldata['Fan Percent']))
 798			{
 799				$test = $alldata['Fan Percent'];
 800				if ($test == 100)
 801					$class = $errorclass;
 802				else
 803					if ($test > 85)
 804						$class = $warnclass;
 805			}
 806		break;
 807	case 'GPU.MHS av':
 808	case 'PGA.MHS av':
 809	case 'ASC.MHS av':
 810	case 'DEVS.MHS av':
 811	case 'SUMMARY.MHS av':
 812	case 'total.MHS av':
 813		$parts = explode('.', $value, 2);
 814		if (count($parts) == 1)
 815			$dec = '';
 816		else
 817			$dec = '.'.$parts[1];
 818		$ret = number_format((float)$parts[0]).$dec;
 819
 820		if ($value == 0)
 821			$class = $errorclass;
 822		else
 823			if (isset($alldata['Difficulty Accepted'])
 824			&&  isset($alldata['Accepted'])
 825			&&  isset($alldata['Utility'])
 826			&&  ($alldata['Difficulty Accepted'] > 0)
 827			&&  ($alldata['Accepted'] > 0))
 828			{
 829				$expected = 60 * $value * (pow(10, 6) / pow(2, 32));
 830				if ($expected == 0)
 831					$expected = 0.000001; // 1 H/s
 832
 833				$da = $alldata['Difficulty Accepted'];
 834				$a = $alldata['Accepted'];
 835				$expected /= ($da / $a);
 836
 837				$ratio = $alldata['Utility'] / $expected;
 838				if ($ratio < 0.9)
 839					$class = $hiclass;
 840				else
 841					if ($ratio > 1.1)
 842						$class = $loclass;
 843			}
 844		break;
 845	case 'GPU.Total MH':
 846	case 'PGA.Total MH':
 847	case 'ASC.Total MH':
 848	case 'DEVS.Total MH':
 849	case 'SUMMARY.Total MH':
 850	case 'total.Total MH':
 851	case 'SUMMARY.Getworks':
 852	case 'POOL.Getworks':
 853	case 'total.Getworks':
 854	case 'GPU.Accepted':
 855	case 'PGA.Accepted':
 856	case 'ASC.Accepted':
 857	case 'DEVS.Accepted':
 858	case 'SUMMARY.Accepted':
 859	case 'POOL.Accepted':
 860	case 'total.Accepted':
 861	case 'GPU.Rejected':
 862	case 'PGA.Rejected':
 863	case 'ASC.Rejected':
 864	case 'DEVS.Rejected':
 865	case 'SUMMARY.Rejected':
 866	case 'POOL.Rejected':
 867	case 'total.Rejected':
 868	case 'SUMMARY.Local Work':
 869	case 'total.Local Work':
 870	case 'SUMMARY.Discarded':
 871	case 'POOL.Discarded':
 872	case 'total.Discarded':
 873	case 'POOL.Diff1 Shares':
 874	case 'total.Diff1 Shares':
 875	case 'GPU.Diff1 Work':
 876	case 'PGA.Diff1 Work':
 877	case 'ASC.Diff1 Work':
 878	case 'total.Diff1 Work':
 879	case 'STATS.Times Sent':
 880	case 'STATS.Bytes Sent':
 881	case 'STATS.Net Bytes Sent':
 882	case 'STATS.Times Recv':
 883	case 'STATS.Bytes Recv':
 884	case 'STATS.Net Bytes Recv':
 885	case 'total.Times Sent':
 886	case 'total.Bytes Sent':
 887	case 'total.Net Bytes Sent':
 888	case 'total.Times Recv':
 889	case 'total.Bytes Recv':
 890	case 'total.Net Bytes Recv':
 891		$parts = explode('.', $value, 2);
 892		if (count($parts) == 1)
 893			$dec = '';
 894		else
 895			$dec = '.'.$parts[1];
 896		$ret = number_format((float)$parts[0]).$dec;
 897		break;
 898	case 'STATS.Hs':
 899	case 'STATS.W':
 900	case 'STATS.history_time':
 901	case 'STATS.Pool Wait':
 902	case 'STATS.Pool Max':
 903	case 'STATS.Pool Min':
 904	case 'STATS.Pool Av':
 905	case 'STATS.Min Diff':
 906	case 'STATS.Max Diff':
 907	case 'STATS.Work Diff':
 908		$parts = explode('.', $value, 2);
 909		if (count($parts) == 1)
 910			$dec = '';
 911		else
 912			$dec = '.'.endzero($parts[1]);
 913		$ret = number_format((float)$parts[0]).$dec;
 914		break;
 915	case 'GPU.Status':
 916	case 'PGA.Status':
 917	case 'ASC.Status':
 918	case 'DEVS.Status':
 919	case 'POOL.Status':
 920		if ($value != 'Alive')
 921			$class = $errorclass;
 922		break;
 923	case 'GPU.Enabled':
 924	case 'PGA.Enabled':
 925	case 'ASC.Enabled':
 926	case 'ASC.Enabled':
 927	case 'DEVS.Enabled':
 928		if ($value != 'Y')
 929			$class = $warnclass;
 930		break;
 931	case 'STATUS.When':
 932	case 'COIN.Current Block Time':
 933		$ret = date($dfmt, $value);
 934		break;
 935	case 'BUTTON.Rig':
 936	case 'BUTTON.Pool':
 937	case 'BUTTON.GPU':
 938		$ret = $value;
 939		break;
 940	case 'SUMMARY.Difficulty Accepted':
 941	case 'GPU.Difficulty Accepted':
 942	case 'PGA.Difficulty Accepted':
 943	case 'ASC.Difficulty Accepted':
 944	case 'DEVS.Difficulty Accepted':
 945	case 'POOL.Difficulty Accepted':
 946	case 'total.Difficulty Accepted':
 947	case 'SUMMARY.Difficulty Rejected':
 948	case 'GPU.Difficulty Rejected':
 949	case 'PGA.Difficulty Rejected':
 950	case 'ASC.Difficulty Rejected':
 951	case 'DEVS.Difficulty Rejected':
 952	case 'POOL.Difficulty Rejected':
 953	case 'total.Difficulty Rejected':
 954	case 'SUMMARY.Difficulty Stale':
 955	case 'POOL.Difficulty Stale':
 956	case 'total.Difficulty Stale':
 957	case 'GPU.Last Share Difficulty':
 958	case 'PGA.Last Share Difficulty':
 959	case 'ASC.Last Share Difficulty':
 960	case 'DEVS.Last Share Difficulty':
 961	case 'POOL.Last Share Difficulty':
 962		if ($value != '')
 963			$ret = number_format((float)$value, 2);
 964		break;
 965	}
 966
 967 if ($section == 'NOTIFY' && substr($name, 0, 1) == '*' && $value != '0')
 968	$class = $errorclass;
 969
 970 if ($class == '' && $section != 'POOL')
 971	$class = classlastshare($when, $alldata, $lstclass, $lstclass);
 972
 973 if ($class == '' && $section == 'total')
 974	$class = $totclass;
 975
 976 if ($class == '' && ($rownum % 2) == 0)
 977	$class = $c2class;
 978
 979 if ($ret === '')
 980	$ret = $b;
 981
 982 return array($ret, $class);
 983}
 984#
 985global $poolcmd;
 986$poolcmd = array(	'Switch to'	=> 'switchpool',
 987			'Enable'	=> 'enablepool',
 988			'Disable'	=> 'disablepool',
 989			'Remove'	=> 'removepool' );
 990#
 991function showhead($cmd, $values, $justnames = false)
 992{
 993 global $poolcmd, $readonly;
 994
 995 newrow();
 996
 997 foreach ($values as $name => $value)
 998 {
 999	if ($name == '0' or $name == '')
1000		$name = '&nbsp;';
1001	echo "<td valign=bottom class=h>$name</td>";
1002 }
1003
1004 if ($justnames === false && $cmd == 'pools' && $readonly === false)
1005	foreach ($poolcmd as $name => $pcmd)
1006		echo "<td valign=bottom class=h>$name</td>";
1007
1008 endrow();
1009}
1010#
1011function showdatetime()
1012{
1013 global $dfmt;
1014
1015 otherrow('<td class=sta>Date: '.date($dfmt).'</td>');
1016}
1017#
1018global $singlerigsum;
1019$singlerigsum = array(
1020 'devs' => array('MHS av' => 1, 'MHS 5s' => 1, 'Accepted' => 1, 'Rejected' => 1,
1021			'Hardware Errors' => 1, 'Utility' => 1, 'Total MH' => 1,
1022			'Diff1 Shares' => 1, 'Diff1 Work' => 1, 'Difficulty Accepted' => 1,
1023			'Difficulty Rejected' => 1),
1024 'pools' => array('Getworks' => 1, 'Accepted' => 1, 'Rejected' => 1, 'Discarded' => 1,
1025			'Stale' => 1, 'Get Failures' => 1, 'Remote Failures' => 1,
1026			'Diff1 Shares' => 1, 'Diff1 Work' => 1, 'Difficulty Accepted' => 1,
1027			'Difficulty Rejected' => 1, 'Difficulty Stale' => 1),
1028 'notify' => array('*' => 1));
1029#
1030function showtotal($total, $when, $oldvalues)
1031{
1032 global $rigtotals;
1033
1034 list($showvalue, $class) = fmt('total', '', 'Total:', $when, null);
1035 echo "<td$class align=right>$showvalue</td>";
1036
1037 $skipfirst = true;
1038 foreach ($oldvalues as $name => $value)
1039 {
1040	if ($skipfirst === true)
1041	{
1042		$skipfirst = false;
1043		continue;
1044	}
1045
1046	if (isset($total[$name]))
1047		$newvalue = $total[$name];
1048	else
1049		$newvalue = '';
1050
1051	list($showvalue, $class) = fmt('total', $name, $newvalue, $when, null);
1052	echo "<td$class";
1053	if ($rigtotals === true)
1054		echo ' align=right';
1055	echo ">$showvalue</td>";
1056 }
1057}
1058#
1059function details($cmd, $list, $rig)
1060{
1061 global $dfmt, $poolcmd, $readonly, $showndate;
1062 global $rownum, $rigtotals, $forcerigtotals, $singlerigsum;
1063
1064 $when = 0;
1065
1066 $stas = array('S' => 'Success', 'W' => 'Warning', 'I' => 'Informational', 'E' => 'Error', 'F' => 'Fatal');
1067
1068 newtable();
1069
1070 if ($showndate === false)
1071 {
1072	showdatetime();
1073
1074	endtable();
1075	newtable();
1076
1077	$showndate = true;
1078 }
1079
1080 if (isset($list['STATUS']))
1081 {
1082	newrow();
1083	echo '<td>Computer: '.$list['STATUS']['Description'].'</td>';
1084	if (isset($list['STATUS']['When']))
1085	{
1086		echo '<td>When: '.date($dfmt, $list['STATUS']['When']).'</td>';
1087		$when = $list['STATUS']['When'];
1088	}
1089	$sta = $list['STATUS']['STATUS'];
1090	echo '<td>Status: '.$stas[$sta].'</td>';
1091	echo '<td>Message: '.$list['STATUS']['Msg'].'</td>';
1092	endrow();
1093 }
1094
1095 if ($rigtotals === true && isset($singlerigsum[$cmd]))
1096	$dototal = $singlerigsum[$cmd];
1097 else
1098	$dototal = array();
1099
1100 $total = array();
1101
1102 $section = '';
1103 $oldvalues = null;
1104 foreach ($list as $item => $values)
1105 {
1106	if ($item == 'STATUS')
1107		continue;
1108
1109	$sectionname = preg_replace('/\d/', '', $item);
1110
1111	// Handle 'devs' possibly containing >1 table
1112	if ($sectionname != $section)
1113	{
1114		if ($oldvalues != null && count($total) > 0
1115		&&  ($rownum > 2 || $forcerigtotals === true))
1116			showtotal($total, $when, $oldvalues);
1117
1118		endtable();
1119		newtable();
1120		showhead($cmd, $values);
1121		$section = $sectionname;
1122	}
1123
1124	newrow();
1125
1126	foreach ($values as $name => $value)
1127	{
1128		list($showvalue, $class) = fmt($section, $name, $value, $when, $values);
1129		echo "<td$class";
1130		if ($rigtotals === true)
1131			echo ' align=right';
1132		echo ">$showvalue</td>";
1133
1134		if (isset($dototal[$name])
1135		||  (isset($dototal['*']) and substr($name, 0, 1) == '*'))
1136		{
1137			if (isset($total[$name]))
1138				$total[$name] += $value;
1139			else
1140				$total[$name] = $value;
1141		}
1142	}
1143
1144	if ($cmd == 'pools' && $readonly === false)
1145	{
1146		reset($values);
1147		$pool = current($values);
1148		foreach ($poolcmd as $name => $pcmd)
1149		{
1150			list($ignore, $class) = fmt('BUTTON', 'Pool', '', $when, $values);
1151			echo "<td$class>";
1152			if ($pool === false)
1153				echo '&nbsp;';
1154			else
1155			{
1156				echo "<input type=button value='Pool $pool'";
1157				echo " onclick='prc(\"$pcmd|$pool&rig=$rig\",\"$name Pool $pool\")'>";
1158			}
1159			echo '</td>';
1160		}
1161	}
1162	endrow();
1163
1164	$oldvalues = $values;
1165 }
1166
1167 if ($oldvalues != null && count($total) > 0
1168 &&  ($rownum > 2 || $forcerigtotals === true))
1169	showtotal($total, $when, $oldvalues);
1170
1171 endtable();
1172}
1173#
1174global $devs;
1175$devs = null;
1176#
1177function gpubuttons($count, $rig)
1178{
1179 global $devs;
1180
1181 $basic = array( 'GPU', 'Enable', 'Disable', 'Restart' );
1182
1183 $options = array(	'intensity' => 'Intensity',
1184			'fan' => 'Fan Percent',
1185			'engine' => 'GPU Clock',
1186			'mem' => 'Memory Clock',
1187			'vddc' => 'GPU Voltage' );
1188
1189 newtable();
1190 newrow();
1191
1192 foreach ($basic as $head)
1193	echo "<td class=h>$head</td>";
1194
1195 foreach ($options as $name => $des)
1196	echo "<td class=h nowrap>$des</td>";
1197
1198 $n = 0;
1199 for ($c = 0; $c < $count; $c++)
1200 {
1201	endrow();
1202	newrow();
1203
1204	foreach ($basic as $name)
1205	{
1206		list($ignore, $class) = fmt('BUTTON', 'GPU', '', 0, null);
1207		echo "<td$class>";
1208
1209		if ($name == 'GPU')
1210			echo $c;
1211		else
1212		{
1213			echo "<input type=button value='$name $c' onclick='prs(\"gpu";
1214			echo strtolower($name);
1215			echo "|$c\",$rig)'>";
1216		}
1217
1218		echo '</td>';
1219	}
1220
1221	foreach ($options as $name => $des)
1222	{
1223		list($ignore, $class) = fmt('BUTTON', 'GPU', '', 0, null);
1224		echo "<td$class>";
1225
1226		if (!isset($devs["GPU$c"][$des]))
1227			echo '&nbsp;';
1228		else
1229		{
1230			$value = $devs["GPU$c"][$des];
1231			echo "<input type=button value='Set $c:' onclick='prs2(\"gpu$name|$c\",$n,$rig)'>";
1232			echo "<input size=7 type=text name=gi$n value='$value' id=gi$n>";
1233			$n++;
1234		}
1235
1236		echo '</td>';
1237	}
1238
1239 }
1240 endrow();
1241 endtable();
1242}
1243#
1244function processgpus($rig)
1245{
1246 global $error;
1247 global $warnfont, $warnoff;
1248
1249 $gpus = api($rig, 'gpucount');
1250
1251 if ($error != null)
1252	otherrow("<td>Error getting GPU count: $warnfont$error$warnoff</td>");
1253 else
1254 {
1255	if (!isset($gpus['GPUS']['Count']))
1256	{
1257		$rw = '<td>No GPU count returned: '.$warnfont;
1258		$rw .= $gpus['STATUS']['STATUS'].' '.$gpus['STATUS']['Msg'];
1259		$rw .= $warnoff.'</td>';
1260		otherrow($rw);
1261	}
1262	else
1263	{
1264		$count = $gpus['GPUS']['Count'];
1265		if ($count == 0)
1266			otherrow('<td>No GPUs</td>');
1267		else
1268			gpubuttons($count, $rig);
1269	}
1270 }
1271}
1272#
1273function showpoolinputs($rig, $ans)
1274{
1275 global $readonly, $poolinputs;
1276
1277 if ($readonly === true || $poolinputs === false)
1278	return;
1279
1280 newtable();
1281 newrow();
1282
1283 $inps = array('Pool URL' => array('purl', 20),
1284		'Worker Name' => array('pwork', 10),
1285		'Worker Password' => array('ppass', 10));
1286 $b = '&nbsp;';
1287
1288 echo "<td align=right class=h> Add a pool: </td><td>";
1289
1290 foreach ($inps as $text => $name)
1291	echo "$text: <input name='".$name[0]."' id='".$name[0]."' value='' type=text size=".$name[1]."> ";
1292
1293 echo "</td><td align=middle><input type=button value='Add' onclick='pla($rig)'></td>";
1294
1295 endrow();
1296
1297 if (count($ans) > 1)
1298 {
1299	newrow();
1300
1301	echo '<td align=right class=h> Set pool priorities: </td>';
1302	echo "<td> Comma list of pool numbers: <input type=text name=prio id=prio size=20>";
1303	echo "</td><td align=middle><input type=button value='Set' onclick='psp($rig)'></td>";
1304
1305	endrow();
1306 }
1307 endtable();
1308}
1309#
1310function process($cmds, $rig)
1311{
1312 global $error, $devs;
1313 global $warnfont, $warnoff;
1314
1315 $count = count($cmds);
1316 foreach ($cmds as $cmd => $des)
1317 {
1318	$process = api($rig, $cmd);
1319
1320	if ($error != null)
1321	{
1322		otherrow("<td colspan=100>Error getting $des: $warnfont$error$warnoff</td>");
1323		break;
1324	}
1325	else
1326	{
1327		details($cmd, $process, $rig);
1328
1329		if ($cmd == 'devs')
1330			$devs = $process;
1331
1332		if ($cmd == 'pools')
1333			showpoolinputs($rig, $process);
1334
1335		# Not after the last one
1336		if (--$count > 0)
1337			otherrow('<td><br><br></td>');
1338	}
1339 }
1340}
1341#
1342function rigname($rig, $rigname)
1343{
1344 global $rigs;
1345
1346 if (isset($rigs[$rig]))
1347 {
1348	$parts = explode(':', $rigs[$rig], 3);
1349	if (count($parts) == 3)
1350		$rigname = $parts[2];
1351 }
1352
1353 return $rigname;
1354}
1355#
1356function riginput($rig, $rigname)
1357{
1358 $rigname = rigname($rig, $rigname);
1359
1360 return "<input type=button value='$rigname' onclick='pr(\"&rig=$rig\",null)'>";
1361}
1362#
1363function rigbutton($rig, $rigname, $when, $row)
1364{
1365 list($value, $class) = fmt('BUTTON', 'Rig', '', $when, $row);
1366
1367 if ($rig === '')
1368	$ri = '&nbsp;';
1369 else
1370	$ri = riginput($rig, $rigname);
1371
1372 return "<td align=middle$class>$ri</td>";
1373}
1374#
1375function showrigs($anss, $headname, $rigname)
1376{
1377 $dthead = array($headname => 1, 'STATUS' => 1, 'Description' => 1, 'When' => 1, 'API' => 1, 'CGMiner' => 1);
1378 showhead('', $dthead);
1379
1380 foreach ($anss as $rig => $ans)
1381 {
1382	if ($ans == null)
1383		continue;
1384
1385	newrow();
1386
1387	$when = 0;
1388	if (isset($ans['STATUS']['When']))
1389		$when = $ans['STATUS']['When'];
1390
1391	foreach ($ans as $item => $row)
1392	{
1393		if ($item != 'STATUS' && $item != 'VERSION')
1394			continue;
1395
1396		foreach ($dthead as $name => $x)
1397		{
1398			if ($item == 'STATUS' && $name == $headname)
1399				echo rigbutton($rig, $rigname.$rig, $when, null);
1400			else
1401			{
1402				if (isset($row[$name]))
1403				{
1404					list($showvalue, $class) = fmt('STATUS', $name, $row[$name], $when, null);
1405					echo "<td$class align=right>$showvalue</td>";
1406				}
1407			}
1408		}
1409	}
1410	endrow();
1411 }
1412}
1413#
1414# $head is a hack but this is just a demo anyway :)
1415function doforeach($cmd, $des, $sum, $head, $datetime)
1416{
1417 global $miner, $port;
1418 global $error, $readonly, $notify, $rigs;
1419 global $warnfont, $warnoff, $dfmt;
1420 global $rigerror;
1421
1422 $when = 0;
1423
1424 $header = $head;
1425 $anss = array();
1426
1427 $count = 0;
1428 $preverr = count($rigerror);
1429 foreach ($rigs as $num => $rig)
1430 {
1431	$anss[$num] = null;
1432
1433	if (isset($rigerror[$rig]))
1434		continue;
1435
1436	$parts = explode(':', $rig, 3);
1437	if (count($parts) >= 2)
1438	{
1439		$miner = $parts[0];
1440		$port = $parts[1];
1441
1442		if (count($parts) > 2)
1443			$name = $parts[2];
1444		else
1445			$name = $num;
1446
1447		$ans = api($name, $cmd);
1448
1449		if ($error != null)
1450		{
1451			$rw = "<td colspan=100>Error on rig $name getting ";
1452			$rw .= "$des: $warnfont$error$warnoff</td>";
1453			otherrow($rw);
1454			$rigerror[$rig] = $error;
1455			$error = null;
1456		}
1457		else
1458		{
1459			$anss[$num] = $ans;
1460			$count++;
1461		}
1462	}
1463 }
1464
1465 if ($count == 0)
1466 {
1467	$rw = '<td>Failed to access any rigs successfully';
1468	if ($preverr > 0)
1469		$rw .= ' (or rigs had previous errors)';
1470	$rw .= '</td>';
1471	otherrow($rw);
1472	return;
1473 }
1474
1475 if ($datetime)
1476 {
1477	showdatetime();
1478	endtable();
1479	newtable();
1480	showrigs($anss, '', 'Rig ');
1481	endtable();
1482	otherrow('<td><br><br></td>');
1483	newtable();
1484
1485	return;
1486 }
1487
1488 $total = array();
1489
1490 foreach ($anss as $rig => $ans)
1491 {
1492	if ($ans == null)
1493		continue;
1494
1495	foreach ($ans as $item => $row)
1496	{
1497		if ($item == 'STATUS')
1498			continue;
1499
1500		if (count($row) > count($header))
1501		{
1502			$header = $head;
1503			foreach ($row as $name => $value)
1504				if (!isset($header[$name]))
1505					$header[$name] = '';
1506		}
1507
1508		if ($sum != null)
1509			foreach ($sum as $name)
1510			{
1511				if (isset($row[$name]))
1512				{
1513					if (isset($total[$name]))
1514						$total[$name] += $row[$name];
1515					else
1516						$total[$name] = $row[$name];
1517				}
1518			}
1519	}
1520 }
1521
1522 if ($sum != null)
1523	$anss['total']['total'] = $total;
1524
1525 showhead('', $header);
1526
1527 foreach ($anss as $rig => $ans)
1528 {
1529	if ($ans == null)
1530		continue;
1531
1532	$when = 0;
1533	if (isset($ans['STATUS']['When']))
1534		$when = $ans['STATUS']['When'];
1535
1536	foreach ($ans as $item => $row)
1537	{
1538		if ($item == 'STATUS')
1539			continue;
1540
1541		newrow();
1542
1543		$section = preg_replace('/\d/', '', $item);
1544
1545		foreach ($header as $name => $x)
1546		{
1547			if ($name == '')
1548			{
1549				if ($rig === 'total')
1550				{
1551					list($ignore, $class) = fmt($rig, '', '', $when, $row);
1552					echo "<td align=right$class>Total:</td>";
1553				}
1554				else
1555					echo rigbutton($rig, "Rig $rig", $when, $row);
1556			}
1557			else
1558			{
1559				if (isset($row[$name]))
1560					$value = $row[$name];
1561				else
1562					$value = null;
1563
1564				list($showvalue, $class) = fmt($section, $name, $value, $when, $row);
1565				echo "<td$class align=right>$showvalue</td>";
1566			}
1567		}
1568		endrow();
1569	}
1570 }
1571}
1572#
1573function refreshbuttons()
1574{
1575 global $ignorerefresh, $changerefresh, $autorefresh;
1576
1577 if ($ignorerefresh == false && $changerefresh == true)
1578 {
1579	echo '&nbsp;&nbsp;&nbsp;&nbsp;';
1580	echo "<input type=button value='Auto Refresh:' onclick='prr(true)'>";
1581	echo "<input type=text name='refval' id='refval' size=2 value='$autorefresh'>";
1582	echo "<input type=button value='Off' onclick='prr(false)'>";
1583 }
1584}
1585#
1586function pagebuttons($rig, $pg)
1587{
1588 global $readonly, $rigs, $userlist, $ses;
1589 global $allowcustompages, $customsummarypages;
1590
1591 if ($rig === null)
1592 {
1593	$prev = null;
1594	$next = null;
1595
1596	if ($pg === null)
1597		$refresh = '';
1598	else
1599		$refresh = "&pg=$pg";
1600 }
1601 else
1602 {
1603	switch (count($rigs))
1604	{
1605	case 0:
1606	case 1:
1607		$prev = null;
1608		$next = null;
1609		break;
1610	case 2:
1611		$prev = null;
1612		$next = ($rig + 1) % count($rigs);
1613		break;
1614	default:
1615		$prev = ($rig - 1) % count($rigs);
1616		$next = ($rig + 1) % count($rigs);
1617		break;
1618	}
1619
1620	$refresh = "&rig=$rig";
1621 }
1622
1623 echo '<tr><td><table cellpadding=0 cellspacing=0 border=0><tr><td nowrap>';
1624 if ($userlist === null || isset($_SESSION[$ses]))
1625 {
1626	if ($prev !== null)
1627		echo riginput($prev, 'Prev').'&nbsp;';
1628	echo "<input type=button value='Refresh' onclick='pr(\"$refresh\",null)'>&nbsp;";
1629	if ($next !== null)
1630		echo riginput($next, 'Next').'&nbsp;';
1631	echo '&nbsp;';
1632	if (count($rigs) > 1)
1633		echo "<input type=button value='Summary' onclick='pr(\"\",null)'>&nbsp;";
1634 }
1635
1636 if ($allowcustompages === true)
1637 {
1638	if ($userlist === null || isset($_SESSION[$ses]))
1639		$list = $customsummarypages;
1640	else
1641	{
1642		if ($userlist !== null && isset($userlist['def']))
1643			$list = array_flip($userlist['def']);
1644		else
1645			$list = array();
1646	}
1647
1648	foreach ($list as $pagename => $data)
1649		echo "<input type=button value='$pagename' onclick='pr(\"&pg=$pagename\",null)'>&nbsp;";
1650 }
1651
1652 echo '</td><td width=100%>&nbsp;</td><td nowrap>';
1653 if ($rig !== null && $readonly === false)
1654 {
1655	$rg = '';
1656	if (count($rigs) > 1)
1657		$rg = " Rig $rig";
1658	echo "<input type=button value='Restart' onclick='prc(\"restart&rig=$rig\",\"Restart CGMiner$rg\")'>";
1659	echo "&nbsp;<input type=button value='Quit' onclick='prc(\"quit&rig=$rig\",\"Quit CGMiner$rg\")'>";
1660 }
1661 refreshbuttons();
1662 if (isset($_SESSION[$ses]))
1663	echo "&nbsp;<input type=button value='Logout' onclick='pr(\"&logout=1\",null)'>";
1664 else
1665	if ($userlist !== null)
1666		echo "&nbsp;<input type=button value='Login' onclick='pr(\"&login=1\",null)'>";
1667
1668 echo "</td></tr></table></td></tr>";
1669}
1670#
1671function doOne($rig, $preprocess)
1672{
1673 global $haderror, $readonly, $notify, $rigs;
1674 global $placebuttons;
1675
1676 htmlhead(true, $rig);
1677
1678 if ($placebuttons == 'top' || $placebuttons == 'both')
1679	pagebuttons($rig, null);
1680
1681 if ($preprocess != null)
1682	process(array($preprocess => $preprocess), $rig);
1683
1684 $cmds = array(	'devs'    => 'device list',
1685		'summary' => 'summary information',
1686		'pools'   => 'pool list');
1687
1688 if ($notify)
1689	$cmds['notify'] = 'device status';
1690
1691 $cmds['config'] = 'cgminer config';
1692
1693 process($cmds, $rig);
1694
1695 if ($haderror == false && $readonly === false)
1696	processgpus($rig);
1697
1698 if ($placebuttons == 'bot' || $placebuttons == 'both')
1699	pagebuttons($rig, null);
1700}
1701#
1702global $sectionmap;
1703# map sections to their api command
1704# DEVS is a special case that will match GPU, PGA or ASC
1705# so you can have a single table with both in it
1706# DATE is hard coded so not in here
1707$sectionmap = array(
1708	'RIGS' => 'version',
1709	'SUMMARY' => 'summary',
1710	'POOL' => 'pools',
1711	'DEVS' => 'devs',
1712	'GPU' => 'devs',	// You would normally use DEVS
1713	'PGA' => 'devs',	// You would normally use DEVS
1714	'ASC' => 'devs',	// You would normally use DEVS
1715	'NOTIFY' => 'notify',
1716	'DEVDETAILS' => 'devdetails',
1717	'STATS' => 'stats',
1718	'CONFIG' => 'config',
1719	'COIN' => 'coin',
1720	'USBSTATS' => 'usbstats');
1721#
1722function joinfields($section1, $section2, $join, $results)
1723{
1724 global $sectionmap;
1725
1726 $name1 = $sectionmap[$section1];
1727 $name2 = $sectionmap[$section2];
1728 $newres = array();
1729
1730 // foreach rig in section1
1731 foreach ($results[$name1] as $rig => $result)
1732 {
1733	$status = null;
1734
1735	// foreach answer section in the rig api call
1736	foreach ($result as $name1b => $fields1b)
1737	{
1738		if ($name1b == 'STATUS')
1739		{
1740			// remember the STATUS from section1
1741			$status = $result[$name1b];
1742			continue;
1743		}
1744
1745		// foreach answer section in the rig api call (for the other api command)
1746		foreach ($results[$name2][$rig] as $name2b => $fields2b)
1747		{
1748			if ($name2b == 'STATUS')
1749				continue;
1750
1751			// If match the same field values of fields in $join
1752			$match = true;
1753			foreach ($join as $field)
1754				if ($fields1b[$field] != $fields2b[$field])
1755				{
1756					$match = false;
1757					break;
1758				}
1759
1760			if ($match === true)
1761			{
1762				if ($status != null)
1763				{
1764					$newres[$rig]['STATUS'] = $status;
1765					$status = null;
1766				}
1767
1768				$subsection = $section1.'+'.$section2;
1769				$subsection .= preg_replace('/[^0-9]/', '', $name1b.$name2b);
1770
1771				foreach ($fields1b as $nam => $val)
1772					$newres[$rig][$subsection]["$section1.$nam"] = $val;
1773				foreach ($fields2b as $nam => $val)
1774					$newres[$rig][$subsection]["$section2.$nam"] = $val;
1775			}
1776		}
1777	}
1778 }
1779 return $newres;
1780}
1781#
1782function joinlr($section1, $section2, $join, $results)
1783{
1784 global $sectionmap;
1785
1786 $name1 = $sectionmap[$section1];
1787 $name2 = $sectionmap[$section2];
1788 $newres = array();
1789
1790 // foreach rig in section1
1791 foreach ($results[$name1] as $rig => $result)
1792 {
1793	$status = null;
1794
1795	// foreach answer section in the rig api call
1796	foreach ($result as $name1b => $fields1b)
1797	{
1798		if ($name1b == 'STATUS')
1799		{
1800			// remember the STATUS from section1
1801			$status = $result[$name1b];
1802			continue;
1803		}
1804
1805		// Build L string to be matched
1806		// : means a string constant otherwise it's a field name
1807		$Lval = '';
1808		foreach ($join['L'] as $field)
1809		{
1810			if (substr($field, 0, 1) == ':')
1811				$Lval .= substr($field, 1);
1812			else
1813				$Lval .= $fields1b[$field];
1814		}
1815
1816		// foreach answer section in the rig api call (for the other api command)
1817		foreach ($results[$name2][$rig] as $name2b => $fields2b)
1818		{
1819			if ($name2b == 'STATUS')
1820				continue;
1821
1822			// Build R string and compare
1823			// : means a string constant otherwise it's a field name
1824			$Rval = '';
1825			foreach ($join['R'] as $field)
1826			{
1827				if (substr($field, 0, 1) == ':')
1828					$Rval .= substr($field, 1);
1829				else
1830					$Rval .= $fields2b[$field];
1831			}
1832
1833			if ($Lval === $Rval)
1834			{
1835				if ($status != null)
1836				{
1837					$newres[$rig]['STATUS'] = $status;
1838					$status = null;
1839				}
1840
1841				$subsection = $section1.'+'.$section2;
1842				$subsection .= preg_replace('/[^0-9]/', '', $name1b.$name2b);
1843
1844				foreach ($fields1b as $nam => $val)
1845					$newres[$rig][$subsection]["$section1.$nam"] = $val;
1846				foreach ($fields2b as $nam => $val)
1847					$newres[$rig][$subsection]["$section2.$nam"] = $val;
1848			}
1849		}
1850	}
1851 }
1852 return $newres;
1853}
1854#
1855function joinall($section1, $section2, $results)
1856{
1857 global $sectionmap;
1858
1859 $name1 = $sectionmap[$section1];
1860 $name2 = $sectionmap[$section2];
1861 $newres = array();
1862
1863 // foreach rig in section1
1864 foreach ($results[$name1] as $rig => $result)
1865 {
1866	// foreach answer section in the rig api call
1867	foreach ($result as $name1b => $fields1b)
1868	{
1869		if ($name1b == 'STATUS')
1870		{
1871			// copy the STATUS from section1
1872			$newres[$rig][$name1b] = $result[$name1b];
1873			continue;
1874		}
1875
1876		// foreach answer section in the rig api call (for the other api command)
1877		foreach ($results[$name2][$rig] as $name2b => $fields2b)
1878		{
1879			if ($name2b == 'STATUS')
1880				continue;
1881
1882			$subsection = $section1.'+'.$section2;
1883			$subsection .= preg_replace('/[^0-9]/', '', $name1b.$name2b);
1884
1885			foreach ($fields1b as $nam => $val)
1886				$newres[$rig][$subsection]["$section1.$nam"] = $val;
1887			foreach ($fields2b as $nam => $val)
1888				$newres[$rig][$subsection]["$section2.$nam"] = $val;
1889		}
1890	}
1891 }
1892 return $newres;
1893}
1894#
1895function joinsections($sections, $results, $errors)
1896{
1897 global $sectionmap;
1898
1899 // GPU's don't have Name,ID fields - so create them
1900 foreach ($results as $section => $res)
1901	foreach ($res as $rig => $result)
1902		foreach ($result as $name => $fields)
1903		{
1904			$subname = preg_replace('/[0-9]/', '', $name);
1905			if ($subname == 'GPU' and isset($result[$name]['GPU']))
1906			{
1907				$results[$section][$rig][$name]['Name'] = 'GPU';
1908				$results[$section][$rig][$name]['ID'] = $result[$name]['GPU'];
1909			}
1910		}
1911
1912 foreach ($sections as $section => $fields)
1913	if ($section != 'DATE' && !isset($sectionmap[$section]))
1914	{
1915		$both = explode('+', $section, 2);
1916		if (count($both) > 1)
1917		{
1918			switch($both[0])
1919			{
1920			case 'SUMMARY':
1921				switch($both[1])
1922				{
1923				case 'POOL':
1924				case 'DEVS':
1925				case 'CONFIG':
1926				case 'COIN':
1927					$sectionmap[$section] = $section;
1928					$results[$section] = joinall($both[0], $both[1], $results);
1929					break;
1930				default:
1931					$errors[] = "Error: Invalid section '$section'";
1932					break;
1933				}
1934				break;
1935			case 'DEVS':
1936				switch($both[1])
1937				{
1938				case 'NOTIFY':
1939				case 'DEVDETAILS':
1940				case 'USBSTATS':
1941					$join = array('Name', 'ID');
1942					$sectionmap[$section] = $section;
1943					$results[$section] = joinfields($both[0], $both[1], $join, $results);
1944					break;
1945				case 'STATS':
1946					$join = array('L' => array('Name','ID'), 'R' => array('ID'));
1947					$sectionmap[$section] = $section;
1948					$results[$section] = joinlr($both[0], $both[1], $join, $results);
1949					break;
1950				default:
1951					$errors[] = "Error: Invalid section '$section'";
1952					break;
1953				}
1954				break;
1955			case 'POOL':
1956				switch($both[1])
1957				{
1958				case 'STATS':
1959					$join = array('L' => array(':POOL','POOL'), 'R' => array('ID'));
1960					$sectionmap[$section] = $section;
1961					$results[$section] = joinlr($both[0], $both[1], $join, $results);
1962					break;
1963				default:
1964					$errors[] = "Error: Invalid section '$section'";
1965					break;
1966				}
1967				break;
1968			default:
1969				$errors[] = "Error: Invalid section '$section'";
1970				break;
1971			}
1972		}
1973		else
1974			$errors[] = "Error: Invalid section '$section'";
1975	}
1976
1977 return array($results, $errors);
1978}
1979#
1980function secmatch($section, $field)
1981{
1982 if ($section == $field)
1983	return true;
1984
1985 if ($section == 'DEVS'
1986 &&  ($field == 'GPU' || $field == 'PGA' || $field == 'ASC'))
1987	return true;
1988
1989 return false;
1990}
1991#
1992function customset($showfields, $sum, $section, $rig, $isbutton, $result, $total)
1993{
1994 foreach ($result as $sec => $row)
1995 {
1996	$secname = preg_replace('/\d/', '', $sec);
1997
1998	if ($sec != 'total')
1999		if (!secmatch($section, $secname))
2000			continue;
2001
2002	newrow();
2003
2004	$when = 0;
2005	if (isset($result['STATUS']['When']))
2006		$when = $result['STATUS']['When'];
2007
2008
2009	if ($isbutton)
2010		echo rigbutton($rig, $rig, $when, $row);
2011	else
2012	{
2013		list($ignore, $class) = fmt('total', '', '', $when, $row);
2014		echo "<td align=middle$class>$rig</td>";
2015	}
2016
2017	foreach ($showfields as $name => $one)
2018	{
2019		if (isset($row[$name]))
2020		{
2021			$value = $row[$name];
2022
2023			if (isset($sum[$section][$name]))
2024			{
2025				if (isset($total[$name]))
2026					$total[$name] += $value;
2027				else
2028					$total[$name] = $value;
2029			}
2030		}
2031		else
2032		{
2033			if ($sec == 'total' && isset($total[$name]))
2034				$value = $total[$name];
2035			else
2036				$value = null;
2037		}
2038
2039		if (strpos($secname, '+') === false)
2040			list($showvalue, $class) = fmt($secname, $name, $value, $when, $row);
2041		else
2042		{
2043			$parts = explode('.', $name, 2);
2044			list($showvalue, $class) = fmt($parts[0], $parts[1], $value, $when, $row);
2045		}
2046
2047		echo "<td$class align=right>$showvalue</td>";
2048	}
2049	endrow();
2050 }
2051 return $total;
2052}
2053#
2054function docalc($func, $data)
2055{
2056 switch ($func)
2057 {
2058 case 'sum':
2059	$tot = 0;
2060	foreach ($data as $val)
2061		$tot += $val;
2062	return $tot;
2063 case 'avg':
2064	$tot = 0;
2065	foreach ($data as $val)
2066		$tot += $val;
2067	return ($tot / count($data));
2068 case 'min':
2069	$ans = null;
2070	foreach ($data as $val)
2071		if ($ans === null)
2072			$ans = $val;
2073		else
2074			if ($val < $ans)
2075				$ans = $val;
2076	return $ans;
2077 case 'max':
2078	$ans = null;
2079	foreach ($data as $val)
2080		if ($ans === null)
2081			$ans = $val;
2082		else
2083			if ($val > $ans)
2084				$ans = $val;
2085	return $ans;
2086 case 'lo':
2087	$ans = null;
2088	foreach ($data as $val)
2089		if ($ans === null)
2090			$ans = $val;
2091		else
2092			if (strcasecmp($val, $ans) < 0)
2093				$ans = $val;
2094	return $ans;
2095 case 'hi':
2096	$ans = null;
2097	foreach ($data as $val)
2098		if ($ans === null)
2099			$ans = $val;
2100		else
2101			if (strcasecmp($val, $ans) > 0)
2102				$ans = $val;
2103	return $ans;
2104 case 'count':
2105	return count($data);
2106 case 'any':
2107 default:
2108	return $data[0];
2109 }
2110}
2111#
2112function docompare($row, $test)
2113{
2114 // invalid $test data means true
2115 if (count($test) < 2)
2116	return true;
2117
2118 if (isset($row[$test[0]]))
2119	$val = $row[$test[0]];
2120 else
2121	$val = null;
2122
2123 if ($test[1] == 'set')
2124	return ($val !== null);
2125
2126 if ($val === null || count($test) < 3)
2127	return true;
2128
2129 switch($test[1])
2130 {
2131 case '=':
2132	return ($val == $test[2]);
2133 case '<':
2134	return ($val < $test[2]);
2135 case '<=':
2136	return ($val <= $test[2]);
2137 case '>':
2138	return ($val > $test[2]);
2139 case '>=':
2140	return ($val >= $test[2]);
2141 case 'eq':
2142	return (strcasecmp($val, $test[2]) == 0);
2143 case 'lt':
2144	return (strcasecmp($val, $test[2]) < 0);
2145 case 'le':
2146	return (strcasecmp($val, $test[2]) <= 0);
2147 case 'gt':
2148	return (strcasecmp($val, $test[2]) > 0);
2149 case 'ge':
2150	return (strcasecmp($val, $test[2]) >= 0);
2151 default:
2152	return true;
2153 }
2154}
2155#
2156function processcompare($which, $ext, $section, $res)
2157{
2158 if (isset($ext[$section][$which]))
2159 {
2160	$proc = $ext[$section][$which];
2161	if ($proc !== null)
2162	{
2163		$res2 = array();
2164		foreach ($res as $rig => $result)
2165			foreach ($result as $sec => $row)
2166			{
2167				$secname = preg_replace('/\d/', '', $sec);
2168				if (!secmatch($section, $secname))
2169					$res2[$rig][$sec] = $row;
2170				else
2171				{
2172					$keep = true;
2173					foreach ($proc as $test)
2174						if (!docompare($row, $test))
2175						{
2176							$keep = false;
2177							break;
2178						}
2179					if ($keep)
2180						$res2[$rig][$sec] = $row;
2181				}
2182			}
2183
2184		$res = $res2;
2185	}
2186 }
2187 return…

Large files files are truncated, but you can click here to view the full file