It works!

This commit is contained in:
2018-01-21 19:44:54 -08:00
parent 055ab45efd
commit b73ab72e0a
3 changed files with 159 additions and 50 deletions

View File

@@ -1,33 +1,25 @@
#!/usr/bin/env python3
# API description: http://www.zpool.ca/site/api
# estimates: values in mBTC/MH/day,
# mBTC/PH/day for sha256
# mBTC/GH/day for scrypt, blake, decred, x11, quark, qubit
# mBTC/kS/day for equihash
# API description (such as it is): http://www.zpool.ca/site/api
import pprint
import json
import urllib.request
import urllib.parse
import sys
import datetime
import time
import subprocess
import os
import socket
import urllib.request
import urllib.parse
# load config
DEBUG=False
cfg=json.loads(open(sys.argv[1]).read())
miners=json.loads(open(sys.argv[2]).read())
algo_map=json.loads(open(sys.argv[3]).read())
card_type=cfg["card_type"]
#user_name=cfg["user_name"]
#miner_name=cfg["miner_name"]
currency=cfg["currency"]
pwrcost=cfg["pwrcost"]
min_profit=cfg["min_profit"]
@@ -36,29 +28,20 @@ payment_addr=cfg["payment_addr"]
os.environ["DISPLAY"]=":0"
# IPv4 address lookup
def addr(host):
return [addr[4][0] for addr in socket.getaddrinfo(host, None) if addr[0] == socket.AF_INET][0]
# grab something from a website
def fetch(prot, host, path, forceipv4=False):
if (forceipv4):
url=prot+"://"+addr(host)+"/"+path
else:
url=prot+"://"+host+"/"+path
r=urllib.request.Request(url, None, {"User-Agent": "Lynx/2.8.8dev.3 libwww-FM/2.14 SSL-MM/1.4.1", "Pragma": "no-cache", "Host": host})
def fetch(url):
r=urllib.request.Request(url, None, {"User-Agent": "Lynx/2.8.8dev.3 libwww-FM/2.14 SSL-MM/1.4.1", "Pragma": "no-cache"})
return urllib.request.urlopen(r).read().decode("utf-8")
# main
if (DEBUG!=True):
exchrate=float(json.loads(fetch("https", "api.coinbase.com", "/v2/exchange-rates?currency=BTC"))["data"]["rates"][currency])
data=json.loads(fetch("http", "www.zpool.ca", "/api/status", True))
else:
exchrate=float(json.loads(open("dbgdata-exchange-rates").read())["data"]["rates"][currency])
data=json.loads(open("dbgdata-status").read())
try:
exchrate=float(json.loads(fetch("https://api.coinbase.com/v2/exchange-rates?currency=BTC"))["data"]["rates"][currency])
data=json.loads(fetch("http://www.zpool.ca/api/status"))
except:
print("unable to retrieve remote data", file=sys.stderr)
sys.exit(-1)
# update algo map
@@ -74,23 +57,36 @@ if (changed==True):
with open(sys.argv[3], "w") as outfile:
json.dump(algo_map, outfile, sort_keys=True, indent=2)
# adjust estimates so they're all in the same units: BTC/day per GH/s
# weed out miners not supported by the pool
filtered_miners={}
for i in data:
data[i]["adjusted_estimate"]=float(data[i]["estimate_current"])*1000
try:
filtered_miners[algo_map[i]]=miners[algo_map[i]]
except:
pass
miners=filtered_miners
# adjust estimates so they're all in the same units: BTC/day per GH/s
for i in data:
data[i]["estimate_current"]=float(data[i]["estimate_current"])*1000
try:
data["sha256"]["adjusted_estimate"]/=1000000000000
data["sha256"]["estimate_current"]/=1000000000
except:
pass
try:
data["equihash"]["adjusted_estimate"]*=1000
data["equihash"]["estimate_current"]*=1000
except:
pass
for i in ["scrypt", "blakecoin", "blake2s", "decred", "x11", "quark", "qubit", "keccak"]:
try:
data[i]["adjusted_estimate"]/=1000
data[i]["estimate_current"]/=1000
except:
pass
# calculate profitability for our hardware
coins={}
for i in data:
if (algo_map[i]!=""):
@@ -99,13 +95,99 @@ for i in data:
coins[i]["algo"]=i
coins[i]["mapped_algo"]=algo_map[i]
coins[i]["name"]=i
coins[i]["estimate"]=data[i]["adjusted_estimate"]*float(coins[i]["speed"]) # factor in our speed
for i in data:
print(i+": "+str(data[i]["estimate_current"])+" "+str(data[i]["adjusted_estimate"]))
print("")
coins[i]["estimate"]=data[i]["estimate_current"]*float(coins[i]["speed"])-24.0*coins[i]["power"]*pwrcost/exchrate
# sort by profitability
sort={}
for i in coins:
print(i+": "+str(coins[i]["estimate"]))
sort[i]=coins[i]["estimate"]
sort=sorted(sort.items(), key=lambda x:x[1], reverse=True)
log=open("current-profit", "w")
for i in sort:
log.write(i[0]+": "+format(i[1], ".8f")+" BTC/day ("+format(i[1]*exchrate, ".2f")+" "+currency+"/day)\n")
log.close()
miner=coins[sort[0][0]]
if (len(sys.argv)==4):
# exit if maximum is below minimum
if (miner["estimate"]<min_profit):
algo_log=open("algo-log", "a")
algo_log.write(str(datetime.datetime.now())+": **NONE**\n")
algo_log.close()
for algo in coins:
subprocess.call(["pkill", "-f", "^"+coins[algo].replace("+", "\\+")])
sys.exit()
else: # manual override
if (sys.argv[4]!="list"):
miner=coins[sys.argv[4]]
else: # list available algos
print("algos: ", end="")
for i in coins:
print(i+" ", end="")
print("")
sys.exit()
# see if miner's already running
try:
subprocess.check_output(["pgrep", "-f", "^"+miner["bin"].replace("+", "\\+")])
current=True
except:
current=False
other=False;
if (current==False):
for algo in miners:
try:
subprocess.check_output(["pgrep", "-f", "^"+miners[algo]["bin"].replace("+", "\\+")])
other=True
except:
pass
if (current==False):
# log a change
algo_log=open("algo-log", "a")
algo_log.write(str(datetime.datetime.now())+": * ("+miner["algo"]+") "+format(miner["estimate"], ".8f")+" "+format(miner["estimate"]*exchrate, ".2f")+"\n")
algo_log.close()
# kill existing miners
for algo in miners:
subprocess.call(["pkill", "-f", "^"+miners[algo]["bin"].replace("+", "\\+")])
time.sleep(3)
if (card_type=="nvidia"): # update card settings
cards=int(subprocess.check_output("nvidia-smi --query-gpu=count --format=csv,noheader,nounits".split(" ")).decode("utf-8").split("\n")[-2])
for i in range(0, cards):
# power limit
if type(miner["power_limit"]) is int:
subprocess.call(("sudo nvidia-smi -i "+str(i)+" -pl "+str(miner["power_limit"])).split(" "))
else:
subprocess.call(("sudo nvidia-smi -i "+str(i)+" -pl "+str(miner["power_limit"][i])).split(" "))
# core overclock
if type(miner["gpu_oc"]) is int:
subprocess.call(("nvidia-settings -a [gpu:"+str(i)+"]/GPUGraphicsClockOffset[2]="+str(miner["gpu_oc"])).split(" "))
subprocess.call(("nvidia-settings -a [gpu:"+str(i)+"]/GPUGraphicsClockOffset[3]="+str(miner["gpu_oc"])).split(" "))
else:
subprocess.call(("nvidia-settings -a [gpu:"+str(i)+"]/GPUGraphicsClockOffset[2]="+str(miner["gpu_oc"][i])).split(" "))
subprocess.call(("nvidia-settings -a [gpu:"+str(i)+"]/GPUGraphicsClockOffset[3]="+str(miner["gpu_oc"][i])).split(" "))
# memory overclock
if type(miner["mem_oc"]) is int:
subprocess.call(("nvidia-settings -a [gpu:"+str(i)+"]/GPUMemoryTransferRateOffset[2]="+str(miner["mem_oc"])).split(" "))
subprocess.call(("nvidia-settings -a [gpu:"+str(i)+"]/GPUMemoryTransferRateOffset[3]="+str(miner["mem_oc"])).split(" "))
else:
subprocess.call(("nvidia-settings -a [gpu:"+str(i)+"]/GPUMemoryTransferRateOffset[2]="+str(miner["mem_oc"][i])).split(" "))
subprocess.call(("nvidia-settings -a [gpu:"+str(i)+"]/GPUMemoryTransferRateOffset[3]="+str(miner["mem_oc"][i])).split(" "))
# fan speed
if type(miner["fan"]) is int:
if (miner["fan"]==0):
subprocess.call(("nvidia-settings -a [gpu:"+str(i)+"]/GPUFanControlState=0").split(" "))
else:
subprocess.call(("nvidia-settings -a [gpu:"+str(i)+"]/GPUFanControlState=1").split(" "))
subprocess.call(("nvidia-settings -a [fan:"+str(i)+"]/GPUTargetFanSpeed="+str(miner["fan"])).split(" "))
else:
if (miner["fan"][i]==0):
subprocess.call(("nvidia-settings -a [gpu:"+str(i)+"]/GPUFanControlState=0").split(" "))
else:
subprocess.call(("nvidia-settings -a [gpu:"+str(i)+"]/GPUFanControlState=1").split(" "))
subprocess.call(("nvidia-settings -a [fan:"+str(i)+"]/GPUTargetFanSpeed="+str(miner["fan"][i])).split(" "))
# launch new miner
subprocess.call(("screen -dmS miner "+miner["bin"]).split(" "))