├── .htaccess
├── README.md
├── etc
└── rc.local
├── opt
└── scripta
│ ├── README.md
│ ├── bin
│ ├── bfgminer
│ ├── bfgminer-rpc
│ ├── cgminer
│ ├── cgminer-gc3355
│ ├── cgminer-monitor.py
│ ├── cgminer_x8_lite
│ └── wdog.py
│ ├── etc
│ ├── bfgminer.conf
│ ├── cron.d
│ │ ├── 5min
│ │ │ ├── ALERTdeviceCount
│ │ │ ├── ALERThashrate
│ │ │ ├── hashrate
│ │ │ ├── inc
│ │ │ └── temp
│ │ └── hourly
│ │ │ └── donate
│ ├── miner.conf
│ ├── miner.options.json
│ ├── miner.pools.json
│ ├── scripta.conf
│ ├── uipasswd
│ └── version
│ ├── http
│ └── rrd
│ │ ├── mhsav-day.png
│ │ ├── mhsav-hour.png
│ │ ├── mhsav-month.png
│ │ ├── mhsav-week.png
│ │ └── mhsav-year.png
│ ├── lib
│ ├── libblkmaker-0.1.la
│ ├── libblkmaker-0.1.so
│ ├── libblkmaker-0.1.so.0
│ ├── libblkmaker-0.1.so.0.3.1
│ ├── libblkmaker-0.1.so.0.4.0
│ ├── libblkmaker-0.1.so.0.4.1
│ ├── libblkmaker_jansson-0.1.la
│ ├── libblkmaker_jansson-0.1.so
│ ├── libblkmaker_jansson-0.1.so.0
│ ├── libblkmaker_jansson-0.1.so.0.3.1
│ ├── libblkmaker_jansson-0.1.so.0.4.0
│ ├── libblkmaker_jansson-0.1.so.0.4.1
│ ├── libusb-1.0.a
│ ├── libusb-1.0.la
│ ├── libusb-1.0.so
│ ├── libusb-1.0.so.2
│ ├── libusb-1.0.so.2.0.0
│ └── pkgconfig
│ │ ├── libblkmaker_jansson-0.1.pc
│ │ └── libusb-1.0.pc
│ ├── modules
│ ├── PiMiner
│ │ ├── LICENSE.txt
│ │ ├── PiMiner.py
│ │ ├── PiMinerDisplay.py
│ │ ├── PiMinerInfo.py
│ │ └── README.md
│ └── cgminerLCDStats
│ │ ├── CgminerRPCClient.py
│ │ ├── MinePeon Install.md
│ │ ├── README.md
│ │ ├── cgminerLCDStats.py
│ │ ├── lcd_and_pi-small.jpg
│ │ ├── lcd_and_pi.jpg
│ │ └── pylcdsysinfo.py
│ ├── startup
│ ├── miner-start.sh
│ └── miner-stop.sh
│ └── var
│ └── rrd
│ └── .keep
├── update.sh
└── var
├── spool
└── cron
│ └── crontabs
│ └── root
└── www
├── apple-touch-icon-precomposed.png
├── css
├── alertify.css
├── bootstrap.min.css
├── bootstrap.no-icons.min.css
├── custom.css
├── font-awesome.min.css
└── theme.css
├── f_backup.php
├── f_graph.php
├── f_hostHardCtl.php
├── f_login.php
├── f_logout.php
├── f_miner.php
├── f_minerHardCtl.php
├── f_minercompat.php
├── f_settings copy.php
├── f_settings.php
├── f_status.php
├── favicon.ico
├── img
├── bg-header1.png
├── favicon-1.ico
├── favicon-1.png
├── favicon.ico
├── favicon.png
├── scripta-logo-152.png
└── scripta-logo-ext-152.png
├── inc
├── ChromePhp.php
├── backup.inc.php
├── bfgminer.inc.php
├── functions.inc.php
├── host.inc.php
├── kitten.mp3
├── kitten.wav
├── miner.inc.php
└── settings.inc.php
├── index.html
├── index.lighttpd.html
├── index.php
├── info.php
├── js
├── alertify.min.js
├── angular.min.js
├── bootstrap.min.js
├── highcharts.js
└── jquery.min.js
├── lighttpd.pem
├── login.php
├── miner.php
├── miner_copy.php
├── ng
├── app.js
├── controllers.js
├── directives.js
├── filters.js
└── services.js
├── partials
├── backup.html
├── miner.html
├── settings.html
├── status.html
└── timezone.html
├── rrd
├── test.php
└── update
├── .updatelog
├── ctrl.php
├── start.php
├── update.php
└── version.php
/.htaccess:
--------------------------------------------------------------------------------
1 | AuthUserFile /opt/scripta/etc/uipassword
2 | AuthType Basic
3 | AuthName "root"
4 | Require valid-user
5 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Updated Image: https://www.dropbox.com/s/v2qdzkj5qx0pkl0/ScriptaV042414.img.zip
2 |
3 | Added donation links
4 |
5 | Watchdog fix
6 |
7 | Graph fix coded into rc.local startup routine. This should be a permanent fix to graph issues
8 |
9 | Scripta- LTC address set as default mining pool
10 |
11 | Note: The Gridseed clock option is set by default at 875. This does produce slightly higher hardware errors, but in the long term the increased hashrate outperforms the subsequent HW errors, especially when mining lower dificulty coins.
12 |
13 | ------------------------------------------------------------------------
14 | 4-22-14
15 | New Image Link: https://www.dropbox.com/s/28u6vtbo3m95fnx/ScriptaGridBeta042114.img.zip
16 |
17 | To get the graphs working login to Scripta and run the following command
18 | ```
19 | sudo chown root:root /var/spool/cron/crontabs/root
20 | ```
21 | Should fix any static graph issues still present. Update script still in progress, reboot and shutdown commands as well.
22 |
23 | ------------------------------------------------------------------------
24 |
25 | This is a new version of Scripta using BFGMiner 3.99 to support both the Round Gridseed and stick USB DualMiners. This particular version was built using the original code and some of Mox235's changes. I will post a complete image file shortly.
26 |
27 | For both WebUI and root access the password is "scripta" (and user is root)
28 | For DualMiner/Gridseed make sure the following options are enabled on the miner settings page:
29 | ```
30 | scan - dualminer:all or gridseed:all
31 |
32 | set-device - dualminer:clock=850 or gridseed:clock=850
33 | ```
34 |
35 | If the device does not automatically recognize your miners, you can ssh root@"scripta IP address" and use command "screen -r" to manually add devices in BFG menu.
36 |
37 | Known Issues:
38 | - WebUI does not load if RPi is turned on with Miner's connected (to work-around this, plug in the RPi and wait until you see yellow and green activity LEDs, then wait 5-10 seconds before plugging in Miner)
39 | - Individual Miner Serial numbers don't show. Plan on adding support to set per-device clock speed by individual serial number.
40 | - Reboot and shutdown commands can be finicky.
41 |
42 |
43 | If you have found use for this version please consider a donation, as we opted out of building it into the program
44 |
45 | BTC: 199GzQnNAs9BBxXSmRxKECNQ1GPF2ZZ55j
46 |
47 | LTC: LVmN9MoAbn4hQSJZrzN65oiL7W4SAY9A2q
48 |
49 | ---== Scripta ==---
50 |
51 | The turnkey solution for litecoin mining with raspberry pi and fpga/asic boards
52 |
53 |
54 | ---=== INSTALL INTRUCTIONS ===---
55 |
56 |
57 |
58 | ---=== The easy way ===---
59 |
60 | 1) Download the full image here http://www.lateralfactory.com/download.php?file=scripta-1_1.tgz
61 |
62 | 2) Burn it on a ssd in your favourite way
63 |
64 | 3) Log in as root from a console (pw is "scripta")
65 |
66 | 4) Remember to change root password with passwd
67 |
68 | 5) Enjoy
69 |
70 |
71 |
72 | ---=== The way of the turtle ===---
73 |
74 | Start from a fresh raspbian wheezy (tested with 2014-01-07) Download here http://downloads.raspberrypi.org/raspbian_latest
75 |
76 | $>raspi-config ( if needed "Expand Filesystem" and reboot )
77 |
78 | $>sudo apt-get update
79 |
80 | $>sudo apt-get install lighttpd
81 |
82 | $>sudo apt-get install php5-common php5-cgi php5 (Pay attention to packet's order)
83 |
84 | $>sudo lighty-enable-mod fastcgi-php
85 |
86 | $>sudo /etc/init.d/lighttpd force-reload
87 |
88 | ---= Add pi user to www-data group =---
89 |
90 | $>sudousermod -a -G www-data pi
91 |
92 | $>sudo apt-get install php5-rrd libexpect-php5 php-auth-sasl php-mail php-net-smtp php-net-socket
93 |
94 |
95 | ---= Needed to enable https =---
96 |
97 | $>sudo mkdir /etc/lighttpd/certs
98 |
99 | $>sudo su
100 |
101 | $>cd /etc/lighttpd/certs
102 |
103 | $>openssl req -new -x509 -keyout lighttpd.pem -out lighttpd.pem -days 365 -nodes
104 |
105 | $>chmod 400 lighttpd.pem
106 |
107 | $>/etc/init.d/lighttpd force-reload
108 |
109 |
110 | ---= edit /etc/lighttpd/lighttpd.conf =---
111 |
112 | $>pico /etc/lighttpd/lighttpd.conf
113 |
114 | ---= add the following lines at the end =---
115 |
116 | $SERVER["socket"] == ":443" {
117 | ssl.engine = "enable"
118 | ssl.pemfile = "/etc/lighttpd/certs/lighttpd.pem"
119 | }
120 |
121 | ---= libs for cgminer =---
122 |
123 | $>sudo apt-get install libjansson4 libusb-1.0-0 ntpdate screen
124 |
125 | ---= install scripta package =---
126 |
127 | $>cd /
128 |
129 | $>tar -xf scripta_1-1.tgz
130 |
131 |
--------------------------------------------------------------------------------
/etc/rc.local:
--------------------------------------------------------------------------------
1 | #!/bin/sh -e
2 | #
3 | # rc.local
4 | #
5 | # This script is executed at the end of each multiuser runlevel.
6 | # Make sure that the script will "exit 0" on success or any other
7 | # value on error.
8 | #
9 | # In order to enable or disable this script just change the execution
10 | # bits.
11 | #
12 | # By default this script does nothing.
13 |
14 | # Print the IP address
15 | _IP=$(hostname -I) || true
16 | if [ "$_IP" ]; then
17 |
18 | echo " "
19 | echo " _________ .__ __ "
20 | echo " / _____/ ___________|__|______/ |______ "
21 | echo " \_____ \_/ ___\_ __ \ \____ \ __\__ \ "
22 | echo " / \ \___| | \/ | |_> > | / __ \_ "
23 | echo "/_______ /\___ >__| |__| __/|__| (____ / "
24 | echo " \/ \/ |__| \/ "
25 |
26 | printf "Connect to http://%s to manage Scripta.\n" "$_IP"
27 | printf "Happy mining!\n"
28 |
29 | sudo /opt/scripta/startup/miner-start.sh &
30 | sudo chown root:root /var/spool/cron/crontabs/root &
31 |
32 | fi
33 |
34 | exit 0
35 |
--------------------------------------------------------------------------------
/opt/scripta/README.md:
--------------------------------------------------------------------------------
1 | Further informations on Scripta can be found at http://www.lateralfactory.com/scripta/
2 |
3 |
--------------------------------------------------------------------------------
/opt/scripta/bin/bfgminer:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/scriptamining/scripta/6c612e9a6df050688921ab14ac330dfabf27c9de/opt/scripta/bin/bfgminer
--------------------------------------------------------------------------------
/opt/scripta/bin/bfgminer-rpc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/scriptamining/scripta/6c612e9a6df050688921ab14ac330dfabf27c9de/opt/scripta/bin/bfgminer-rpc
--------------------------------------------------------------------------------
/opt/scripta/bin/cgminer:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/scriptamining/scripta/6c612e9a6df050688921ab14ac330dfabf27c9de/opt/scripta/bin/cgminer
--------------------------------------------------------------------------------
/opt/scripta/bin/cgminer-gc3355:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/scriptamining/scripta/6c612e9a6df050688921ab14ac330dfabf27c9de/opt/scripta/bin/cgminer-gc3355
--------------------------------------------------------------------------------
/opt/scripta/bin/cgminer-monitor.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | # Romain Dura | romain@shazbits.com
3 | # https://github.com/shazbits/cgminer-monitor
4 | # BTC 1Kcn1Hs76pbnBpBQHwdsDmr3CZYcoCAwjj
5 | #
6 |
7 | import socket
8 | import sys
9 | import time
10 | import smtplib
11 | import json
12 | import os
13 | import threading
14 | import SimpleHTTPServer
15 | import SocketServer
16 | import urllib2
17 |
18 |
19 | #
20 | # Config
21 | #
22 |
23 | bfgminer_host = 'localhost'
24 | bfgminer_port = 4028
25 | email_smtp_server = 'smtp.gmail.com:587'
26 | email_login = 'mylogin'
27 | email_password = 'mypassword'
28 | email_from = 'myemail@example.com'
29 | email_to = 'myemail@example.com'
30 | email_subject = 'Miner warning detected'
31 | monitor_interval = 15
32 | monitor_wait_after_email = 60
33 | monitor_http_interface = '0.0.0.0'
34 | monitor_http_port = 84
35 | monitor_restart_bfgminer_if_sick = True
36 | monitor_send_email_alerts = True
37 | monitor_max_temperature = 85
38 | monitor_min_mhs_scrypt = 0.5
39 | monitor_min_mhs_sha256 = 500
40 | monitor_enable_pools = False
41 |
42 | # MMCFE pools (www.wemineltc.com, dgc.mining-foreman.org, megacoin.miningpool.co, etc.)
43 | # Replace the URLs and/or API keys by your own, add as many pools as you like
44 | pools = [
45 | {
46 | 'url': 'http://www.digicoinpool.com/api?api_key=1234567890',
47 | 'cur': 'DGC'
48 | },
49 | {
50 | 'url': 'http://www.wemineltc.com/api?api_key=1234567890',
51 | 'cur': 'LTC'
52 | },
53 | ]
54 |
55 |
56 | #
57 | # Shared between monitor and http server
58 | #
59 |
60 | shared_output = ''
61 | shared_output_lock = threading.Lock()
62 |
63 |
64 | #
65 | # cgminer RPC
66 | #
67 |
68 | class BfgminerClient:
69 | def __init__(self, host, port):
70 | self.host = host
71 | self.port = port
72 |
73 | def command(self, command, parameter):
74 | # sockets are one time use. open one for each command
75 | sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
76 |
77 | try:
78 | sock.connect((self.host, self.port))
79 | if parameter:
80 | self._send(sock, json.dumps({"command": command, "parameter": parameter}))
81 | else:
82 | self._send(sock, json.dumps({"command": command}))
83 | received = self._receive(sock)
84 | except Exception as e:
85 | print e
86 | sock.close()
87 | return None
88 |
89 | sock.shutdown(socket.SHUT_RDWR)
90 | sock.close()
91 |
92 | # the null byte makes json decoding unhappy
93 | try:
94 | decoded = json.loads(received.replace('\x00', ''))
95 | return decoded
96 | except:
97 | pass # restart makes it fail, but it's ok
98 |
99 | def _send(self, sock, msg):
100 | totalsent = 0
101 | while totalsent < len(msg):
102 | sent = sock.send(msg[totalsent:])
103 | if sent == 0:
104 | raise RuntimeError("socket connection broken")
105 | totalsent = totalsent + sent
106 |
107 | def _receive(self, sock, size=65500):
108 | msg = ''
109 | while True:
110 | chunk = sock.recv(size)
111 | if chunk == '':
112 | # end of message
113 | break
114 | msg = msg + chunk
115 | return msg
116 |
117 |
118 | #
119 | # Utils
120 | #
121 |
122 | def SendEmail(from_addr, to_addr_list, cc_addr_list,
123 | subject, message, login, password,
124 | smtpserver=email_smtp_server):
125 | header = 'From: %s\n' % from_addr
126 | header += 'To: %s\n' % ','.join(to_addr_list)
127 | header += 'Cc: %s\n' % ','.join(cc_addr_list)
128 | header += 'Subject: %s\n\n' % subject
129 |
130 | server = smtplib.SMTP(smtpserver)
131 | server.starttls()
132 | server.login(login, password)
133 | server.sendmail(from_addr, to_addr_list, header + message)
134 | server.quit()
135 |
136 |
137 | #
138 | # Monitor
139 | #
140 |
141 | def StartMonitor(client):
142 | os.system('cls')
143 | while (True):
144 | output = ''
145 |
146 | must_send_email = False
147 | must_restart = False
148 |
149 | result = client.command('coin', None)
150 | coin = ''
151 | if result:
152 | coin = result['COIN'][0]['Hash Method']
153 | output = 'Coin : %s\n' % coin
154 |
155 | result = client.command('pools', None)
156 | if result:
157 | output += 'Pool URL : %s\n' % (result['POOLS'][0]['Stratum URL'])
158 | warning = ' <----- /!\\' if result['POOLS'][0]['Status'] != 'Alive' else ''
159 | must_send_email = True if warning != '' else must_send_email
160 | output += 'Pool : %s%s\n' % (result['POOLS'][0]['Status'], warning)
161 |
162 | # Put this in a loop for multi-gpu support
163 | result = client.command('gpu', '0')
164 | if result:
165 | gpu_result = result['GPU'][0]
166 | warning = ' <----- /!\\' if gpu_result['Status'] != 'Alive' else ''
167 | must_restart = True if warning != '' else False
168 | must_send_email = True if warning != '' else must_send_email
169 | output += 'GPU 0 : %s%s\n' % (gpu_result['Status'], warning)
170 |
171 | min_mhs = monitor_min_mhs_scrypt if coin == 'scrypt' else monitor_min_mhs_sha256
172 | warning = ' <----- /!\\' if gpu_result['MHS 1s'] < min_mhs else ''
173 | must_send_email = True if warning != '' else must_send_email
174 | output += 'MHS 1s/av: %s/%s%s\n' % (gpu_result['MHS 1s'], gpu_result['MHS av'], warning)
175 |
176 | warning = ' <----- /!\\' if gpu_result['Temperature'] > monitor_max_temperature else ''
177 | must_send_email = True if warning != '' else must_send_email
178 | output += 'Temp : %s%s\n' % (gpu_result['Temperature'], warning)
179 | output += 'Intensity: %s\n' % gpu_result['Intensity']
180 |
181 | result = client.command('summary', None)
182 | if result:
183 | if result['SUMMARY'][0]['Hardware Errors'] > 0:
184 | must_send_email = True
185 | output += 'HW err : %s%s\n' % (result['SUMMARY'][0]['Hardware Errors'], ' <----- /!\\')
186 |
187 | result = client.command('stats', None)
188 | if result:
189 | uptime = result['STATS'][0]['Elapsed']
190 | output += 'Uptime : %02d:%02d:%02d\n' % (uptime / 3600, (uptime / 60) % 60, uptime % 60)
191 | print output
192 |
193 | global shared_output
194 | global shared_output_lock
195 | shared_output_lock.acquire()
196 | shared_output = output
197 | shared_output_lock.release()
198 |
199 | if must_restart and monitor_restart_bfgminer_if_sick:
200 | print 'Restarting'
201 | result = client.command('restart', None)
202 |
203 | if must_send_email and monitor_send_email_alerts and uptime > 10:
204 | SendEmail(from_addr=email_from, to_addr_list=[email_to], cc_addr_list=[],
205 | subject=email_subject,
206 | message=output,
207 | login=email_login,
208 | password=email_password)
209 | time.sleep(monitor_wait_after_email)
210 |
211 | # Sleep by increments of 1 second to catch the keyboard interrupt
212 | for i in range(monitor_interval):
213 | time.sleep(1)
214 |
215 | os.system('cls')
216 |
217 |
218 | #
219 | # HTTP server request handler
220 | #
221 |
222 | class BFMinerRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
223 | def do_GET(self):
224 | self.send_response(200)
225 |
226 | if self.path == '/favicon.ico':
227 | return
228 |
229 | self.send_header("Content-type", "text/html")
230 | self.end_headers()
231 |
232 | global shared_output
233 | global shared_output_lock
234 | shared_output_lock.acquire()
235 | html_output = shared_output[:-1] # one too many \n
236 | shared_output_lock.release()
237 |
238 | # Get balance from pools
239 | pools_output = ''
240 | if monitor_enable_pools:
241 | td_div = '
'
242 | for pool in pools:
243 | try:
244 | response = urllib2.urlopen(pool['url'])
245 | data = json.load(response)
246 | pools_output += '\n \n' + td_div + '\n' + 'pool' + '' + td_div + pool['cur'] + ' %.6f' % (float(data['confirmed_rewards']))
247 | except urllib2.HTTPError as e:
248 | pools_output += '\n \n' + td_div + '\n' + 'pool' + '' + td_div + pool['cur'] + ' Error: ' + str(e.code)
249 | except urllib2.URLError as e:
250 | pools_output += '\n \n' + td_div + '\n' + 'pool' + '' + td_div + pool['cur'] + ' Error: ' + e.reason
251 | except:
252 | pools_output += '\n \n' + td_div + '\n' + 'pool' + '' + td_div + pool['cur'] + ' Error: unsupported pool?'
253 |
254 | # Format results from the monitor
255 | td_div = ''
256 | html_output = ('\n \n' + td_div + '\n').join(html_output.replace(': ', '' + td_div).split('\n'))
257 | html_output += pools_output
258 | html = """
259 |
260 |
261 |
262 | bfgminer monitor
263 |
264 |
265 |
266 |
267 | """ + html_output + """
268 |
269 |
270 |
271 |
272 | """
273 | self.wfile.write(html)
274 |
275 |
276 | #
277 | # usage: cgminer-monitor.py [command] [parameter]
278 | # No arguments: monitor + http server mode. Press CTRL+C to stop.
279 | # Arguments: send the command with optional parameter and exit.
280 | #
281 |
282 | if __name__ == "__main__":
283 | command = sys.argv[1] if len(sys.argv) > 1 else None
284 | parameter = sys.argv[2] if len(sys.argv) > 2 else None
285 |
286 | client = BFgminerClient(bfgminer_host, bfgminer_port)
287 |
288 | if command:
289 | # An argument was specified, ask cgminer and exit
290 | result = client.command(command, parameter)
291 | print result if result else 'Cannot get valid response from bfgminer'
292 | else:
293 | # No argument, start the monitor and the http server
294 | try:
295 | server = SocketServer.TCPServer((monitor_http_interface, monitor_http_port), BFGMinerRequestHandler)
296 | threading.Thread(target=server.serve_forever).start()
297 | StartMonitor(client)
298 | except KeyboardInterrupt:
299 | server.shutdown()
300 |
301 |
--------------------------------------------------------------------------------
/opt/scripta/bin/cgminer_x8_lite:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/scriptamining/scripta/6c612e9a6df050688921ab14ac330dfabf27c9de/opt/scripta/bin/cgminer_x8_lite
--------------------------------------------------------------------------------
/opt/scripta/bin/wdog.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | #
3 | # Scripta watchdog test for cgminer status
4 | #
5 | # parts used from cgminer-monitor.py
6 | # Romain Dura | romain@shazbits.com
7 | # https://github.com/shazbits/cgminer-monitor
8 | # BTC 1Kcn1Hs76pbnBpBQHwdsDmr3CZYcoCAwjj
9 | #
10 |
11 | import socket
12 | import sys
13 | import time
14 | import smtplib
15 | import json
16 | import os
17 | import threading
18 | import SimpleHTTPServer
19 | import SocketServer
20 | import urllib2
21 | import datetime, time
22 | import pprint
23 |
24 | #
25 | # Config
26 | #
27 |
28 | cgminer_host = 'localhost'
29 | cgminer_port = 4028
30 | monitor_interval = 15
31 | monitor_wait_after_email = 10
32 |
33 | shared_output = ''
34 | shared_output_lock = threading.Lock()
35 |
36 | #
37 | # cgminer RPC
38 | #
39 |
40 | class CgminerClient:
41 | def __init__(self, host, port):
42 | self.host = host
43 | self.port = port
44 |
45 | def command(self, command, parameter):
46 | # sockets are one time use. open one for each command
47 | sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
48 |
49 | try:
50 | sock.connect((self.host, self.port))
51 | if parameter:
52 | self._send(sock, json.dumps({"command": command, "parameter": parameter}))
53 | else:
54 | self._send(sock, json.dumps({"command": command}))
55 | received = self._receive(sock)
56 | except Exception as e:
57 | print e
58 | sock.close()
59 | return None
60 |
61 | sock.shutdown(socket.SHUT_RDWR)
62 | sock.close()
63 |
64 | # the null byte makes json decoding unhappy
65 | try:
66 | decoded = json.loads(received.replace('\x00', ''))
67 | return decoded
68 | except:
69 | pass # restart makes it fail, but it's ok
70 |
71 | def _send(self, sock, msg):
72 | totalsent = 0
73 | while totalsent < len(msg):
74 | sent = sock.send(msg[totalsent:])
75 | if sent == 0:
76 | raise RuntimeError("socket connection broken")
77 | totalsent = totalsent + sent
78 |
79 | def _receive(self, sock, size=65500):
80 | msg = ''
81 | while True:
82 | chunk = sock.recv(size)
83 | if chunk == '':
84 | # end of message
85 | break
86 | msg = msg + chunk
87 | return msg
88 |
89 |
90 | #
91 | # Utils
92 | #
93 |
94 | def SendEmail(from_addr, to_addr_list, cc_addr_list,
95 | subject, message, login, password,
96 | smtpserver):
97 | header = 'From: %s\n' % from_addr
98 | header += 'To: %s\n' % ','.join(to_addr_list)
99 | header += 'Cc: %s\n' % ','.join(cc_addr_list)
100 | header += 'Subject: %s\n\n' % subject
101 |
102 | server = smtplib.SMTP(smtpserver)
103 | server.starttls()
104 | server.login(login, password)
105 | server.sendmail(from_addr, to_addr_list, header + message)
106 | server.quit()
107 | print 'send email: ' + to_addr_list[0]
108 |
109 |
110 | if __name__ == "__main__":
111 |
112 | now = (datetime.datetime.now()-datetime.datetime(1970,1,1)).total_seconds()
113 |
114 | if os.path.exists('/tmp/wdog.ts'):
115 | ts_file=open('/tmp/wdog.ts','r')
116 | dt = now - float(ts_file.readline())
117 | ts_file.close();
118 | else:
119 | ts_file=open('/tmp/wdog.ts','w')
120 | ts_file.write(str(now));
121 | ts_file.close;
122 | dt = 0.0;
123 |
124 | if os.path.exists('/tmp/reboot.ts'):
125 | print 'OK - wait for reboot command'
126 | sys.exit(0)
127 |
128 | conf_file=open('/opt/scripta/etc/scripta.conf')
129 | conf = json.load(conf_file)
130 | pprint.pprint(conf)
131 | conf_file.close()
132 |
133 | if conf['rebootEnable']:
134 | conf['rebootEnable'] = False
135 | with open('/opt/scripta/etc/scripta.conf', 'w') as outfile:
136 | json.dump(conf, outfile)
137 | print 'OK - reboot command'
138 | sys.exit(1)
139 |
140 | if not conf['recoverEnable']:
141 | print 'OK - scripta watchdog disabled'
142 | sys.exit(0)
143 |
144 | if dt < 60.0:
145 | print 'OK - wait for cgminer startup ' + str(dt) + ' sec'
146 | sys.exit(0)
147 |
148 | print 'expected device count: ' + str(conf['miningExpDev'])
149 | print 'expected min hashrate: ' + str(conf['miningExpHash'])
150 |
151 | pid_file=open('/opt/scripta/var/bfgminer.pid','r')
152 | if not pid_file:
153 | print 'ERROR - bfgminer.pid not found'
154 | else:
155 | pid = int(pid_file.readline())
156 | pid_file.close()
157 | ps = '/proc/' + str(pid) + '/'
158 | if os.path.exists(ps):
159 | print 'OK - bfgminer process running'
160 | else:
161 | output = 'ERROR - bfgminer process not running (pid ' + ps + ')'
162 | time.sleep(3)
163 | if not os.path.exists(ps):
164 | output = 'ERROR - bfgminer process not running (pid ' + ps + ')'
165 | if conf['alertEnable']:
166 | SendEmail(
167 | from_addr='scripta@hotmail.com',
168 | to_addr_list=[conf['alertEmailTo']],
169 | cc_addr_list=[],
170 | subject='Scripta Reboot [' + conf['alertDevice'] + ']',
171 | message=output,
172 | login=conf['alertSmtpUser'],
173 | password=conf['alertSmtpPwd'],
174 | smtpserver=conf['alertSmtp'] + ':' + str(conf['alertSmtpPort']))
175 | time.sleep(monitor_wait_after_email)
176 | ts_file=open('/tmp/reboot.ts','w')
177 | ts_file.write(str(now));
178 | ts_file.close;
179 | sys.exit(1) # reboot
180 |
181 | client = CgminerClient(cgminer_host, cgminer_port)
182 |
183 | result = client.command('pgacount', None)
184 | if result:
185 | dev = result['PGAS'][0]['Count']
186 | if conf['miningExpDev'] > dev:
187 | output = 'ERROR - device count: ' + str(dev) + '\n\n' + pprint.pformat(result)
188 | print output
189 | if conf['alertEnable']:
190 | SendEmail(
191 | from_addr='scripta@hotmail.com',
192 | to_addr_list=[conf['alertEmailTo']],
193 | cc_addr_list=[],
194 | subject='Scripta Reboot [' + conf['alertDevice'] + ']',
195 | message=output,
196 | login=conf['alertSmtpUser'],
197 | password=conf['alertSmtpPwd'],
198 | smtpserver=conf['alertSmtp'] + ':' + str(conf['alertSmtpPort']))
199 | time.sleep(monitor_wait_after_email)
200 | ts_file=open('/tmp/reboot.ts','w')
201 | ts_file.write(str(now));
202 | ts_file.close;
203 | sys.exit(1) # reboot
204 | else:
205 | print 'OK - device count: ' + str(dev)
206 | else:
207 | print 'OK - cgminer not ready'
208 | sys.exit(0);
209 |
210 | result = client.command('devs', None)
211 | if result:
212 | for d in result['DEVS']:
213 | if conf['miningExpHash'] > d['MHS rolling']:
214 | output = 'ERROR - ' + str(d['Name']) + str(d['ID']) + ' hashrate: ' + str(d['MHS rolling']) + '\n\n' + pprint.pformat(result)
215 | print output
216 | if conf['alertEnable']:
217 | SendEmail(
218 | from_addr='scripta@hotmail.com',
219 | to_addr_list=[conf['alertEmailTo']],
220 | cc_addr_list=[],
221 | subject='Scripta Reboot [' + conf['alertDevice'] + ']',
222 | message=output,
223 | login=conf['alertSmtpUser'],
224 | password=conf['alertSmtpPwd'],
225 | smtpserver=conf['alertSmtp'] + ':' + str(conf['alertSmtpPort']))
226 | time.sleep(monitor_wait_after_email)
227 | ts_file=open('/tmp/reboot.ts','w')
228 | ts_file.write(str(now));
229 | ts_file.close;
230 | sys.exit(1) # reboot
231 | else:
232 | print 'OK - ' + str(d['ID']) + ' hashrate: ' + str(d['MHS rolling'])
233 |
234 | sys.exit(0)
235 |
--------------------------------------------------------------------------------
/opt/scripta/etc/bfgminer.conf:
--------------------------------------------------------------------------------
1 | {
2 | "scrypt" : true,
3 | "api-listen": true,
4 | "api-port": "4028",
5 | "expiry": "120",
6 | "hotplug": "5",
7 | "log": "5",
8 | "no-pool-disable": true,
9 | "queue": "1",
10 | "scan-time": "60",
11 | "shares": "0",
12 | "kernel-path" : "/usr/local/bin",
13 | "api-allow": "W:127.0.0.1,W192.168.1/0",
14 | "scan" : "gridseed:all",
15 | "set-device" : "gridseed:clock=850",
16 | "pools": [
17 | {
18 | "url" : "stratum+tcp://multi.ghash.io:3333",
19 | "user" : "richmondimage.gridseed2",
20 | "pass" : "x",
21 | "pool-priority" : "0"
22 | }
23 | ]
24 | }
--------------------------------------------------------------------------------
/opt/scripta/etc/cron.d/5min/ALERTdeviceCount:
--------------------------------------------------------------------------------
1 | #!/usr/bin/php
2 | $devcount and $settings['donateActive'] == 0) {
30 | if ($settings['miningExpDev'] <> $devcount ) {
31 |
32 | // Send an email if the devices dont match and set the deviceWarn falt
33 |
34 | $message = "Scripta notification: " . $settings['alertDevice'] . ": Unexpected device count " . $devcount . " (Expected " . $settings['miningExpDev'] . ")";
35 |
36 | sendEmail($settings, $message, $message);
37 |
38 | // Set the warning flag
39 |
40 | $settings['devicesWarn'] = 1;
41 | writeSettings($settings);
42 |
43 |
44 | }
45 |
46 | if($settings['devicesWarn'] == 1 and $settings['miningExpDev'] == $devcount) {
47 |
48 | $message = "Scripta notification: " . $settings['alertDevice'] . ": Unexpected device count recovered";
49 |
50 | sendEmail($settings, $message, $message);
51 |
52 | // Clear the warning flag
53 | $settings['devicesWarn'] = 0;
54 | writeSettings($settings);
55 |
56 | }
57 |
58 | }
59 | var_dump($settings);
60 |
61 | function deviceCount($devs) {
62 |
63 | $devices = 0;
64 |
65 | foreach ($devs as $dev) {
66 | if ($dev['MHS5s'] > 0) {
67 | $devices++;
68 | }
69 | }
70 |
71 | return $devices;
72 |
73 | }
74 |
--------------------------------------------------------------------------------
/opt/scripta/etc/cron.d/5min/ALERThashrate:
--------------------------------------------------------------------------------
1 | #!/usr/bin/php
2 | $hashrate and $settings['donateActive'] == 0) {
16 |
17 | // Send an email if the devices dont match and set the deviceWarn falt
18 |
19 |
20 | $warning = "Scripta notification: " . $settings['alertDevice'] . ": Unexpected hashrate " . $hashrate . " MH/s (Expected " . $settings['miningExpHash'] . " MH/s)";
21 |
22 | sendEmail($settings, $warning, $warning);
23 |
24 |
25 | // Set the warning flag
26 |
27 | $settings['hashWarn'] = 1;
28 | writeSettings($settings);
29 | echo " fault";
30 |
31 | }
32 |
33 | if($settings['hashWarn'] == 1 and $settings['miningExpHash'] < $hashrate) {
34 |
35 | $warning = "Scripta notification: " . $settings['alertDevice'] . ": Unexpected hashrate recovered";
36 |
37 | sendEmail($settings, $warning, $warning);
38 |
39 | // Clear the warning flag
40 | $settings['hashWarn'] = 0;
41 | writeSettings($settings);
42 | echo " nofault";
43 |
44 | }
45 |
46 |
--------------------------------------------------------------------------------
/opt/scripta/etc/cron.d/5min/hashrate:
--------------------------------------------------------------------------------
1 | #!/usr/bin/php
2 |
--------------------------------------------------------------------------------
/opt/scripta/etc/cron.d/5min/inc:
--------------------------------------------------------------------------------
1 | /var/www/inc
--------------------------------------------------------------------------------
/opt/scripta/etc/cron.d/5min/temp:
--------------------------------------------------------------------------------
1 | #!/usr/bin/php
2 |
47 |
--------------------------------------------------------------------------------
/opt/scripta/etc/cron.d/hourly/donate:
--------------------------------------------------------------------------------
1 | #!/usr/bin/php
2 | 0){
17 |
18 | if (date('H') == 12) {
19 | $miner = "/opt/scripta/etc/miner.conf";
20 | $donate = "/opt/scripta/etc/miner.conf.donate";
21 | $original = "/opt/scripta/etc/miner.conf.orig";
22 |
23 | // Take your miner info and backup
24 | copy($miner, $original);
25 |
26 | // Sleep for 60 secconds to avoid monitor scripts
27 | sleep(30);
28 |
29 | $settings['donateActive'] = 1;
30 | writeSettings($settings);
31 |
32 | // Restart using donation pools
33 | copy($donate, $miner);
34 |
35 | exec("/usr/bin/killall cgminer");
36 | exec("/usr/bin/killall bfgminer");
37 |
38 | sleep(5);
39 |
40 | // Copy back the normal pools
41 |
42 | copy($original, $miner);
43 |
44 | // Switch back to your pools after x minutes
45 | sleep($settings['donateAmount'] * 60);
46 |
47 | $settings['donateActive'] = 0;
48 | writeSettings($settings);
49 |
50 | exec("/usr/bin/killall cgminer");
51 | exec("/usr/bin/killall bfgminer");
52 |
53 | echo "Finish !";
54 | }
55 | }
56 |
57 |
58 |
59 | // stratum.btcguild.com:3333 MinePeon_Donate MinePeon_Donate
60 | // pool.50btc.com:8332 Donate
61 |
--------------------------------------------------------------------------------
/opt/scripta/etc/miner.conf:
--------------------------------------------------------------------------------
1 | {
2 | "api-listen": true,
3 | "api-port": "4028",
4 | "expiry": "120",
5 | "hotplug": "5",
6 | "log": "5",
7 | "no-pool-disable": true,
8 | "queue": "1",
9 | "scan-time": "30",
10 | "scrypt": true,
11 | "shares": "0",
12 | "scan": "dualminer:all",
13 | "set-device": "dualminer:clock=850",
14 | "api-allow": "W:127.0.0.1,W:192.168.1/24",
15 | "pools": [
16 | {
17 | "url": "stratum+tcp://multi.ghash.io:3333",
18 | "user": "richmondimage.dual",
19 | "pass": "x",
20 | "prio": "0"
21 | },
22 | {
23 | "url": "stratum+tcp://ltc.ghash.io:3333",
24 | "user": "richmondimage.scripta",
25 | "pass": "x",
26 | "prio": "1"
27 | }
28 | ]
29 | }
--------------------------------------------------------------------------------
/opt/scripta/etc/miner.options.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "key": "api-listen",
4 | "value": true
5 | },
6 | {
7 | "key": "api-port",
8 | "value": "4028"
9 | },
10 | {
11 | "key": "expiry",
12 | "value": "120"
13 | },
14 | {
15 | "key": "hotplug",
16 | "value": "5"
17 | },
18 | {
19 | "key": "log",
20 | "value": "5"
21 | },
22 | {
23 | "key": "no-pool-disable",
24 | "value": true
25 | },
26 | {
27 | "key": "queue",
28 | "value": "1"
29 | },
30 | {
31 | "key": "scan-time",
32 | "value": "30"
33 | },
34 | {
35 | "key": "scrypt",
36 | "value": true
37 | },
38 | {
39 | "key": "shares",
40 | "value": "0"
41 | },
42 | {
43 | "key": "scan",
44 | "value": "dualminer:all"
45 | },
46 | {
47 | "key": "set-device",
48 | "value": "dualminer:clock=850"
49 | },
50 | {
51 | "key": "api-allow",
52 | "value": "W:127.0.0.1,W:192.168.1/24"
53 | }
54 | ]
--------------------------------------------------------------------------------
/opt/scripta/etc/miner.pools.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "url": "stratum+tcp://multi.ghash.io:3333",
4 | "user": "richmondimage.dual",
5 | "pass": "x",
6 | "prio": "0"
7 | },
8 | {
9 | "url": "stratum+tcp://ltc.ghash.io:3333",
10 | "user": "richmondimage.scripta",
11 | "pass": "x",
12 | "prio": "1"
13 | }
14 | ]
--------------------------------------------------------------------------------
/opt/scripta/etc/scripta.conf:
--------------------------------------------------------------------------------
1 | {
2 | "userHelp": false,
3 | "userTimezone": "America/New_York",
4 | "date": "2014-04-12 00:18:57",
5 | "remoteEnable": false,
6 | "recoverEnable": true,
7 | "alertEnable": false,
8 | "donateEnable": false,
9 | "alertDevice": "",
10 | "alertEmail": "",
11 | "alertSmtp": "",
12 | "alertSmtpUser": "",
13 | "alertSmtpPwd": "",
14 | "miningExpDev": 6,
15 | "liveMax": 100,
16 | "devicesWarn": 0,
17 | "alertSmtpPort": 587,
18 | "miningExpHash": 300,
19 | "hashWarn": 1
20 | }
--------------------------------------------------------------------------------
/opt/scripta/etc/uipasswd:
--------------------------------------------------------------------------------
1 | scripta:9a4f049c0f8e3b60ddf7ddf0d01a9d0e
--------------------------------------------------------------------------------
/opt/scripta/etc/version:
--------------------------------------------------------------------------------
1 | 1.0
2 |
--------------------------------------------------------------------------------
/opt/scripta/http/rrd/mhsav-day.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/scriptamining/scripta/6c612e9a6df050688921ab14ac330dfabf27c9de/opt/scripta/http/rrd/mhsav-day.png
--------------------------------------------------------------------------------
/opt/scripta/http/rrd/mhsav-hour.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/scriptamining/scripta/6c612e9a6df050688921ab14ac330dfabf27c9de/opt/scripta/http/rrd/mhsav-hour.png
--------------------------------------------------------------------------------
/opt/scripta/http/rrd/mhsav-month.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/scriptamining/scripta/6c612e9a6df050688921ab14ac330dfabf27c9de/opt/scripta/http/rrd/mhsav-month.png
--------------------------------------------------------------------------------
/opt/scripta/http/rrd/mhsav-week.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/scriptamining/scripta/6c612e9a6df050688921ab14ac330dfabf27c9de/opt/scripta/http/rrd/mhsav-week.png
--------------------------------------------------------------------------------
/opt/scripta/http/rrd/mhsav-year.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/scriptamining/scripta/6c612e9a6df050688921ab14ac330dfabf27c9de/opt/scripta/http/rrd/mhsav-year.png
--------------------------------------------------------------------------------
/opt/scripta/lib/libblkmaker-0.1.la:
--------------------------------------------------------------------------------
1 | # libblkmaker-0.1.la - a libtool library file
2 | # Generated by libtool (GNU libtool) 2.4.2
3 | #
4 | # Please DO NOT delete this file!
5 | # It is necessary for linking the library.
6 |
7 | # The name that we can dlopen(3).
8 | dlname='libblkmaker-0.1.so.0'
9 |
10 | # Names of this library.
11 | library_names='libblkmaker-0.1.so.0.4.1 libblkmaker-0.1.so.0 libblkmaker-0.1.so'
12 |
13 | # The name of the static archive.
14 | old_library=''
15 |
16 | # Linker flags that can not go in dependency_libs.
17 | inherited_linker_flags=''
18 |
19 | # Libraries that this one depends upon.
20 | dependency_libs=''
21 |
22 | # Names of additional weak libraries provided by this library
23 | weak_library_names=''
24 |
25 | # Version information for libblkmaker-0.1.
26 | current=4
27 | age=4
28 | revision=1
29 |
30 | # Is this an already installed library?
31 | installed=yes
32 |
33 | # Should we warn about portability when linking against -modules?
34 | shouldnotlink=no
35 |
36 | # Files to dlopen/dlpreopen
37 | dlopen=''
38 | dlpreopen=''
39 |
40 | # Directory that this library needs to be installed in:
41 | libdir='/opt/minepeon/lib'
42 |
--------------------------------------------------------------------------------
/opt/scripta/lib/libblkmaker-0.1.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/scriptamining/scripta/6c612e9a6df050688921ab14ac330dfabf27c9de/opt/scripta/lib/libblkmaker-0.1.so
--------------------------------------------------------------------------------
/opt/scripta/lib/libblkmaker-0.1.so.0:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/scriptamining/scripta/6c612e9a6df050688921ab14ac330dfabf27c9de/opt/scripta/lib/libblkmaker-0.1.so.0
--------------------------------------------------------------------------------
/opt/scripta/lib/libblkmaker-0.1.so.0.3.1:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/scriptamining/scripta/6c612e9a6df050688921ab14ac330dfabf27c9de/opt/scripta/lib/libblkmaker-0.1.so.0.3.1
--------------------------------------------------------------------------------
/opt/scripta/lib/libblkmaker-0.1.so.0.4.0:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/scriptamining/scripta/6c612e9a6df050688921ab14ac330dfabf27c9de/opt/scripta/lib/libblkmaker-0.1.so.0.4.0
--------------------------------------------------------------------------------
/opt/scripta/lib/libblkmaker-0.1.so.0.4.1:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/scriptamining/scripta/6c612e9a6df050688921ab14ac330dfabf27c9de/opt/scripta/lib/libblkmaker-0.1.so.0.4.1
--------------------------------------------------------------------------------
/opt/scripta/lib/libblkmaker_jansson-0.1.la:
--------------------------------------------------------------------------------
1 | # libblkmaker_jansson-0.1.la - a libtool library file
2 | # Generated by libtool (GNU libtool) 2.4.2
3 | #
4 | # Please DO NOT delete this file!
5 | # It is necessary for linking the library.
6 |
7 | # The name that we can dlopen(3).
8 | dlname='libblkmaker_jansson-0.1.so.0'
9 |
10 | # Names of this library.
11 | library_names='libblkmaker_jansson-0.1.so.0.4.1 libblkmaker_jansson-0.1.so.0 libblkmaker_jansson-0.1.so'
12 |
13 | # The name of the static archive.
14 | old_library=''
15 |
16 | # Linker flags that can not go in dependency_libs.
17 | inherited_linker_flags=''
18 |
19 | # Libraries that this one depends upon.
20 | dependency_libs=' -L.libs /opt/minepeon/lib/libblkmaker-0.1.la -ljansson'
21 |
22 | # Names of additional weak libraries provided by this library
23 | weak_library_names=''
24 |
25 | # Version information for libblkmaker_jansson-0.1.
26 | current=4
27 | age=4
28 | revision=1
29 |
30 | # Is this an already installed library?
31 | installed=yes
32 |
33 | # Should we warn about portability when linking against -modules?
34 | shouldnotlink=no
35 |
36 | # Files to dlopen/dlpreopen
37 | dlopen=''
38 | dlpreopen=''
39 |
40 | # Directory that this library needs to be installed in:
41 | libdir='/opt/minepeon/lib'
42 |
--------------------------------------------------------------------------------
/opt/scripta/lib/libblkmaker_jansson-0.1.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/scriptamining/scripta/6c612e9a6df050688921ab14ac330dfabf27c9de/opt/scripta/lib/libblkmaker_jansson-0.1.so
--------------------------------------------------------------------------------
/opt/scripta/lib/libblkmaker_jansson-0.1.so.0:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/scriptamining/scripta/6c612e9a6df050688921ab14ac330dfabf27c9de/opt/scripta/lib/libblkmaker_jansson-0.1.so.0
--------------------------------------------------------------------------------
/opt/scripta/lib/libblkmaker_jansson-0.1.so.0.3.1:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/scriptamining/scripta/6c612e9a6df050688921ab14ac330dfabf27c9de/opt/scripta/lib/libblkmaker_jansson-0.1.so.0.3.1
--------------------------------------------------------------------------------
/opt/scripta/lib/libblkmaker_jansson-0.1.so.0.4.0:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/scriptamining/scripta/6c612e9a6df050688921ab14ac330dfabf27c9de/opt/scripta/lib/libblkmaker_jansson-0.1.so.0.4.0
--------------------------------------------------------------------------------
/opt/scripta/lib/libblkmaker_jansson-0.1.so.0.4.1:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/scriptamining/scripta/6c612e9a6df050688921ab14ac330dfabf27c9de/opt/scripta/lib/libblkmaker_jansson-0.1.so.0.4.1
--------------------------------------------------------------------------------
/opt/scripta/lib/libusb-1.0.a:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/scriptamining/scripta/6c612e9a6df050688921ab14ac330dfabf27c9de/opt/scripta/lib/libusb-1.0.a
--------------------------------------------------------------------------------
/opt/scripta/lib/libusb-1.0.la:
--------------------------------------------------------------------------------
1 | # libusb-1.0.la - a libtool library file
2 | # Generated by libtool (GNU libtool) 2.4.2
3 | #
4 | # Please DO NOT delete this file!
5 | # It is necessary for linking the library.
6 |
7 | # The name that we can dlopen(3).
8 | dlname='libusb-1.0.so.2'
9 |
10 | # Names of this library.
11 | library_names='libusb-1.0.so.2.0.0 libusb-1.0.so.2 libusb-1.0.so'
12 |
13 | # The name of the static archive.
14 | old_library='libusb-1.0.a'
15 |
16 | # Linker flags that can not go in dependency_libs.
17 | inherited_linker_flags=' -pthread'
18 |
19 | # Libraries that this one depends upon.
20 | dependency_libs=' -ludev'
21 |
22 | # Names of additional weak libraries provided by this library
23 | weak_library_names=''
24 |
25 | # Version information for libusb-1.0.
26 | current=2
27 | age=0
28 | revision=0
29 |
30 | # Is this an already installed library?
31 | installed=yes
32 |
33 | # Should we warn about portability when linking against -modules?
34 | shouldnotlink=no
35 |
36 | # Files to dlopen/dlpreopen
37 | dlopen=''
38 | dlpreopen=''
39 |
40 | # Directory that this library needs to be installed in:
41 | libdir='/opt/minepeon/lib'
42 |
--------------------------------------------------------------------------------
/opt/scripta/lib/libusb-1.0.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/scriptamining/scripta/6c612e9a6df050688921ab14ac330dfabf27c9de/opt/scripta/lib/libusb-1.0.so
--------------------------------------------------------------------------------
/opt/scripta/lib/libusb-1.0.so.2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/scriptamining/scripta/6c612e9a6df050688921ab14ac330dfabf27c9de/opt/scripta/lib/libusb-1.0.so.2
--------------------------------------------------------------------------------
/opt/scripta/lib/libusb-1.0.so.2.0.0:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/scriptamining/scripta/6c612e9a6df050688921ab14ac330dfabf27c9de/opt/scripta/lib/libusb-1.0.so.2.0.0
--------------------------------------------------------------------------------
/opt/scripta/lib/pkgconfig/libblkmaker_jansson-0.1.pc:
--------------------------------------------------------------------------------
1 | prefix=/opt/minepeon
2 | exec_prefix=${prefix}
3 | libdir=${exec_prefix}/lib
4 | includedir=${prefix}/include
5 |
6 | Name: libblkmaker_jansson
7 | Description: Bitcoin block maker library.
8 | Version: 0.1
9 | URL: http://gitorious.org/bitcoin/libblkmaker
10 | Libs: -L${libdir} -lblkmaker-0.1 -lblkmaker_jansson-0.1
11 | Cflags: -I${includedir}/libblkmaker-0.1
12 |
--------------------------------------------------------------------------------
/opt/scripta/lib/pkgconfig/libusb-1.0.pc:
--------------------------------------------------------------------------------
1 | prefix=/opt/minepeon
2 | exec_prefix=${prefix}
3 | libdir=${exec_prefix}/lib
4 | includedir=${prefix}/include
5 |
6 | Name: libusb-1.0
7 | Description: C API for USB device access from Linux, Mac OS X, OpenBSD, NetBSD and Windows userspace
8 | Version: 1.0.16-rc10
9 | Libs: -L${libdir} -lusb-1.0
10 | Libs.private: -ludev -pthread
11 | Cflags: -I${includedir}/libusb-1.0
12 |
13 |
--------------------------------------------------------------------------------
/opt/scripta/modules/PiMiner/PiMiner.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 |
3 | import sys, subprocess, time, urllib2, socket
4 | sys.path.append("/home/pi/Adafruit-Raspberry-Pi-Python-Code/Adafruit_CharLCDPlate")
5 | from Adafruit_CharLCDPlate import Adafruit_CharLCDPlate
6 | from PiMinerDisplay import PiMinerDisplay
7 |
8 | HOLD_TIME = 3.0 #Time (seconds) to hold select button for shut down
9 | REFRESH_TIME= 3.0 #Time (seconds) between data updates
10 | HALT_ON_EXIT= True
11 | display = PiMinerDisplay()
12 | lcd = display.lcd
13 | prevCol = -1
14 | prev = -1
15 | lastTime = time.time()
16 |
17 | def shutdown():
18 | lcd.clear()
19 | if HALT_ON_EXIT:
20 | lcd.message('Wait 30 seconds\nto unplug...')
21 | subprocess.call("sync")
22 | subprocess.call(["shutdown", "-h", "now"])
23 | else:
24 | exit(0)
25 |
26 | '''
27 | #WIP - startup on boot
28 | def internetOn():
29 | try:
30 | response=urllib2.urlopen('http://google.com',timeout=3)
31 | return True
32 | except urllib2.URLError as err:
33 | pass
34 | return False
35 | '''
36 |
37 | #Check for network connection at startup
38 | t = time.time()
39 | while True:
40 | lcd.clear()
41 | lcd.message('checking network\nconnection ...')
42 | if (time.time() - t) > 120:
43 | # No connection reached after 2 minutes
44 | lcd.clear()
45 | lcd.message('network is\nunavailable')
46 | time.sleep(30)
47 | exit(0)
48 | try:
49 | s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
50 | s.connect(('8.8.8.8', 0))
51 | lcd.backlight(lcd.ON)
52 | lcd.clear()
53 | lcd.message('IP address:\n' + s.getsockname()[0])
54 | time.sleep(5)
55 | display.initInfo() # Start info gathering/display
56 | break # Success
57 | except:
58 | time.sleep(1) # Pause a moment, keep trying
59 | '''
60 | if internetOn() == True:
61 | time.sleep(5)
62 | break # Success
63 | else:
64 | time.sleep(1) # Pause a moment, keep trying
65 | '''
66 |
67 | # Listen for button presses
68 | while True:
69 | b = lcd.buttons()
70 | if b is not prev:
71 | if lcd.buttonPressed(lcd.SELECT):
72 | tt = time.time() # Start time of button press
73 | while lcd.buttonPressed(lcd.SELECT): # Wait for button release
74 | if (time.time() - tt) >= HOLD_TIME: # Extended hold?
75 | shutdown() # We're outta here
76 | display.backlightStep()
77 | elif lcd.buttonPressed(lcd.LEFT):
78 | display.scrollRight()
79 | elif lcd.buttonPressed(lcd.RIGHT):
80 | display.scrollLeft()
81 | elif lcd.buttonPressed(lcd.UP):
82 | display.modeUp()
83 | elif lcd.buttonPressed(lcd.DOWN):
84 | display.modeDown()
85 | prev = b
86 | lastTime = time.time()
87 | else:
88 | now = time.time()
89 | since = now - lastTime
90 | if since > REFRESH_TIME or since < 0.0:
91 | display.update()
92 | lastTime = now
93 |
--------------------------------------------------------------------------------
/opt/scripta/modules/PiMiner/PiMinerDisplay.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 |
3 | from PiMinerInfo import PiMinerInfo
4 | from Adafruit_CharLCDPlate import Adafruit_CharLCDPlate
5 |
6 | class PiMinerDisplay:
7 |
8 | col = []
9 | prevCol = 0
10 | lcd = Adafruit_CharLCDPlate()
11 | info = None
12 | mode = 1
13 | offset = 0
14 | maxOffset = 0
15 | screen = []
16 |
17 | def __init__(self):
18 | self.lcd.clear()
19 | self.col = (self.lcd.ON, self.lcd.OFF, self.lcd.YELLOW, self.lcd.OFF,
20 | self.lcd.GREEN, self.lcd.OFF, self.lcd.TEAL, self.lcd.OFF,
21 | self.lcd.BLUE, self.lcd.OFF, self.lcd.VIOLET, self.lcd.OFF,
22 | self.lcd.RED, self.lcd.OFF)
23 | self.lcd.backlight(self.col[self.prevCol])
24 |
25 | #Show initial info (call after network connected)
26 | def initInfo(self):
27 | self.info = PiMinerInfo()
28 | self.dispLocalInfo()
29 |
30 | #Display Local Info - Accepted, Rejected, HW Errors \n Average Hashrate
31 | def dispLocalInfo(self):
32 | self.dispScreen(self.info.screen1)
33 |
34 | #Display Pool Name \n Remote hashrate
35 | def dispPoolInfo(self):
36 | self.dispScreen(self.info.screen2)
37 |
38 | #Display Rewards (confirmed + unconfirmed) \n Current Hash
39 | def dispRewardsInfo(self):
40 | self.dispScreen(self.info.screen3)
41 |
42 | #Display Error rate & Uptime
43 | def dispUptimeInfo(self):
44 | self.dispScreen(self.info.screen4)
45 |
46 | #Display rewards & price
47 | def dispValueInfo(self):
48 | self.dispScreen(self.info.screen5)
49 |
50 | #Send text to display
51 | def dispScreen(self, newScreen):
52 | self.screen = newScreen
53 | try:
54 | self.maxOffset = max((len(self.screen[0]) - 16), (len(self.screen[1]) - 16))
55 | self.lcd.clear()
56 | s = self.screen[0] + '\n' + self.screen[1]
57 | self.lcd.message(s)
58 | except TypeError:
59 | self.lcd.clear()
60 | self.lcd.message('connecting\nto cgminer ...')
61 |
62 |
63 | #Cycle Backlight Color / On/Off
64 | def backlightStep(self):
65 | if self.prevCol is (len(self.col) -1): self.prevCol = -1
66 | newCol = self.prevCol + 1
67 | self.lcd.backlight(self.col[newCol])
68 | self.prevCol = newCol
69 |
70 | #Offset text to the right
71 | def scrollLeft(self):
72 | if self.offset >= self.maxOffset: return
73 | self.lcd.scrollDisplayLeft()
74 | self.offset += 1
75 |
76 | #Offset text to the left
77 | def scrollRight(self):
78 | if self.offset <= 0: return
79 | self.lcd.scrollDisplayRight()
80 | self.offset -= 1
81 |
82 | #Display next info screen
83 | def modeUp(self):
84 | self.mode += 1
85 | if self.mode > 4: self.mode = 0
86 | self.update()
87 |
88 | #Display previous info screen
89 | def modeDown(self):
90 | self.mode -= 1
91 | if self.mode < 0: self.mode = 4
92 | self.update()
93 |
94 | #Update display
95 | def update(self):
96 | self.info.refresh()
97 | if self.mode == 0: self.dispPoolInfo()
98 | elif self.mode == 1: self.dispLocalInfo()
99 | elif self.mode == 2: self.dispRewardsInfo()
100 | elif self.mode == 3: self.dispUptimeInfo()
101 | elif self.mode == 4: self.dispValueInfo()
102 |
--------------------------------------------------------------------------------
/opt/scripta/modules/PiMiner/PiMinerInfo.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 |
3 | #This file uses code from fcicq's cgmonitor.py released under GPLv3:
4 | #https://gist.github.com/fcicq/4975730
5 | #for details see LICENSE.txt
6 |
7 | import subprocess
8 | import socket
9 | import time
10 | import urllib
11 | import json
12 | import time
13 |
14 | class PiMinerInfo:
15 |
16 | host = ''
17 | port = 4028
18 | errRate = 0.0
19 | accepted = 0.0
20 | hw = 0.0
21 | diff1shares = 0.0
22 | uptime = ''
23 | screen1 = ['no data','no data']
24 | screen2 = ['no data','no data']
25 | screen3 = ['no data','no data']
26 | screen4 = ['no data','no data']
27 | screen5 = ['no data','no data']
28 | currency = 'USD' #USD GBP EUR JPY AUD CAD CHF CNY DKK HKD PLN RUB SEK SGD THB NOK CZK
29 | dollars = ['USD', 'AUD', 'CAD'] #currencies with displayable symbols
30 | lastCheck = time.time() #time of last price check
31 | priceWait = 60.0 #interval between price checks
32 | priceLast = '-' #last price via mtgox
33 | priceLo = '-' #low price
34 | priceHi = '-' #high price
35 |
36 | def __init__(self):
37 | self.host = self.get_ipaddress()
38 | self.refresh()
39 | self.checkPrice()
40 |
41 | def reportError(self, s):
42 | self.screen1 = [s, s]
43 | self.screen2 = [s, s]
44 | self.screen3 = [s, s]
45 | self.screen4 = [s, s]
46 |
47 | def value_split(self, s):
48 | r = s.split('=')
49 | if len(r) == 2: return r
50 | return r[0], ''
51 |
52 | def response_split(self, s):
53 | try:
54 | r = s.split(',')
55 | title = r[0]
56 | d = dict(map(self.value_split, r[1:]))
57 | return title, d
58 | except ValueError:
59 | self.reportError('value error')
60 |
61 | def get_ipaddress(self):
62 | arg = 'ip route list'
63 | p = subprocess.Popen(arg,shell=True,stdout=subprocess.PIPE)
64 | data = p.communicate()
65 | split_data = data[0].split()
66 | self.ipaddr = split_data[split_data.index('src')+1]
67 | s = '%s' % self.ipaddr
68 | self.reportError(s)
69 | return self.ipaddr
70 |
71 | def parse_time(self, t):
72 | r = []
73 | m = t // 60
74 | d = 0
75 | if t >= 86400:
76 | d = t // 86400
77 | t = t % 86400
78 | r.append('%02d:%02d:%02d' % (d, t // 3600, (t % 3600) // 60)) #seconds == t % 60
79 | return ' '.join(r)
80 |
81 | def cg_rpc(self, host, port, command):
82 | try:
83 | s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
84 | s.connect((host, port))
85 | s.sendall(command)
86 | time.sleep(0.02)
87 | data = s.recv(8192)
88 | s.close()
89 | except Exception as e:
90 | self.reportError(e)
91 | return
92 | if data:
93 | d = data.strip('\x00|').split('|')
94 | return map(self.response_split, d)
95 | return None
96 |
97 | def hashrate(self, h):
98 | u = 'Mh/s'
99 | if h >= 1000.0:
100 | u = 'Gh/s'
101 | h = h / 1000.0
102 | elif h >= 1000000.0:
103 | u = 'Th/s'
104 | h = h / 1000000.0
105 | s = '%s %s' % (h, u)
106 | return s
107 |
108 | def abbrev(self, v):
109 | v = int(v)
110 | if v >= 1000:
111 | va = float(v) / 1000.0
112 | vs = '%.1f' % va
113 | vs = vs.replace('.', 'k')
114 | return vs
115 | elif v >= 1000000:
116 | va = float(v) / 1000000.0
117 | vs = '%.1f' % va
118 | vs = vs.replace('.', 'm')
119 | return vs
120 | #billion
121 | else:
122 | return '%d' % v
123 |
124 | def parse_summary(self, r):
125 | if not (isinstance(r, (list, tuple)) and len(r) == 2):
126 | return
127 | try:
128 | if not r[0][0] == 'STATUS=S' and r[1][0] == 'SUMMARY':
129 | return
130 | d = r[1][1]
131 | self.uptime = self.parse_time(int(d['Elapsed']))
132 | self.accepted = float(d['Accepted'])
133 | self.hw = float(d['Hardware Errors'])
134 | try:
135 | #self.errRate = self.hw / self.accepted * 100.0
136 | self.errRate = 100.0 * self.hw / (self.diff1shares + self.hw)
137 | except Exception as e:
138 | self.errRate = 0.0
139 | acc = self.abbrev(d['Accepted'])
140 | rej = self.abbrev(d['Rejected'])
141 | hw = self.abbrev(d['Hardware Errors'])
142 | s1 = 'A:%s R:%s H:%s' % (acc, rej, hw)
143 | s2 = 'avg:%s' % self.hashrate(float(d['MHS av']))
144 | return [s1, s2]
145 | except Exception as e:
146 | return [str(e), str(e)]
147 |
148 | def conv_prio_dict(self, p):
149 | if isinstance(p, (tuple, list, )):
150 | try:
151 | pd = dict(p)
152 | except TypeError:
153 | pd = zip(p, range(len(p)))
154 | return pd
155 | if isinstance(p, dict): return p
156 | return {}
157 |
158 | def parse_pools(self, r):
159 | if not isinstance(r, (list, tuple)): return ['format', 'error']
160 |
161 | try:
162 | if not r[0][0] == 'STATUS=S': return ['status', 'error']
163 | remote_time = int(r[0][1]['When'])
164 | for rp in r[1:]:
165 | if rp[0][0:4] != 'POOL': continue
166 | d = rp[1]
167 | self.diff1shares = float(d['Diff1 Shares'])
168 | if d['URL'].startswith('stratum+tcp://'): d['URL'] = d['URL'][14:]
169 | if d['URL'].startswith('http://'): d['URL'] = d['URL'][7:]
170 | d['URL'] = d['URL'].rstrip('/')
171 | if d['Status'] == 'Alive':
172 | s1 = '%s' % d['URL']
173 | s2 = '%s' % d['User']
174 | return [s1, s2]
175 | except Exception as e:
176 | return [str(e), str(e)]
177 |
178 | def parse_config(self, r):
179 | if not isinstance(r, (list, tuple)): return
180 | try:
181 | if not r[0][0] == 'STATUS=S': return
182 | if not r[1][0] == 'CONFIG': return
183 | d = r[1][1]
184 | return 'devcs: %s' % (int(d.get('GPU Count','0')) + int(d.get('PGA Count','0')) + int(d.get('ASC Count','0')))
185 | except Exception as e:
186 | return str(e)
187 |
188 | def parse_coin(self, r):
189 | if not isinstance(r, (list, tuple)): return
190 | try:
191 | d = r[1][1]
192 | return 'diff: %.2fm' % (float(d['Network Difficulty']) / 1000000.0)
193 | except Exception as e:
194 | return str(e)
195 |
196 | def checkPrice(self):
197 | try:
198 | url = 'https://data.mtgox.com/api/2/BTC***/money/ticker'.replace('***', self.currency)
199 | f = urllib.urlopen(url)
200 | except Exception as e:
201 | self.reportError(e)
202 | return None
203 | data = None
204 | if f:
205 | pricesData = f.read()
206 | prices_json = json.loads(pricesData)
207 | if prices_json and prices_json['result'] == 'success':
208 | data = prices_json['data']
209 |
210 | #dollar symbol currencies
211 | if self.currency in self.dollars:
212 | self.priceLast = data['last']['display_short'] if data else '-'
213 | self.priceLo = data['low']['display_short'] if data else '-'
214 | a, self.priceLo = self.priceLo.split('$')
215 | self.priceHi = data['high']['display_short'] if data else '-'
216 | a, self.priceHi = self.priceHi.split('$')
217 |
218 | #non-compatible symbol currencies
219 | else:
220 | self.priceLast = ('%.2f ' % float(data['last']['value']) if data else '-') + self.currency
221 | self.priceLo = '%.2f' % float(data['low']['value']) if data else '-'
222 | self.priceHi = '%.2f' % float(data['high']['value']) if data else '-'
223 |
224 | def refresh(self):
225 |
226 | s = self.cg_rpc(self.host, self.port, 'summary')
227 | self.screen1 = self.parse_summary(s)
228 |
229 | s = self.cg_rpc(self.host, self.port, 'pools')
230 | self.screen3 = self.parse_pools(s)
231 |
232 | s = self.cg_rpc(self.host, self.port, 'config')
233 | self.screen2[0] = self.parse_config(s)
234 | s = self.cg_rpc(self.host, self.port, 'coin')
235 | self.screen4[1] = self.parse_coin(s)
236 |
237 | self.screen4[0] = 'time: %s' % self.uptime
238 | self.screen2[1] = 'error: %.2f%%' % self.errRate
239 |
240 | now = time.time()
241 | since = now - self.lastCheck
242 | if since >= self.priceWait:
243 | self.checkPrice()
244 | self.lastCheck = time.time()
245 |
246 | self.screen5[0] = 'last: %s' % self.priceLast
247 | self.screen5[1] = 'H:' + self.priceHi + ' L:' + self.priceLo
248 |
--------------------------------------------------------------------------------
/opt/scripta/modules/PiMiner/README.md:
--------------------------------------------------------------------------------
1 | PiMiner v1.1
2 | =======
3 |
4 | Python scripts for interfacing cgminer with the Adafruit 16x2 LCD + Keypad Kit for Raspberry Pi.
5 |
6 | Project tutorial: http://learn.adafruit.com/piminer-raspberry-pi-bitcoin-miner
7 |
8 | In progress!
9 |
10 | Adafruit invests time and resources providing this open source code, please support Adafruit and open-source hardware by purchasing products from Adafruit!
11 |
12 | Written by Collin Cunningham for Adafruit Industries. BSD license, all text above must be included in any redistribution
13 |
14 | To download, log into your Pi with Internet accessibility and type: git clone https://github.com/adafruit/PiMiner.git
15 |
16 |
17 | Changes
18 | -------------
19 |
20 | Version 1.1
21 | - Added mining auto-start after boot (see tutorial)
22 | - Time format changed to dd:hh:mm
23 | - Abbreviated large share count; ex. "1k2"
24 | - Revised error % calculation: 100 * HW / (diff1shares + HW)
25 | - Added MtGox last, high, & low price ("currency" var can be set in script)
26 | - Misc. tutorial revisions
27 |
28 |
29 | Version 1.0
30 | - Initial release
31 |
--------------------------------------------------------------------------------
/opt/scripta/modules/cgminerLCDStats/CgminerRPCClient.py:
--------------------------------------------------------------------------------
1 |
2 | #
3 | # class to accesss cgminer via RPC API
4 | #
5 |
6 | import socket
7 | import urlparse
8 | import urllib
9 | import time
10 | import json
11 |
12 | #
13 | # execute cgminer API remote procedure call
14 | def command(command, host, port):
15 | try:
16 | s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
17 | s.connect((host, port))
18 | s.sendall(json.dumps({"command": command})) # send API request formatted as json
19 | time.sleep(0.02)
20 |
21 | # loop until a zero byte indicates we got all the data
22 | data = ""
23 | while True:
24 | buffer = s.recv(65535)
25 | if '\x00' in buffer:
26 | data += buffer # keep the buffer and bail from the loop - we got all the data
27 | break # zero found, so we must have all the data TODO break in loop is ugly
28 | else:
29 | data += buffer # No zero found yet, append current buffer to data and loop for more
30 |
31 | s.close() # close the socket
32 |
33 | except Exception as e:
34 | print "API Exception executing command: " + command
35 | print str(e) # TODO conditonal logging
36 | raise Exception ("API Connection Error")
37 |
38 | if data:
39 | try:
40 | data = data.replace('\x00', '') # the null byte makes json decoding unhappy
41 | decoded = json.loads(data) # we sent a json request, so expect json response
42 | return decoded
43 | except:
44 | # TODO conditional loggging
45 | print "JSON decoding error - bad JSON sring:"
46 | print data
47 | pass # swallow the exception (normal use shouldn't throw one ?)
48 |
49 |
--------------------------------------------------------------------------------
/opt/scripta/modules/cgminerLCDStats/MinePeon Install.md:
--------------------------------------------------------------------------------
1 | This is a quick guide to installing the cgminerLCDStats.py script on MinePeon. Note that I'm new to MinePeon as well as Arch linux for ARM. I welcome any input on this guide.
2 |
3 | I started with a fresh install of the current version of MinePeon, v0.2.2. I took the usual steps to verify cgminer was working correctly, and that my Pi would come up on the same internal I.P. address each time.
4 |
5 | To begin the installation, I logged in to the Pi via ssh from my main machine. I find it way easier to interact with the Pi command line over ssh, rather than logging into the Pi itself. When entering the following commands, it's easiest to copy and paste them into the terminal window. Wait for each step to complete and watch for errors. Some of the updates require user interaction, so say yes if prompted.
6 |
7 | Ok, let's get started. Log on to your Pi with this command:
8 | ssh minepeon@YOURIP - example: ssh minepeon@192.168.1.111
9 |
10 | Make sure the OS is up to date (Optional step - skip this is you want too, or are already on a recent version):
11 | `sudo pacman -Syu`
12 |
13 | Get the "git" utility for downloading packages:
14 | `sudo pacman -S git`
15 |
16 | Make sure we have all the latest MinePeon packages (Optional step - skip this is you want too, or are already on a recent version):
17 | `cd /opt/minepeon/`
18 | `git pull`
19 | `cd /opt/minepeon/http/`
20 | `git pull`
21 |
22 | Optional: Verify Python2 is already installed (it should be) - current version is Python 2.7.5:
23 | `python2 -V`
24 |
25 | Install pyUSB library:
26 | `cd ~`
27 | `git clone https://github.com/walac/pyusb.git`
28 | `cd pyusb`
29 | `sudo python2 setup.py install`
30 |
31 | Install the cgminerLCDStats.py script and required modules:
32 | `cd ~`
33 | `git clone https://github.com/cardcomm/cgminerLCDStats.git`
34 | `cd cgminerLCDStats`
35 |
36 | Ok, that's it. We should be ready to go. Make sure the LCD display is connected, and let's start the script. You can start it with the default options using the following command:
37 | `sudo python2 cgminerLCDStats.py`
38 |
39 | If everything went well, you should now see your cgminer stats displayed on the USB screen. Enjoy!
40 |
41 | Note: By default, the display refreshes every 30 seconds. You can change this, and other behavior using the following command line options:
42 |
43 | Options:
44 | -h, --help show this help message and exit
45 | -s, --simple Show simple display layout instead of default
46 | -d REFRESHDELAY, --refresh-delay=REFRESHDELAY
47 | REFRESHDELAY = Time delay between screen/API refresh
48 | -i HOST, --host=HOST I.P. Address of cgminer API host
49 |
50 |
--------------------------------------------------------------------------------
/opt/scripta/modules/cgminerLCDStats/README.md:
--------------------------------------------------------------------------------
1 | cgminerLCDStats
2 | ===============
3 |
4 | Simple script to get data from cgminer API and display it on the "LCD sys info" display. See links below for where you can purchase the display used for this project.
5 |
6 | If you feel this code is useful, please consider a donation to:
7 | BTC address: 15aGZp2pCbpAFHcjHVrx2G746PXFo9VEed
8 |
9 | Run as root to avoid permissions issues : sudo python cgminerLCDStats.py [options]
10 |
11 | Usage: cgminerLCDStats.py [options] arg
12 |
13 | Options:
14 | `-h, --help show this help message and exit`
15 | `-s, --simple Show simple display layout instead of default`
16 | `-d REFRESHDELAY, --refresh-delay=REFRESHDELAY where REFRESHDELAY = Time delay between screen/API refresh`
17 | `-i HOST, --host=HOST I.P. Address of cgminer API host`
18 | `-c TIMEDISPLAYFORMAT, --clock=TIMEDISPLAYFORMAT Options 12 or 24 - Clock Display 12hr / 24hr`
19 |
20 | Where to buy the LCD Display Unit:
21 | http://www.ebay.com/itm/USB-2-8-TFT-LCD-module-LCD-sys-info-display-temperature-fan-AIDA64-LCD-Smartie-/121004607232?pt=LH_DefaultDomain_0&hash=item1c2c6fc700
22 |
23 | For more specifics about the "LCD sys info" display this code supports, see:
24 | http://coldtearselectronics.wikispaces.com/USB+LCD+-+LCD+System+info
25 | https://github.com/dangardner/pylcdsysinfo
26 |
27 | Note: A HUGE thank you goes out to Kano for is invaluable assitance with this code.
28 | He's a key developer on the cgminer project, and was a big help in sorting out problems I had writing this script.
29 | https://bitcointalk.org/index.php?action=profile;u=36044
30 |
31 | Copyright (c) 2013 Cardinal Commmunications
32 |
33 | Permission to use, copy, modify, and/or distribute this software for any
34 | purpose with or without fee is hereby granted, provided that the above
35 | copyright notice and this permission notice appear in all copies.
36 |
37 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
38 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
39 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
40 | SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
41 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
42 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
43 | IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
44 |
45 | Please check the library code module "pylcdsysinfo.py" for copyright and author information.
46 |
--------------------------------------------------------------------------------
/opt/scripta/modules/cgminerLCDStats/lcd_and_pi-small.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/scriptamining/scripta/6c612e9a6df050688921ab14ac330dfabf27c9de/opt/scripta/modules/cgminerLCDStats/lcd_and_pi-small.jpg
--------------------------------------------------------------------------------
/opt/scripta/modules/cgminerLCDStats/lcd_and_pi.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/scriptamining/scripta/6c612e9a6df050688921ab14ac330dfabf27c9de/opt/scripta/modules/cgminerLCDStats/lcd_and_pi.jpg
--------------------------------------------------------------------------------
/opt/scripta/startup/miner-start.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | sudo /usr/sbin/ntpdate -u pool.ntp.org
3 | sudo /usr/bin/screen -dmS bfgminer /opt/scripta/bin/bfgminer -c /opt/scripta/etc/miner.conf
4 | sleep 1
5 | echo `pidof bfgminer` > /opt/scripta/var/bfgminer.pid
6 |
7 |
8 |
--------------------------------------------------------------------------------
/opt/scripta/startup/miner-stop.sh:
--------------------------------------------------------------------------------
1 | #sudo kill $(cat /opt/scripta/var/cgminer.lock)
2 |
3 | sudo /usr/bin/screen -S bfgminer -X quit
4 |
--------------------------------------------------------------------------------
/opt/scripta/var/rrd/.keep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/scriptamining/scripta/6c612e9a6df050688921ab14ac330dfabf27c9de/opt/scripta/var/rrd/.keep
--------------------------------------------------------------------------------
/update.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | /usr/bin/screen -S bfgminer -X quit
3 | cd /
4 | git pull
5 | sudo cp -Ru /scripta/etc/rc.local /etc/rc.local
6 | sudo cp -Ru /scripta/opt/scripta/ /opt/
7 | sudo cp -Ru /scripta/var/ /
8 | sudo cp -Ru /scripta/update.sh /update.sh
9 | sudo chown -R www-data:www-data /opt/scripta
10 | sudo chown -R www-data:www-data /var/www
11 | sudo chmod -R 775 /opt/scripta/startup/*.sh
12 | sudo chmod -R 775 /etc/rc.local
13 | sudo chmod -R 775 /var/www
14 | sleep 5
15 | sudo reboot
16 |
--------------------------------------------------------------------------------
/var/spool/cron/crontabs/root:
--------------------------------------------------------------------------------
1 | # DO NOT EDIT THIS FILE - edit the master and reinstall.
2 | # (/tmp/crontab.NXCETO/crontab installed on Wed Apr 16 21:19:35 2014)
3 | # (Cron version -- $Id: crontab.c,v 2.13 1994/01/17 03:20:37 vixie Exp $)
4 | # Edit this file to introduce tasks to be run by cron.
5 | #
6 | # Each task to run has to be defined through a single line
7 | # indicating with different fields when the task will be run
8 | # and what command to run for the task
9 | #
10 | # To define the time you can provide concrete values for
11 | # minute (m), hour (h), day of month (dom), month (mon),
12 | # and day of week (dow) or use '*' in these fields (for 'any').#
13 | # Notice that tasks will be started based on the cron's system
14 | # daemon's notion of time and timezones.
15 | #
16 | # Output of the crontab jobs (including errors) is sent through
17 | # email to the user the crontab file belongs to (unless redirected).
18 | #
19 | # For example, you can run a backup of all your user accounts
20 | # at 5 a.m every week with:
21 | # 0 5 * * 1 tar -zcf /var/backups/home.tgz /home/
22 | #
23 | # For more information see the manual pages of crontab(5) and cron(8)
24 | #
25 | # m h dom mon dow command
26 | 0,5,10,15,20,25,30,35,40,45,50,55 * * * * /usr/bin/php5 /opt/scripta/etc/cron.d/5min/ALERTdeviceCount
27 | 0,5,10,15,20,25,30,35,40,45,50,55 * * * * /usr/bin/php5 /opt/scripta/etc/cron.d/5min/ALERThashrate
28 | 0,5,10,15,20,25,30,35,40,45,50,55 * * * * /usr/bin/php5 /opt/scripta/etc/cron.d/5min/hashrate
29 | 0,5,10,15,20,25,30,35,40,45,50,55 * * * * /usr/bin/php5 /opt/scripta/etc/cron.d/5min/temp
30 | 0,5,10,15,20,25,30,35,40,45,50,55 * * * * /usr/bin/php5 /opt/scripta/etc/cron.d/5min/RECORDhashrate
31 |
--------------------------------------------------------------------------------
/var/www/apple-touch-icon-precomposed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/scriptamining/scripta/6c612e9a6df050688921ab14ac330dfabf27c9de/var/www/apple-touch-icon-precomposed.png
--------------------------------------------------------------------------------
/var/www/css/alertify.css:
--------------------------------------------------------------------------------
1 | /*! alertify 0.4.0rc1 (Fabien Doiron) | MIT */
2 | /* alertify-transitions */
3 | .alertify-cover{position:fixed;z-index:9999;top:0;bottom:0;left:0;right:0;}.alertify-dialog{position:fixed;z-index:99999;top:50px;left:50%;opacity:1;-webkit-transition:all 500ms cubic-bezier(0.175,0.885,0.32,1.275);-moz-transition:all 500ms cubic-bezier(0.175,0.885,0.32,1.275);-ms-transition:all 500ms cubic-bezier(0.175,0.885,0.32,1.275);-o-transition:all 500ms cubic-bezier(0.175,0.885,0.32,1.275);transition:all 500ms cubic-bezier(0.175,0.885,0.32,1.275);}.alertify-resetFocus{border:0;clip:rect(0000);height:1px;width:1px;overflow:hidden;position:absolute;margin:-1px;padding:0;}.alertify-text{margin-bottom:15px;width:100%;font-size:100%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;}.alertify-button,.alertify-button:hover,.alertify-button:active,.alertify-button:visited{background:none;text-decoration:none;border:none;line-height:1.5;font-size:100%;display:inline-block;cursor:pointer;margin-left:5px;}.is-alertify-cover-hidden{display:none;}.is-alertify-dialog-hidden{opacity:0;display:none;-webkit-transform:translate(0,-150px);-moz-transform:translate(0,-150px);-ms-transform:translate(0,-150px);-o-transform:translate(0,-150px);transform:translate(0,-150px);}:root * > .is-alertify-dialog-hidden{display:block;}.alertify-logs{position:fixed;z-index:9999;}.alertify-log{position:relative;display:block;opacity:0;-webkit-transition:all 500ms cubic-bezier(0.175,0.885,0.32,1.275);-moz-transition:all 500ms cubic-bezier(0.175,0.885,0.32,1.275);-ms-transition:all 500ms cubic-bezier(0.175,0.885,0.32,1.275);-o-transition:all 500ms cubic-bezier(0.175,0.885,0.32,1.275);transition:all 500ms cubic-bezier(0.175,0.885,0.32,1.275);}.is-alertify-log-showing{opacity:1;}.is-alertify-log-hidden{opacity:0;}
4 | /* alertify-default */
5 | .alertify-dialog{width:550px;margin-left:-275px;background:#FFF;border:10px solid rgba(0,0,0,0.7);border-radius:8px;box-shadow:0 3px 3px rgba(0,0,0,0.3);-webkit-background-clip:padding;-moz-background-clip:padding;background-clip:padding-box;}.alertify-dialog-inner{padding:25px;}.alertify-inner{text-align:center;}.alertify-text{border:1px solid #ccc;border-radius:4px;padding:10px;}.alertify-button{border-radius:4px;color:#FFF;font-weight:700;text-decoration:none;text-shadow:1px 1px 0 rgba(0,0,0,0.5);box-shadow:inset 0 1px 0 0 rgba(255,255,255,0.5);background-image:linear-gradient(top,rgba(255,255,255,0.3), rgba(255,255,255,0));padding:6px 15px;}.alertify-button:hover,.alertify-button:focus{outline:none;background-image:linear-gradient(top,rgba(0,0,0,0.1), rgba(0,0,0,0));}.alertify-button:focus{box-shadow:0 0 10px #2b72d5;}.alertify-button:active{position:relative;box-shadow:inset 0 2px 4px rgba(0,0,0,0.15), 0 1px 2px rgba(0,0,0,0.05);}.alertify-button-cancel,.alertify-button-cancel:hover,.alertify-button-cancel:focus{background-color:#fe1a00;border:1px solid #cb1500;}.alertify-button-ok,.alertify-button-ok:hover,.alertify-button-ok:focus{background-color:#5cb811;border:1px solid #45890d;}.alertify-logs{position:fixed;z-index:9999;bottom:8px;right:8px;width:300px;}.alertify-log{margin-top:8px;right:-300px;border-radius:4px;padding:16px;}.alertify-log-info{background:rgba(0,0,0,0.9);color:#FFF;text-shadow:-1px -1px 0 rgba(0,0,0,0.5);}.alertify-log-error{color:#FFF;background:rgba(254,26,0,0.9);}.alertify-log-success{color:#FFF;background:rgba(92,184,17,0.9);}.is-alertify-log-showing{right:0;}.is-alertify-log-hidden{right:-300px;}@media only screen and max-width 680px{.alertify-dialog{width:90%;left:5%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;margin:0;}}
6 |
--------------------------------------------------------------------------------
/var/www/css/custom.css:
--------------------------------------------------------------------------------
1 | body
2 | {
3 | font-family: 'News Cycle', sans-serif;
4 | color: #222;
5 | line-height: 1.4;
6 | text-rendering: optimizeLegibility;
7 | /* -webkit-text-stroke: 0.35px; */
8 | }
9 |
10 | h1, h2, h3, h4, h5, h6, .h1, .h2, .h3, .h4, .h5, .h6 {
11 | font-family: 'News Cycle', sans-serif;
12 | font-weight: 700;
13 | line-height: 1.1;
14 | }
15 |
16 | a, .btn { color: #68a72f; }
17 | a:hover, a:focus, .btn:hover { color: #076633; }
18 | .btn, .input-group-addon, .form-control { border-radius: 2px; }
19 | .btn
20 | {
21 | font-weight: 700;
22 | line-height: 1.45em;
23 | background-color: #F4F4F4;
24 | }
25 |
26 | footer { color: #aaa; }
27 |
28 | /* repeat bootstrap btns */
29 | .btn-primary {
30 | color: #fff;
31 | background-color: #428bca;
32 | border-color: #357ebd
33 | }
34 |
35 | .btn-primary:hover, .btn-primary:focus, .btn-primary:active, .btn-primary.active,
36 | .open .dropdown-toggle.btn-primary {
37 | color: #fff;
38 | background-color: #3276b1;
39 | border-color: #285e8e
40 | }
41 |
42 | .btn-primary:active, .btn-primary.active, .open .dropdown-toggle.btn-primary {
43 | background-image: none
44 | }
45 |
46 | .btn-primary.disabled, .btn-primary[disabled], fieldset[disabled] .btn-primary,
47 | .btn-primary.disabled:hover, .btn-primary[disabled]:hover, fieldset[disabled] .btn-primary:hover,
48 | .btn-primary.disabled:focus, .btn-primary[disabled]:focus, fieldset[disabled] .btn-primary:focus,
49 | .btn-primary.disabled:active, .btn-primary[disabled]:active, fieldset[disabled] .btn-primary:active,
50 | .btn-primary.disabled.active, .btn-primary[disabled].active, fieldset[disabled] .btn-primary.active {
51 | background-color: #428bca;
52 | border-color: #357ebd
53 | }
54 |
55 | .btn-warning {
56 | color: #fff;
57 | background-color: #f0ad4e;
58 | border-color: #eea236
59 | }
60 |
61 | .btn-warning:hover, .btn-warning:focus, .btn-warning:active, .btn-warning.active,
62 | .open .dropdown-toggle.btn-warning {
63 | color: #fff;
64 | background-color: #ed9c28;
65 | border-color: #d58512
66 | }
67 |
68 | .btn-warning:active, .btn-warning.active, .open .dropdown-toggle.btn-warning {
69 | background-image: none
70 | }
71 |
72 | .btn-warning.disabled, .btn-warning[disabled], fieldset[disabled] .btn-warning,
73 | .btn-warning.disabled:hover, .btn-warning[disabled]:hover, fieldset[disabled] .btn-warning:hover,
74 | .btn-warning.disabled:focus, .btn-warning[disabled]:focus, fieldset[disabled] .btn-warning:focus,
75 | .btn-warning.disabled:active, .btn-warning[disabled]:active, fieldset[disabled] .btn-warning:active,
76 | .btn-warning.disabled.active, .btn-warning[disabled].active, fieldset[disabled] .btn-warning.active {
77 | background-color: #f0ad4e;
78 | border-color: #eea236
79 | }
80 |
81 | .btn-danger {
82 | color: #fff;
83 | background-color: #d9534f;
84 | border-color: #d43f3a
85 | }
86 |
87 | .btn-danger:hover, .btn-danger:focus, .btn-danger:active, .btn-danger.active,
88 | .open .dropdown-toggle.btn-danger {
89 | color: #fff;
90 | background-color: #d2322d;
91 | border-color: #ac2925
92 | }
93 | /* */
94 |
95 | .alertify-logs {font-weight:700;}
96 |
97 | /* header.navbar { position: fixed; width: 100%; } */
98 | header.navbar .container
99 | {
100 | background-color: transparent;
101 | background-image: url(../img/bg-header1.png);
102 | background-repeat: no-repeat;
103 | background-position: 100% 100%;
104 | }
105 |
106 | .navbar-default { border-color: #9DD374; }
107 | .navbar-brand { height: 140px; }
108 | .navbar-brand img { height: 100%; }
109 |
110 | .navbar-collapse.collapse { position: relative; }
111 | .nav.navbar-nav {position: absolute; bottom: 0; left: 280px}
112 | .navbar-nav.navbar-right { position: absolute; right: 20px; bottom: 0; }
113 |
114 | .navbar-nav > li { font-weight: bold; }
115 | .navbar-default .navbar-nav > .active > a, .navbar-default .navbar-nav>.active>a:hover
116 | {
117 | color: #fff;
118 | background-color: #9DD374;
119 | border-radius: 2px;
120 | border-bottom-left-radius: 0;
121 | border-bottom-right-radius: 0;
122 | }
123 |
124 | .list-group-item
125 | {
126 | border-width: 1px 0 1px 0;
127 | border-color: #D5D5D5;
128 | }
129 | /*
130 | .list-group-item:first-child {
131 | border-top-right-radius: 2px;
132 | border-top-left-radius: 2px;
133 | }
134 | */
135 |
136 | a.list-group-item:hover, a.list-group-item:focus {
137 | margin-right: -20px;
138 | padding-right: 40px;
139 | color: #111;
140 | }
141 |
142 | a.list-group-item:hover:after, a.list-group-item:focus:after
143 | {
144 | content: '>';
145 | position: absolute;
146 | right: 0;
147 | top: 0;
148 | bottom: 0;
149 | padding: 4px;
150 | font-size: 2em;
151 | line-height: 1em;
152 | color: #090;
153 | }
--------------------------------------------------------------------------------
/var/www/css/theme.css:
--------------------------------------------------------------------------------
1 |
2 | /* Structure */
3 | body{
4 | padding-bottom: 50px;
5 | }
6 | .navbar{
7 | margin-bottom: 0px;
8 | }
9 | .container.down{
10 | opacity: .5
11 | }
12 |
13 | /* Display on hover */
14 | .scripta-trigger .scripta-more{
15 | display: none;
16 | }
17 | .scripta-trigger:hover .scripta-more{
18 | display: inline-block;
19 | }
20 |
21 | /* Status charts */
22 | .graph-live{
23 | height: 159px;
24 | width: 100%
25 | }
26 |
27 | /* Status tables */
28 | td,th{
29 | white-space: nowrap;
30 | }
31 | .table-right td,.table-right tfoot th{
32 | text-align: right
33 | }
34 | .table-right td.text-left,.table-right tfoot th.text-left{
35 | text-align: left
36 | }
37 | tr.text-muted{
38 | background: #f5f5f5;
39 | }
40 |
41 | /* Index / Shorten wide values in tables and show them on hover */
42 | .ellipsis{
43 | overflow: hidden;
44 | text-overflow: ellipsis;
45 | -o-text-overflow: ellipsis;
46 | white-space: nowrap;
47 | max-width: 80px;
48 | }
49 | .ellipsis:hover{
50 | overflow: visible;
51 | max-width:none;
52 | width:auto;
53 | background-color: #fff!important;
54 | }
55 |
56 | /* Settings */
57 | input:required:invalid{
58 | border-color: rgb(233, 50, 45);
59 | box-shadow: 0px 0px 6px rgb(248, 185, 183);
60 | color: rgb(185, 74, 72);
61 | border-color: rgb(238, 95, 91);
62 | }
63 |
--------------------------------------------------------------------------------
/var/www/f_backup.php:
--------------------------------------------------------------------------------
1 | 'success', 'text' => 'Backup saved');
47 | foreach ($items as $key => $value) {
48 | if($value['selected']){
49 | $r['data'][$key]=secure_copy($baseFolder.$value['name'],$backupFolder.$_REQUEST['name'].'/'.$value['name']);
50 | }
51 | }
52 | }
53 | else{
54 | $r['info'][]=array('type' => 'success', 'text' => 'Backup not saved');
55 | }
56 | }
57 |
58 | // Copy folder from backupFolder back to baseFolder
59 | elseif (!empty($_REQUEST['restore']) && @is_dir($backupFolder.$_REQUEST['restore'])) {
60 | $restore = $_REQUEST['restore'];
61 |
62 | // Scan backup and remove . & ..
63 | $items = @scandir($backupFolder.$restore);
64 | if(!empty($items)){
65 | array_shift($items);
66 | array_shift($items);
67 | $r['info'][]=array('type' => 'success', 'text' => 'Restored!');
68 | }
69 | else{
70 | $r['info'][]=array('type' => 'danger', 'text' => 'Could not find backup');
71 | }
72 | foreach ($items as $key => $value) {
73 | // To return success: $r['data'][$key]=...
74 | secure_copy($backupFolder.$restore .'/'.$value,$baseFolder.$value);
75 | }
76 | }
77 |
78 | // Get a list of all backups and their content
79 | else{
80 | // Scan backup folder and remove . & ..
81 | $items = @scandir($backupFolder);
82 | if(!empty($items)){
83 | array_shift($items);
84 | array_shift($items);
85 | }
86 | else{exit;}
87 | rsort($items);
88 |
89 | // Scan subfolders, in the future this should also return the files
90 | foreach ($items as $key => $value) {
91 | $r['data'][$key]['dir']=$value;
92 | $r['data'][$key]['items']=@scandir($backupFolder.'/'.$value);
93 | if(!empty($r['data'][$key]['items'])){
94 | array_shift($r['data'][$key]['items']);
95 | array_shift($r['data'][$key]['items']);
96 | }
97 | }
98 | }
99 |
100 | echo json_encode($r);
101 | ?>
102 |
--------------------------------------------------------------------------------
/var/www/f_graph.php:
--------------------------------------------------------------------------------
1 |
43 |
--------------------------------------------------------------------------------
/var/www/f_hostHardCtl.php:
--------------------------------------------------------------------------------
1 |
18 |
--------------------------------------------------------------------------------
/var/www/f_login.php:
--------------------------------------------------------------------------------
1 |
35 |
--------------------------------------------------------------------------------
/var/www/f_logout.php:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/var/www/f_miner.php:
--------------------------------------------------------------------------------
1 |
29 |
--------------------------------------------------------------------------------
/var/www/f_minerHardCtl.php:
--------------------------------------------------------------------------------
1 |
18 |
--------------------------------------------------------------------------------
/var/www/f_minercompat.php:
--------------------------------------------------------------------------------
1 | $value) {
21 | if($key=='pools'){
22 | $r['data']['pools']=$value;
23 | }
24 | else{
25 | $r['data']['options'][]=array('key'=>$key,'value'=>$value);
26 | }
27 | }
28 | file_put_contents($configPools, json_encode($r['data']['pools'], JSON_PRETTY_PRINT | JSON_NUMERIC_CHECK));
29 | file_put_contents($configOptns, json_encode($r['data']['options'], JSON_PRETTY_PRINT | JSON_NUMERIC_CHECK));
30 | $r['info'][]=array('type' => 'success', 'text' => 'Compatibility reload done');
31 | }
32 | else{
33 | $r['info'][]=array('type' => 'error', 'text' => 'miner.conf not found');
34 | }
35 |
36 | echo json_encode($r);
37 | ?>
38 |
--------------------------------------------------------------------------------
/var/www/f_settings copy.php:
--------------------------------------------------------------------------------
1 | 0) {
28 | file_put_contents($configUipwd,'scripta:' . md5($pass) );
29 | $r['info'][]=array('type' => 'success', 'text' => 'Web password saved');
30 | }
31 | }
32 |
33 | // Manage settings
34 | elseif (!empty($_REQUEST['settings'])) {
35 | $newdata = json_decode($_REQUEST['settings'], true);
36 | $r['data'] = json_decode(@file_get_contents($configScripta), true);
37 |
38 | // Sync current with new settings
39 | if(!empty($newdata)&&is_array($newdata)){
40 | foreach ($newdata as $key => $value) {
41 | $r['data'][$key]=$value;
42 | }
43 | file_put_contents($configScripta, json_encode($r['data'], JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES));
44 | $r['info'][]=array('type' => 'success', 'text' => 'Configuration saved');
45 | }
46 | // Load current settings
47 | else{
48 | $r['info'][]=array('type' => 'info', 'text' => 'Configuration loaded');
49 | }
50 |
51 | if(isset($r['data']['userTimezone'])){
52 | date_default_timezone_set($r['data']['userTimezone']);
53 | $r['data']['date'] = date('Y-m-d H:i:s');
54 | }
55 | }
56 |
57 | // Manage pools
58 | elseif (!empty($_REQUEST['pools'])) {
59 | $newdata = json_decode($_REQUEST['pools'], true);
60 | $r['data'] = json_decode(@file_get_contents($configPools), true);
61 |
62 | foreach ($r['data'] as $id => $p)
63 | {
64 | $r['data'][$id]['url'] = str_replace('stratum tcp','stratum+tcp',$p['url']);
65 | }
66 | $m=0;
67 | foreach ($newdata as $id => $p)
68 | {
69 | $newdata[$id]['url'] = str_replace('stratum tcp','stratum+tcp',$p['url']);
70 | if($p['prio'] > $m) $m=$p['prio'];
71 | }
72 |
73 | ChromePhp::log($newdata);
74 | ChromePhp::log($m);
75 |
76 | if($m>0){
77 | $pl=array();
78 | for ($pp = 0; $pp <= $m; $pp++) {
79 | foreach ($newdata as $id => $p){
80 | if($p['prio'] == $pp) $pl[]=$newdata[$id];
81 | }
82 | }
83 | $newdata = $pl;
84 | }
85 |
86 | // Overwrite current with new pools
87 | if(!empty($newdata)&&is_array($newdata)){
88 | file_put_contents($configPools, json_encode($newdata, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES));
89 | minerConfigGenerate();
90 | $r['data']=$newdata;
91 | $r['info'][]=array('type' => 'success', 'text' => 'Pools config saved');
92 | }
93 | // Load current settings
94 | elseif(!empty($r['data'])&&is_array($r['data'])){
95 | $r['info'][]=array('type' => 'info', 'text' => 'Pools config loaded');
96 | }
97 | // Load new settings
98 | else{
99 | $r['data']=array(array('url'=>'empty'));
100 | $r['info'][]=array('type' => 'error', 'text' => 'Pools config not found');
101 | }
102 | }
103 |
104 | // Manage miner.conf
105 | elseif (!empty($_REQUEST['options'])) {
106 | $newdata = json_decode($_REQUEST['options'], true);
107 | $r['data'] = json_decode(@file_get_contents($configOptns), true);
108 |
109 | // Overwrite current with new config
110 | if(!empty($newdata)&&is_array($newdata)){
111 | file_put_contents($configOptns, json_encode($newdata, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES));
112 | minerConfigGenerate();
113 | $r['data']=$newdata;
114 | $r['info'][]=array('type' => 'success', 'text' => 'Miner options saved');
115 | }
116 | // Load current settings
117 | elseif(!empty($r['data'])&&is_array($r['data'])){
118 | $r['info'][]=array('type' => 'info', 'text' => 'Miner options loaded');
119 | }
120 | // Load new settings
121 | else{
122 | $r['data']=array(array('key'=>'algo','value'=>'c'));
123 | $r['info'][]=array('type' => 'error', 'text' => 'Miner options not found');
124 | }
125 | }
126 |
127 | // Set system timezone to what is stored in settings
128 | elseif (!empty($_REQUEST['timezone'])) {
129 | $timezone = json_decode($_REQUEST['timezone']);
130 | ini_set( 'date.timezone', $timezone );
131 | putenv('TZ=' . $timezone);
132 | date_default_timezone_set($timezone);
133 | $r['data']['date'] = date('Y-m-d H:i:s');
134 | $r['info'][]=array('type' => 'info', 'text' => 'Timezone is '.$timezone );
135 | }
136 |
137 | echo json_encode($r);
138 |
139 | function minerConfigGenerate(){
140 | global $configOptns,$configPools,$configMiner;
141 | $options = json_decode(@file_get_contents($configOptns), true);
142 |
143 | // Angular objects ==> miner
144 | // {key:k,value:v} ==> {k:v}
145 | foreach ($options as $o) {
146 | $miner[$o['key']]=$o['value'];
147 | }
148 |
149 | $miner['pools']= json_decode(@file_get_contents($configPools), true);
150 | file_put_contents($configMiner, json_encode($miner, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES));
151 | }
152 | ?>
153 |
--------------------------------------------------------------------------------
/var/www/f_settings.php:
--------------------------------------------------------------------------------
1 | 0) {
28 | file_put_contents($configUipwd,'scripta:' . md5($pass) );
29 | $r['info'][]=array('type' => 'success', 'text' => 'Web password saved');
30 | }
31 | }
32 |
33 | // Manage settings
34 | elseif (!empty($_REQUEST['settings'])) {
35 | $newdata = json_decode($_REQUEST['settings'], true);
36 | $r['data'] = json_decode(@file_get_contents($configScripta), true);
37 |
38 | // Sync current with new settings
39 | if(!empty($newdata)&&is_array($newdata)){
40 | foreach ($newdata as $key => $value) {
41 | $r['data'][$key]=$value;
42 | }
43 | file_put_contents($configScripta, json_encode($r['data'], JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES));
44 | $r['info'][]=array('type' => 'success', 'text' => 'Configuration saved');
45 | }
46 | // Load current settings
47 | else{
48 | $r['info'][]=array('type' => 'info', 'text' => 'Configuration loaded');
49 | }
50 |
51 | if(isset($r['data']['userTimezone'])){
52 | date_default_timezone_set($r['data']['userTimezone']);
53 | $r['data']['date'] = date('Y-m-d H:i:s');
54 | }
55 | }
56 |
57 | // Manage pools
58 | elseif (!empty($_REQUEST['pools'])) {
59 | $newdata = json_decode($_REQUEST['pools'], true);
60 | $r['data'] = json_decode(@file_get_contents($configPools), true);
61 |
62 | foreach ($r['data'] as $id => $p)
63 | {
64 | $r['data'][$id]['url'] = str_replace('stratum tcp','stratum+tcp',$p['url']);
65 | }
66 | $m=0;
67 | foreach ($newdata as $id => $p)
68 | {
69 | $newdata[$id]['url'] = str_replace('stratum tcp','stratum+tcp',$p['url']);
70 | if($p['prio'] > $m) $m=$p['prio'];
71 | }
72 |
73 | ChromePhp::log($newdata);
74 | ChromePhp::log($m);
75 |
76 | if($m>0){
77 | $pl=array();
78 | for ($pp = 0; $pp <= $m; $pp++) {
79 | foreach ($newdata as $id => $p){
80 | if($p['prio'] == $pp) $pl[]=$newdata[$id];
81 | }
82 | }
83 | $newdata = $pl;
84 | }
85 |
86 | // Overwrite current with new pools
87 | if(!empty($newdata)&&is_array($newdata)){
88 | file_put_contents($configPools, json_encode($newdata, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES));
89 | minerConfigGenerate();
90 | $r['data']=$newdata;
91 | $r['info'][]=array('type' => 'success', 'text' => 'Pools config saved');
92 | }
93 | // Load current settings
94 | elseif(!empty($r['data'])&&is_array($r['data'])){
95 | $r['info'][]=array('type' => 'info', 'text' => 'Pools config loaded');
96 | }
97 | // Load new settings
98 | else{
99 | $r['data']=array(array('url'=>'empty'));
100 | $r['info'][]=array('type' => 'error', 'text' => 'Pools config not found');
101 | }
102 | }
103 |
104 | // Manage miner.conf
105 | elseif (!empty($_REQUEST['options'])) {
106 | $newdata = json_decode($_REQUEST['options'], true);
107 | $r['data'] = json_decode(@file_get_contents($configOptns), true);
108 |
109 | // Overwrite current with new config
110 | if(!empty($newdata)&&is_array($newdata)){
111 | file_put_contents($configOptns, json_encode($newdata, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES));
112 | minerConfigGenerate();
113 | $r['data']=$newdata;
114 | $r['info'][]=array('type' => 'success', 'text' => 'Miner options saved');
115 | }
116 | // Load current settings
117 | elseif(!empty($r['data'])&&is_array($r['data'])){
118 | $r['info'][]=array('type' => 'info', 'text' => 'Miner options loaded');
119 | }
120 | // Load new settings
121 | else{
122 | $r['data']=array(array('key'=>'algo','value'=>'c'));
123 | $r['info'][]=array('type' => 'error', 'text' => 'Miner options not found');
124 | }
125 | }
126 |
127 | // Set system timezone to what is stored in settings
128 | elseif (!empty($_REQUEST['timezone'])) {
129 | $timezone = json_decode($_REQUEST['timezone']);
130 | ini_set( 'date.timezone', $timezone );
131 | putenv('TZ=' . $timezone);
132 | date_default_timezone_set($timezone);
133 | $r['data']['date'] = date('Y-m-d H:i:s');
134 | $r['info'][]=array('type' => 'info', 'text' => 'Timezone is '.$timezone );
135 | }
136 |
137 | echo json_encode($r);
138 |
139 | function minerConfigGenerate(){
140 | global $configOptns,$configPools,$configMiner;
141 | $options = json_decode(@file_get_contents($configOptns), true);
142 |
143 | // Angular objects ==> miner
144 | // {key:k,value:v} ==> {k:v}
145 | foreach ($options as $o) {
146 | $miner[$o['key']]=$o['value'];
147 | }
148 |
149 | $miner['pools']= json_decode(@file_get_contents($configPools), true);
150 | file_put_contents($configMiner, json_encode($miner, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES));
151 | }
152 | ?>
153 |
--------------------------------------------------------------------------------
/var/www/f_status.php:
--------------------------------------------------------------------------------
1 | 'Hoeba','ID'=>0,'Temperature'=>rand(20,35),'MHS5s'=>rand(80000,100000),'MHSav'=>rand(90000,100000),'LongPoll'=>'N','Getworks'=>200,'Accepted'=>rand(70,200),'Rejected'=>rand(1,10),'HardwareErrors'=>rand(0,50),'Utility'=>1.2,'LastShareTime'=>time()-rand(0,10));
42 | $r['status']['devs'][]=array('Name'=>'Debug','ID'=>1,'Temperature'=>rand(20,35),'MHS5s'=>rand(40000,50000),'MHSav'=>rand(45000,50000),'LongPoll'=>'N','Getworks'=>1076,'Accepted'=>1324,'Rejected'=>1,'HardwareErrors'=>46,'Utility'=>1.2,'LastShareTime'=>time()-rand(0,40));
43 | $r['status']['devs'][]=array('Name'=>'Wut','ID'=>2,'Temperature'=>rand(20,35),'MHS5s'=>rand(6000,9000),'MHSav'=>rand(7000,8000),'LongPoll'=>'N','Getworks'=>1076,'Accepted'=>1324,'Rejected'=>1,'HardwareErrors'=>46,'Utility'=>1.2,'LastShareTime'=>time()-rand(0,300));
44 | $r['status']['devs'][]=array('Name'=>'Wut','ID'=>4,'Temperature'=>rand(20,35),'MHS5s'=>0,'MHSav'=>0,'LongPoll'=>'N','Getworks'=>400,'Accepted'=>0,'Rejected'=>0,'HardwareErrors'=>0,'Utility'=>0,'LastShareTime'=>time()-rand(400,900));
45 | $r['status']['devs'][]=array('Name'=>'More','ID'=>3,'Temperature'=>rand(20,35),'MHS5s'=>rand(500,1000),'MHSav'=>rand(600,800),'LongPoll'=>'N','Getworks'=>1076,'Accepted'=>1324,'Rejected'=>1,'HardwareErrors'=>46,'Utility'=>1.2,'LastShareTime'=>time()-rand(0,300));
46 | $r['status']['pools'][]=array('POOL'=>5,'URL'=>'http://stratum.mining.eligius.st:3334','Status'=>'Alive','Priority'=>9,'LongPoll'=>'N','Getworks'=>10760,'Accepted'=>50430,'Rejected'=>60,'Discarded'=>21510,'Stale'=>0,'GetFailures'=>0,'RemoteFailures'=>0,'User'=>'1BveW6ZoZmx31uaXTEKJo5H9CK318feKKY','LastShareTime'=>1375501281,'Diff1Shares'=>20306,'ProxyType'=>'','Proxy'=>'','DifficultyAccepted'=>20142,'DifficultyRejected'=>24,'DifficultyStale'=>0,'LastShareDifficulty'=>4,'HasStratum'=>true,'StratumActive'=>true,'StratumURL'=>'stratum.mining.eligius.st','HasGBT'=>false,'BestShare'=>40657);
47 | }
48 |
49 | $devices = 0;
50 | $MHSav = 0;
51 | $MHS5s = 0;
52 | $Accepted = 0;
53 | $Rejected = 0;
54 | $HardwareErrors = 0;
55 | $Utility = 0;
56 |
57 | ChromePhp::log($r['status']);
58 |
59 | if(!empty($r['status']['devs'])){
60 | foreach ($r['status']['devs'] as $id => $dev) {
61 | $devices += $dev['MHS5s']>0?1:0; // Only count hashing devices
62 | $MHS5s += $dev['MHS5s'];
63 | $MHSav += $dev['MHSav'];
64 | $Accepted += $dev['Accepted'];
65 | $Rejected += $dev['Rejected'];
66 | $HardwareErrors += $dev['HardwareErrors'];
67 | $Utility += $dev['Utility'];
68 | $r['status']['devs'][$id]['TotalShares']=$dev['Accepted']+$dev['Rejected']+$dev['HardwareErrors'];
69 | }
70 | }
71 |
72 | $r['status']['dtot']=array(
73 | 'devices'=>$devices,
74 | 'MHS5s'=>$MHS5s,
75 | 'MHSav'=>$MHSav,
76 | 'Accepted'=>$Accepted,
77 | 'Rejected'=>$Rejected,
78 | 'HardwareErrors'=>$HardwareErrors,
79 | 'Utility'=>$Utility,
80 | 'TotalShares'=>$Accepted+$Rejected+$HardwareErrors);
81 |
82 | // CPU intensive stuff
83 | if(!empty($_REQUEST['all'])){
84 | $ret = sys_getloadavg();
85 | $r['status']['pi']['load'] = $ret[2];
86 | $ret = explode(' ', exec('cat /proc/uptime'));
87 | $r['status']['pi']['uptime'] = $ret[0];
88 | $r['status']['pi']['temp'] = exec('cat /sys/class/thermal/thermal_zone0/temp')/1000;
89 |
90 | // What other interesting stuff is in summary?
91 | $summary=bfgminer('summary');
92 | if(!empty($summary['data']['SUMMARY'][0]['Elapsed'])){
93 | $r['status']['uptime'] = $summary['data']['SUMMARY'][0]['Elapsed'];
94 | }
95 | else{
96 | $r['status']['uptime'] = 0;
97 | }
98 | }
99 |
100 | $r['status']['time'] = time();
101 |
102 | //ChromePhp::log($r);
103 |
104 | echo json_encode($r);
105 | ?>
--------------------------------------------------------------------------------
/var/www/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/scriptamining/scripta/6c612e9a6df050688921ab14ac330dfabf27c9de/var/www/favicon.ico
--------------------------------------------------------------------------------
/var/www/img/bg-header1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/scriptamining/scripta/6c612e9a6df050688921ab14ac330dfabf27c9de/var/www/img/bg-header1.png
--------------------------------------------------------------------------------
/var/www/img/favicon-1.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/scriptamining/scripta/6c612e9a6df050688921ab14ac330dfabf27c9de/var/www/img/favicon-1.ico
--------------------------------------------------------------------------------
/var/www/img/favicon-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/scriptamining/scripta/6c612e9a6df050688921ab14ac330dfabf27c9de/var/www/img/favicon-1.png
--------------------------------------------------------------------------------
/var/www/img/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/scriptamining/scripta/6c612e9a6df050688921ab14ac330dfabf27c9de/var/www/img/favicon.ico
--------------------------------------------------------------------------------
/var/www/img/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/scriptamining/scripta/6c612e9a6df050688921ab14ac330dfabf27c9de/var/www/img/favicon.png
--------------------------------------------------------------------------------
/var/www/img/scripta-logo-152.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/scriptamining/scripta/6c612e9a6df050688921ab14ac330dfabf27c9de/var/www/img/scripta-logo-152.png
--------------------------------------------------------------------------------
/var/www/img/scripta-logo-ext-152.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/scriptamining/scripta/6c612e9a6df050688921ab14ac330dfabf27c9de/var/www/img/scripta-logo-ext-152.png
--------------------------------------------------------------------------------
/var/www/inc/ChromePhp.php:
--------------------------------------------------------------------------------
1 |
23 | */
24 | class ChromePhp
25 | {
26 | /**
27 | * @var string
28 | */
29 | const VERSION = '4.1.0';
30 |
31 | /**
32 | * @var string
33 | */
34 | const HEADER_NAME = 'X-ChromeLogger-Data';
35 |
36 | /**
37 | * @var string
38 | */
39 | const BACKTRACE_LEVEL = 'backtrace_level';
40 |
41 | /**
42 | * @var string
43 | */
44 | const LOG = 'log';
45 |
46 | /**
47 | * @var string
48 | */
49 | const WARN = 'warn';
50 |
51 | /**
52 | * @var string
53 | */
54 | const ERROR = 'error';
55 |
56 | /**
57 | * @var string
58 | */
59 | const GROUP = 'group';
60 |
61 | /**
62 | * @var string
63 | */
64 | const INFO = 'info';
65 |
66 | /**
67 | * @var string
68 | */
69 | const GROUP_END = 'groupEnd';
70 |
71 | /**
72 | * @var string
73 | */
74 | const GROUP_COLLAPSED = 'groupCollapsed';
75 |
76 | /**
77 | * @var string
78 | */
79 | const TABLE = 'table';
80 |
81 | /**
82 | * @var string
83 | */
84 | protected $_php_version;
85 |
86 | /**
87 | * @var int
88 | */
89 | protected $_timestamp;
90 |
91 | /**
92 | * @var array
93 | */
94 | protected $_json = array(
95 | 'version' => self::VERSION,
96 | 'columns' => array('log', 'backtrace', 'type'),
97 | 'rows' => array()
98 | );
99 |
100 | /**
101 | * @var array
102 | */
103 | protected $_backtraces = array();
104 |
105 | /**
106 | * @var bool
107 | */
108 | protected $_error_triggered = false;
109 |
110 | /**
111 | * @var array
112 | */
113 | protected $_settings = array(
114 | self::BACKTRACE_LEVEL => 1
115 | );
116 |
117 | /**
118 | * @var ChromePhp
119 | */
120 | protected static $_instance;
121 |
122 | /**
123 | * Prevent recursion when working with objects referring to each other
124 | *
125 | * @var array
126 | */
127 | protected $_processed = array();
128 |
129 | /**
130 | * constructor
131 | */
132 | private function __construct()
133 | {
134 | $this->_php_version = phpversion();
135 | $this->_timestamp = $this->_php_version >= 5.1 ? $_SERVER['REQUEST_TIME'] : time();
136 | $this->_json['request_uri'] = $_SERVER['REQUEST_URI'];
137 | }
138 |
139 | /**
140 | * gets instance of this class
141 | *
142 | * @return ChromePhp
143 | */
144 | public static function getInstance()
145 | {
146 | if (self::$_instance === null) {
147 | self::$_instance = new self();
148 | }
149 | return self::$_instance;
150 | }
151 |
152 | /**
153 | * logs a variable to the console
154 | *
155 | * @param mixed $data,... unlimited OPTIONAL number of additional logs [...]
156 | * @return void
157 | */
158 | public static function log()
159 | {
160 | $args = func_get_args();
161 | return self::_log('', $args);
162 | }
163 |
164 | /**
165 | * logs a warning to the console
166 | *
167 | * @param mixed $data,... unlimited OPTIONAL number of additional logs [...]
168 | * @return void
169 | */
170 | public static function warn()
171 | {
172 | $args = func_get_args();
173 | return self::_log(self::WARN, $args);
174 | }
175 |
176 | /**
177 | * logs an error to the console
178 | *
179 | * @param mixed $data,... unlimited OPTIONAL number of additional logs [...]
180 | * @return void
181 | */
182 | public static function error()
183 | {
184 | $args = func_get_args();
185 | return self::_log(self::ERROR, $args);
186 | }
187 |
188 | /**
189 | * sends a group log
190 | *
191 | * @param string value
192 | */
193 | public static function group()
194 | {
195 | $args = func_get_args();
196 | return self::_log(self::GROUP, $args);
197 | }
198 |
199 | /**
200 | * sends an info log
201 | *
202 | * @param mixed $data,... unlimited OPTIONAL number of additional logs [...]
203 | * @return void
204 | */
205 | public static function info()
206 | {
207 | $args = func_get_args();
208 | return self::_log(self::INFO, $args);
209 | }
210 |
211 | /**
212 | * sends a collapsed group log
213 | *
214 | * @param string value
215 | */
216 | public static function groupCollapsed()
217 | {
218 | $args = func_get_args();
219 | return self::_log(self::GROUP_COLLAPSED, $args);
220 | }
221 |
222 | /**
223 | * ends a group log
224 | *
225 | * @param string value
226 | */
227 | public static function groupEnd()
228 | {
229 | $args = func_get_args();
230 | return self::_log(self::GROUP_END, $args);
231 | }
232 |
233 | /**
234 | * sends a table log
235 | *
236 | * @param string value
237 | */
238 | public static function table()
239 | {
240 | $args = func_get_args();
241 | return self::_log(self::TABLE, $args);
242 | }
243 |
244 | /**
245 | * internal logging call
246 | *
247 | * @param string $type
248 | * @return void
249 | */
250 | protected static function _log($type, array $args)
251 | {
252 | // nothing passed in, don't do anything
253 | if (count($args) == 0 && $type != self::GROUP_END) {
254 | return;
255 | }
256 |
257 | $logger = self::getInstance();
258 |
259 | $logger->_processed = array();
260 |
261 | $logs = array();
262 | foreach ($args as $arg) {
263 | $logs[] = $logger->_convert($arg);
264 | }
265 |
266 | $backtrace = debug_backtrace(false);
267 | $level = $logger->getSetting(self::BACKTRACE_LEVEL);
268 |
269 | $backtrace_message = 'unknown';
270 | if (isset($backtrace[$level]['file']) && isset($backtrace[$level]['line'])) {
271 | $backtrace_message = $backtrace[$level]['file'] . ' : ' . $backtrace[$level]['line'];
272 | }
273 |
274 | $logger->_addRow($logs, $backtrace_message, $type);
275 | }
276 |
277 | /**
278 | * converts an object to a better format for logging
279 | *
280 | * @param Object
281 | * @return array
282 | */
283 | protected function _convert($object)
284 | {
285 | // if this isn't an object then just return it
286 | if (!is_object($object)) {
287 | return $object;
288 | }
289 |
290 | //Mark this object as processed so we don't convert it twice and it
291 | //Also avoid recursion when objects refer to each other
292 | $this->_processed[] = $object;
293 |
294 | $object_as_array = array();
295 |
296 | // first add the class name
297 | $object_as_array['___class_name'] = get_class($object);
298 |
299 | // loop through object vars
300 | $object_vars = get_object_vars($object);
301 | foreach ($object_vars as $key => $value) {
302 |
303 | // same instance as parent object
304 | if ($value === $object || in_array($value, $this->_processed, true)) {
305 | $value = 'recursion - parent object [' . get_class($value) . ']';
306 | }
307 | $object_as_array[$key] = $this->_convert($value);
308 | }
309 |
310 | $reflection = new ReflectionClass($object);
311 |
312 | // loop through the properties and add those
313 | foreach ($reflection->getProperties() as $property) {
314 |
315 | // if one of these properties was already added above then ignore it
316 | if (array_key_exists($property->getName(), $object_vars)) {
317 | continue;
318 | }
319 | $type = $this->_getPropertyKey($property);
320 |
321 | if ($this->_php_version >= 5.3) {
322 | $property->setAccessible(true);
323 | }
324 |
325 | try {
326 | $value = $property->getValue($object);
327 | } catch (ReflectionException $e) {
328 | $value = 'only PHP 5.3 can access private/protected properties';
329 | }
330 |
331 | // same instance as parent object
332 | if ($value === $object || in_array($value, $this->_processed, true)) {
333 | $value = 'recursion - parent object [' . get_class($value) . ']';
334 | }
335 |
336 | $object_as_array[$type] = $this->_convert($value);
337 | }
338 | return $object_as_array;
339 | }
340 |
341 | /**
342 | * takes a reflection property and returns a nicely formatted key of the property name
343 | *
344 | * @param ReflectionProperty
345 | * @return string
346 | */
347 | protected function _getPropertyKey(ReflectionProperty $property)
348 | {
349 | $static = $property->isStatic() ? ' static' : '';
350 | if ($property->isPublic()) {
351 | return 'public' . $static . ' ' . $property->getName();
352 | }
353 |
354 | if ($property->isProtected()) {
355 | return 'protected' . $static . ' ' . $property->getName();
356 | }
357 |
358 | if ($property->isPrivate()) {
359 | return 'private' . $static . ' ' . $property->getName();
360 | }
361 | }
362 |
363 | /**
364 | * adds a value to the data array
365 | *
366 | * @var mixed
367 | * @return void
368 | */
369 | protected function _addRow(array $logs, $backtrace, $type)
370 | {
371 | // if this is logged on the same line for example in a loop, set it to null to save space
372 | if (in_array($backtrace, $this->_backtraces)) {
373 | $backtrace = null;
374 | }
375 |
376 | // for group, groupEnd, and groupCollapsed
377 | // take out the backtrace since it is not useful
378 | if ($type == self::GROUP || $type == self::GROUP_END || $type == self::GROUP_COLLAPSED) {
379 | $backtrace = null;
380 | }
381 |
382 | if ($backtrace !== null) {
383 | $this->_backtraces[] = $backtrace;
384 | }
385 |
386 | $row = array($logs, $backtrace, $type);
387 |
388 | $this->_json['rows'][] = $row;
389 | $this->_writeHeader($this->_json);
390 | }
391 |
392 | protected function _writeHeader($data)
393 | {
394 | header(self::HEADER_NAME . ': ' . $this->_encode($data));
395 | }
396 |
397 | /**
398 | * encodes the data to be sent along with the request
399 | *
400 | * @param array $data
401 | * @return string
402 | */
403 | protected function _encode($data)
404 | {
405 | return base64_encode(utf8_encode(json_encode($data)));
406 | }
407 |
408 | /**
409 | * adds a setting
410 | *
411 | * @param string key
412 | * @param mixed value
413 | * @return void
414 | */
415 | public function addSetting($key, $value)
416 | {
417 | $this->_settings[$key] = $value;
418 | }
419 |
420 | /**
421 | * add ability to set multiple settings in one call
422 | *
423 | * @param array $settings
424 | * @return void
425 | */
426 | public function addSettings(array $settings)
427 | {
428 | foreach ($settings as $key => $value) {
429 | $this->addSetting($key, $value);
430 | }
431 | }
432 |
433 | /**
434 | * gets a setting
435 | *
436 | * @param string key
437 | * @return mixed
438 | */
439 | public function getSetting($key)
440 | {
441 | if (!isset($this->_settings[$key])) {
442 | return null;
443 | }
444 | return $this->_settings[$key];
445 | }
446 | }
447 |
--------------------------------------------------------------------------------
/var/www/inc/backup.inc.php:
--------------------------------------------------------------------------------
1 | 'danger', 'text' => 'Source file is not readable');
57 | }
58 | elseif (is_file($src)&&is_dir($dst) || is_dir($src)&&is_file($dst)) {
59 | $r['info'][]=array('type' => 'danger', 'text' => 'File and folder mixup');
60 | }
61 | elseif (is_file($dst)) {
62 | $r['info'][]=array('type' => 'danger', 'text' => 'Destination file already exists');
63 | }
64 |
65 | // Copy it already!
66 | if (@is_file($src)) {
67 | $r['type']='file';
68 | if (!@copy($src, $dst)) {
69 | $r['files'][0]=array('file'=>pathinfo($dst,PATHINFO_BASENAME),'success'=>false);
70 | }
71 | else{
72 | $r['success']=true;
73 | $r['files'][0]=array('file'=>pathinfo($dst,PATHINFO_BASENAME),'success'=>true);
74 | }
75 | }
76 | elseif (@is_dir($src)) {
77 | $r['type']='dir';
78 | if (recurse_copy($src, $dst)) {
79 | $r['success']=true;
80 | }
81 | }
82 |
83 | return $r;
84 | }
85 |
86 | // Copy a folder recursively
87 | function recurse_copy($src,$dst,$level=3) {
88 | $success=true;
89 | if($level==0) return $success;
90 | global $r;
91 | $dir = opendir($src);
92 | @mkdir($dst);
93 | while(false !== ( $file = readdir($dir))) {
94 | if (( $file != '.' ) && ( $file != '..' )) {
95 | if ( is_dir($src . '/' . $file) ) {
96 | $c=recurse_copy($src . '/' . $file,$dst . '/' . $file,$level-1);
97 | }
98 | else {
99 | $c=@copy($src . '/' . $file,$dst . '/' . $file);
100 | $r['files'][]=array('file'=>pathinfo($dst,PATHINFO_BASENAME),'success'=>$c);
101 | }
102 | $success=$success&&$c;
103 | }
104 | }
105 | closedir($dir);
106 | return $success;
107 | }
108 | ?>
109 |
--------------------------------------------------------------------------------
/var/www/inc/bfgminer.inc.php:
--------------------------------------------------------------------------------
1 | 'error', 'text' => 'Miner: '.$errno.' '.$errorMessage);
38 | }
39 | // Socket success
40 | else{
41 | fwrite($client, json_encode($c));
42 | $response = stream_get_contents($client);
43 | fclose($client);
44 |
45 | // Cleanup json
46 | $response = preg_replace('/[^[:alnum:][:punct:]]/','',$response);
47 |
48 | // Add api response
49 | $r['data'] = json_decode($response, true);
50 | $r['info'][]=array('type' => 'info', 'text' => 'Miner: '.$command);
51 | }
52 |
53 | return $r;
54 | }
55 | ?>
56 |
--------------------------------------------------------------------------------
/var/www/inc/functions.inc.php:
--------------------------------------------------------------------------------
1 | $settings['alertSmtp'],
15 | 'debug' => false,
16 | 'auth' => true,
17 | 'username' => $settings['alertSmtpUser'],
18 | 'password' => $settings['alertSmtpPwd'],
19 | 'port' => $settings['alertSmtpPort'],
20 |
21 | );
22 |
23 | //$settings['alertDevice']
24 |
25 | $mail = Mail::factory('smtp', $mailSettings );
26 |
27 | $headers = array('From'=>$settings['alertEmail'], 'Subject'=>$subject);
28 | $esito = $mail->send($settings['alertEmail'], $headers, $body);
29 | if (PEAR::isError($esito)) { print($esito->getMessage());}else{print "end";}
30 | }
31 | ?>
--------------------------------------------------------------------------------
/var/www/inc/host.inc.php:
--------------------------------------------------------------------------------
1 | Reboot
12 | * 1 ---> Shutdown
13 | */
14 |
15 | function hostHardCtl($op,$pass){
16 | openlog("myScriptLog", LOG_PID | LOG_PERROR, LOG_LOCAL0);
17 | syslog(LOG_WARNING, "Attempting to exec hostHardCtl");
18 |
19 | switch ($op) {
20 | case 0:
21 | $cmd = '"/sbin/shutdown -r now"';
22 | break;
23 | case 1:
24 | $cmd = '"/sbin/shutdown -h now"';
25 | break;
26 | default:
27 | syslog(LOG_WARNING, "unknown command");
28 | break;
29 | }
30 |
31 | //$cmd = '"ls -la /root"';
32 |
33 | $cases = array (
34 | array (0 => "Password: ", 1 => "PASSWORD")
35 | );
36 |
37 | $full_cmd = "su -c ".$cmd;
38 | syslog(LOG_WARNING, "execute: ". $full_cmd);
39 | $stream = expect_popen($full_cmd);
40 | $ret = expect_expectl($stream, $cases);
41 |
42 | switch ($ret) {
43 | case "PASSWORD":
44 | fwrite ($stream, $pass."\n");
45 | syslog(LOG_WARNING, "pwd: ". $pass);
46 | break;
47 | case EXP_TIMEOUT:
48 | syslog(LOG_WARNING, "EXP_TIMEOUT");
49 | return false;
50 | break;
51 | case EXP_EOF:
52 | syslog(LOG_WARNING, "EXP_EOF");
53 | return false;
54 | break;
55 | default:
56 | syslog(LOG_WARNING, "EXP_TIMEOUT");
57 | return false;
58 | break;
59 | }
60 |
61 | $out = '';
62 | while ($line = fgets($stream)) {
63 | $out .= $line;
64 | syslog(LOG_WARNING, "ret: ". $line);
65 | }
66 | fclose ($stream);
67 | closelog();
68 | return $out;
69 | }
70 | ?>
71 |
72 |
--------------------------------------------------------------------------------
/var/www/inc/kitten.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/scriptamining/scripta/6c612e9a6df050688921ab14ac330dfabf27c9de/var/www/inc/kitten.mp3
--------------------------------------------------------------------------------
/var/www/inc/kitten.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/scriptamining/scripta/6c612e9a6df050688921ab14ac330dfabf27c9de/var/www/inc/kitten.wav
--------------------------------------------------------------------------------
/var/www/inc/miner.inc.php:
--------------------------------------------------------------------------------
1 | $command,
7 | 'parameter' => $parameter
8 | );
9 |
10 | $jsonCmd = json_encode($command);
11 |
12 | $host = '127.0.0.1';
13 | $port = 4028;
14 |
15 | $client = @stream_socket_client('tcp://'.$host.':'.$port, $errno, $errorMessage);
16 |
17 | if ($client === false) {
18 | return false;
19 | }
20 | fwrite($client, $jsonCmd);
21 | $response = stream_get_contents($client);
22 | fclose($client);
23 | $response = preg_replace('/[^[:alnum:][:punct:]]/','',$response);
24 | $response = json_decode($response, true);
25 | return $response;
26 |
27 | }
28 |
29 |
--------------------------------------------------------------------------------
/var/www/inc/settings.inc.php:
--------------------------------------------------------------------------------
1 | 'cli') {
4 | header('Location: https://' . $_SERVER["SERVER_NAME"] . $_SERVER['REQUEST_URI']);
5 | }
6 |
7 | $settings = json_decode(@file_get_contents('/opt/scripta/etc/scripta.conf'), true);
8 | $settings['donateEnable'] = true;
9 |
10 |
11 |
12 | if(isset($settings['userTimezone'])){
13 | $timezone = $settings['userTimezone'];
14 | ini_set( 'date.timezone', $timezone );
15 | putenv('TZ=' . $timezone);
16 | date_default_timezone_set($timezone);
17 | }
18 |
19 |
20 |
21 |
22 | function writeSettings($settings, $file = 'scripta.conf') {
23 | // Call this when you want settings to be saved with writeSettings($settings);
24 | // can be used to save to an alternat file name with writeSettings($settings, 'OtherFileName.conf);
25 |
26 | file_put_contents("/opt/scripta/etc/" . $file, json_encode($settings, JSON_PRETTY_PRINT | JSON_NUMERIC_CHECK));
27 | }
28 |
29 | ?>
30 |
--------------------------------------------------------------------------------
/var/www/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Scripta
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
26 |
27 |
37 |
38 | {{counter}}s
39 |
40 | {{downTime}}s downtime
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 | Loading angular.js the first time might take some seconds... Hang tight!
54 |
55 |
56 |
57 |
58 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
--------------------------------------------------------------------------------
/var/www/index.lighttpd.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Welcome page
6 |
19 |
20 |
21 |
22 |
26 |
27 |
You should replace this page with your own web pages as soon as possible.
28 | Unless you changed its configuration, your new server is configured as follows:
29 |
30 | Configuration files can be found in /etc/lighttpd . Please read /etc/lighttpd/conf-available/README file.
31 | The DocumentRoot, which is the directory under which all your HTML files should exist, is set to /var/www .
32 | CGI scripts are looked for in /usr/lib/cgi-bin , which is where Debian packages will place their scripts. You can enable cgi module by using command "lighty-enable-mod cgi" .
33 | Log files are placed in /var/log/lighttpd , and will be rotated weekly. The frequency of rotation can be easily changed by editing /etc/logrotate.d/lighttpd .
34 | The default directory index is index.html , meaning that requests for a directory /foo/bar/ will give the contents of the file /var/www/foo/bar/index.html if it exists (assuming that /var/www is your DocumentRoot).
35 | You can enable user directories by using command "lighty-enable-mod userdir"
36 |
37 |
About this page
38 |
39 | This is a placeholder page installed by the Debian release of the Lighttpd server package.
40 |
41 |
42 | This computer has installed the Debian GNU/Linux operating system, but it has nothing to do with the Debian Project. Please do not contact the Debian Project about it.
43 |
44 |
45 | If you find a bug in this Lighttpd package, or in Lighttpd itself, please file a bug report on it. Instructions on doing this, and the list of known bugs of this package, can be found in the
46 | Debian Bug Tracking System.
47 |
48 |
49 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
--------------------------------------------------------------------------------
/var/www/index.php:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
12 |
13 |
14 | Scr|pta
15 |
16 |
17 |
18 |
19 |
20 |
21 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
41 |
42 |
52 |
53 |
54 | {{counter}}s
55 |
56 | {{downTime}}s downtime
57 |
58 |
59 |
60 |
61 |
62 | Logout
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 | Loading angular.js the first time might take some seconds... Hang tight!
73 |
74 |
75 |
76 |
77 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
147 |
148 |
149 |
--------------------------------------------------------------------------------
/var/www/info.php:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/var/www/js/alertify.min.js:
--------------------------------------------------------------------------------
1 | /*! alertify 0.4.0rc1 (Fabien Doiron) | MIT */
2 | (function(t,e,n){var i=function(){var t,n,i;return n=function(){this.on=function(t,e,n){t.addEventListener(e,n,!1)},this.off=function(t,e,n){t.removeEventListener(e,n,!1)}},i=function(){this.on=function(t,e,n){t.attachEvent("on"+e,n)},this.off=function(t,e,n){t.detachEvent("on"+e,n)}},t={_version:"0.4.0",_prefix:"alertify",get:function(t){return e.getElementById(t)},on:function(t,e,r){"function"==typeof t.addEventListener?(t.addEventListener(e,r,!1),n.call(this)):t.attachEvent&&(t.attachEvent("on"+e,r),i.call(this))},off:function(t,e,r){"function"==typeof t.removeEventListener?(t.removeEventListener(e,r,!1),n.call(this)):t.detachEvent&&(t.detachEvent("on"+e,r),i.call(this))}}}(),r=function(){var t=function(){};return t.prototype=i,t=new t}(),o=function(){var t,e;return t=function(t,e,i){var r=!1;return r=i&&e===n?!0:"object"===t?"object"==typeof e&&!(e instanceof Array):typeof e===t},e={messages:{invalidArguments:"Invalid arguments"},isFunction:function(e,n){return t("function",e,n)},isNumber:function(e,n){return t("number",e,n)},isObject:function(e,n){return t("object",e,n)},isString:function(e,n){return t("string",e,n)}}}(),s=function(){var t,i={};return t=function(t,e){var i;if(!o.isObject(t)||!o.isObject(e,!0))throw Error(o.messages.invalidArguments);if(e!==n){if(e.attributes)for(i in e.attributes)e.attributes.hasOwnProperty(i)&&t.setAttribute(i,e.attributes[i]);e.classes&&(t.className=e.classes)}return t},i={create:function(n,i){var r;if(!o.isString(n)||!o.isObject(i,!0))throw Error(o.messages.invalidArguments);return r=e.createElement(n),r=t(r,i)},ready:function(t){if(!o.isObject(t))throw Error(o.messages.invalidArguments);t&&null!==t.scrollTop||this.ready()}}}(),a=function(){var t;return t=function(){var t,e,i=!1,r=s.create("fakeelement"),o={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"otransitionend",transition:"transitionend"};for(t in o)if(r.style[t]!==n){e=o[t],i=!0;break}return{type:e,supported:i}},t()}(),c=function(){var t={ENTER:13,ESC:27,SPACE:32};return t}(),l=function(){var t=function(){var t,i,l,u,f,p,h,d,y,b,v,m,g,k,E,w={},F={},N=!1,S=[],A={},C=r._prefix+"-dialog",x=r._prefix+"-cover",j=C+" is-"+C+"-showing",O=C+" is-"+C+"-hidden",T=x+" is-"+x+"-showing",L=x+" is-"+x+"-hidden";return A={buttons:{holder:'{{buttons}} ',submit:'{{ok}} ',ok:'{{ok}} ',cancel:'{{cancel}} '},input:'
',message:'{{message}}
',log:'{{message}} '},l=function(t){d=function(e){var i="";return e.preventDefault!==n&&e.preventDefault(),g(),f(),w.input&&(i=w.input.value),"function"==typeof t.accept&&(w.input?t.accept(i):t.accept()),!1},h=function(e){return e.preventDefault!==n&&e.preventDefault(),g(),f(),"function"==typeof t.deny&&t.deny(),!1},v=function(t){var e=t.keyCode;e!==c.SPACE||w.input||d(t),e===c.ESC&&w.cancel&&h(t)},y=function(){w.input?w.input.focus():w.cancel?w.cancel.focus():w.ok.focus()},r.on(w.reset,"focus",y),w.ok&&r.on(w.ok,"click",d),w.cancel&&r.on(w.cancel,"click",h),r.on(e.body,"keyup",v),w.form&&r.on(w.form,"submit",d),a.supported||k()},i=function(t,e){return F.buttonReverse?e+t:t+e},u=function(t){var e="",n=t.type,r=t.message;switch(e+='',"none"===F.buttonFocus&&(e+='
'),"prompt"===n&&(e+='
"),e+='
Reset Focus ',e+="
",n){case"confirm":e=e.replace("{{buttons}}",i(A.buttons.cancel,A.buttons.ok)),e=e.replace("{{ok}}",F.labels.ok).replace("{{cancel}}",F.labels.cancel);break;case"prompt":e=e.replace("{{buttons}}",i(A.buttons.cancel,A.buttons.submit)),e=e.replace("{{ok}}",F.labels.ok).replace("{{cancel}}",F.labels.cancel);break;case"alert":e=e.replace("{{buttons}}",A.buttons.ok),e=e.replace("{{ok}}",F.labels.ok)}return e},f=function(){var e;S.splice(0,1),S.length>0?m(!0):(N=!1,e=function(t){t.stopPropagation(),r.off(this,a.type,e)},a.supported?(r.on(F.el,a.type,e),F.el.className=O):F.el.className=O,F.cover.className=L,t.focus())},p=function(){var t=s.create("div",{classes:L}),n=s.create("section",{classes:O});return e.body.appendChild(t),e.body.appendChild(n),s.ready(t),s.ready(n),F.cover=t,n},m=function(t){var e,i=S[0];N=!0,e=function(t){t.stopPropagation(),k(),r.off(this,a.type,e)},a.supported&&!t&&r.on(F.el,a.type,e),F.el.innerHTML=u(i),F.cover.className=T,F.el.className=j,w.reset=r.get("alertify-resetFocus"),w.ok=r.get("alertify-ok")||n,w.cancel=r.get("alertify-cancel")||n,w.focus="cancel"===F.buttonFocus&&w.cancel?w.cancel:"none"===F.buttonFocus?r.get("alertify-noneFocus"):w.ok,w.input=r.get("alertify-text")||n,w.form=r.get("alertify-form")||n,"string"==typeof i.placeholder&&""!==i.placeholder&&(w.input.value=i.placeholder),t&&k(),l(i)},g=function(){r.off(e.body,"keyup",v),r.off(w.reset,"focus",y),w.input&&r.off(w.form,"submit",b),w.ok&&r.off(w.ok,"click",d),w.cancel&&r.off(w.cancel,"click",h)},k=function(){w.input?(w.input.focus(),w.input.select()):w.focus.focus()},E=function(n,i,r,s,a){if(!(o.isString(n)&&o.isString(i)&&o.isFunction(r,!0)&&o.isFunction(s,!0)&&o.isString(a,!0)))throw Error(o.messages.invalidArguments);F.el=F.el||p(),t=e.activeElement,S.push({type:n,message:i,accept:r,deny:s,placeholder:a}),N||m()},{buttonFocus:"ok",buttonReverse:!1,cover:n,el:n,labels:{ok:"OK",cancel:"Cancel"},alert:function(t,e){return F=this,E("alert",t,e),this},confirm:function(t,e,n){return F=this,E("confirm",t,e,n),this},prompt:function(t,e,n,i){return F=this,E("prompt",t,e,n,i),this}}};return new t}(),u=function(){var t,e,i,c,l=r._prefix+"-log",u=l+" is-"+l+"-showing",f=l+" is-"+l+"-hidden";return t=function(t,e,i,r){if(!(o.isObject(t)&&o.isString(e)&&o.isString(i)&&o.isNumber(r,!0)))throw Error(o.messages.invalidArguments);this.delay=r!==n?r:5e3,this.msg=i,this.parent=t,this.type=e,this.create(),this.show()},e=function(t){t.stopPropagation(),this.el!==n&&(r.off(this.el,a.type,this.fn),i.call(this))},i=function(){this.parent.removeChild(this.el),delete this.el},c=function(){var t=this;0!==this.delay&&setTimeout(function(){t.close()},this.delay)},t.prototype.close=function(){var t=this;this.el!==n&&this.el.parentNode===this.parent&&(a.supported?(this.fn=function(n){e.call(t,n)},r.on(this.el,a.type,this.fn),this.el.className=f+" "+l+"-"+this.type):i.call(this))},t.prototype.create=function(){if(this.el===n){var t=s.create("article",{classes:f+" "+l+"-"+this.type});t.innerHTML=this.msg,this.parent.appendChild(t),s.ready(t),this.el=t}},t.prototype.show=function(){var t=this;this.el!==n&&(r.on(this.el,"click",function(){t.close()}),this.el.className=u+" "+l+"-"+this.type,c.call(this))},t}(),f=function(){var t,i,a,c;return t=function(){var t=s.create("section",{classes:r._prefix+"-logs"});return e.body.appendChild(t),s.ready(t),t},i=function(e,n,i){return a(e,n,i),this.el=this.el||t(),new u(this.el,e,n,i)},a=function(t,e,n){if(!o.isString(t)||!o.isString(e)||!o.isNumber(n,!0))throw Error(o.messages.invalidArguments)},c={delay:5e3,el:n,create:function(t,e,n){return i.call(this,t,e,n)},error:function(t,e){return i.call(this,"error",t,e)},info:function(t,e){return i.call(this,"info",t,e)},success:function(t,e){return i.call(this,"success",t,e)}}}();r.dialog=l,r.log=f,window.Alertify=r})(this,document);
--------------------------------------------------------------------------------
/var/www/lighttpd.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN PRIVATE KEY-----
2 | MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCp4yeDMiOFxkLv
3 | 78H/EQE0ZJFA9qtkCaOPB9TnYT98gBm75QIAmncQoPlpZvIEFnYfvSiVow2THS4b
4 | vz+z7F2qSCqBVin32QKKLMDkVKFUdQ3ffGUyMQYPyn0EnDs8x46BATtHCCO272Ti
5 | 7fAEorP+sBB452o132tOFvV8iSGxgYjUTarV6DT3b8xHdOqmcvtH95C4OF+4237C
6 | WSX+RF/XwuOr3y19bY/NWg9TqLPlsB5eZfZTXRoHmkCqU10t2NJISXQP6g5rt3FO
7 | G/pGSsKfg2RSZrqr1EmR8Bp/2r8Him3XdtsoI343sRv0AA5YPwi0UEB2HWt3lHO/
8 | p/v9ychXAgMBAAECggEAPOWUEE80tIsxC1jiLVAnImS6PJMvNJjP7EFea+JMI5C3
9 | qMaaRSUZcPiC7ulb72MtzIq9tYXRI97d3ExdxV0A5j0gH2SHfrRnWKhaLH65pdCf
10 | vHCWxbsU9SwcTD7EbTELP+r1GK0uQDDn9QBdfQvlgXITNYOeatk/WaqZLJ7rWPkE
11 | VHVUN+FU094CzeIclX5Z/bt/HnW442ypyEyeXyJAMcCx8nMMKth3pKeBMsuzKJzd
12 | qg1KCMiuJfY/06pVUEqBtYfpe0SXqIZc1qTTFHYdQvIOMjXTEq/TbVuZhXOHMHo9
13 | D8nP2E3/tjPHhACFZNayhLt1GNjbfJIXMfZrEmbuQQKBgQDRKYjyT1c+ZnZF+yVh
14 | K2P++VbWYQnEbbF0+LTR3Um5uRTXXd1wGGx8HJWmyrQG8wpzhCXDSm1WkG7BAwaq
15 | 7f+08f9ReB99ed0LejmdFxCY9zU2iS/wQNXufGHB2QlHHyvm4WFu2lM3NzDBdZgD
16 | 2ltuoZJVp2wCI2vmQQzloiIHTwKBgQDP7iOxzLpoq4iDEtmZ3+RniTIWxav6ACx3
17 | US2xaaK8kXwCxJo69Gf20niWGrVn/HRX06L4xumsNCAPCp232AU0hrMb450zkHPc
18 | YS7B3JzJW2vZyVg1r4co2z6Avgo29aX/M7sye0HTyxEB913IQ8iVXy0MzcGffqQL
19 | NJ3/HbFseQKBgFAqGSC1o/x4jNAZh6QMW1D4A346xuGQITlxsOvWYlFaTFCW2y4B
20 | TmLrGbhJbGJVeCX5+fc1aV6KEMjM/hs5CI4zSeXRolAXCs9BUx+QHX5jEPQL9GGi
21 | l9vFtDn1kwa9PbhJnWw9JTO+ZWNgTJj9cZmfN1S4zD6tkMc5G1ZPo7clAoGBAM7I
22 | 7gasq9XcgW6ZGH7HAsdU0dOD0nxWH+KpgN+nRohxxvqZuyhWV+5HclUVSsOXdbzC
23 | ZJk0eL8hN6C91gw3cTXDn+xkeLoHNrI8k9uIIwS9PozgiDEb1zbykz5FwLLXqbYb
24 | JFgX7GdM1CU4dLPtdVXXyV2qYpzTvSDHuzkztndBAoGBAKf90jw5ECPrQrvcV3Cq
25 | I0UiAmwZVHM81TfAGlVSvlCfTKUH5U9g7/fNmJ2ERlgpcKu9Kb2W3fzIbWqaIQYu
26 | BPY6OK7Fj4cjJAIMFsMQhrwNuAWDRCBFCzJpTgEm3M1bVG32jyraqH9AbsUXRIeq
27 | GWYVaV6udf1LQ/OYN2eY1IBY
28 | -----END PRIVATE KEY-----
29 | -----BEGIN CERTIFICATE-----
30 | MIIDXTCCAkWgAwIBAgIJAP3hS6UzK4NiMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV
31 | BAYTAklUMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX
32 | aWRnaXRzIFB0eSBMdGQwHhcNMTQwMjIxMDc1OTM2WhcNMTUwMjIxMDc1OTM2WjBF
33 | MQswCQYDVQQGEwJJVDETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50
34 | ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
35 | CgKCAQEAqeMngzIjhcZC7+/B/xEBNGSRQParZAmjjwfU52E/fIAZu+UCAJp3EKD5
36 | aWbyBBZ2H70olaMNkx0uG78/s+xdqkgqgVYp99kCiizA5FShVHUN33xlMjEGD8p9
37 | BJw7PMeOgQE7Rwgjtu9k4u3wBKKz/rAQeOdqNd9rThb1fIkhsYGI1E2q1eg092/M
38 | R3TqpnL7R/eQuDhfuNt+wlkl/kRf18Ljq98tfW2PzVoPU6iz5bAeXmX2U10aB5pA
39 | qlNdLdjSSEl0D+oOa7dxThv6RkrCn4NkUma6q9RJkfAaf9q/B4pt13bbKCN+N7Eb
40 | 9AAOWD8ItFBAdh1rd5Rzv6f7/cnIVwIDAQABo1AwTjAdBgNVHQ4EFgQUmq4ILR/Q
41 | TGT5Jm3Yg+uiwSn07GkwHwYDVR0jBBgwFoAUmq4ILR/QTGT5Jm3Yg+uiwSn07Gkw
42 | DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAJPhEA9JNwFNIC3EHgXve
43 | +KXC5A8XZWFJDBZlQlbtkZ/xjXE/Uw7wdE/cHqAJtK5UTO7cc48lIWiXb6h2aORl
44 | qpWbYCWVTYxgA7WrdvIFNLlCcrCO8OcTuJl/ra5Y5nzPD0DM+Se4riosTEmQozYA
45 | aUrlIDINWdmPULlBlExmKBcMv+yazi3vAIJYHwKdzPZyt3O+vBl+FFAVMD5SpiOq
46 | P+1NPEQz6DS/uIG80/HF6Q2WoB5ZKiQeHQGZPLZI5WMLdNdeU3lYX+SKAm04NkA5
47 | BoWG5iOVchYF9+t8AexKeLCnJPoNiyz6LomlpzHIToVvf2qlNqh3rwRxuknF+Ji9
48 | zg==
49 | -----END CERTIFICATE-----
50 |
--------------------------------------------------------------------------------
/var/www/login.php:
--------------------------------------------------------------------------------
1 |
8 |
9 |
10 |
11 |
12 |
13 | Scr|pta
14 |
15 |
16 |
17 |
18 |
19 |
20 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
48 |
49 |
68 |
69 |
70 |
79 |
80 |
81 |
82 |
83 |
115 |
116 |
117 |
118 |
119 |
--------------------------------------------------------------------------------
/var/www/ng/app.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | if (window.location.protocol != "https:")
4 | window.location.href = "https:" + window.location.href.substring(window.location.protocol.length);
5 |
6 | // Declare app level module which depends on filters, and services
7 | angular.module('Scripta', ['Scripta.filters', 'Scripta.services', 'Scripta.directives', 'Scripta.controllers'])
8 | .config(['$routeProvider', function($routeProvider) {
9 | $routeProvider.when('/status', {templateUrl: 'partials/status.html', controller: 'CtrlStatus'});
10 | $routeProvider.when('/miner', {templateUrl: 'partials/miner.html', controller: 'CtrlMiner'});
11 | $routeProvider.when('/settings', {templateUrl: 'partials/settings.html', controller: 'CtrlSettings'});
12 | $routeProvider.when('/backup', {templateUrl: 'partials/backup.html', controller: 'CtrlBackup'});
13 |
14 | $routeProvider.otherwise({redirectTo: '/status'});
15 | }]);
16 |
--------------------------------------------------------------------------------
/var/www/ng/controllers.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | /* Controllers */
4 |
5 | angular.module('Scripta.controllers', [])
6 |
7 |
8 | // Main: stores status
9 | .controller('CtrlMain', function($scope,$http,$timeout,$window,$filter) {
10 | // Settings
11 | $scope.settings={};
12 | $scope.settingsMaster={};
13 | // Pools
14 | $scope.pools={};
15 | $scope.options={};
16 | // Status
17 | $scope.status={};
18 | $scope.status.extra=true; // Request extra data
19 | $scope.title="Miner interface initialization";
20 | // Refresh
21 | $scope.intervalAuto = true; // Automatically adjust interval
22 | $scope.intervalMax = 20; // Default refresh rate
23 | // Live graph
24 | $scope.live=[];
25 | $scope.settings.liveMax=50;
26 | $scope.upLast=0;
27 | $scope.downLast=0;
28 | // Alerts
29 | Alertify.log.delay=10000;
30 |
31 | // Sync settings
32 | // Note: not possible to remove settings!
33 | $scope.sync = function(action,data,alert) {
34 | action = action || 'settings';
35 | data = data || 'load';
36 | $http.get('f_settings.php?'+action+'='+angular.toJson(data)).success(function(d){
37 | if(d.info){
38 | angular.forEach(d.info, function(v,k) {Alertify.log.create(v.type, v.text);});
39 | }
40 | if(action=='settings'){
41 | $scope.settings=angular.copy(d['data']);
42 | }
43 | else if(action=='pools'){
44 | $scope.pools=d['data'];
45 | }
46 | else if(action=='options'){
47 | $scope.options=d['data'];
48 | }
49 | else if(action=='timezone'){
50 | $scope.settings.date=d.data.date;
51 | }
52 | });
53 | }
54 | $scope.syncDelay = function(ms,action,data,alert) {
55 | action = action || 'settings';
56 | data = data || false;
57 | ms = ms || 1000;
58 | var syncNow = function(){
59 | $scope.sync(action,data,alert);
60 | }
61 | return $timeout(syncNow, ms);
62 | }
63 |
64 | // Sync settings
65 | $scope.sync('settings')
66 |
67 | // Get status and save in scope
68 | $scope.tick = function(once,all) {
69 | $http.get('f_status.php?'+($scope.settings.userDeveloper?'dev=1&':'')+(all||$scope.status.extra?'all=1':'')).success(function(d){
70 | if(d.info){
71 | angular.forEach(d.info, function(v,k) {Alertify.log.create(v.type, v.text);});
72 | }
73 | // Update status
74 | angular.forEach(d.status, function(v,k) {$scope.status[k]=v;});
75 | // Title
76 | $scope.title=$scope.status.minerDown?'Miner DOWN -':'['+$filter('mhs')($scope.status.dtot.MHS5s)+'h] ['+$scope.status.dtot.devices+' dev]';
77 | // Live Graphs
78 | $scope.live.push([Date.now(),1000000*$scope.status.dtot.MHS5s]);
79 | // Stop requesting extra data
80 | $scope.status.extra=false;
81 | })
82 | .error(function(){
83 | // Title
84 | $scope.title='Scripta DOWN -';
85 | // Live Graphs
86 | $scope.live.push([Date.now(),0]);
87 | })
88 | .then(function(){
89 | if($scope.live.length>$scope.settings.liveMax){
90 | $scope.live=$scope.live.slice(-$scope.settings.liveMax);
91 | }
92 | // Manage interval
93 | if($scope.interval<$scope.intervalMax){
94 | $scope.interval++;
95 | }
96 | });
97 | }
98 |
99 | $scope.intervalSet = function(num) {
100 | if(num<2){
101 | $scope.intervalAuto=!$scope.intervalAuto;
102 | if($scope.intervalAuto) $scope.interval=1;
103 | }
104 | else{
105 | $scope.intervalMax=num;
106 | $scope.interval=num;
107 | }
108 | };
109 | var count = function () {
110 | $timeout(count, 1000);
111 | if($scope.counter>0){
112 | $scope.counter--;
113 | }
114 | else{
115 | $scope.counter=$scope.interval-1;
116 | $scope.tick();
117 | }
118 | };
119 | count();
120 |
121 | $scope.$watch('title', function(b,a) {
122 | $window.document.title=b+' Scripta';
123 | });
124 |
125 | $scope.$watch('intervalAuto', function(b,a) {
126 | Alertify.log.info('Automatic refresh rate '+(b?'en':'dis')+'abled');
127 | });
128 |
129 | $scope.$watch('intervalMax', function(b,a) {
130 | Alertify.log.info('Refresh rate is now '+b);
131 | if($scope.counter>b){
132 | $scope.counter=0;
133 | }
134 | $scope.status.extra=true;
135 | });
136 |
137 | $scope.$watch('status.minerDown', function(b,a) {
138 | if(b){
139 | $scope.upLast=Date.now();
140 | Alertify.log.error('Miner seems down');
141 | }
142 | else{
143 | $scope.downLast=Date.now();
144 | Alertify.log.success('Miner is up!');
145 | }
146 | $scope.interval=1;
147 | $scope.counter=0;
148 | $scope.status.extra=true;
149 | });
150 | })
151 |
152 |
153 | .controller('CtrlStatus', function($scope,$http) {
154 | $scope.status.extra=true;
155 | $scope.num=0;
156 |
157 | $scope.graphUpdate = function() {
158 | $http.get('f_graph.php').success(function(d){
159 |
160 | if(d){
161 | Alertify.log.success("Graphs updated");
162 | }
163 | else{
164 | Alertify.log.error("Update graph ended in error");
165 | }
166 | $scope.num++;
167 | }).error(function(){
168 | Alertify.log.error("Update graph ended in error: https enabled?");
169 | });
170 | }
171 | })
172 |
173 |
174 | .controller('CtrlMiner', function($scope,$http,$timeout) {
175 | $scope.status.extra=true;
176 | $scope.sync('pools');
177 | $scope.sync('options');
178 |
179 | $scope.minerCompat = function(command,parameter) {
180 | $http.get('f_minercompat.php').success(function(d){
181 | if(d.info){
182 | angular.forEach(d.info, function(v,k) {Alertify.log.create(v.type, v.text);});
183 | }
184 | if(d.data.pools){
185 | $scope.pools=d.data.pools;
186 | }
187 | if(d.data.options){
188 | $scope.options=d.data.options;
189 | }
190 | });
191 | }
192 |
193 | $scope.bfgminer = function(command,parameter) {
194 | $scope.tick();
195 |
196 | var execute = function(){
197 | $http.get('f_miner.php?command='+(command || 'summary')+'¶meter='+parameter).success(function(d){
198 | if(d.info){
199 | angular.forEach(d.info, function(v,k) {Alertify.log.create(v.type, v.text);});
200 | }
201 | $scope.tick();
202 | });
203 | }
204 | $timeout(execute, 1000);
205 | };
206 |
207 | $scope.bfgminerHardCtl = function(command) {
208 | $scope.tick();
209 |
210 | var execute = function(){
211 | $http.get('f_minerHardCtl.php?command='+(command)).success(function(d){
212 | if(d.info){
213 | angular.forEach(d.info, function(v,k) {Alertify.log.create(v.type, v.text);});
214 | }
215 | $scope.tick();
216 | });
217 | }
218 | $timeout(execute, 1000);
219 | };
220 |
221 | $scope.hostHardCtl = function(command) {
222 | $scope.tick();
223 | var execute = function(){
224 | $http.get('f_hostHardCtl.php?command='+(command)+'&pass=p0c4t0p4').success(function(d){
225 | if(d.info){
226 | angular.forEach(d.info, function(v,k) {Alertify.log.create(v.type, v.text);});
227 | }
228 | $scope.tick();
229 | });
230 | }
231 | $timeout(execute, 1000);
232 | };
233 |
234 | $scope.poolAdd = function(a) {
235 | a = a || {};
236 | $scope.pools.push(a);
237 | $scope.poolForm.$setDirty()
238 | };
239 | $scope.poolRemove = function(index) {
240 | $scope.pools.splice(index,1);
241 | $scope.poolForm.$setDirty()
242 | };
243 | $scope.poolSave = function() {
244 | $scope.sync('pools',$scope.pools,1);
245 | $scope.poolForm.$setPristine();
246 | };
247 | $scope.poolBack = function() {
248 | $scope.sync('pools',0,1);
249 | $scope.poolForm.$setPristine();
250 | };
251 |
252 | $scope.optionAdd = function(a) {
253 | a = a || {};
254 | $scope.options.push(a);
255 | $scope.optionForm.$setDirty()
256 | };
257 | $scope.optionRemove = function(index) {
258 | $scope.options.splice(index,1);
259 | $scope.optionForm.$setDirty()
260 | };
261 | $scope.optionSave = function() {
262 | $scope.sync('options',$scope.options,1);
263 | $scope.optionForm.$setPristine();
264 | };
265 | $scope.optionBack = function() {
266 | $scope.sync('options',0,1);
267 | $scope.optionForm.$setPristine();
268 | };
269 | })
270 |
271 |
272 | .controller('CtrlSettings', function($scope) {
273 | $scope.status.extra=true;
274 | })
275 |
276 |
277 | .controller('CtrlBackup', function($scope,$http,$timeout) {
278 | $scope.thisFolder = '/opt/scripta/';
279 | $scope.backupFolder = '/opt/scripta/backup/';
280 | $scope.backupName = GetDateTime();
281 | $scope.backups = [];
282 | $scope.restoring = 0;
283 | $scope.items = [
284 | {selected:true,name:'etc/scripta.conf'},
285 | {selected:true,name:'etc/miner.pools.json'},
286 | {selected:true,name:'etc/miner.options.json'}
287 | ];
288 |
289 | $scope.addItem = function() {
290 | $scope.items.push({selected:true,name:$scope.newItem});
291 | $scope.newItem = '';
292 | };
293 | $scope.selItem = function() {
294 | var count = 0;
295 | angular.forEach($scope.items, function(item) {
296 | count += item.selected ? 1 : 0;
297 | });
298 | return count;
299 | };
300 |
301 |
302 | $scope.backupLocal = function() {
303 | var promise = $http.get('f_backup.php?name='+$scope.backupName+'&backup='+angular.toJson($scope.items)).success(function(d){
304 | if(d.info){
305 | angular.forEach(d.info, function(v,k) {Alertify.log.create(v.type, v.text);});
306 | }
307 | angular.forEach(d.data, function(v,k) {
308 | if(v.success){
309 | $scope.items[k].bak=true;
310 | $scope.items[k].selected=false;
311 | }
312 | else{
313 | $scope.items[k].fail=true;
314 | }
315 | });// Add to existing
316 | $scope.reload();
317 | });
318 | return promise;
319 | };
320 |
321 | $scope.backupExport = function() {
322 | $scope.backupLocal().then(function(){
323 | $scope.exportZip($scope.backupName);
324 | });
325 | };
326 |
327 | $scope.exportZip = function(name) {
328 | name=name||$scope.backups[$scope.restoring].dir;
329 | window.location.href='f_backup.php?export='+name;
330 | };
331 |
332 | $scope.choose = function(i) {
333 | $scope.restoring=i;
334 | };
335 |
336 | $scope.restore = function() {
337 | $http.get('f_backup.php?restore='+$scope.backups[$scope.restoring].dir).success(function(d){
338 | if(d.info){
339 | angular.forEach(d.info, function(v,k) {Alertify.log.create(v.type, v.text);});
340 | }
341 | $scope.syncDelay(300,'settings');
342 | $scope.syncDelay(600,'pools');
343 | $scope.syncDelay(900,'options');
344 | });
345 | };
346 |
347 | $scope.reload = function(wait) {
348 | wait=wait||0;
349 | var syncNow = function(){
350 | $http.get('f_backup.php').success(function(d){
351 | if(d.data){
352 | $scope.backups=d.data;
353 | }
354 | });
355 | }
356 | //return
357 | $timeout(syncNow, wait);
358 | };
359 | $scope.reload();
360 | });
361 |
362 |
363 | function GetDateTime() {
364 | var now = new Date();
365 | return [[now.getFullYear(),AddZero(now.getMonth() + 1),AddZero(now.getDate())].join(''), [AddZero(now.getHours()), AddZero(now.getMinutes())].join('')].join('-');
366 | }
367 |
368 | function AddZero(num) {
369 | return (num >= 0 && num < 10) ? '0' + num : num + '';
370 | }
371 |
--------------------------------------------------------------------------------
/var/www/ng/directives.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | /* Directives */
4 | angular.module('Scripta.directives', [])
5 |
6 | // Sets background color by interpolating between green and red.
7 | // Thinking about oth interpolation functions or maybe more colors
8 | .directive('statusItem', function() {
9 | return function(scope, element, attrs) {
10 | var i=attrs.statusItem;
11 | var g=attrs.good; // Threshold good: green
12 | var b=attrs.bad; // Threshold bad: red
13 |
14 | function update(){
15 | var x=2*(i-g)/(b-g);
16 | x= x<0 ?0:x;
17 | x= x>2 ?2:x;
18 | element.css('background',(b==g)?'#666':'rgb('+Math.round(Math.min(x, 1)*(217-92)+92)+','+Math.round((2 - Math.max(x, 1)) * (184-83)+83)+',85)');
19 | element.css('color','#fff');
20 | }
21 |
22 | scope.$watch(attrs.good, function(v) {g=v;update();});
23 | scope.$watch(attrs.bad, function(v) {b=v;update();});
24 | scope.$watch(attrs.statusItem, function(v) {i=v;update();});
25 | }
26 | })
27 | // Toggles .active based on $location.path()
28 | .directive('menuActive', function($rootScope,$location) {
29 | return function(scope, element, attrs) {
30 | $rootScope.$on('$routeChangeStart', function (event, next, current) {
31 | (element.children()[0].hash === '#'+$location.path()) ? element.addClass('active') : element.removeClass('active');
32 | });
33 | }
34 | })
35 |
36 | .directive('graphLive', function () {
37 | return {
38 | restrict: 'C',
39 | scope: {
40 | live: '='
41 | },
42 | controller: function ($scope, $element, $attrs) {
43 | },
44 | link: function (scope, element, attrs) {
45 | var chart = new Highcharts.Chart({
46 | chart: {
47 | renderTo: attrs.id,
48 | type: 'areaspline',
49 | spacingLeft: 0,
50 | spacingRight: 0
51 | },
52 | colors: ['rgb(0,0,0)'],
53 | legend: {enabled: false},
54 | subtitle: {text: ''},
55 | title: {
56 | text: 'Hashrate',
57 | align: 'center',
58 | verticalAlign: 'bottom',
59 | },
60 | xAxis: {
61 | type: 'datetime',
62 | minPadding: 0,
63 | maxPadding: 0,
64 | tickPixelInterval: 120
65 | },
66 | yAxis: {
67 | tickPixelInterval: 30,
68 | title: {
69 | text: ''
70 | },
71 | opposite: true
72 | },
73 | tooltip: {
74 | formatter: function() {
75 | var hs=this.y/1000,h=this.y+' ';
76 | if(hs > 10){h=hs.toPrecision(4)+' k';}hs/=1000;
77 | if(hs > 10){h=hs.toPrecision(4)+' M';}hs/=1000;
78 | if(hs > 10){h=hs.toPrecision(4)+' G';}hs/=1000;
79 | if(hs > 10){h=hs.toPrecision(4)+' T';}
80 | return Highcharts.dateFormat('%Y-%m-%d %H:%M:%S', this.x) +' '+ h +'h/s';
81 | }
82 | },
83 | plotOptions: {
84 | areaspline: {
85 | fillOpacity: 0.1,
86 | marker: {
87 | enabled: false,
88 | states: {
89 | hover: {
90 | enabled: true
91 | }
92 | }
93 | }
94 | }
95 | },
96 | series: [{
97 | name: 'hashrate',
98 | data: [[Date.now(),0]]
99 | }]
100 | });
101 |
102 | var liveTrack=0;
103 | scope.$watch('live', function (newlist) {
104 | var n=angular.copy(newlist);
105 | if(!n || !n.length)return;
106 | if(liveTrack<2){
107 | chart.series[0].setData(n);
108 | }
109 | else{
110 | chart.series[0].addPoint(n[n.length-1],true,n.lengthBackup settings
2 |
3 |
58 |
59 | Restore settings from backup
60 |
61 |
66 |
67 |
68 | There seems to be no files in this backup, this can happen if permission was denied.
69 |
70 |
71 |
72 | {{i}}
73 |
74 |
75 |
76 | Reload list will scan the backup folder for saved backups.
77 | 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.
78 | Export ... will make a zipfile of the items in the currently selected backup and serve it as a download.
79 | 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.
80 |
81 |
Reload list
82 |
Restore
83 |
Export {{backups[restoring].dir}}.zip
84 |
Import file...
85 |
86 |
87 |
88 |
89 |
93 |
94 |
--------------------------------------------------------------------------------
/var/www/partials/miner.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
Available pools
11 |
12 | Click to add pool to pool's list
13 |
14 |
27 |
28 |
29 |
30 |
31 |
32 |
33 | Miner commands
34 |
35 |
36 | Ordered from gentle to rough.
37 |
38 |
45 |
46 |
47 |
48 |
Pools
49 |
50 | The settings below serve as direct input to the miner. One little error can and will let the miner crash.
51 |
52 |
82 |
83 |
84 |
85 |
107 |
108 |
109 | Reload settings
2 |
Scr|pta
3 |
50 |
51 |
74 |
75 |
76 |
128 |
129 |
130 |
216 |
--------------------------------------------------------------------------------
/var/www/partials/status.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | Graphs
4 |
5 | Static -
6 | Live -
7 | Refresh -
8 | More
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 | Graphs
28 |
29 | Static -
30 | Live -
31 | Refresh -
32 | Auto-refresh in {{counter}}s
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
No devices running
41 |
Devices
42 |
43 |
44 |
45 | Device
46 | ID
47 | Temp
48 | Hashrate 5s
49 | Hashrate av
50 | Accepted
51 | Rejected
52 | HW Errors
53 | Utility
54 | Last Share Time
55 |
56 |
57 |
58 |
59 |
60 |
61 | {{d.Temperature}} °C
62 | {{(d.MHS5s*1024)}} Kh/s
63 | {{(d.MHSav*1024)}} Kh/s
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 | {{status.dtot.devices}} devs Totals
74 | {{status.dtot.MHS5s|mhs}}h/s
75 | {{status.dtot.MHSav|mhs}}h/s
76 |
77 |
78 |
79 | " . $ . "
80 |
81 |
82 |
83 |
84 |
85 |
No pools loaded
86 |
Pools
87 |
88 |
89 |
90 | URL
91 | User
92 | Status
93 | Pr
94 | GW
95 | Acc
96 | Rej
97 | Disc
98 | Last
99 | Diff1
100 | DAcc
101 | DRej
102 | DLast
103 | Best
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
--------------------------------------------------------------------------------
/var/www/rrd:
--------------------------------------------------------------------------------
1 | /opt/scripta/http/rrd/
--------------------------------------------------------------------------------
/var/www/test.php:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/var/www/update/ctrl.php:
--------------------------------------------------------------------------------
1 | currentVersionName = CURRENT_VERSION_NAME;
7 | $update->currentVersion = CURRENT_VERSION;
8 | $update->updateUrl = REPOSITORY_URL;
9 |
10 | //Check for a new update
11 | $latest = $update->checkUpdate();
12 |
13 | if ($latest !== false) {
14 | if ($latest > $update->currentVersion) {
15 | //Install new update
16 | echo "An update is available.\nDo you want to download and install it now?\nMining activities will not be affected.\nCurrent Version: ".$update->currentVersionName."\nNew version: ".$update->latestVersionName;
17 | }
18 | else {
19 | //echo "Current Version is up to date";
20 | echo '';
21 | }
22 | }
23 | else {
24 | echo $update->getLastError();
25 | }
26 |
27 | ?>
--------------------------------------------------------------------------------
/var/www/update/start.php:
--------------------------------------------------------------------------------
1 | currentVersionName = CURRENT_VERSION_NAME;
7 | $update->currentVersion = CURRENT_VERSION;
8 | $update->updateUrl = REPOSITORY_URL;
9 |
10 | //Check for a new update
11 | echo "Download file...\n";
12 | $latest = $update->checkUpdate();
13 | if ($latest !== false) {
14 | if ($latest > $update->currentVersion) {
15 | //Install new update
16 | echo "Installing Update...\n";
17 | if ($update->update()) {
18 | echo "Update successful!";
19 | }
20 | else {
21 | echo "Update failed!";
22 | }
23 |
24 | }
25 | else {
26 | echo "Current Version is up to date";
27 | }
28 | }
29 | else {
30 | echo $update->getLastError();
31 | }
32 |
33 | ?>
34 |
--------------------------------------------------------------------------------
/var/www/update/update.php:
--------------------------------------------------------------------------------
1 | _log = $log;
89 | }
90 |
91 | /*
92 | * Log a message if logging is enabled
93 | *
94 | * @param string $message The message
95 | *
96 | * @return void
97 | */
98 | public function log($message) {
99 | if ($this->_log) {
100 | $this->_lastError = $message;
101 |
102 | $log = fopen($this->logFile, 'a');
103 |
104 | if ($log) {
105 | $message = date('
').$message."\n";
106 | fputs($log, $message);
107 | fclose($log);
108 | }
109 | else {
110 | die('Could not write log file!');
111 | }
112 | }
113 | }
114 |
115 | /*
116 | * Get the latest error
117 | *
118 | * @return string Last error
119 | */
120 | public function getLastError() {
121 | if (!is_null($this->_lastError))
122 | return $this->_lastError;
123 | else
124 | return false;
125 | }
126 |
127 | private function _removeDir($dir) {
128 | if (is_dir($dir)) {
129 | $objects = scandir($dir);
130 | foreach ($objects as $object) {
131 | if ($object != "." && $object != "..") {
132 | if (filetype($dir."/".$object) == "dir")
133 | $this->_removeDir($dir."/".$object);
134 | else
135 | unlink($dir."/".$object);
136 | }
137 | }
138 | reset($objects);
139 | rmdir($dir);
140 | }
141 | }
142 |
143 | /*
144 | * Check for a new version
145 | *
146 | * @return string The latest version
147 | */
148 | public function checkUpdate() {
149 | $this->log('Checking for a new update. . .');
150 |
151 | $updateFile = $this->updateUrl.'/update.ini';
152 |
153 | $update = @file_get_contents($updateFile);
154 | if ($update === false) {
155 | $this->log('Could not retrieve update file `'.$updateFile.'`!');
156 | return false;
157 | }
158 | else {
159 | $versions = parse_ini_string($update, true);
160 | if (is_array($versions)) {
161 | $keyOld = 0;
162 | $latest = 0;
163 | $update = '';
164 |
165 | foreach ($versions as $key => $version) {
166 |
167 | if ($key > $keyOld) {
168 | $keyOld = $key;
169 | $latest = $version['version'];
170 | $update = $version['url'];
171 | }
172 | }
173 |
174 | $this->log('New version found `'.$latest.'`.');
175 | $this->latestVersion = $keyOld;
176 | $this->latestVersionName = $latest;
177 | $this->latestUpdate = $update;
178 |
179 | return $keyOld;
180 | }
181 | else {
182 | $this->log('Unable to parse update file!');
183 | return false;
184 | }
185 | }
186 | }
187 |
188 | /*
189 | * Download the update
190 | *
191 | * @param string $updateUrl Url where to download from
192 | * @param string $updateFile Path where to save the download
193 | */
194 | public function downloadUpdate($updateUrl, $updateFile) {
195 | $this->log('Downloading update...');
196 | $update = @file_get_contents($updateUrl);
197 |
198 | if ($update === false) {
199 | $this->log('Could not download update `'.$updateUrl.'`!');
200 | return false;
201 | }
202 |
203 | $handle = fopen($updateFile, 'w');
204 |
205 | if (!$handle) {
206 | $this->log('Could not save update file `'.$updateFile.'`!');
207 | return false;
208 | }
209 |
210 | if (!fwrite($handle, $update)) {
211 | $this->log('Could not write to update file `'.$updateFile.'`!');
212 | return false;
213 | }
214 |
215 | fclose($handle);
216 |
217 | return true;
218 | }
219 |
220 | /*
221 | * Install update
222 | *
223 | * @param string $updateFile Path to the update file
224 | */
225 | public function install($updateFile) {
226 | $zip = zip_open($updateFile);
227 |
228 | while ($file = zip_read($zip)) {
229 | $filename = zip_entry_name($file);
230 | $foldername = $this->installDir.dirname($filename);
231 |
232 | $this->log('Updating `'.$filename.'`!');
233 |
234 | if (!is_dir($foldername)) {
235 | if (!mkdir($foldername, $this->dirPermissions, true)) {
236 | $this->log('Could not create folder `'.$foldername.'`!');
237 | }
238 | }
239 |
240 | $contents = zip_entry_read($file, zip_entry_filesize($file));
241 |
242 | //Skip if entry is a directory
243 | if (substr($filename, -1, 1) == '/')
244 | continue;
245 |
246 | //Write to file
247 | if (!is_writable($this->installDir.$filename)) {
248 | $this->log('Could not update `'.$this->installDir.$filename.'`, not writeable!');
249 | return false;
250 | }
251 |
252 | $updateHandle = @fopen($this->installDir.$filename, 'w');
253 |
254 | if (!$updateHandle) {
255 | $this->log('Could not update file `'.$this->installDir.$filename.'`!');
256 | return false;
257 | }
258 |
259 | if (!fwrite($updateHandle, $contents)) {
260 | $this->log('Could not write to file `'.$this->installDir.$filename.'`!');
261 | return false;
262 | }
263 |
264 | fclose($updateHandle);
265 |
266 | //If file is a update script, include
267 | if ($filename == $this->updateScriptName) {
268 | $this->log('Try to include update script `'.$this->installDir.$filename.'`.');
269 | require($this->installDir.$filename);
270 | $this->log('Update script `'.$this->installDir.$filename.'` included!');
271 | unlink($this->installDir.$filename);
272 | }
273 | }
274 |
275 | zip_close($zip);
276 |
277 | if ($this->removeTempDir) {
278 | $this->log('Temporary directory `'.$this->tempDir.'` deleted.');
279 | $this->_removeDir($this->tempDir);
280 | }
281 |
282 | $this->log('Update `'.$this->latestVersion.'` installed.');
283 |
284 | return true;
285 | }
286 |
287 |
288 | /*
289 | * Update to the latest version
290 | */
291 | public function update() {
292 | //Check for latest version
293 | if ((is_null($this->latestVersion)) or (is_null($this->latestUpdate))) {
294 | $this->checkUpdate();
295 | }
296 |
297 | if ((is_null($this->latestVersion)) or (is_null($this->latestUpdate))) {
298 | return false;
299 | }
300 |
301 | //Update
302 | if ($this->latestVersion > $this->currentVersion) {
303 | $this->log('Updating...');
304 |
305 | //Add slash at the end of the path
306 | if ($this->tempDir[strlen($this->tempDir)-1] != '/');
307 | $this->tempDir = $this->tempDir.'/';
308 |
309 | if ((!is_dir($this->tempDir)) and (!mkdir($this->tempDir, 0777, true))) {
310 | $this->log('Temporary directory `'.$this->tempDir.'` does not exist and could not be created!');
311 | return false;
312 | }
313 |
314 | if (!is_writable($this->tempDir)) {
315 | $this->log('Temporary directory `'.$this->tempDir.'` is not writeable!');
316 | return false;
317 | }
318 |
319 | $updateFile = $this->tempDir.'/'.$this->latestVersion.'.zip';
320 | $updateUrl = $this->updateUrl.'/'.$this->latestVersion.'.zip';
321 |
322 | //Download update
323 | if (!is_file($updateFile)) {
324 | if (!$this->downloadUpdate($updateUrl, $updateFile)) {
325 | $this->log('Failed to download update!');
326 | return false;
327 | }
328 |
329 | $this->log('Latest update downloaded to `'.$updateFile.'`.');
330 | }
331 | else {
332 | $this->log('Latest update already downloaded to `'.$updateFile.'`.');
333 | }
334 |
335 | //Unzip
336 | return $this->install($updateFile);
337 | }
338 | else {
339 | $this->log('No update available!');
340 | return false;
341 | }
342 | }
343 | }
--------------------------------------------------------------------------------
/var/www/update/version.php:
--------------------------------------------------------------------------------
1 |
6 |
--------------------------------------------------------------------------------