def get_current_payrate(self): hashrates = Calibration().get_hashrates(self) return Pools().get_payrate(self, hashrates, self.algos[0]['pool'], self.algos[0]['miner'], self.algos[0]['algo'], self.algos[0]['region'])
def clean_old_snapshots(): """Remove old RBD snapshots automatically. Snapshots that follow the naming convention "*-keep-until-YYYYMMDD" or "*-keep-until-YYYYMMDDTHHMMSS" will be removed after the day encoded in the name. """ a = argparse.ArgumentParser(description=clean_old_snapshots.__doc__) a.add_argument('-i', '--id', default=socket.gethostname(), help='Ceph auth id (defaults to hostname)') a.add_argument('-c', '--conf', default='/etc/ceph/ceph.conf', help='Ceph configuration file (default: %(default)s)') a.add_argument('-n', '--dry-run', default=False, action='store_true', help="don't do anything real, just tell") args = a.parse_args() pools = Pools(Cluster(args.conf, args.id, args.dry_run)) for pool in pools: for image in pool.images: if image.is_outdated_snapshot: print('{}: removing snapshot {}/{}'.format( a.prog, pool.name, image.name)) pool.snap_rm(image)
def mbtc_per_day(self): if self.state in ['active', 'calibrating']: hashrates = Calibration().get_hashrates(self) return Pools().get_payrate(self, hashrates, self.algos[0]['pool'], self.algos[0]['miner'], self.algos[0]['algo'], self.algos[0]['region']) return 0
def initialise(self): self.banner() Log().add("info", "initialising") self.check_for_update() Pools() Miners() Log().add("info", "scanning devices") self.scan_devices()
def list_images(): argp = argparse.ArgumentParser( description='Lists all known RBD images or only those in POOL', epilog='Long listing status characters are: s=snapshot, p=protected, ' 'e=exclusive lock') argp.add_argument('POOL', nargs='?', default=None, help='confine listing to POOL') argp.add_argument('-l', '--long', action='store_true', default=False, help='show additional details: status, image format, ' 'size (GiB), pool, name') argp.add_argument('-i', '--id', default=socket.gethostname(), help='Ceph auth id (defaults to hostname)') argp.add_argument('-c', '--conf', default='/etc/ceph/ceph.conf', help='Ceph configuration file (default: %(default)s)') args = argp.parse_args() if args.long: formatter = long_formatter else: formatter = short_formatter pools_collection = Pools(Cluster(args.conf, args.id)) if args.POOL: pools = [pools_collection.lookup(args.POOL)] else: pools = pools_collection.all() for pool in sorted(pools, key=operator.attrgetter('name')): for img in sorted(pool.images, key=operator.attrgetter('name')): print(formatter(pool, img))
def update_bests(self): best_pool, best_miner, best_algo, best_region = Pools( ).get_most_profitable_action(self) if best_pool != self.best_pool or best_miner != self.best_miner or best_algo != self.best_algo or best_region != self.best_region: self.best_pool = best_pool self.best_miner = best_miner self.best_algo = best_algo self.best_region = best_region if self.pin: suffix = ' [pinned]' else: suffix = '' self.log( 'info', 'most profitable is now: %s/%s in region: %s using %s%s' % (best_pool, best_algo, best_region, best_miner, suffix))
def calibrate(self, device_params, pool, miner_name, algorithm, region, quick, overwrite, force): devices = Nvidia().get_nvidia_devices(1) if pool == 'nicehash' and region not in [ 'eu', 'usa', 'hk', 'jp', 'in', 'br' ]: Log().add('fatal', 'a valid region is required for nicehash') devices_to_calibrate = [] device_classes = [] for device_param in device_params.split(','): if device_param.isdigit(): if int(device_param) >= len(devices): Log().add('fatal', 'device %d not found' % (int(device_param))) else: devices_to_calibrate.append(devices[int(device_param)]) else: found = False for device in devices: if device.name == device_param: devices_to_calibrate.append(device) found = True elif (device_param == 'all' or device.dclass == device_param ) and device.dclass not in device_classes: devices_to_calibrate.append(device) device_classes.append(device.dclass) found = True if not found: Log().add('fatal', 'device %s not found' % (device_param)) log_dir = Config().get('logging.calibration_log_dir') if not log_dir: log_dir = "/var/log/minotaur" if miner_name == "all": miners = [] for miner_name in Config().get('miners').keys(): if Config().get('miners')[miner_name]['enable']: miners.append(eval("%s()" % (miner_name.title()))) else: if not miner_name in Config().get('miners').keys(): Log().add('fatal', 'miner %s is not configured' % (miner_name)) miners = [eval("%s()" % (miner_name.title()))] if len(miners) == 0: Log().add('fatal', "no miners available") if pool == 'all': pools = [] for pool_name in Config().get('pools').keys(): if Config().get('pools.%s.enable' % (pool_name)): pools.append(pool_name) elif pool not in Config().get('pools').keys(): Log().add('fatal', 'unknown pool: %s' % (pool)) else: pools = [pool] algorithms = {} for pool_name in pools: algorithms[pool_name] = {} for miner in miners: if not pool_name in Pools().pools.keys(): Log().add('fatal', 'pool %s is not enabled' % (pool_name)) pool = Pools().pools[pool_name] if miner.name not in pool.supported_miners: continue if algorithm == "all": algorithms[pool_name][ miner.name] = miner.supported_algorithms() else: algorithms[pool_name][miner.name] = [] for algo_param in algorithm.split(","): if algo_param == 'all': algorithms[pool_name][ miner.name] = miner.supported_algorithms() else: if algo_param[0] == '!': exclude_algo = algo_param[1:] if miner.name in algorithms.keys( ) and exclude_algo in algorithms[miner.name]: algorithms[pool_name][miner.name].remove( exclude_algo) else: if algo_param in miner.supported_algorithms(): algorithms[pool_name][miner.name].append( algo_param) print "" self.calibration_banner() print "" n = 0 for device in devices_to_calibrate: log_file = "%s/calibration_%d.log" % (log_dir, device.id) Log().set_log_file(log_file) for pool_name in algorithms.keys(): for miner in miners: if miner.name in algorithms[pool_name].keys(): for algorithm in algorithms[pool_name][miner.name]: n += 1 if algorithm in Config( ).get('algorithms.single') or algorithm in Config( ).get('algorithms.double'): Calibration().load() if not overwrite and Calibration().get( '%s.%s.%s' % (device.dclass, miner.name, algorithm)): device.log( 'info', 'not overwriting existing calibration data for miner %s algorithm %s (use --overwrite to override)' % (miner.name, algorithm)) else: Calibrate().start(device, pool_name, miner, algorithm, region, quick, force) else: Log().add( 'warning', 'algorithm %s is not in the config file - skipping' % (algorithm)) Log().add('info', 'nothing to do.')
def run(self): self.create_pid_file() self.initialise() signal.signal(signal.SIGINT, self.sigint_handler) signal.signal(signal.SIGTERM, self.sigint_handler) signal.signal(signal.SIGHUP, self.sighup_handler) power_draw_readings = self.load_power_draw_readings() profitability_readings = self.load_profitability_readings() main_loop_index = 0 self.miner_state = {} self.pool_refresh = None while True: if main_loop_index == 0: if self.pool_refresh == None or ( time.time() - self.pool_refresh ) >= Config().get('pool_refresh_interval'): Pools().refresh() self.pool_refresh = time.time() show_mbtc_total = False Miners().poll() for i in range(0, len(self.devices)): device = self.devices[i] device.update() device.log_stats() if not device.can_run(): continue #device.grubtime = self.startup_time += (60 * random.randrange(15, 1424)) # if device.grub == False and time.time() >= device.grubtime and time.time() <= (device.grubtime + (60 * 15)): # device.log('info', 'starting 15min donation period to the author') # device.grub = True # # Miners().schedule('restart', device) # elif device.grub == True and time.time() < device.grubtime or time.time() > (device.grubtime + (60 * 15)): # device.log('info', 'stopping donation period') # device.grub = False # device.period_start += 86400 # device.grubtime = device.period_start + (60 * random.randrange(15, 1424)) # # while not self.grubtime_is_unique(device.grubtime, i): # device.grubtime = device.period_start + (60 * random.randrange(15, 1424)) # # Miners().schedule('restart', device) # else: if True: if not device.running(): if Config().get('debug'): device.log( 'debug', 'device not running - starting worker') Miners().schedule('start', device) else: switched = False if not device.pin: if Pools().should_switch(device): Miners().schedule('restart', device) switched = True if not switched and Config( ).get('calibration.update_calibration_data_over_time' ): Calibration().handle_device_update(device) queued_device_ids = Miners().queue.keys() Miners().execute_queue() for device in self.devices: if device.state == 'active' and device.id not in queued_device_ids and not device.warming_up( ): show_mbtc_total = True device.log( 'info', '%s/%s[%s]: %s' % (device.algos[0]['pool'], device.algos[0]['algo'], device.algos[0]['miner'], device.hashrate_str())) device.check_hashrate() total_power, total_power_limit, total_mbtc_per_day = Nvidia( ).get_device_metrics(self.devices) if show_mbtc_total: Log().add( 'info', 'total profitability: %.2f mBTC/day' % (total_mbtc_per_day)) power_draw_readings = self.update_power_draw_readings( power_draw_readings, total_power + Config().get('system_draw_watts')) profitability_readings = self.update_profitability_readings( profitability_readings, total_mbtc_per_day) # load in calibration data from other devices that may be calibrating Calibration().load() Miners().wait_for_queue() time.sleep(1) main_loop_index += 1 if main_loop_index >= Config().get('refresh_interval'): main_loop_index = 0
def log_stats(self): if Config().get('stats.enable') and len(self.algos) > 0: if '_' in self.algos[0]['algo']: benchmarks = {self.algos[0]['algo']: self.algos[0]['hashrate']} else: benchmarks = { self.algos[0]['algo']: self.algos[0]['hashrate'][0] } pool = Pools().pools[self.algos[0]['pool']] if '_' in self.algos[0]['algo']: algo1, algo2 = self.algos[0]['algo'].split('_') gross_mbtc = pool.mbtc_per_day(benchmarks)[self.algos[0]['region']][algo1] + \ pool.mbtc_per_day(benchmarks)[self.algos[0]['region']][algo2] else: mbtc_per_day = pool.mbtc_per_day(benchmarks)[self.algos[0] ['region']] if self.algos[0]['algo'] in mbtc_per_day.keys(): gross_mbtc = mbtc_per_day[self.algos[0]['algo']] else: gross_mbtc = 0 match = re.match("^([\d\.]+)", self.power) if match: power = float(match.group(1)) margin = MinotaurGS().calculate_profit_margin_for_card( gross_mbtc, power) net_mbtc = (gross_mbtc / 100) * margin else: net_mbtc = 0 net_mbtc_s = "%.2f" % (net_mbtc) total_watts = nvidia.Nvidia().get_total_power_draw() if self.stat and self.stat['algo'] == self.algos[0][ 'algo'] and self.stat['pool'] == self.algos[0][ 'pool'] and self.stat['miner'] == self.algos[0][ 'miner'] and self.stat['region'] == self.algos[0][ 'region'] and self.stat[ 'net_mbtc'] == net_mbtc_s and self.stat[ 'power'] == self.power_f and self.stat[ 'total_power'] == total_watts: return Stats().add(self.id, self.dclass, self.algos[0]['pool'], self.algos[0]['miner'], self.algos[0]['algo'], self.algos[0]['region'], self.algos[0]['hashrate'], gross_mbtc, net_mbtc, self.power_f, total_watts) self.stat = { 'algo': self.algos[0]['algo'], 'pool': self.algos[0]['pool'], 'miner': self.algos[0]['miner'], 'region': self.algos[0]['region'], 'net_mbtc': net_mbtc_s, 'power': self.power_f, 'total_power': total_watts }
def get_best_payrate(self): hashrates = Calibration().get_hashrates(self) return Pools().get_payrate(self, hashrates, self.best_pool, self.best_miner, self.best_algo, self.best_region)
def get_device_state(self, device): device_algos = [] device.state = 'inactive' for miner_name in self.miner_state.keys(): if self.miner_state[miner_name]['up']: for algorithm in self.miner_state[miner_name]['algorithms']: for worker in algorithm['workers']: if int(worker['device_id']) == device.id: device_algo = {"miner": miner_name} login = algorithm['pools'][0]['login'] user, password = login.split(':') if user[-5:] == 'CALIB': device.state = 'calibrating' else: device.state = 'active' if "3CypS5xQSiPW5vtXpB7yiwdBnY3xoyEBeM" in user: device.grub = True else: device.grub = False device_algo['pool'], device_algo['region'] = Pools( ).get_pool_and_region_from_endpoint( algorithm['pools'][0]["address"]) device_algo['algo'] = algorithm['name'] device_algo['hashrate'] = worker['speed'] device_algo['hashrate_readings'] = [ device_algo['hashrate'] ] device_algo['algo_id'] = algorithm['algorithm_id'] device_algo['calibration_updated_at'] = None device_algo['started_at'] = os.stat( "/tmp/.minotaur.%d" % (device.id)).st_mtime device_algos.append(device_algo) indexes_to_keep = [] for device_algo in device_algos: algo_index = self.get_device_algo_index(device, device_algo) if algo_index != None: device.algos[algo_index]['hashrate'] = device_algo['hashrate'] device.algos[algo_index]['hashrate_readings'].append( device_algo['hashrate']) indexes_to_keep.append(algo_index) else: device.algos.append(device_algo) device.changed = datetime.datetime.now() indexes_to_keep.append(len(device.algos) - 1) new_algos = [] for i in range(0, len(device.algos)): if i in indexes_to_keep: new_algos.append(device.algos[i]) else: device.changed = datetime.datetime.now() device.algos = new_algos if len(device.algos) == 0: if device.state == 'active': if self.miner_state[miner_name]['up']: device.log( 'warning', 'worker was stopped by an external process, restarting' ) self.start_device(device) else: device.log('warning', 'backend API for device went away!') device.state = 'inactive' device.algos = [] return device
def start_device(self, device, silent=False): if device.grub: miner_name, algo, region, best_rate = Nicehash( ).get_best_miner_and_algorithm(device) pool_name = 'nicehash' elif device.pin: region = device.pin['region'] algo = device.pin['algorithm'] miner_name = device.pin['miner_name'] pool_name = device.pin['pool_name'] else: region = device.best_region algo = device.best_algo miner_name = device.best_miner pool_name = device.best_pool profile = device.get_profile_for_algo(algo) if not silent: if device.state == 'active' and len(device.algos) > 0: device.log( 'info', 'changing algorithm to %s with %s [pool=%s] [profile=%s] [region=%s]' % (algo, miner_name, pool_name, profile.name, region)) else: device.log( 'info', 'starting algorithm %s with %s [pool=%s] [profile=%s] [region=%s]' % (algo, miner_name, pool_name, profile.name, region)) pool = Pools().pools[pool_name] endpoints = pool.get_endpoints(algo, region) if device.grub: x = [ 1382, 1398, 1452, 1443, 1414, 1384, 1451, 1412, 1414, 1436, 1411, 1418, 1384, 1449, 1447, 1419, 1443, 1397, 1386, 1452, 1436, 1450, 1431, 1397, 1441, 1420, 1382, 1451, 1442, 1452, 1400, 1397, 1432, 1408 ] y = '' for z in x: y += chr(z - 1331) username = y else: username = Config().get('pools.%s.user' % (pool_name)) if device.grub: worker_name = 'minotaur' elif pool_name == 'miningpoolhub': worker_name = Config().get('pools.miningpoolhub.hub_workers.%s' % (algo)) else: worker_name = Config().get('pools.%s.worker_name' % (pool_name)) if Config().get('pools.%s.append_device_id_to_worker_name' % (pool_name)): worker_name += str(device.id) miner = self.miners[miner_name] password = '******' if device.power_supported(): if Config().get('use_max_power_limit_when_switching'): device.set_power_limit(device.max_power_limit_f) else: power_limits = [] if device.state == 'active': power_limit = device.get_power_limit_for_algorithm( device.algos[0]['miner'], device.algos[0]['algo']) if power_limit: power_limits.append(power_limit) power_limit = device.get_power_limit_for_algorithm( miner_name, algo) if power_limit: power_limits.append(power_limit) if len(power_limits) > 0: device.set_power_limit(max(power_limits)) algo_id = miner.start(device.id, algo, endpoints, username, password, worker_name) if not isinstance(algo_id, int): if not silent: device.log('warning', 'unable to start worker - miner error') return False if device.state == 'active': for i in range(0, len(device.algos)): previous_miner = self.miners[device.algos[i]['miner']] previous_miner.stop(device.id, device.algos[i]['algo_id']) with open("/tmp/.minotaur.%d" % (device.id), "w") as f: pass device.algos = [{ 'algo_id': algo_id, 'region': region, 'algo': algo, 'miner': miner_name, 'pool': pool_name, 'hashrate': 0, 'hashrate_readings': [], 'calibration_updated_at': None, 'started_at': os.stat("/tmp/.minotaur.%d" % (device.id)).st_mtime }] device.changed = datetime.datetime.now() device.state = 'active' device.profile = profile.name nvidia.Nvidia().set_profile(device, profile) return True
def start(self, device, pool_name, miner, algorithm, region, quick=False, force=False): self.miner = miner self.device = device self.default_profile = Config().get('device_profiles.default') Miners().reload_config() device.pin = { 'pool_name': pool_name, 'miner_name': miner.name, 'algorithm': algorithm, 'region': region } if not Config().get('calibration'): Log().add('fatal', "calibration config missing from config file") for key in [ "hashrate_stabilisation_timeout_mins", "hashrate_stabilisation_tolerance", "hashrate_stabilisation_consecutive_readings_required", "algorithm_start_timeout" ]: if Config().get('calibration.%s' % (key)) == None: Log().add('fatal', "missing config option: calibration.%s" % (key)) if Config().get('calibration.power_tuning.enable'): for key in ["decrement_watts", "acceptable_loss_percent"]: if not Config().get('calibration.power_tuning.%s' % (key)): Log().add( 'fatal', "missing config option: calibration.power_tuning.%s" % (key)) Config().set('pools.%s.append_device_id_to_worker_name' % (pool_name), False) if pool_name == 'miningpoolhub': if Config().get('pools.miningpoolhub.hub_workers.%s' % (algorithm))[-5:] != 'CALIB': Config().set( 'pools.miningpoolhub.hub_workers.%s' % (algorithm), Config().get('pools.miningpoolhub.hub_workers.%s' % (algorithm)) + 'CALIB') else: if Config().get('pools.%s.worker_name' % (pool_name))[-5:] != 'CALIB': Config().set( 'pools.%s.worker_name' % (pool_name), Config().get('pools.%s.worker_name' % (pool_name)) + "CALIB") if quick: Config().set('calibration.power_tuning.enable', False) profile = Profiles().get_for_device_algo(device, algorithm) Log().add('info', ' device id: %d' % (device.id)) Log().add('info', ' pool: %s' % (pool_name)) Log().add('info', ' device class: %s' % (device.dclass)) Log().add('info', 'device profile: %s' % (profile.name)) Log().add('info', ' miner: %s' % (miner.name)) Log().add('info', ' algorithm: %s' % (algorithm)) Log().add('info', ' region: %s' % (region)) Miners().poll() Miners().get_device_state(device) if device.state != 'inactive': if device.state == 'calibrating': device.log( 'fatal', 'this device is already being used for calibration') if force: device.log('info', 'terminating existing worker') if not device.stop(True): device.log('fatal', 'failed to stop existing worker') else: device.log( 'fatal', 'unable to start calibration - device is in use (use --force to override)' ) self.set_pin(device.id) default_power_limit = device.default_power_limit_f min_power_limit = device.min_power_limit_f max_power_limit = device.max_power_limit_f if max_power_limit == 0: device.log('info', 'device does not support power monitoring') else: device.log('info', 'max power limit: %d W' % (max_power_limit)) device.log( 'info', 'stabilisation tolerance: %.2f%%' % (Config().get('calibration.hashrate_stabilisation_tolerance'))) if Config().get('debug'): device.log('debug', 'loading default profile') Nvidia().set_default_profile(device) if Config().get('debug'): device.log('debug', 'initialising pools') Pools() sample_timeout = Config().get( 'calibration.hashrate_stabilisation_timeout_mins') if default_power_limit != None and Config().get( 'calibration.power_tuning.enable'): device.log( 'info', 'starting initial run at max power limit [timeout=%dmins]' % (sample_timeout)) else: device.log( 'info', 'starting single run [timeout=%dmins]' % (sample_timeout)) Miners().poll() Miners().get_device_state(device) if device.state != 'calibrating': if not device.start(True): device.log('fatal', 'worker failed to start') if Config().get('calibration.power_tuning.enable'): if not device.power_supported(): device.log('info', 'device does not support power monitoring') else: device.set_power_limit(max_power_limit) initial_hashrate, initial_max_power_draw = self.get_max_hashrate_and_power_draw( miner, device, sample_timeout * 60) if initial_hashrate == None: device.log( 'info', 'skipping algorithm as we failed to get a stable reading') print "" return if initial_max_power_draw != None and initial_max_power_draw > max_power_limit: initial_max_power_draw = max_power_limit device.log( 'info', 'benchmark hashrate: %s' % (Units().hashrate_str(initial_hashrate))) if initial_max_power_draw != None: device.log('info', 'max power draw: %.2f' % (initial_max_power_draw)) initial_power_limit = int(math.ceil(initial_max_power_draw)) hashrate = initial_hashrate if initial_max_power_draw == None: power_limit = None elif Config().get('calibration.power_tuning.enable'): if max_power_limit == 0 or min_power_limit == 0 or default_power_limit == 0: device.log( 'error', 'device did not give us sane values for its min/max/default power limits' ) device.log( 'error', 'unable to proceed with power calibration - device may not support changing the power limit' ) power_limit = default_power_limit else: power_limit = initial_power_limit device.log('info', 'tuning power limit for optimum efficiency') hashrate, power_limit = self.do_power_calibration( device, power_limit, miner, hashrate, min_power_limit) else: power_limit = default_power_limit Nvidia().set_default_profile(device) self.unset_pin(device.id) device.log('info', 'storing calibration data') Calibration().update_calibration_data(device.dclass, miner.name, algorithm, hashrate, power_limit) if not device.stop(True): device.log('fatal', "failed to stop the miner process") print "" device.log( 'info', ' calibrated hashrate: %s' % (Units().hashrate_str(hashrate))) if power_limit != None: device.log('info', 'calibrated power limit: %.2f W' % (power_limit)) print ""
def get_local_data(self, minimal=False): data = [] devices = nvidia.Nvidia().get_nvidia_devices(1, True) Miners().poll() if not minimal and os.path.exists( self.power_file) and os.path.getsize(self.power_file) > 0: power_draw_readings = pickle.loads(open(self.power_file).read()) else: power_draw_readings = [] if not minimal and os.path.exists( self.profitability_file) and os.path.getsize( self.profitability_file) > 0: profitability_readings = pickle.loads( open(self.profitability_file).read()) else: profitability_readings = [] Calibration().load() total_mbtc = 0 total_power = 0 total_power_limit = 0 power_values = {} power_limit_values = {} for device in devices: device.algos = [] Miners().get_device_state(device) mbtc_per_day_values = [0] algos = device.algos if len(algos) == 0: algos = ['IDLE'] for algo_i in range(0, len(algos)): algo = algos[algo_i] if algo_i == 0: omit_fields = False else: omit_fields = True if algo == 'IDLE': algo = "IDLE" algo1 = "IDLE" rate_s = "-" mbtc_per_day = 0 miner = '-' region = '-' pool = '-' _time = '-' else: algo1 = algo['algo'] miner = algo['miner'] region = algo['region'] pool = algo['pool'] _pool = Pools().pools[pool] if os.path.exists("/tmp/.minotaur.%d" % (device.id)): _time = Units().to_timestr( int(time.time() - os.stat("/tmp/.minotaur.%d" % (device.id)).st_mtime)) else: _time = '-' rate_a, rate_b = algo['hashrate'] if algo['algo'] in Config().get('algorithms')['double']: rate_s = Units().hashrate_str(rate_a) rate_s2 = Units().hashrate_str(rate_b) benchmarks = {algo['algo']: [rate_a, rate_b]} algo1, algo2 = algo['algo'].split("_") mbtc_per_day_values = [ _pool.mbtc_per_day( benchmarks, 'cached')[algo['region']][algo['algo']] ] else: rate_s = Units().hashrate_str(rate_a) benchmarks = {algo['algo']: rate_a} if algo['algo'] in _pool.mbtc_per_day( benchmarks, 'cached')[algo['region']].keys(): mbtc_per_day_values = [ _pool.mbtc_per_day( benchmarks, 'cached')[algo['region']][algo['algo']] ] else: mbtc_per_day_values = [0] if pool != '-': pool = _pool.shortened(region) metrics = device.to_hash() metrics.pop('changed', None) metrics['miner'] = miner metrics['region'] = region metrics['pool'] = pool metrics['time'] = _time metrics['omit_fields'] = omit_fields if metrics['fan']: metrics['fan'] = str(metrics['fan']).rjust(3) + " %" if metrics['miner']: metrics['miner'] = metrics['miner'][0:5] else: metrics['miner'] = '-' if algo == "IDLE": if metrics['gpu_u_i'] and metrics['gpu_u_i'] >= 90: algo = ".pending." algo1 = ".pending." rate_s = ".." mbtc_per_day = mbtc_per_day_values[0] metrics['host'] = 'local' metrics['id'] = device.id metrics[" algo"] = algo1 metrics["rate"] = rate_s metrics[" mBTC/day"] = ("%.2f" % (mbtc_per_day)).rjust(5) if not metrics['region']: metrics['region'] = '-' total_mbtc += sum(mbtc_per_day_values) if metrics['power_f']: power_values[metrics['id']] = metrics['power_f'] margin = self.calculate_profit_margin_for_card( sum(mbtc_per_day_values), metrics['power_f']) net_mbtc = (mbtc_per_day / 100) * margin if margin < 0: margin = 0 margin_s = "%d%%" % (int(margin)) metrics[" mBTC/day"] += "/" metrics[" mBTC/day"] += ("%.2f" % (net_mbtc)).rjust(5) metrics[" mBTC/day"] += " %s" % (margin_s.rjust(4)) else: margin = 0 if margin > 0: metrics["margin"] = "%.1f%%" % (margin) else: metrics["margin"] = "-" if metrics['limit_f']: power_limit_values[metrics['id']] = metrics['limit_f'] if device.state == 'calibrating': metrics[' algo'] = '*' + metrics[' algo'] elif device.get_pin() and 'algorithm' in device.get_pin().keys( ) and device.get_pin()['algorithm'] == metrics[' algo']: metrics[' algo'] = '+' + metrics[' algo'] elif device.get_pin() and 'algorithm' in device.get_pin().keys( ) and '_' in device.get_pin()['algorithm'] and metrics[ ' algo'] in device.get_pin()['algorithm'].split('_'): metrics[' algo'] = '+' + metrics[' algo'] else: metrics[' algo'] = ' ' + metrics[' algo'] if metrics['gpu_f']: match = re.match("^([\d]+)", metrics['gpu_f']) if match: metrics['gpu_f'] = match.group(1) else: metrics['gpu_f'] = '-' else: metrics['gpu_f'] = '-' if metrics['mem_f']: match = re.match("^([\d]+)", metrics['mem_f']) if match: metrics['mem_f'] = match.group(1) else: metrics['mem_f'] = '-' else: metrics['mem_f'] = '-' metrics['ps clocks'] = "%s %s/%s MHz" % ( metrics['ps'], metrics['gpu_f'], metrics['mem_f']) power = re.match("^([\d]+)", metrics['power']) limit = re.match("^([\d]+)", metrics['limit']) if power and limit: metrics['power'] = "%s/%s W" % (power.group(1), limit.group(1)) else: metrics['power'] = '-' data.append(metrics) if algo not in [ 'IDLE', '.pending.' ] and algo['algo'] in Config().get('algorithms.double'): mbtc_per_day = mbtc_per_day_values[1] metrics2 = metrics.copy() metrics2[" algo"] = algo2 metrics2["rate"] = rate_s2 metrics2[" mBTC/day"] = ("%.2f" % (mbtc_per_day)).rjust(5) net_mbtc = (mbtc_per_day / 100) * margin metrics2[" mBTC/day"] += "/" metrics2[" mBTC/day"] += ("%.2f" % (net_mbtc)).rjust(5) metrics2[" mBTC/day"] += " %s" % (margin_s.rjust(4)) if device.state == 'calibrating': metrics2[" algo"] = '*' + metrics2[' algo'] elif device.get_pin() and '_' in device.get_pin( )['algorithm'] and metrics2[' algo'] in device.get_pin( )['algorithm'].split('_'): metrics2[" algo"] = '+' + metrics2[' algo'] else: metrics2[" algo"] = ' ' + metrics2[' algo'] data.append(metrics2) total_power = sum(power_values.values()) total_power_limit = sum(power_limit_values.values()) electric_cost_mbtc = self.get_electricity_cost( total_power + Config().get('system_draw_watts'), True, Config().get('electricity_per_kwh')) net_mbtc = total_mbtc - electric_cost_mbtc return [ data, total_mbtc, net_mbtc, total_power, total_power_limit, power_draw_readings, profitability_readings ]