all this we check after initial period of n seconds after miner started - this to provide for initial tolerance
import subprocess
import threading
import sys
import re
import time
set this one for your miner
minerCommand = “cat sample_output”
change these optionally
setupTime = 15 # initially in when miner starts no action will be taken in setupTime seconds
expectedGpuHashRate = 15.0 # expected minimum S/s rate for each GPU
gpuHashRateTime = 30 # for each gpuHashRateTime time interval in seconds
gpuHashRateCount = 3 # if more than this num GPUs hash below expectedGpuHashRate script will terminate the miner
rejectedShareTime = 16 # for each time interval
rejectedShareCount = 4 # if more than this number of shares are rejected miner will be terminated
acceptedShareTime = 120 # for each time interval
acceptedShareCount = 1 # if less than this number of shares is accepted miner will be terminated
do not change these
setupCounter = 0
gpuHashRateCounter = 0
rejectedShareCounter = 0
acceptedShareCounter = 0
gpuHashRateDecrement = 0
rejectedShareDecrement = 0
acceptedShareDecrement = 0
def stdout_thread(pipe):
‘’’ proces stdout from miner ‘’’
global gpuHashRateCounter, rejectedShareCounter, acceptedShareCounter
cummulativeHashRate = {‘T’: 0.0}
avgHashSamples = 0
while True:
out = pipe.stdout.readline()
if len(out) == 0:
break
else:
sys.stdout.buffer.write(bytes('S{:2d} H{:3d} R{:3d} A{:3d} '.format(setupCounter, gpuHashRateCounter, \
rejectedShareCounter, acceptedShareCounter), 'utf-8'))
hr = list(str(x.group()).split() for x in re.finditer(b'(?<=zec-sa#)\d: \d+(\.\d+)', out))
hr = list(list(float(a.strip("'b:")) for a in b) for b in hr)
hr = [{'gpu': int(h[0]), 'S/s': h[1]} for h in hr]
hr.append({'gpu': 'T', 'S/s': sum(h['S/s'] for h in hr)})
if len(hr) > 1:
for r in hr:
if r['gpu'] not in cummulativeHashRate:
cummulativeHashRate[r['gpu']] = 0.0
if r['gpu'] != 'T':
cummulativeHashRate[r['gpu']] += r['S/s']
cummulativeHashRate['T'] += r['S/s']
if r['S/s'] < expectedGpuHashRate:
gpuHashRateCounter -= gpuHashRateDecrement
gpuHashRateCounter = max(gpuHashRateCounter, 0)
avgHashSamples += 1
for r in hr:
r['avg'] = cummulativeHashRate[r['gpu']] / avgHashSamples
hr = ', '.join(["g{} h{:5.1f} a{:5.1f}".format(r['gpu'], r['S/s'], r['avg']) for r in hr])
sys.stdout.buffer.write(bytes(hr, 'utf-8'))
hr = re.search(b'accepted', out)
if hr:
acceptedShareCounter += acceptedShareDecrement
acceptedShareCounter = min(acceptedShareCounter, acceptedShareTime)
hr = re.search(b'rejected', out)
if hr:
rejectedShareCounter -= rejectedShareDecrement
rejectedShareCounter = max(rejectedShareCounter, 0)
sys.stdout.buffer.write(bytes("\r", 'utf-8'))
sys.stdout.flush()
def stderr_thread(pipe):
‘’’ proces stderr from miner ‘’’
while True:
err = pipe.stderr.readline()
if len(err) == 0:
break
else:
sys.stdout.buffer.write(err)
sys.stdout.flush()
def time_thread():
‘’’ update Counters and check criteria for stopping the miner ‘’’
global setupCounter, gpuHashRateCounter, rejectedShareCounter, acceptedShareCounter
while True:
sys.stdout.buffer.write(bytes('S{:2d} H{:3d} R{:3d} A{:3d} \r'.format(setupCounter, gpuHashRateCounter, \
rejectedShareCounter, acceptedShareCounter), 'utf-8'))
setupCounter -= 1
setupCounter = max(setupCounter, 0)
gpuHashRateCounter += 1
gpuHashRateCounter = min(gpuHashRateCounter, gpuHashRateTime)
rejectedShareCounter += 1
rejectedShareCounter = min(rejectedShareCounter, rejectedShareTime)
acceptedShareCounter -= 1
acceptedShareCounter = max(acceptedShareCounter, 0)
if not (setupCounter or (gpuHashRateCounter and rejectedShareCounter and acceptedShareCounter)):
sys.stdout.buffer.write(bytes("\nFault found. Restarting.\n\n", 'utf-8'))
sys.stdout.flush()
break
sys.stdout.flush()
time.sleep(1)
def exec_command(command, cwd=None):
‘’’ start the miner ‘’’
global setupCounter, gpuHashRateCounter, rejectedShareCounter, acceptedShareCounter, gpuHashRateDecrement,
rejectedShareDecrement, acceptedShareDecrement
if cwd is not None:
print('[' + ' '.join(command) + '] in ' + cwd)
else:
print('[' + ' '.join(command) + ']')
setupCounter = setupTime
gpuHashRateCounter = gpuHashRateTime
rejectedShareCounter = rejectedShareTime
acceptedShareCounter = acceptedShareTime
gpuHashRateDecrement = int(gpuHashRateTime / gpuHashRateCount)
rejectedShareDecrement = int(rejectedShareTime / rejectedShareCount)
acceptedShareDecrement = int(acceptedShareTime / acceptedShareCount)
t_thread = threading.Thread(name='time_thread', target=time_thread)
process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=cwd)
out_thread = threading.Thread(name='stdout_thread', target=stdout_thread, args=(process,))
#err_thread = threading.Thread(name='stderr_thread', target=stderr_thread, args=(process,))
out_thread.start()
#err_thread.start()
t_thread.start()
t_thread.join()
#out_thread.join()
#err_thread.join() # let's not wait... if time thread finished then we're done
process.kill()
time.sleep(3) # wait for it
return 0
endless loop that starts the miner
while True:
exec_command(minerCommand.split())