1
|
|
|
'''calls miner api''' |
2
|
|
|
#based on https://github.com/tsileo/pycgminer |
3
|
|
|
import socket |
4
|
|
|
import json |
5
|
|
|
|
6
|
|
|
class MinerApi(object): |
7
|
|
|
"""cgminer api client""" |
8
|
|
|
def __init__(self, host='localhost', port=4028, timeout=2, retry_count=3): |
9
|
|
|
self.host = host |
10
|
|
|
self.port = port |
11
|
|
|
self.timeout = timeout |
12
|
|
|
self.retry_count = retry_count |
13
|
|
|
self.encoding = 'utf-8' |
14
|
|
|
|
15
|
|
|
def command(self, command, arg=None): |
16
|
|
|
socket.setdefaulttimeout(self.timeout) |
17
|
|
|
retries_remaining = self.retry_count |
18
|
|
|
while retries_remaining > 0: |
19
|
|
|
try: |
20
|
|
|
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) |
21
|
|
|
sock.connect((self.host, self.port)) |
22
|
|
|
payload = {"command": command} |
23
|
|
|
if arg is not None: |
24
|
|
|
payload['parameter'] = arg |
25
|
|
|
sock.send(bytes(json.dumps(payload), self.encoding)) |
26
|
|
|
#for some reason on linux, cannot shutdown write yet |
27
|
|
|
#s.shutdown(socket.SHUT_WR) |
28
|
|
|
received = self._receive(sock) |
29
|
|
|
sock.shutdown(socket.SHUT_RDWR) |
30
|
|
|
except Exception as ex: |
31
|
|
|
retries_remaining -= 1 |
32
|
|
|
if retries_remaining <= 0: |
33
|
|
|
return dict({'STATUS': [{'STATUS': 'error', 'description': "{0}:{1}".format(self.host, ex)}]}) |
34
|
|
|
else: |
35
|
|
|
# remove null byte in first character and add missing comma in stats command |
36
|
|
|
# fix lcd command |
37
|
|
|
# fix alternate miner software that puts \n in Miner Type |
38
|
|
|
return json.loads(received[:-1].replace('}{', '},{').replace('[,', '[').replace('\n', '')) |
39
|
|
|
finally: |
40
|
|
|
sock.close() |
41
|
|
|
|
42
|
|
|
def _receive(self, sock, max_bytes=4096): |
43
|
|
|
fullresponse = '' |
44
|
|
|
while True: |
45
|
|
|
more = sock.recv(max_bytes) |
46
|
|
|
if not more: |
47
|
|
|
break |
48
|
|
|
fullresponse += more.decode(self.encoding) |
49
|
|
|
return fullresponse |
50
|
|
|
|
51
|
|
|
def __getattr__(self, attr): |
52
|
|
|
'''a pattern that converts an attribute into a miner command. |
53
|
|
|
Examples: stats, pools |
54
|
|
|
''' |
55
|
|
|
def out(arg=None): |
56
|
|
|
return self.command(attr, arg) |
57
|
|
|
return out |
58
|
|
|
|