miner.php 22 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021
  1. <?php
  2. session_start();
  3. #
  4. global $miner, $port, $readonly, $notify, $rigs, $socktimeoutsec;
  5. global $checklastshare, $hidefields;
  6. #
  7. # Don't touch these 2 - see $rigs below
  8. $miner = null;
  9. $port = null;
  10. #
  11. # Set $readonly to true to force miner.php to be readonly
  12. # Set $readonly to false then it will check cgminer 'privileged'
  13. $readonly = false;
  14. #
  15. # Set $notify to false to NOT attempt to display the notify command
  16. # Set $notify to true to attempt to display the notify command
  17. # If your older version of cgminer returns an 'Invalid command'
  18. # coz it doesn't have notify - it just shows the error status table
  19. $notify = true;
  20. #
  21. # set $checklastshare to true to do the following checks:
  22. # If a device's last share is 12x expected ago then display as an error
  23. # If a device's last share is 8x expected ago then display as a warning
  24. # If either of the above is true, also display the whole line highlighted
  25. # This assumes shares are 1 difficulty shares
  26. $checklastshare = true;
  27. #
  28. # Set $rigs to an array of your cgminer rigs that are running
  29. # format: 'IP:Port' or 'Host:Port'
  30. # If you only have one rig, it will just show the detail of that rig
  31. # If you have more than one rig it will show a summary of all the rigs
  32. # with buttons to show the details of each rig
  33. # e.g. $rigs = array('127.0.0.1:4028','myrig.com:4028');
  34. $rigs = array('127.0.0.1:4028');
  35. #
  36. # This should be OK for most cases
  37. # However, the longer it is the longer you have to wait while php
  38. # hangs if the target cgminer isn't runnning or listening
  39. # Feel free to increase it if your network is very slow
  40. # Also, on some windows PHP, apparently the $usec is ignored
  41. $socktimeoutsec = 10;
  42. #
  43. # List of fields NOT to be displayed
  44. # You can use this to hide data you don't want to see or don't want
  45. # shown on a public web page
  46. # The list of sections are: SUMMARY, POOL, PGA, GPU, NOTIFY, CONFIG
  47. # See the web page for the list of field names (the table headers)
  48. # It is an array of 'SECTION.Field Name' => 1
  49. # This example would hide the slightly more sensitive pool information
  50. #$hidefields = array('POOL.URL' => 1, 'POOL.User' => 1);
  51. $hidefields = array();
  52. #
  53. $here = $_SERVER['PHP_SELF'];
  54. #
  55. global $tablebegin, $tableend, $warnfont, $warnoff, $dfmt;
  56. #
  57. $tablebegin = '<tr><td><table border=1 cellpadding=5 cellspacing=0>';
  58. $tableend = '</table></td></tr>';
  59. $warnfont = '<font color=red><b>';
  60. $warnoff = '</b></font>';
  61. $dfmt = 'H:i:s j-M-Y \U\T\CP';
  62. #
  63. # Ensure it is only ever shown once
  64. global $showndate;
  65. $showndate = false;
  66. #
  67. # For summary page to stop retrying failed rigs
  68. global $rigerror;
  69. $rigerror = array();
  70. #
  71. function htmlhead($checkapi)
  72. {
  73. global $error, $readonly, $here;
  74. if ($readonly === false && $checkapi === true)
  75. {
  76. $access = api('privileged');
  77. if ($error != null
  78. || !isset($access['STATUS']['STATUS'])
  79. || $access['STATUS']['STATUS'] != 'S')
  80. $readonly = true;
  81. }
  82. ?>
  83. <html><head><title>Mine</title>
  84. <style type='text/css'>
  85. td { color:blue; font-family:verdana,arial,sans; font-size:13pt; }
  86. td.h { color:blue; font-family:verdana,arial,sans; font-size:13pt; background:#d0ffff }
  87. td.err { color:black; font-family:verdana,arial,sans; font-size:13pt; background:#ff3050 }
  88. td.warn { color:black; font-family:verdana,arial,sans; font-size:13pt; background:#ffb050 }
  89. td.sta { color:green; font-family:verdana,arial,sans; font-size:13pt; }
  90. td.tot { color:blue; font-family:verdana,arial,sans; font-size:13pt; background:#fff8f2 }
  91. td.lst { color:blue; font-family:verdana,arial,sans; font-size:13pt; background:#ffffdd }
  92. </style>
  93. </head><body bgcolor=#ecffff>
  94. <script type='text/javascript'>
  95. function pr(a,m){if(m!=null){if(!confirm(m+'?'))return}window.location="<?php echo $here ?>"+a}
  96. <?php
  97. if ($readonly === false && $checkapi === true)
  98. {
  99. ?>
  100. function prc(a,m){pr('?arg='+a,m)}
  101. 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)}
  102. 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)}
  103. <?php
  104. }
  105. ?>
  106. </script>
  107. <table width=100% height=100% border=0 cellpadding=0 cellspacing=0 summary='Mine'>
  108. <tr><td align=center valign=top>
  109. <table border=0 cellpadding=4 cellspacing=0 summary='Mine'>
  110. <?php
  111. }
  112. #
  113. global $error;
  114. $error = null;
  115. #
  116. function getsock($addr, $port)
  117. {
  118. global $error, $socktimeoutsec;
  119. $socket = null;
  120. $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
  121. if ($socket === false || $socket === null)
  122. {
  123. $error = socket_strerror(socket_last_error());
  124. $msg = "socket create(TCP) failed";
  125. $error = "ERR: $msg '$error'\n";
  126. return null;
  127. }
  128. // Ignore if this fails since the socket connect may work anyway
  129. // and nothing is gained by aborting if the option cannot be set
  130. // since we don't know in advance if it can connect
  131. socket_set_option($socket, SOL_SOCKET, SO_SNDTIMEO, array('sec' => $socktimeoutsec, 'usec' => 0));
  132. $res = socket_connect($socket, $addr, $port);
  133. if ($res === false)
  134. {
  135. $error = socket_strerror(socket_last_error());
  136. $msg = "socket connect($addr,$port) failed";
  137. $error = "ERR: $msg '$error'\n";
  138. socket_close($socket);
  139. return null;
  140. }
  141. return $socket;
  142. }
  143. #
  144. function readsockline($socket)
  145. {
  146. $line = '';
  147. while (true)
  148. {
  149. $byte = socket_read($socket, 1);
  150. if ($byte === false || $byte === '')
  151. break;
  152. if ($byte === "\0")
  153. break;
  154. $line .= $byte;
  155. }
  156. return $line;
  157. }
  158. #
  159. function api($cmd)
  160. {
  161. global $miner, $port, $hidefields;
  162. $socket = getsock($miner, $port);
  163. if ($socket != null)
  164. {
  165. socket_write($socket, $cmd, strlen($cmd));
  166. $line = readsockline($socket);
  167. socket_close($socket);
  168. if (strlen($line) == 0)
  169. {
  170. $error = "WARN: '$cmd' returned nothing\n";
  171. return $line;
  172. }
  173. # print "$cmd returned '$line'\n";
  174. $data = array();
  175. $objs = explode('|', $line);
  176. foreach ($objs as $obj)
  177. {
  178. if (strlen($obj) > 0)
  179. {
  180. $items = explode(',', $obj);
  181. $item = $items[0];
  182. $id = explode('=', $items[0], 2);
  183. if (count($id) == 1 or !ctype_digit($id[1]))
  184. $name = $id[0];
  185. else
  186. $name = $id[0].$id[1];
  187. if (strlen($name) == 0)
  188. $name = 'null';
  189. $sectionname = preg_replace('/\d/', '', $name);
  190. if (isset($data[$name]))
  191. {
  192. $num = 1;
  193. while (isset($data[$name.$num]))
  194. $num++;
  195. $name .= $num;
  196. }
  197. $counter = 0;
  198. foreach ($items as $item)
  199. {
  200. $id = explode('=', $item, 2);
  201. if (isset($hidefields[$sectionname.'.'.$id[0]]))
  202. continue;
  203. if (count($id) == 2)
  204. $data[$name][$id[0]] = $id[1];
  205. else
  206. $data[$name][$counter] = $id[0];
  207. $counter++;
  208. }
  209. }
  210. }
  211. return $data;
  212. }
  213. return null;
  214. }
  215. #
  216. function getparam($name, $both = false)
  217. {
  218. $a = null;
  219. if (isset($_POST[$name]))
  220. $a = $_POST[$name];
  221. if (($both === true) and ($a === null))
  222. {
  223. if (isset($_GET[$name]))
  224. $a = $_GET[$name];
  225. }
  226. if ($a == '' || $a == null)
  227. return null;
  228. // limit to 1K just to be safe
  229. return substr($a, 0, 1024);
  230. }
  231. #
  232. function classlastshare($when, $alldata, $warnclass, $errorclass)
  233. {
  234. global $checklastshare;
  235. if ($checklastshare === false)
  236. return '';
  237. if ($when == 0)
  238. return '';
  239. if (!isset($alldata['MHS av']))
  240. return '';
  241. if (!isset($alldata['Last Share Time']))
  242. return '';
  243. $expected = pow(2, 32) / ($alldata['MHS av'] * pow(10, 6));
  244. $howlong = $when - $alldata['Last Share Time'];
  245. if ($howlong < 1)
  246. $howlong = 1;
  247. if ($howlong > ($expected * 12))
  248. return $errorclass;
  249. if ($howlong > ($expected * 8))
  250. return $warnclass;
  251. return '';
  252. }
  253. #
  254. function fmt($section, $name, $value, $when, $alldata)
  255. {
  256. global $dfmt;
  257. if ($alldata == null)
  258. $alldata = array();
  259. $errorclass = ' class=err';
  260. $warnclass = ' class=warn';
  261. $lstclass = ' class=lst';
  262. $b = '&nbsp;';
  263. $ret = $value;
  264. $class = '';
  265. if ($value === null)
  266. $ret = $b;
  267. else
  268. switch ($section.'.'.$name)
  269. {
  270. case 'GPU.Last Share Time':
  271. case 'PGA.Last Share Time':
  272. if ($value == 0
  273. || (isset($alldata['Last Share Pool']) && $alldata['Last Share Pool'] == -1))
  274. {
  275. $ret = 'Never';
  276. $class = $warnclass;
  277. }
  278. else
  279. {
  280. $ret = date('H:i:s', $value);
  281. $class = classlastshare($when, $alldata, $warnclass, $errorclass);
  282. }
  283. break;
  284. case 'POOL.Last Share Time':
  285. if ($value == 0)
  286. $ret = 'Never';
  287. else
  288. $ret = date('H:i:s d-M', $value);
  289. break;
  290. case 'GPU.Last Share Pool':
  291. case 'PGA.Last Share Pool':
  292. if ($value == -1)
  293. {
  294. $ret = 'None';
  295. $class = $warnclass;
  296. }
  297. break;
  298. case 'SUMMARY.Elapsed':
  299. $s = $value % 60;
  300. $value -= $s;
  301. $value /= 60;
  302. if ($value == 0)
  303. $ret = $s.'s';
  304. else
  305. {
  306. $m = $value % 60;
  307. $value -= $m;
  308. $value /= 60;
  309. if ($value == 0)
  310. $ret = sprintf("%dm$b%02ds", $m, $s);
  311. else
  312. {
  313. $h = $value % 24;
  314. $value -= $h;
  315. $value /= 24;
  316. if ($value == 0)
  317. $ret = sprintf("%dh$b%02dm$b%02ds", $h, $m, $s);
  318. else
  319. {
  320. if ($value == 1)
  321. $days = '';
  322. else
  323. $days = 's';
  324. $ret = sprintf("%dday$days$b%02dh$b%02dm$b%02ds", $value, $h, $m, $s);
  325. }
  326. }
  327. }
  328. break;
  329. case 'NOTIFY.Last Well':
  330. if ($value == '0')
  331. {
  332. $ret = 'Never';
  333. $class = $warnclass;
  334. }
  335. else
  336. $ret = date('H:i:s', $value);
  337. break;
  338. case 'NOTIFY.Last Not Well':
  339. if ($value == '0')
  340. $ret = 'Never';
  341. else
  342. {
  343. $ret = date('H:i:s', $value);
  344. $class = $errorclass;
  345. }
  346. break;
  347. case 'NOTIFY.Reason Not Well':
  348. if ($value != 'None')
  349. $class = $errorclass;
  350. break;
  351. case 'GPU.Utility':
  352. case 'PGA.Utility':
  353. case 'SUMMARY.Utility':
  354. $ret = $value.'/m';
  355. if ($value == 0)
  356. $class = $warnclass;
  357. break;
  358. case 'PGA.Temperature':
  359. $ret = $value.'&deg;C';
  360. break;
  361. case 'GPU.Temperature':
  362. $ret = $value.'&deg;C';
  363. case 'GPU.GPU Clock':
  364. case 'GPU.Memory Clock':
  365. case 'GPU.GPU Voltage':
  366. case 'GPU.GPU Activity':
  367. if ($value == 0)
  368. $class = $warnclass;
  369. break;
  370. case 'GPU.Fan Percent':
  371. if ($value == 0)
  372. $class = $warnclass;
  373. else
  374. {
  375. if ($value == 100)
  376. $class = $errorclass;
  377. else
  378. if ($value > 85)
  379. $class = $warnclass;
  380. }
  381. break;
  382. case 'GPU.Fan Speed':
  383. if ($value == 0)
  384. $class = $warnclass;
  385. else
  386. if (isset($alldata['Fan Percent']))
  387. {
  388. $test = $alldata['Fan Percent'];
  389. if ($test == 100)
  390. $class = $errorclass;
  391. else
  392. if ($test > 85)
  393. $class = $warnclass;
  394. }
  395. break;
  396. case 'GPU.MHS av':
  397. case 'PGA.MHS av':
  398. case 'SUMMARY.MHS av':
  399. case 'GPU.Total MH':
  400. case 'PGA.Total MH':
  401. case 'SUMMARY.Total MH':
  402. case 'SUMMARY.Getworks':
  403. case 'GPU.Accepted':
  404. case 'PGA.Accepted':
  405. case 'SUMMARY.Accepted':
  406. case 'GPU.Rejected':
  407. case 'PGA.Rejected':
  408. case 'SUMMARY.Rejected':
  409. case 'SUMMARY.Local Work':
  410. case 'POOL.Getworks':
  411. case 'POOL.Accepted':
  412. case 'POOL.Rejected':
  413. case 'POOL.Discarded':
  414. $parts = explode('.', $value, 2);
  415. if (count($parts) == 1)
  416. $dec = '';
  417. else
  418. $dec = '.'.$parts[1];
  419. $ret = number_format($parts[0]).$dec;
  420. break;
  421. case 'GPU.Status':
  422. case 'PGA.Status':
  423. case 'POOL.Status':
  424. if ($value != 'Alive')
  425. $class = $errorclass;
  426. break;
  427. case 'GPU.Enabled':
  428. case 'PGA.Enabled':
  429. if ($value != 'Y')
  430. $class = $warnclass;
  431. break;
  432. case 'STATUS.When':
  433. $ret = date($dfmt, $value);
  434. break;
  435. }
  436. if ($section == 'NOTIFY' && substr($name, 0, 1) == '*' && $value != '0')
  437. $class = $errorclass;
  438. if ($class == '' && $section != 'POOL')
  439. $class = classlastshare($when, $alldata, $lstclass, $lstclass);
  440. return array($ret, $class);
  441. }
  442. #
  443. global $poolcmd;
  444. $poolcmd = array( 'Switch to' => 'switchpool',
  445. 'Enable' => 'enablepool',
  446. 'Disable' => 'disablepool' );
  447. #
  448. function showhead($cmd, $item, $values)
  449. {
  450. global $poolcmd, $readonly;
  451. echo '<tr>';
  452. foreach ($values as $name => $value)
  453. {
  454. if ($name == '0' or $name == '')
  455. $name = '&nbsp;';
  456. echo "<td valign=bottom class=h>$name</td>";
  457. }
  458. if ($cmd == 'pools' && $readonly === false)
  459. foreach ($poolcmd as $name => $pcmd)
  460. echo "<td valign=bottom class=h>$name</td>";
  461. echo '</tr>';
  462. }
  463. #
  464. function details($cmd, $list, $rig)
  465. {
  466. global $tablebegin, $tableend, $dfmt;
  467. global $poolcmd, $readonly;
  468. global $showndate;
  469. $when = 0;
  470. $stas = array('S' => 'Success', 'W' => 'Warning', 'I' => 'Informational', 'E' => 'Error', 'F' => 'Fatal');
  471. echo $tablebegin;
  472. if ($showndate === false)
  473. {
  474. echo '<tr><td class=sta>Date: '.date($dfmt).'</td></tr>';
  475. echo $tableend.$tablebegin;
  476. $showndate = true;
  477. }
  478. if (isset($list['STATUS']))
  479. {
  480. echo '<tr>';
  481. echo '<td>Computer: '.$list['STATUS']['Description'].'</td>';
  482. if (isset($list['STATUS']['When']))
  483. {
  484. echo '<td>When: '.date($dfmt, $list['STATUS']['When']).'</td>';
  485. $when = $list['STATUS']['When'];
  486. }
  487. $sta = $list['STATUS']['STATUS'];
  488. echo '<td>Status: '.$stas[$sta].'</td>';
  489. echo '<td>Message: '.$list['STATUS']['Msg'].'</td>';
  490. echo '</tr>';
  491. }
  492. $section = '';
  493. foreach ($list as $item => $values)
  494. {
  495. if ($item == 'STATUS')
  496. continue;
  497. $sectionname = preg_replace('/\d/', '', $item);
  498. if ($sectionname != $section)
  499. {
  500. echo $tableend.$tablebegin;
  501. showhead($cmd, $item, $values);
  502. $section = $sectionname;
  503. }
  504. echo '<tr>';
  505. foreach ($values as $name => $value)
  506. {
  507. list($showvalue, $class) = fmt($section, $name, $value, $when, $values);
  508. echo "<td$class>$showvalue</td>";
  509. }
  510. if ($cmd == 'pools' && $readonly === false)
  511. {
  512. reset($values);
  513. $pool = current($values);
  514. foreach ($poolcmd as $name => $pcmd)
  515. {
  516. echo '<td>';
  517. if ($pool === false)
  518. echo '&nbsp;';
  519. else
  520. {
  521. echo "<input type=button value='Pool $pool'";
  522. echo " onclick='prc(\"$pcmd|$pool&rig=$rig\",\"$name Pool $pool\")'>";
  523. }
  524. echo '</td>';
  525. }
  526. }
  527. echo '</tr>';
  528. }
  529. echo $tableend;
  530. }
  531. #
  532. global $devs;
  533. $devs = null;
  534. #
  535. function gpubuttons($count, $rig)
  536. {
  537. global $tablebegin, $tableend;
  538. global $devs;
  539. $basic = array( 'GPU', 'Enable', 'Disable', 'Restart' );
  540. $options = array( 'intensity' => 'Intensity',
  541. 'fan' => 'Fan Percent',
  542. 'engine' => 'GPU Clock',
  543. 'mem' => 'Memory Clock',
  544. 'vddc' => 'GPU Voltage' );
  545. echo $tablebegin.'<tr>';
  546. foreach ($basic as $head)
  547. echo "<td>$head</td>";
  548. foreach ($options as $name => $des)
  549. echo "<td nowrap>$des</td>";
  550. $n = 0;
  551. for ($c = 0; $c < $count; $c++)
  552. {
  553. echo '</tr><tr>';
  554. foreach ($basic as $name)
  555. {
  556. echo '<td>';
  557. if ($name == 'GPU')
  558. echo $c;
  559. else
  560. {
  561. echo "<input type=button value='$name $c' onclick='prs(\"gpu";
  562. echo strtolower($name);
  563. echo "|$c\",$rig)'>";
  564. }
  565. echo '</td>';
  566. }
  567. foreach ($options as $name => $des)
  568. {
  569. echo '<td>';
  570. if (!isset($devs["GPU$c"][$des]))
  571. echo '&nbsp;';
  572. else
  573. {
  574. $value = $devs["GPU$c"][$des];
  575. echo "<input type=button value='Set $c:' onclick='prs2(\"gpu$name|$c\",$n,$rig)'>";
  576. echo "<input size=7 type=text name=gi$n value='$value' id=gi$n>";
  577. $n++;
  578. }
  579. echo '</td>';
  580. }
  581. }
  582. echo '</tr>'.$tableend;
  583. }
  584. #
  585. function processgpus($rig)
  586. {
  587. global $error;
  588. global $warnfont, $warnoff;
  589. $gpus = api('gpucount');
  590. if ($error != null)
  591. echo '<tr><td>Error getting GPU count: '.$warnfont.$error.$warnoff.'</td></tr>';
  592. else
  593. {
  594. if (!isset($gpus['GPUS']['Count']))
  595. echo '<tr><td>No GPU count returned: '.$warnfont.$gpus['STATUS']['STATUS'].' '.$gpus['STATUS']['Msg'].$ro.'</td></tr>';
  596. else
  597. {
  598. $count = $gpus['GPUS']['Count'];
  599. if ($count == 0)
  600. echo '<tr><td>No GPUs</td></tr>';
  601. else
  602. gpubuttons($count, $rig);
  603. }
  604. }
  605. }
  606. #
  607. function process($cmds, $rig)
  608. {
  609. global $error, $devs;
  610. global $warnfont, $warnoff;
  611. foreach ($cmds as $cmd => $des)
  612. {
  613. $process = api($cmd);
  614. if ($error != null)
  615. {
  616. echo "<tr><td colspan=100>Error getting $des: ";
  617. echo $warnfont.$error.$warnoff.'</td></tr>';
  618. break;
  619. }
  620. else
  621. {
  622. details($cmd, $process, $rig);
  623. echo '<tr><td><br><br></td></tr>';
  624. if ($cmd == 'devs')
  625. $devs = $process;
  626. }
  627. }
  628. }
  629. #
  630. # $head is a hack but this is just a demo anyway :)
  631. function doforeach($cmd, $des, $sum, $head, $datetime)
  632. {
  633. global $miner, $port;
  634. global $error, $readonly, $notify, $rigs;
  635. global $tablebegin, $tableend, $warnfont, $warnoff, $dfmt;
  636. global $rigerror;
  637. $when = 0;
  638. $header = $head;
  639. $anss = array();
  640. $count = 0;
  641. $preverr = count($rigerror);
  642. foreach ($rigs as $rig)
  643. {
  644. if (isset($rigerror[$rig]))
  645. continue;
  646. $parts = explode(':', $rig, 2);
  647. if (count($parts) == 2)
  648. {
  649. $miner = $parts[0];
  650. $port = $parts[1];
  651. $ans = api($cmd);
  652. if ($error != null)
  653. {
  654. echo "<tr><td colspan=100>Error on rig $count getting $des: ";
  655. echo $warnfont.$error.$warnoff.'</td></tr>';
  656. $rigerror[$rig] = $error;
  657. $error = null;
  658. }
  659. else
  660. $anss[$count] = $ans;
  661. }
  662. $count++;
  663. }
  664. if (count($anss) == 0)
  665. {
  666. echo '<tr><td>Failed to access any rigs successfully';
  667. if ($preverr > 0)
  668. echo ' (or rigs had previous errors)';
  669. echo '</td></tr>';
  670. return;
  671. }
  672. if ($datetime)
  673. {
  674. echo '<tr><td class=sta>Date: '.date($dfmt).'</td></tr>';
  675. echo $tableend.$tablebegin;
  676. $dthead = array('' => 1, 'STATUS' => 1, 'Description' => 1, 'When' => 1, 'API' => 1, 'CGMiner' => 1);
  677. showhead('', null, $dthead);
  678. foreach ($anss as $rig => $ans)
  679. {
  680. echo '<tr>';
  681. foreach ($ans as $item => $row)
  682. {
  683. if ($item != 'STATUS' && $item != 'VERSION')
  684. continue;
  685. foreach ($dthead as $name => $x)
  686. {
  687. if ($item == 'STATUS' && $name == '')
  688. echo "<td align=right><input type=button value='Rig $rig' onclick='pr(\"?rig=$rig\",null)'></td>";
  689. else
  690. {
  691. if (isset($row[$name]))
  692. {
  693. list($showvalue, $class) = fmt('STATUS', $name, $row[$name], $when, null);
  694. echo "<td$class align=right>$showvalue</td>";
  695. }
  696. }
  697. }
  698. }
  699. echo '</tr>';
  700. }
  701. echo $tableend;
  702. echo '<tr><td><br><br></td></tr>';
  703. echo $tablebegin;
  704. return;
  705. }
  706. $total = array();
  707. foreach ($anss as $rig => $ans)
  708. {
  709. foreach ($ans as $item => $row)
  710. {
  711. if ($item == 'STATUS')
  712. continue;
  713. if (count($row) > count($header))
  714. {
  715. $header = $head;
  716. foreach ($row as $name => $value)
  717. if (!isset($header[$name]))
  718. $header[$name] = '';
  719. }
  720. if ($sum != null)
  721. foreach ($sum as $name)
  722. {
  723. if (isset($row[$name]))
  724. {
  725. if (isset($total[$name]))
  726. $total[$name] += $row[$name];
  727. else
  728. $total[$name] = $row[$name];
  729. }
  730. }
  731. }
  732. }
  733. if ($sum != null)
  734. $anss['total']['total'] = $total;
  735. showhead('', null, $header);
  736. $section = '';
  737. foreach ($anss as $rig => $ans)
  738. {
  739. $when = 0;
  740. if (isset($ans['STATUS']['When']))
  741. $when = $ans['STATUS']['When'];
  742. foreach ($ans as $item => $row)
  743. {
  744. if ($item == 'STATUS')
  745. continue;
  746. echo '<tr>';
  747. $newsection = preg_replace('/\d/', '', $item);
  748. if ($newsection != 'total')
  749. $section = $newsection;
  750. foreach ($header as $name => $x)
  751. {
  752. if ($name == '')
  753. {
  754. if ($rig === 'total')
  755. echo "<td align=right class=tot>Total:</td>";
  756. else
  757. echo "<td align=right><input type=button value='Rig $rig' onclick='pr(\"?rig=$rig\",null)'></td>";
  758. }
  759. else
  760. {
  761. if (isset($row[$name]))
  762. $value = $row[$name];
  763. else
  764. $value = null;
  765. list($showvalue, $class) = fmt($section, $name, $value, $when, $row);
  766. if ($rig === 'total' and $class == '')
  767. $class = ' class=tot';
  768. echo "<td$class align=right>$showvalue</td>";
  769. }
  770. }
  771. echo '</tr>';
  772. }
  773. }
  774. }
  775. #
  776. function doOne($rig, $preprocess)
  777. {
  778. global $error, $readonly, $notify;
  779. global $rigs;
  780. htmlhead(true);
  781. $error = null;
  782. echo "<tr><td><table cellpadding=0 cellspacing=0 border=0><tr><td>";
  783. echo "<input type=button value='Refresh' onclick='pr(\"?rig=$rig\",null)'></td>";
  784. if (count($rigs) > 1)
  785. echo "<td><input type=button value='Summary' onclick='pr(\"\",null)'></td>";
  786. echo "<td width=100%>&nbsp;</td><td>";
  787. if ($readonly === false)
  788. {
  789. $msg = 'Quit CGMiner';
  790. if (count($rigs) > 1)
  791. $msg .= " Rig $rig";
  792. echo "<input type=button value='Quit' onclick='prc(\"quit&rig=$rig\",\"$msg\")'>";
  793. }
  794. echo "</td></tr></table></td></tr>";
  795. if ($preprocess != null)
  796. process(array($preprocess => $preprocess), $rig);
  797. $cmds = array( 'devs' => 'device list',
  798. 'summary' => 'summary information',
  799. 'pools' => 'pool list');
  800. if ($notify)
  801. $cmds['notify'] = 'device status';
  802. $cmds['config'] = 'cgminer config';
  803. process($cmds, $rig);
  804. if ($error == null && $readonly === false)
  805. processgpus($rig);
  806. }
  807. #
  808. function display()
  809. {
  810. global $tablebegin, $tableend;
  811. global $miner, $port;
  812. global $error, $readonly, $notify, $rigs;
  813. $rig = trim(getparam('rig', true));
  814. $arg = trim(getparam('arg', true));
  815. $preprocess = null;
  816. if ($arg != null and $arg != '')
  817. {
  818. $num = null;
  819. if ($rig != null and $rig != '')
  820. {
  821. if ($rig >= 0 and $rig < count($rigs))
  822. $num = $rig;
  823. }
  824. else
  825. if (count($rigs) == 0)
  826. $num = 0;
  827. if ($num != null)
  828. {
  829. $parts = explode(':', $rigs[$num], 2);
  830. if (count($parts) == 2)
  831. {
  832. $miner = $parts[0];
  833. $port = $parts[1];
  834. $preprocess = $arg;
  835. }
  836. }
  837. }
  838. if ($rigs == null or count($rigs) == 0)
  839. {
  840. echo "<tr><td>No rigs defined</td></tr>";
  841. return;
  842. }
  843. if (count($rigs) == 1)
  844. {
  845. $parts = explode(':', $rigs[0], 2);
  846. if (count($parts) == 2)
  847. {
  848. $miner = $parts[0];
  849. $port = $parts[1];
  850. doOne(0, $preprocess);
  851. }
  852. else
  853. echo '<tr><td>Invalid "$rigs" array</td></tr>';
  854. return;
  855. }
  856. if ($rig != null and $rig != '' and $rig >= 0 and $rig < count($rigs))
  857. {
  858. $parts = explode(':', $rigs[$rig], 2);
  859. if (count($parts) == 2)
  860. {
  861. $miner = $parts[0];
  862. $port = $parts[1];
  863. doOne($rig, $preprocess);
  864. }
  865. else
  866. echo '<tr><td>Invalid "$rigs" array</td></tr>';
  867. return;
  868. }
  869. htmlhead(false);
  870. echo "<tr><td><table cellpadding=0 cellspacing=0 border=0><tr><td>";
  871. echo "<input type=button value='Refresh' onclick='pr(\"\",null)'>";
  872. echo "</td></tr></table></td></tr>";
  873. if ($preprocess != null)
  874. process(array($preprocess => $preprocess), $rig);
  875. echo $tablebegin;
  876. doforeach('version', 'rig summary', array(), array(), true);
  877. $sum = array('MHS av', 'Getworks', 'Found Blocks', 'Accepted', 'Rejected', 'Discarded', 'Stale', 'Utility', 'Local Work', 'Total MH');
  878. doforeach('summary', 'summary information', $sum, array(), false);
  879. echo $tableend;
  880. echo '<tr><td><br><br></td></tr>';
  881. echo $tablebegin;
  882. doforeach('devs', 'device list', $sum, array(''=>'','ID'=>'','Name'=>''), false);
  883. echo $tableend;
  884. echo '<tr><td><br><br></td></tr>';
  885. echo $tablebegin;
  886. doforeach('pools', 'pool list', $sum, array(''=>''), false);
  887. echo $tableend;
  888. }
  889. #
  890. display();
  891. #
  892. ?>
  893. </table></td></tr></table>
  894. </body></html>