I recently received an ASIC miner, and I use the popular cgminer, an ASIC miner (written in C) for Bitcoin (and Litecoin).
Cgminer provides an RPC API that let you retrieve stats about your device(s), and I'm buidling an open source monitoring dashboard, RigsMonitoring writen in Python, accessing the API with Python is easy using sockets.
Enable cgminer API
To enable the API, you need to add --api-listen
and --api-allow W:0/0
.
sudo nohup ./cgminer -o stratum.bitcoin.cz:3333 -u myworker -p mypass --api-allow W:0/0 --api-listen&
Accessing the API with Python
A detailled documentation is available in the API-README file.
The API talks JSON, listens on port 4048 by default, and a basic request looks like {"command":"CMD","parameter":"PARAM"}
.
import socket
import json
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect(('localhost', 4028))
Make a request with the summary command, JSON encoded.
sock.send(json.dumps({'command': 'summary'}))
Next, receive the response (alway JSON encoded):
resp = ''
while 1:
buf = sock.recv(4096)
if buf:
resp += buf
else:
break
resp
You can notice the null byte \x00
at the end of the response.
Finally, we shutdown the socket.
sock.shutdown(socket.SHUT_RDWR)
sock.close()
And decode the response (without the null byte):
json.loads(resp[:-1])
Cgminer API wrapper
Now that we successfully called the API, here is a basic wrapper, with argument support:
import socket
import json
class CgminerAPI(object):
""" Cgminer RPC API wrapper. """
def __init__(self, host='localhost', port=4028):
self.data = {}
self.host = host
self.port = port
def command(self, command, arg=None):
""" Initialize a socket connection,
send a command (a json encoded dict) and
receive the response (and decode it).
"""
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
sock.connect((self.host, self.port))
payload = {"command": command}
if arg is not None:
# Parameter must be converted to basestring (no int)
payload.update({'parameter': unicode(arg)})
sock.send(json.dumps(payload))
received = self._receive(sock)
finally:
sock.shutdown(socket.SHUT_RDWR)
sock.close()
return json.loads(received[:-1])
def _receive(self, sock, size=4096):
msg = ''
while 1:
chunk = sock.recv(size)
if chunk:
msg += chunk
else:
break
return msg
def __getattr__(self, attr):
def out(arg=None):
return self.command(attr, arg)
return out
Check that the wrapper is actually working, by calling the command
method:
cgminer = CgminerAPI()
cgminer.command('summary')
Have you noticed the __getattr__
magic method, it return the command
so instead of calling the command method, we can call the method that correspond to the command we want, it allows us to:
cgminer.summary()
And it even handles argument:
cgminer.asc(0)
Pycgminer
I released the code on pypi and you can check out the project on github: pycgminer.
$ pip install pycgminer
from pycgminer import CgminerAPI
cgminer = CgminerAPI()
print cgminer.devs()
Don't hesitate to submit a pull request!
Feedback
Don't hesitate to let me know if you have any questions/suggestions !
Tip with Bitcoin
Tip me with Bitcoin and vote for this post!
Leave a comment