diff --git a/README.md b/README.md
index 077a462..434c1dc 100644
--- a/README.md
+++ b/README.md
@@ -1,83 +1,141 @@
----== Scripta ==---
-The turnkey solution for litecoin mining with raspberry pi and fpga/asic boards
+Inital information compiled from lots of good stuff around Scripta at litecointalk
+[fourm posts](https://litecointalk.org/index.php?topic=9908.msg143787#msg143787)
+
+1. Started with Scripta 1.1 [image](http://www.lateralfactory.com/download.php?file=scripta-1_1.tgz)
+ * source files in image do not match current Scripta [repo](https://github.com/scriptamining/scripta.git)
+ * rsync github files to image to get starting code base (all uses of "minepeon" replaced with "scripta")
+ * origianl MinePeon [project](http://minepeon.com/index.php/Main_Page) has lots of good PI setup and helpful info
+
+2. Update raspberry to newest kernel (3.10.33+) and added 'slub_debug=FP' to bootline.conf
+ * this should fix the wierd USB debug error logging issues.
+
+3. Set ssh port to 22. Should probably turn off root ssh access and change password.
+ ssh root@10.0.1.28
+ root password: scripta
+ web password: scripta
+
+4. Change locales to en_US
+
+5. Add wifi support (wlan0)
+ * set ssid and psk in `network` block at `/etc/wpa_supplicant/wpa_supplicant.conf`
+
+6. Build GridSeed GS3355 specific version of cgminer with mulit-frequency support from [repo](https://github.com/girnyau/cgminer-gc3355)
+ * modified cgminer-gc3355 to report Frequency and Serial in API calls: [repo](https://github.com/mox235/cgminer-gc3355)
+
+7. Edit `/opt/scripta/startup/miner-start.sh` to use cgminer-gc3355
+
+8. Remove Scripta LTC donation address. Disable MinePeon BTC hash time donation option. Need to determine the right thing to do since _most_ of the web interface stuff is directly from the [MinePeonUI project](https://github.com/MineForeman/zArchive-MinePeonWebUI.git)
+ * other Scripta rebranded PI images at [Crypto Pros](http://www.cryptopros.com/2014/03/gridseed-dual-miner-first-look-amazing.html)
+ * and [Hash Master](https://hash-master.com/blog/using-your-raspberry-pi-as-a-gridseed-mining-controller/)
+ * different PI web-based controller for Gridseed at [Hashra](https://github.com/HASHRA)
+
+9. Fix pool URL JSON encoding. Add back miner config name/values settings from MinePeonUI. All cgminer settings can be changed or added from miner form.
+ * priority used to reorder pool list
+ * ability to set per GSD frequency based on Serial # from freq list:
+ ```
+ static const int opt_frequency[] = {
+ 700, 706, 713, 719, 725, 731, 738, 744,
+ 750, 756, 763, 769, 775, 781, 788, 794,
+ 800, 813, 825, 838, 850, 863, 875, 888,
+ 900, 913, 925, 938, 950, 963, 975, 988,
+ 1000, 1013, 1025, 1038, 1050, 1063, 1075, 1088,
+ 1100, 1113, 1125, 1138, 1150, 1163, 1175, 1188,
+ 1200, 1213, 1225, 1238, 1250, 1263, 1275, 1288,
+ 1300, 1313, 1325, 1338, 1350, 1363, 1375, 1388,
+ 1400,
+ -1
+ };
+ ```
+10. Modify Status table
+ * show KHs instead of MHs
+ * replace Name with GSD Serial Number
+ * replace Temperature with Frequency
+ * remove percentages for DiffAccept and DiffReject
+
+11. Open Issues
+ * maybe reported [hashrate](http://cryptomining-blog.com/1760-what-is-the-actual-hashrate-you-get-from-your-gridseed-asic/) is not quite accurate
+ * something weird with system time display, timezone, day-light savings
+ * graphs should auto-refresh when /status page loads
+
+mega link [scripta-20140330.img](https://mega.co.nz/#!D5RiSZTR!wcDqC3yOeUrYC6tqYM7Lh5YbRjVpdtQhg29CagL4ZsI)
+
+---
+
+scripta-20140401
+
+ * updated PI firmware to maybe fix usb slub crash
+ * fix cgminer to always start at boot `/etc/rc.local`
+ * gzip image
+
+mega link [scripta-20140401.img.gz](https://mega.co.nz/#!Tx42mJab!XMpNsU6cfS23GAuli3C_BgwrdJ15sFLqEF7QNgrYTN4)
+
+---
+
+scripta-20140408
+
+ * install [watchdog](http://linux.die.net/man/8/watchdog) service
+ * load `bcm2708_wdog` kernel module
+ * modify `/opt/watchdog.conf` to reboot PI if bad things happen. See below.
+ * add UI option for cgminer specific watchdog script `/opt/scripta/bin/wdog.py`. See below.
+ * add/fix UI option for manual reboot
+ * option for email notification on PI automatic reboot. *YOUR EMAIL PASSWORD IS STORED IN PLAIN TEXT SO PLAN ACCORDINGLY*
+
+Once the watchdog is enabled, it is possible to get in a reboot loop. If this happens, disable the system watchdog by quick edit of `/etc/watchdog.conf` after boot and comment out `watchdog-device = /dev/watchdog`. The cgminer API based watchdog script can be disabled by using the UI checkbox or commenting out `test-binary = /opt/scripta/bin/wdog.py` in the same config file. You will have about 30 seconds each loop to try and unscrew things.
+
+The system watchdog daemon will check the following every 30 seconds:
+ - sytem load less than 24/18/12
+ - more than 1 page of RAM available
+ - syslog still alive
+ - cgminer specific watchdog script `/opt/scripta/bin/wdog.py` that uses the following logic:
+
+ ```
+ if (UI manual reboot)
+ {
+ force PI reboot
+ }
+ if (UI auto reboot)
+ {
+ if (sytem up for more than 60 seconds)
+ {
+ if (cgminer process not running)
+ {
+ if (UI enable) send email
+ force PI reboot
+ }
+ if (ASIC device count less UI device count)
+ {
+ if (UI enable) send email
+ force PI reboot
+ }
+ for (each ASIC device)
+ {
+ if (device hashrate less than UI value)
+ {
+ if (UI enable) send email
+ force PI reboot
+ }
+ }
+ }
+ }
+ OK (yay!!!)
+ ```
+ - watchdog details logged to syslog
+
+mega link [scripta-20140408.img.gz](https://mega.co.nz/#!ah4XkCpL!A-b_10rNj1GvfQN36waTzxCRCHB_8UltIA4pFgaXIkw)
+
+---
+
+scripta-20140423
+
+ * Install wicd and wicd-curses to help with WiFi network configuration. Use `wicd-curses` to setup your WiFi.
+ * Fixed double emails from "cgminer process not running" reboot.
+ * Update openssl (heartbleed)
+ * Upgrade/downgrade rpi firmware to use 3.10.36+ kernel. Maybe more stable USB than 20140408 version using "next" branch (??)
+ * Replace miner with bfgminer for stability. Update browser options to display status. No longer able to set/display individual GSD clock frequencies.
+
+Miner bfgminer 3.99.0 seems to be more stable than wierd cgminer 3.7.2 branch. Ongoing gridseed support scheduled to be merged into main bfgminer in next (4.0.0) main version release.
+
+mega link [scripta-20140423.img.gz](https://mega.co.nz/#!PwB0jIzK!ltpfKSBv_IOc1gsyPog3eotnprKFOBoOoEkgiPN3-GY)
----=== INSTALL INTRUCTIONS ===---
-
-
-
----=== The easy way ===---
-
-1) Download the full image here http://www.lateralfactory.com/download.php?file=scripta-1_1.tgz
-
-2) Burn it on a ssd in your favourite way
-
-3) Log in as root from a console (pw is "scripta")
-
-4) Remember to change root password with passwd
-
-5) Enjoy
-
-
-
----=== The way of the turtle ===---
-
-Start from a fresh raspbian wheezy (tested with 2014-01-07) Download here http://downloads.raspberrypi.org/raspbian_latest
-
-$>raspi-config ( if needed "Expand Filesystem" and reboot )
-
-$>sudo apt-get update
-
-$>sudo apt-get install lighttpd
-
-$>sudo apt-get install php5-common php5-cgi php5 (Pay attention to packet's order)
-
-$>sudo lighty-enable-mod fastcgi-php
-
-$>sudo /etc/init.d/lighttpd force-reload
-
----= Add pi user to www-data group =---
-
-$>sudousermod -a -G www-data pi
-
-$>sudo apt-get install php5-rrd libexpect-php5 php-auth-sasl php-mail php-net-smtp php-net-socket
-
-
----= Needed to enable https =---
-
-$>sudo mkdir /etc/lighttpd/certs
-
-$>sudo su
-
-$>cd /etc/lighttpd/certs
-
-$>openssl req -new -x509 -keyout lighttpd.pem -out lighttpd.pem -days 365 -nodes
-
-$>chmod 400 lighttpd.pem
-
-$>/etc/init.d/lighttpd force-reload
-
-
----= edit /etc/lighttpd/lighttpd.conf =---
-
-$>pico /etc/lighttpd/lighttpd.conf
-
----= add the following lines at the end =---
-
-$SERVER["socket"] == ":443" {
- ssl.engine = "enable"
- ssl.pemfile = "/etc/lighttpd/certs/lighttpd.pem"
-}
-
----= libs for cgminer =---
-
-$>sudo apt-get install libjansson4 libusb-1.0-0 ntpdate screen
-
----= install scripta package =---
-
-$>cd /
-
-$>tar -xf scripta_1-1.tgz
-
----= point your browser on raspberry ip address, enjoy! =---
diff --git a/etc/rc.local b/etc/rc.local
index c880c94..aa43ef1 100644
--- a/etc/rc.local
+++ b/etc/rc.local
@@ -11,10 +11,11 @@
#
# By default this script does nothing.
+/opt/scripta/startup/miner-start.sh
+sleep 10
+
# Print the IP address
_IP=$(hostname -I) || true
-if [ "$_IP" ]; then
-
echo " "
echo " _________ .__ __ "
echo " / _____/ ___________|__|______/ |______ "
@@ -22,12 +23,8 @@ echo " \_____ \_/ ___\_ __ \ \____ \ __\__ \ "
echo " / \ \___| | \/ | |_> > | / __ \_ "
echo "/_______ /\___ >__| |__| __/|__| (____ / "
echo " \/ \/ |__| \/ "
-
printf "Connect to http://%s to manage Scripta.\n" "$_IP"
printf "Happy mining!\n"
-sudo /opt/scripta/startup/miner-start.sh &
-
-fi
-
exit 0
+
diff --git a/opt/scripta/bin/cgminer-gc3355 b/opt/scripta/bin/cgminer-gc3355
new file mode 100755
index 0000000..022851d
Binary files /dev/null and b/opt/scripta/bin/cgminer-gc3355 differ
diff --git a/opt/scripta/bin/cgminer-monitor.py b/opt/scripta/bin/cgminer-monitor.py
new file mode 100644
index 0000000..2029a66
--- /dev/null
+++ b/opt/scripta/bin/cgminer-monitor.py
@@ -0,0 +1,300 @@
+#!/usr/bin/python
+# Romain Dura | romain@shazbits.com
+# https://github.com/shazbits/cgminer-monitor
+# BTC 1Kcn1Hs76pbnBpBQHwdsDmr3CZYcoCAwjj
+#
+
+import socket
+import sys
+import time
+import smtplib
+import json
+import os
+import threading
+import SimpleHTTPServer
+import SocketServer
+import urllib2
+
+
+#
+# Config
+#
+
+cgminer_host = 'localhost'
+cgminer_port = 4028
+email_smtp_server = 'smtp.gmail.com:587'
+email_login = 'mylogin'
+email_password = 'mypassword'
+email_from = 'myemail@example.com'
+email_to = 'myemail@example.com'
+email_subject = 'Miner warning detected'
+monitor_interval = 15
+monitor_wait_after_email = 60
+monitor_http_interface = '0.0.0.0'
+monitor_http_port = 84
+monitor_restart_cgminer_if_sick = True
+monitor_send_email_alerts = True
+monitor_max_temperature = 85
+monitor_min_mhs_scrypt = 0.5
+monitor_min_mhs_sha256 = 500
+monitor_enable_pools = False
+
+# MMCFE pools (www.wemineltc.com, dgc.mining-foreman.org, megacoin.miningpool.co, etc.)
+# Replace the URLs and/or API keys by your own, add as many pools as you like
+pools = [
+ {
+ 'url': 'http://www.digicoinpool.com/api?api_key=1234567890',
+ 'cur': 'DGC'
+ },
+ {
+ 'url': 'http://www.wemineltc.com/api?api_key=1234567890',
+ 'cur': 'LTC'
+ },
+]
+
+
+#
+# Shared between monitor and http server
+#
+
+shared_output = ''
+shared_output_lock = threading.Lock()
+
+
+#
+# cgminer RPC
+#
+
+class CgminerClient:
+ def __init__(self, host, port):
+ self.host = host
+ self.port = port
+
+ def command(self, command, parameter):
+ # sockets are one time use. open one for each command
+ sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+
+ try:
+ sock.connect((self.host, self.port))
+ if parameter:
+ self._send(sock, json.dumps({"command": command, "parameter": parameter}))
+ else:
+ self._send(sock, json.dumps({"command": command}))
+ received = self._receive(sock)
+ except Exception as e:
+ print e
+ sock.close()
+ return None
+
+ sock.shutdown(socket.SHUT_RDWR)
+ sock.close()
+
+ # the null byte makes json decoding unhappy
+ try:
+ decoded = json.loads(received.replace('\x00', ''))
+ return decoded
+ except:
+ pass # restart makes it fail, but it's ok
+
+ def _send(self, sock, msg):
+ totalsent = 0
+ while totalsent < len(msg):
+ sent = sock.send(msg[totalsent:])
+ if sent == 0:
+ raise RuntimeError("socket connection broken")
+ totalsent = totalsent + sent
+
+ def _receive(self, sock, size=65500):
+ msg = ''
+ while True:
+ chunk = sock.recv(size)
+ if chunk == '':
+ # end of message
+ break
+ msg = msg + chunk
+ return msg
+
+
+#
+# Utils
+#
+
+def SendEmail(from_addr, to_addr_list, cc_addr_list,
+ subject, message, login, password,
+ smtpserver=email_smtp_server):
+ header = 'From: %s\n' % from_addr
+ header += 'To: %s\n' % ','.join(to_addr_list)
+ header += 'Cc: %s\n' % ','.join(cc_addr_list)
+ header += 'Subject: %s\n\n' % subject
+
+ server = smtplib.SMTP(smtpserver)
+ server.starttls()
+ server.login(login, password)
+ server.sendmail(from_addr, to_addr_list, header + message)
+ server.quit()
+
+
+#
+# Monitor
+#
+
+def StartMonitor(client):
+ os.system('cls')
+ while (True):
+ output = ''
+
+ must_send_email = False
+ must_restart = False
+
+ result = client.command('coin', None)
+ coin = ''
+ if result:
+ coin = result['COIN'][0]['Hash Method']
+ output = 'Coin : %s\n' % coin
+
+ result = client.command('pools', None)
+ if result:
+ output += 'Pool URL : %s\n' % (result['POOLS'][0]['Stratum URL'])
+ warning = ' <----- /!\\' if result['POOLS'][0]['Status'] != 'Alive' else ''
+ must_send_email = True if warning != '' else must_send_email
+ output += 'Pool : %s%s\n' % (result['POOLS'][0]['Status'], warning)
+
+ # Put this in a loop for multi-gpu support
+ result = client.command('gpu', '0')
+ if result:
+ gpu_result = result['GPU'][0]
+ warning = ' <----- /!\\' if gpu_result['Status'] != 'Alive' else ''
+ must_restart = True if warning != '' else False
+ must_send_email = True if warning != '' else must_send_email
+ output += 'GPU 0 : %s%s\n' % (gpu_result['Status'], warning)
+
+ min_mhs = monitor_min_mhs_scrypt if coin == 'scrypt' else monitor_min_mhs_sha256
+ warning = ' <----- /!\\' if gpu_result['MHS 1s'] < min_mhs else ''
+ must_send_email = True if warning != '' else must_send_email
+ output += 'MHS 1s/av: %s/%s%s\n' % (gpu_result['MHS 1s'], gpu_result['MHS av'], warning)
+
+ warning = ' <----- /!\\' if gpu_result['Temperature'] > monitor_max_temperature else ''
+ must_send_email = True if warning != '' else must_send_email
+ output += 'Temp : %s%s\n' % (gpu_result['Temperature'], warning)
+ output += 'Intensity: %s\n' % gpu_result['Intensity']
+
+ result = client.command('summary', None)
+ if result:
+ if result['SUMMARY'][0]['Hardware Errors'] > 0:
+ must_send_email = True
+ output += 'HW err : %s%s\n' % (result['SUMMARY'][0]['Hardware Errors'], ' <----- /!\\')
+
+ result = client.command('stats', None)
+ if result:
+ uptime = result['STATS'][0]['Elapsed']
+ output += 'Uptime : %02d:%02d:%02d\n' % (uptime / 3600, (uptime / 60) % 60, uptime % 60)
+ print output
+
+ global shared_output
+ global shared_output_lock
+ shared_output_lock.acquire()
+ shared_output = output
+ shared_output_lock.release()
+
+ if must_restart and monitor_restart_cgminer_if_sick:
+ print 'Restarting'
+ result = client.command('restart', None)
+
+ if must_send_email and monitor_send_email_alerts and uptime > 10:
+ SendEmail(from_addr=email_from, to_addr_list=[email_to], cc_addr_list=[],
+ subject=email_subject,
+ message=output,
+ login=email_login,
+ password=email_password)
+ time.sleep(monitor_wait_after_email)
+
+ # Sleep by increments of 1 second to catch the keyboard interrupt
+ for i in range(monitor_interval):
+ time.sleep(1)
+
+ os.system('cls')
+
+
+#
+# HTTP server request handler
+#
+
+class CGMinerRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
+ def do_GET(self):
+ self.send_response(200)
+
+ if self.path == '/favicon.ico':
+ return
+
+ self.send_header("Content-type", "text/html")
+ self.end_headers()
+
+ global shared_output
+ global shared_output_lock
+ shared_output_lock.acquire()
+ html_output = shared_output[:-1] # one too many \n
+ shared_output_lock.release()
+
+ # Get balance from pools
+ pools_output = ''
+ if monitor_enable_pools:
+ td_div = '
'
+ for pool in pools:
+ try:
+ response = urllib2.urlopen(pool['url'])
+ data = json.load(response)
+ pools_output += '\n \n' + td_div + '\n' + 'pool' + '' + td_div + pool['cur'] + ' %.6f' % (float(data['confirmed_rewards']))
+ except urllib2.HTTPError as e:
+ pools_output += '\n \n' + td_div + '\n' + 'pool' + '' + td_div + pool['cur'] + ' Error: ' + str(e.code)
+ except urllib2.URLError as e:
+ pools_output += '\n \n' + td_div + '\n' + 'pool' + '' + td_div + pool['cur'] + ' Error: ' + e.reason
+ except:
+ pools_output += '\n \n' + td_div + '\n' + 'pool' + '' + td_div + pool['cur'] + ' Error: unsupported pool?'
+
+ # Format results from the monitor
+ td_div = ''
+ html_output = ('\n \n' + td_div + '\n').join(html_output.replace(': ', '' + td_div).split('\n'))
+ html_output += pools_output
+ html = """
+
+
+
+ cgminer monitor
+
+
+
+
+ """ + html_output + """
+
+
+
+
+ """
+ self.wfile.write(html)
+
+
+#
+# usage: cgminer-monitor.py [command] [parameter]
+# No arguments: monitor + http server mode. Press CTRL+C to stop.
+# Arguments: send the command with optional parameter and exit.
+#
+
+if __name__ == "__main__":
+ command = sys.argv[1] if len(sys.argv) > 1 else None
+ parameter = sys.argv[2] if len(sys.argv) > 2 else None
+
+ client = CgminerClient(cgminer_host, cgminer_port)
+
+ if command:
+ # An argument was specified, ask cgminer and exit
+ result = client.command(command, parameter)
+ print result if result else 'Cannot get valid response from cgminer'
+ else:
+ # No argument, start the monitor and the http server
+ try:
+ server = SocketServer.TCPServer((monitor_http_interface, monitor_http_port), CGMinerRequestHandler)
+ threading.Thread(target=server.serve_forever).start()
+ StartMonitor(client)
+ except KeyboardInterrupt:
+ server.shutdown()
+
diff --git a/opt/scripta/bin/wdog.py b/opt/scripta/bin/wdog.py
new file mode 100644
index 0000000..9650eb6
--- /dev/null
+++ b/opt/scripta/bin/wdog.py
@@ -0,0 +1,234 @@
+#!/usr/bin/python
+#
+# Scripta watchdog test for cgminer status
+#
+# parts used from cgminer-monitor.py
+# Romain Dura | romain@shazbits.com
+# https://github.com/shazbits/cgminer-monitor
+# BTC 1Kcn1Hs76pbnBpBQHwdsDmr3CZYcoCAwjj
+#
+
+import socket
+import sys
+import time
+import smtplib
+import json
+import os
+import threading
+import SimpleHTTPServer
+import SocketServer
+import urllib2
+import datetime, time
+import pprint
+
+#
+# Config
+#
+
+cgminer_host = 'localhost'
+cgminer_port = 4028
+monitor_interval = 15
+monitor_wait_after_email = 10
+
+shared_output = ''
+shared_output_lock = threading.Lock()
+
+#
+# cgminer RPC
+#
+
+class CgminerClient:
+ def __init__(self, host, port):
+ self.host = host
+ self.port = port
+
+ def command(self, command, parameter):
+ # sockets are one time use. open one for each command
+ sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+
+ try:
+ sock.connect((self.host, self.port))
+ if parameter:
+ self._send(sock, json.dumps({"command": command, "parameter": parameter}))
+ else:
+ self._send(sock, json.dumps({"command": command}))
+ received = self._receive(sock)
+ except Exception as e:
+ print e
+ sock.close()
+ return None
+
+ sock.shutdown(socket.SHUT_RDWR)
+ sock.close()
+
+ # the null byte makes json decoding unhappy
+ try:
+ decoded = json.loads(received.replace('\x00', ''))
+ return decoded
+ except:
+ pass # restart makes it fail, but it's ok
+
+ def _send(self, sock, msg):
+ totalsent = 0
+ while totalsent < len(msg):
+ sent = sock.send(msg[totalsent:])
+ if sent == 0:
+ raise RuntimeError("socket connection broken")
+ totalsent = totalsent + sent
+
+ def _receive(self, sock, size=65500):
+ msg = ''
+ while True:
+ chunk = sock.recv(size)
+ if chunk == '':
+ # end of message
+ break
+ msg = msg + chunk
+ return msg
+
+
+#
+# Utils
+#
+
+def SendEmail(from_addr, to_addr_list, cc_addr_list,
+ subject, message, login, password,
+ smtpserver):
+ header = 'From: %s\n' % from_addr
+ header += 'To: %s\n' % ','.join(to_addr_list)
+ header += 'Cc: %s\n' % ','.join(cc_addr_list)
+ header += 'Subject: %s\n\n' % subject
+
+ server = smtplib.SMTP(smtpserver)
+ server.starttls()
+ server.login(login, password)
+ server.sendmail(from_addr, to_addr_list, header + message)
+ server.quit()
+ print 'send email: ' + to_addr_list[0]
+
+
+if __name__ == "__main__":
+
+ now = (datetime.datetime.now()-datetime.datetime(1970,1,1)).total_seconds()
+
+ if os.path.exists('/tmp/wdog.ts'):
+ ts_file=open('/tmp/wdog.ts','r')
+ dt = now - float(ts_file.readline())
+ ts_file.close();
+ else:
+ ts_file=open('/tmp/wdog.ts','w')
+ ts_file.write(str(now));
+ ts_file.close;
+ dt = 0.0;
+
+ if os.path.exists('/tmp/reboot.ts'):
+ print 'OK - wait for reboot command'
+ sys.exit(0)
+
+ conf_file=open('/opt/scripta/etc/scripta.conf')
+ conf = json.load(conf_file)
+ pprint.pprint(conf)
+ conf_file.close()
+
+ if conf['rebootEnable']:
+ conf['rebootEnable'] = False
+ with open('/opt/scripta/etc/scripta.conf', 'w') as outfile:
+ json.dump(conf, outfile)
+ print 'OK - reboot command'
+ sys.exit(1)
+
+ if not conf['recoverEnable']:
+ print 'OK - scripta watchdog disabled'
+ sys.exit(0)
+
+ if dt < 60.0:
+ print 'OK - wait for cgminer startup ' + str(dt) + ' sec'
+ sys.exit(0)
+
+ print 'expected device count: ' + str(conf['miningExpDev'])
+ print 'expected min hashrate: ' + str(conf['miningExpHash'])
+
+ pid_file=open('/var/run/bfgminer.pid','r')
+ if not pid_file:
+ print 'ERROR - bfgminer.pid not found'
+ else:
+ pid = int(pid_file.readline())
+ pid_file.close()
+ ps = '/proc/' + str(pid) + '/'
+ if os.path.exists(ps):
+ print 'OK - bfgminer process running'
+ else:
+ output = 'ERROR - bfgminer process not running (pid ' + ps + ')'
+ time.sleep(3)
+ if not os.path.exists(ps):
+ output = 'ERROR - bfgminer process not running (pid ' + ps + ')'
+ if conf['alertEnable']:
+ SendEmail(
+ from_addr='scripta@hotmail.com',
+ to_addr_list=[conf['alertEmailTo']],
+ cc_addr_list=[],
+ subject='Scripta Reboot [' + conf['alertDevice'] + ']',
+ message=output,
+ login=conf['alertSmtpUser'],
+ password=conf['alertSmtpPwd'],
+ smtpserver=conf['alertSmtp'] + ':' + str(conf['alertSmtpPort']))
+ time.sleep(monitor_wait_after_email)
+ ts_file=open('/tmp/reboot.ts','w')
+ ts_file.write(str(now));
+ ts_file.close;
+ sys.exit(1) # reboot
+
+ client = CgminerClient(cgminer_host, cgminer_port)
+
+ result = client.command('pgacount', None)
+ if result:
+ dev = result['PGAS'][0]['Count']
+ if conf['miningExpDev'] > dev:
+ output = 'ERROR - device count: ' + str(dev) + '\n\n' + pprint.pformat(result)
+ print output
+ if conf['alertEnable']:
+ SendEmail(
+ from_addr='scripta@hotmail.com',
+ to_addr_list=[conf['alertEmailTo']],
+ cc_addr_list=[],
+ subject='Scripta Reboot [' + conf['alertDevice'] + ']',
+ message=output,
+ login=conf['alertSmtpUser'],
+ password=conf['alertSmtpPwd'],
+ smtpserver=conf['alertSmtp'] + ':' + str(conf['alertSmtpPort']))
+ time.sleep(monitor_wait_after_email)
+ ts_file=open('/tmp/reboot.ts','w')
+ ts_file.write(str(now));
+ ts_file.close;
+ sys.exit(1) # reboot
+ else:
+ print 'OK - device count: ' + str(dev)
+ else:
+ print 'OK - cgminer not ready'
+ sys.exit(0);
+
+ result = client.command('devs', None)
+ if result:
+ for d in result['DEVS']:
+ if conf['miningExpHash'] > d['MHS av']:
+ output = 'ERROR - ' + str(d['Name']) + str(d['ID']) + ' hashrate: ' + str(d['MHS av']) + '\n\n' + pprint.pformat(result)
+ print output
+ if conf['alertEnable']:
+ SendEmail(
+ from_addr='scripta@hotmail.com',
+ to_addr_list=[conf['alertEmailTo']],
+ cc_addr_list=[],
+ subject='Scripta Reboot [' + conf['alertDevice'] + ']',
+ message=output,
+ login=conf['alertSmtpUser'],
+ password=conf['alertSmtpPwd'],
+ smtpserver=conf['alertSmtp'] + ':' + str(conf['alertSmtpPort']))
+ time.sleep(monitor_wait_after_email)
+ ts_file=open('/tmp/reboot.ts','w')
+ ts_file.write(str(now));
+ ts_file.close;
+ sys.exit(1) # reboot
+ else:
+ print 'OK - ' + str(d['ID']) + ' hashrate: ' + str(d['MHS av'])
+
+ sys.exit(0)
\ No newline at end of file
diff --git a/opt/scripta/etc/miner.conf b/opt/scripta/etc/miner.conf
index e0e6b65..db016c2 100644
--- a/opt/scripta/etc/miner.conf
+++ b/opt/scripta/etc/miner.conf
@@ -1,19 +1,42 @@
{
"api-listen": true,
"api-port": "4028",
+ "api-allow": "W:127.0.0.1,192.168.100.0/24",
"expiry": "120",
"hotplug": "5",
"log": "5",
"no-pool-disable": true,
- "queue": "1",
+ "no-show-processors": true,
+ "no-show-procs": true,
+ "no-submit-stale": true,
+ "queue": "90",
"scan-time": "30",
"scrypt": true,
"shares": "0",
+ "scan": [
+ "gridseed:all"
+ ],
+ "set-device": [
+ "gridseed:clock=825"
+ ],
"pools": [
{
- "url": "stratum tcp:\/\/global.wemineltc.com:3335",
- "user": "drfranz.gs",
- "pass": "gs"
+ "url": "stratum+tcp://us.ltcrabbit.com:3334",
+ "user": "mox235.0",
+ "pass": "0",
+ "prio": "0"
+ },
+ {
+ "url": "stratum+tcp://stratum.scryptguild.com:3333",
+ "user": "mox235_0",
+ "pass": "0",
+ "prio": "1"
+ },
+ {
+ "url": "stratum+tcp://usa.wemineltc.com:3336",
+ "user": "mox235.0",
+ "pass": "0",
+ "prio": "2"
}
]
-}
\ No newline at end of file
+}
diff --git a/opt/scripta/etc/miner.options.json b/opt/scripta/etc/miner.options.json
index a49f1bb..8bd199d 100644
--- a/opt/scripta/etc/miner.options.json
+++ b/opt/scripta/etc/miner.options.json
@@ -8,39 +8,65 @@
"value": "4028"
},
{
- "key": "expiry",
- "value": "120"
- },
- {
- "key": "hotplug",
- "value": "5"
- },
- {
- "key": "log",
- "value": "5"
- },
- {
- "key": "no-pool-disable",
- "value": true
- },
- {
- "key": "queue",
- "value": "1"
- },
- {
- "key": "scan-time",
- "value": "30"
- },
- {
- "key": "scan-time",
- "value": "30"
- },
-{
- "key": "scrypt",
- "value": true
- },
-{
- "key": "shares",
- "value": "0"
- }
+ "key": "api-allow",
+ "value": "W:127.0.0.1,192.168.100.0/24"
+ },
+ {
+ "key": "expiry",
+ "value": "120"
+ },
+ {
+ "key": "hotplug",
+ "value": "5"
+ },
+ {
+ "key": "log",
+ "value": "5"
+ },
+ {
+ "key": "no-pool-disable",
+ "value": true
+ },
+ {
+ "key": "no-show-processors",
+ "value": true
+ },
+ {
+ "key": "no-show-procs",
+ "value": true
+ },
+ {
+ "key": "no-submit-stale",
+ "value": true
+ },
+ {
+ "key": "queue",
+ "value": "90"
+ },
+ {
+ "key": "scan-time",
+ "value": "30"
+ },
+ {
+ "key": "scrypt",
+ "value": true
+ },
+ {
+ "key": "shares",
+ "value": "0"
+ },
+ {
+ "key": "scan",
+ "value":
+ [
+ "gridseed:all"
+ ]
+ },
+ {
+ "key": "set-device",
+ "value":
+ [
+ "gridseed:clock=825"
+ ]
+ }
]
diff --git a/opt/scripta/etc/miner.pools.json b/opt/scripta/etc/miner.pools.json
index 946e384..62e9035 100644
--- a/opt/scripta/etc/miner.pools.json
+++ b/opt/scripta/etc/miner.pools.json
@@ -1,7 +1,18 @@
[
{
- "url": "stratum tcp:\/\/global.wemineltc.com:3335",
- "user": "drfranz.gs",
- "pass": "gs"
+ "url": "stratum tcp:\/\/usa.wemineltc.com:3336",
+ "user": "mox235.1",
+ "pass": "\"1\""
+ },
+ {
+ "url": "stratum tcp:\/\/united.wemineltc.com:3335",
+ "user": "mox235.1",
+ "pass": "\"1\""
+ },
+ {
+ "url": "stratum tcp:\/\/stratum.scryptguild.com:3333",
+ "user": "mox235_gridseed",
+ "pass": "\"1\""
}
-]
\ No newline at end of file
+]
+
diff --git a/opt/scripta/http/rrd/rrd b/opt/scripta/http/rrd/rrd
deleted file mode 100644
index 7a90797..0000000
--- a/opt/scripta/http/rrd/rrd
+++ /dev/null
@@ -1 +0,0 @@
-rrd
\ No newline at end of file
diff --git a/opt/scripta/startup/.miner-start.sh.swp b/opt/scripta/startup/.miner-start.sh.swp
deleted file mode 100644
index a173e3b..0000000
Binary files a/opt/scripta/startup/.miner-start.sh.swp and /dev/null differ
diff --git a/opt/scripta/startup/miner-start.sh b/opt/scripta/startup/miner-start.sh
index bc53286..a9977fa 100644
--- a/opt/scripta/startup/miner-start.sh
+++ b/opt/scripta/startup/miner-start.sh
@@ -1,8 +1,5 @@
#!/bin/bash
-sudo /usr/sbin/ntpdate -u pool.ntp.org
-sudo /usr/bin/screen -dmS cgminer /opt/scripta/bin/cgminer -c /opt/scripta/etc/miner.conf
-
-#sudo /opt/scripta/bin/cgminer -c /opt/scripta/etc/miner.conf >> /dev/null &
-#echo $! > /opt/scripta/var/cgminer.lock
-
-
+/usr/sbin/ntpdate -u pool.ntp.org
+/usr/bin/screen -dmS cgminer /opt/scripta/bin/cgminer-gc3355 -c /opt/scripta/etc/miner.conf
+sleep 1
+echo `pidof bfgminer` > /opt/scripta/var/bfgminer.pid
\ No newline at end of file
diff --git a/var/www/f_settings.php b/var/www/f_settings.php
index d942aee..258c9cd 100644
--- a/var/www/f_settings.php
+++ b/var/www/f_settings.php
@@ -6,6 +6,8 @@
die();
}
+include('inc/ChromePhp.php');
+
/*
f_settings syncs settings in different files and always returns new state
returns settings and ['date']
@@ -38,8 +40,9 @@
foreach ($newdata as $key => $value) {
$r['data'][$key]=$value;
}
- file_put_contents($configScripta, json_encode($r['data'], JSON_PRETTY_PRINT | JSON_NUMERIC_CHECK));
+ file_put_contents($configScripta, json_encode($r['data'], JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES));
$r['info'][]=array('type' => 'success', 'text' => 'Configuration saved');
+ if ($r['data']['rebootEnable']) $r['info'][]=array('type' => 'success', 'text' => 'Reboot Now');
}
// Load current settings
else{
@@ -56,10 +59,32 @@
elseif (!empty($_REQUEST['pools'])) {
$newdata = json_decode($_REQUEST['pools'], true);
$r['data'] = json_decode(@file_get_contents($configPools), true);
+
+ foreach ($r['data'] as $id => $p)
+ {
+ $r['data'][$id]['url'] = str_replace('stratum tcp','stratum+tcp',$p['url']);
+ }
+ $m=0;
+ foreach ($newdata as $id => $p)
+ {
+ $newdata[$id]['url'] = str_replace('stratum tcp','stratum+tcp',$p['url']);
+ if($p['prio'] > $m) $m=$p['prio'];
+ }
+
+ // reorder pool list based on priority
+ if($m>0){
+ $pl=array();
+ for ($pp = 0; $pp <= $m; $pp++) {
+ foreach ($newdata as $id => $p){
+ if($p['prio'] == $pp) $pl[]=$newdata[$id];
+ }
+ }
+ $newdata = $pl;
+ }
// Overwrite current with new pools
if(!empty($newdata)&&is_array($newdata)){
- file_put_contents($configPools, json_encode($newdata, JSON_PRETTY_PRINT | JSON_NUMERIC_CHECK));
+ file_put_contents($configPools, json_encode($newdata, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES));
minerConfigGenerate();
$r['data']=$newdata;
$r['info'][]=array('type' => 'success', 'text' => 'Pools config saved');
@@ -82,7 +107,7 @@
// Overwrite current with new config
if(!empty($newdata)&&is_array($newdata)){
- file_put_contents($configOptns, json_encode($newdata, JSON_PRETTY_PRINT | JSON_NUMERIC_CHECK));
+ file_put_contents($configOptns, json_encode($newdata, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES));
minerConfigGenerate();
$r['data']=$newdata;
$r['info'][]=array('type' => 'success', 'text' => 'Miner options saved');
@@ -117,10 +142,15 @@ function minerConfigGenerate(){
// Angular objects ==> miner
// {key:k,value:v} ==> {k:v}
foreach ($options as $o) {
- $miner[$o['key']]=$o['value'];
+ if ($o['key']=='scan' || $o['key']=='set-device'){
+ $miner[$o['key']]=array($o['value']);
+ }
+ else{
+ $miner[$o['key']]=$o['value'];
+ }
}
$miner['pools']= json_decode(@file_get_contents($configPools), true);
- file_put_contents($configMiner, json_encode($miner, JSON_PRETTY_PRINT));
+ file_put_contents($configMiner, json_encode($miner, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES));
}
?>
diff --git a/var/www/f_status.php b/var/www/f_status.php
index 30eace5..f6b6942 100644
--- a/var/www/f_status.php
+++ b/var/www/f_status.php
@@ -12,6 +12,7 @@
header('Content-type: application/json');
include('inc/cgminer.inc.php');
+include('inc/ChromePhp.php');
// Miner data
//$r['summary'] = cgminer('summary', '')['SUMMARY'];
@@ -53,6 +54,8 @@
$HardwareErrors = 0;
$Utility = 0;
+// ChromePhp::log($r['status']);
+
if(!empty($r['status']['devs'])){
foreach ($r['status']['devs'] as $id => $dev) {
$devices += $dev['MHS5s']>0?1:0; // Only count hashing devices
@@ -66,18 +69,10 @@
}
}
-
-$ret = explode(' ',$MHS5s);
-$KHS5s = ($ret[0]/1024). " Kh/s";
-$ret = explode(' ',$MHSav);
-$KHSav = ($ret[0]/1024). " Kh/s";
-
$r['status']['dtot']=array(
'devices'=>$devices,
'MHS5s'=>$MHS5s,
'MHSav'=>$MHSav,
- 'KHS5s'=>$KHS5s,
- 'KHSav'=>$KHSav,
'Accepted'=>$Accepted,
'Rejected'=>$Rejected,
'HardwareErrors'=>$HardwareErrors,
diff --git a/var/www/inc/ChromePhp.php b/var/www/inc/ChromePhp.php
new file mode 100644
index 0000000..577b1ce
--- /dev/null
+++ b/var/www/inc/ChromePhp.php
@@ -0,0 +1,446 @@
+
+ */
+class ChromePhp
+{
+ /**
+ * @var string
+ */
+ const VERSION = '4.1.0';
+
+ /**
+ * @var string
+ */
+ const HEADER_NAME = 'X-ChromeLogger-Data';
+
+ /**
+ * @var string
+ */
+ const BACKTRACE_LEVEL = 'backtrace_level';
+
+ /**
+ * @var string
+ */
+ const LOG = 'log';
+
+ /**
+ * @var string
+ */
+ const WARN = 'warn';
+
+ /**
+ * @var string
+ */
+ const ERROR = 'error';
+
+ /**
+ * @var string
+ */
+ const GROUP = 'group';
+
+ /**
+ * @var string
+ */
+ const INFO = 'info';
+
+ /**
+ * @var string
+ */
+ const GROUP_END = 'groupEnd';
+
+ /**
+ * @var string
+ */
+ const GROUP_COLLAPSED = 'groupCollapsed';
+
+ /**
+ * @var string
+ */
+ const TABLE = 'table';
+
+ /**
+ * @var string
+ */
+ protected $_php_version;
+
+ /**
+ * @var int
+ */
+ protected $_timestamp;
+
+ /**
+ * @var array
+ */
+ protected $_json = array(
+ 'version' => self::VERSION,
+ 'columns' => array('log', 'backtrace', 'type'),
+ 'rows' => array()
+ );
+
+ /**
+ * @var array
+ */
+ protected $_backtraces = array();
+
+ /**
+ * @var bool
+ */
+ protected $_error_triggered = false;
+
+ /**
+ * @var array
+ */
+ protected $_settings = array(
+ self::BACKTRACE_LEVEL => 1
+ );
+
+ /**
+ * @var ChromePhp
+ */
+ protected static $_instance;
+
+ /**
+ * Prevent recursion when working with objects referring to each other
+ *
+ * @var array
+ */
+ protected $_processed = array();
+
+ /**
+ * constructor
+ */
+ private function __construct()
+ {
+ $this->_php_version = phpversion();
+ $this->_timestamp = $this->_php_version >= 5.1 ? $_SERVER['REQUEST_TIME'] : time();
+ $this->_json['request_uri'] = $_SERVER['REQUEST_URI'];
+ }
+
+ /**
+ * gets instance of this class
+ *
+ * @return ChromePhp
+ */
+ public static function getInstance()
+ {
+ if (self::$_instance === null) {
+ self::$_instance = new self();
+ }
+ return self::$_instance;
+ }
+
+ /**
+ * logs a variable to the console
+ *
+ * @param mixed $data,... unlimited OPTIONAL number of additional logs [...]
+ * @return void
+ */
+ public static function log()
+ {
+ $args = func_get_args();
+ return self::_log('', $args);
+ }
+
+ /**
+ * logs a warning to the console
+ *
+ * @param mixed $data,... unlimited OPTIONAL number of additional logs [...]
+ * @return void
+ */
+ public static function warn()
+ {
+ $args = func_get_args();
+ return self::_log(self::WARN, $args);
+ }
+
+ /**
+ * logs an error to the console
+ *
+ * @param mixed $data,... unlimited OPTIONAL number of additional logs [...]
+ * @return void
+ */
+ public static function error()
+ {
+ $args = func_get_args();
+ return self::_log(self::ERROR, $args);
+ }
+
+ /**
+ * sends a group log
+ *
+ * @param string value
+ */
+ public static function group()
+ {
+ $args = func_get_args();
+ return self::_log(self::GROUP, $args);
+ }
+
+ /**
+ * sends an info log
+ *
+ * @param mixed $data,... unlimited OPTIONAL number of additional logs [...]
+ * @return void
+ */
+ public static function info()
+ {
+ $args = func_get_args();
+ return self::_log(self::INFO, $args);
+ }
+
+ /**
+ * sends a collapsed group log
+ *
+ * @param string value
+ */
+ public static function groupCollapsed()
+ {
+ $args = func_get_args();
+ return self::_log(self::GROUP_COLLAPSED, $args);
+ }
+
+ /**
+ * ends a group log
+ *
+ * @param string value
+ */
+ public static function groupEnd()
+ {
+ $args = func_get_args();
+ return self::_log(self::GROUP_END, $args);
+ }
+
+ /**
+ * sends a table log
+ *
+ * @param string value
+ */
+ public static function table()
+ {
+ $args = func_get_args();
+ return self::_log(self::TABLE, $args);
+ }
+
+ /**
+ * internal logging call
+ *
+ * @param string $type
+ * @return void
+ */
+ protected static function _log($type, array $args)
+ {
+ // nothing passed in, don't do anything
+ if (count($args) == 0 && $type != self::GROUP_END) {
+ return;
+ }
+
+ $logger = self::getInstance();
+
+ $logger->_processed = array();
+
+ $logs = array();
+ foreach ($args as $arg) {
+ $logs[] = $logger->_convert($arg);
+ }
+
+ $backtrace = debug_backtrace(false);
+ $level = $logger->getSetting(self::BACKTRACE_LEVEL);
+
+ $backtrace_message = 'unknown';
+ if (isset($backtrace[$level]['file']) && isset($backtrace[$level]['line'])) {
+ $backtrace_message = $backtrace[$level]['file'] . ' : ' . $backtrace[$level]['line'];
+ }
+
+ $logger->_addRow($logs, $backtrace_message, $type);
+ }
+
+ /**
+ * converts an object to a better format for logging
+ *
+ * @param Object
+ * @return array
+ */
+ protected function _convert($object)
+ {
+ // if this isn't an object then just return it
+ if (!is_object($object)) {
+ return $object;
+ }
+
+ //Mark this object as processed so we don't convert it twice and it
+ //Also avoid recursion when objects refer to each other
+ $this->_processed[] = $object;
+
+ $object_as_array = array();
+
+ // first add the class name
+ $object_as_array['___class_name'] = get_class($object);
+
+ // loop through object vars
+ $object_vars = get_object_vars($object);
+ foreach ($object_vars as $key => $value) {
+
+ // same instance as parent object
+ if ($value === $object || in_array($value, $this->_processed, true)) {
+ $value = 'recursion - parent object [' . get_class($value) . ']';
+ }
+ $object_as_array[$key] = $this->_convert($value);
+ }
+
+ $reflection = new ReflectionClass($object);
+
+ // loop through the properties and add those
+ foreach ($reflection->getProperties() as $property) {
+
+ // if one of these properties was already added above then ignore it
+ if (array_key_exists($property->getName(), $object_vars)) {
+ continue;
+ }
+ $type = $this->_getPropertyKey($property);
+
+ if ($this->_php_version >= 5.3) {
+ $property->setAccessible(true);
+ }
+
+ try {
+ $value = $property->getValue($object);
+ } catch (ReflectionException $e) {
+ $value = 'only PHP 5.3 can access private/protected properties';
+ }
+
+ // same instance as parent object
+ if ($value === $object || in_array($value, $this->_processed, true)) {
+ $value = 'recursion - parent object [' . get_class($value) . ']';
+ }
+
+ $object_as_array[$type] = $this->_convert($value);
+ }
+ return $object_as_array;
+ }
+
+ /**
+ * takes a reflection property and returns a nicely formatted key of the property name
+ *
+ * @param ReflectionProperty
+ * @return string
+ */
+ protected function _getPropertyKey(ReflectionProperty $property)
+ {
+ $static = $property->isStatic() ? ' static' : '';
+ if ($property->isPublic()) {
+ return 'public' . $static . ' ' . $property->getName();
+ }
+
+ if ($property->isProtected()) {
+ return 'protected' . $static . ' ' . $property->getName();
+ }
+
+ if ($property->isPrivate()) {
+ return 'private' . $static . ' ' . $property->getName();
+ }
+ }
+
+ /**
+ * adds a value to the data array
+ *
+ * @var mixed
+ * @return void
+ */
+ protected function _addRow(array $logs, $backtrace, $type)
+ {
+ // if this is logged on the same line for example in a loop, set it to null to save space
+ if (in_array($backtrace, $this->_backtraces)) {
+ $backtrace = null;
+ }
+
+ // for group, groupEnd, and groupCollapsed
+ // take out the backtrace since it is not useful
+ if ($type == self::GROUP || $type == self::GROUP_END || $type == self::GROUP_COLLAPSED) {
+ $backtrace = null;
+ }
+
+ if ($backtrace !== null) {
+ $this->_backtraces[] = $backtrace;
+ }
+
+ $row = array($logs, $backtrace, $type);
+
+ $this->_json['rows'][] = $row;
+ $this->_writeHeader($this->_json);
+ }
+
+ protected function _writeHeader($data)
+ {
+ header(self::HEADER_NAME . ': ' . $this->_encode($data));
+ }
+
+ /**
+ * encodes the data to be sent along with the request
+ *
+ * @param array $data
+ * @return string
+ */
+ protected function _encode($data)
+ {
+ return base64_encode(utf8_encode(json_encode($data)));
+ }
+
+ /**
+ * adds a setting
+ *
+ * @param string key
+ * @param mixed value
+ * @return void
+ */
+ public function addSetting($key, $value)
+ {
+ $this->_settings[$key] = $value;
+ }
+
+ /**
+ * add ability to set multiple settings in one call
+ *
+ * @param array $settings
+ * @return void
+ */
+ public function addSettings(array $settings)
+ {
+ foreach ($settings as $key => $value) {
+ $this->addSetting($key, $value);
+ }
+ }
+
+ /**
+ * gets a setting
+ *
+ * @param string key
+ * @return mixed
+ */
+ public function getSetting($key)
+ {
+ if (!isset($this->_settings[$key])) {
+ return null;
+ }
+ return $this->_settings[$key];
+ }
+}
diff --git a/var/www/index.php b/var/www/index.php
index 491db8b..3c1d437 100644
--- a/var/www/index.php
+++ b/var/www/index.php
@@ -22,7 +22,7 @@
-->
-
+
@@ -85,11 +85,11 @@
-
Temp {{status.pi.temp}} °C
-
- Load {{100*status.pi.load|number:0}}
+ Load {{status.pi.load|number:2}}
Scripta , by Lateral Factory under GPLv3 License
-LTC Donations welcome : Lcb3cy5nPnh3pQWPCpa55Zg8ShZj5kUHYC
+
diff --git a/var/www/login.php b/var/www/login.php
index 8f83799..4810992 100644
--- a/var/www/login.php
+++ b/var/www/login.php
@@ -73,7 +73,7 @@
Scripta , by Lateral Factory under GPLv3 License
-LTC Donations welcome : Lcb3cy5nPnh3pQWPCpa55Zg8ShZj5kUHYC
+
diff --git a/var/www/miner.php b/var/www/miner.php
index c8217d2..1e66b6c 100644
--- a/var/www/miner.php
+++ b/var/www/miner.php
@@ -1040,7 +1040,7 @@ function fmt($section, $name, $value, $when, $alldata)
if ($ret === '')
$ret = $b;
-
+
return array(
$ret,
$class
diff --git a/var/www/partials/backup.html b/var/www/partials/backup.html
index e4b3b50..0552217 100644
--- a/var/www/partials/backup.html
+++ b/var/www/partials/backup.html
@@ -1,7 +1,43 @@
-Backup
+Backup settings
-Restore
+Restore settings from backup
@@ -31,20 +67,20 @@
Restore
There seems to be no files in this backup, this can happen if permission was denied.
-
+
Reload list will scan the backup folder for saved backups.
- Restore will copy the items in the currently selected backup to the active Scripta folder. Restart the miner to let it use the restored settings.
+ Restore will copy the items in the currently selected backup to the active MinePeon folder. Restart the miner to let it use the restored settings.
Export ... will make a zipfile of the items in the currently selected backup and serve it as a download.
Import file... lets you upload a zip file and will add it to the list of backups. If it does not show up, try to reload the list.
Reload list
Restore
-
Export archived backup
+
Export {{backups[restoring].dir}}.zip
Import file...
@@ -55,4 +91,4 @@ Restore
-
+
\ No newline at end of file
diff --git a/var/www/partials/miner.html b/var/www/partials/miner.html
index 40c36a4..9e4bdf3 100644
--- a/var/www/partials/miner.html
+++ b/var/www/partials/miner.html
@@ -12,16 +12,21 @@ Available pools
Click to add pool to pool's list
-
+
Pools
-
The settings below serve as direct input to the miner. One little error can and will let the miner crash.