def add_if_supported(ip, model_id): # check if the miner is supported by the software try: supported_miner = [id for id in MODELS.keys() if id == model_id][0] add_miner(ip, supported_miner, "") return True except IndexError as i: return False
def poll(self): miner_stats = get_stats(self.ip) # if miner not accessible if miner_stats['STATUS'][0]['STATUS'] == 'error': self.is_inactive = True self.errors.append(miner_stats['STATUS'][0]['description']) else: try: # Get worker name miner_pools = get_pools(self.ip) active_pool = [ pool for pool in miner_pools['POOLS'] if pool['Stratum Active'] ] except Exception as k: active_pool = [] try: self.worker = active_pool[0]['User'] except Exception as e: self.worker = "" # Get miner's ASIC chips asic_chains = [ miner_stats['STATS'][1][chain] for chain in miner_stats['STATS'][1].keys() if "chain_acs" in chain ] # count number of working chips o = [str(o).count('o') for o in asic_chains] Os = sum(o) # count number of defective chips X = [str(x).count('x') for x in asic_chains] C = [str(x).count('C') for x in asic_chains] B = [str(x).count('B') for x in asic_chains] Xs = sum(X) Bs = sum(B) Cs = sum(C) # get number of in-active chips _dash_chips = [str(x).count('-') for x in asic_chains] _dash_chips = sum(_dash_chips) # Get total number of chips according to miner's model # convert miner.model.chips to int list and sum chips_list = [ int(y) for y in str(MODELS.get(self.model_id).get('chips')).split(',') ] total_chips = sum(chips_list) self.chips.update({ 'Os': Os, 'Xs': Xs, '-': _dash_chips, 'total': total_chips }) # Get the temperatures of the miner according to miner's model self.temperatures = [ int(miner_stats['STATS'][1][temp]) for temp in sorted(miner_stats['STATS'][1].keys(), key=lambda x: str(x)) if re.search( MODELS.get(self.model_id).get('temp_keys') + '[0-9]', temp) if miner_stats['STATS'][1][temp] != 0 ] # Get fan speeds self.fan_speeds = [ miner_stats['STATS'][1][fan] for fan in sorted(miner_stats['STATS'][1].keys(), key=lambda x: str(x)) if re.search("fan" + '[0-9]', fan) if miner_stats['STATS'][1][fan] != 0 ] # Get GH/S 5s try: self.hash_rate_ghs5s = float( str(miner_stats['STATS'][1]['GHS 5s'])) except Exception as e: miner_summary = get_summary(self.ip) self.hash_rate_ghs5s = float( str(miner_summary['SUMMARY'][0]['GHS 5s'])) # Normalize hashrate new_value, new_unit = update_unit_and_value( self.hash_rate_ghs5s, MODELS[self.model_id]['unit']) self.normalized_hash_rate = "{:3.2f} {}".format( new_value, new_unit) # Get HW Errors try: # Probably the miner is an Antminer E3 or S17 miner_summary = get_summary(self.ip) self.hw_error_rate = miner_summary['SUMMARY'][0][ 'Device Hardware%'] except Exception as e: # self.hw_error_rate = miner_stats['STATS'][1]['Device Hardware%'] # this seems to work self.hw_error_rate = 0 # Get uptime self.uptime = str( timedelta(seconds=miner_stats['STATS'][1]['Elapsed'])) # Flash error messages if Xs > 0: error_message = ("[WARNING] '{}' chips are defective on " "miner '{}'.").format(Xs, self.ip) # current_app.logger.warning(error_message) # flash(error_message, "warning") self.warnings.append(error_message) if Os + Xs < total_chips: error_message = ( "[ERROR] ASIC chips are missing from miner " "'{}'. Your Antminer '{}' has '{}/{} chips'.").format( self.ip, self.model_id, Os + Xs, total_chips) # current_app.logger.error(error_message) # flash(error_message, "error") self.errors.append(error_message) if Bs > 0: # flash an info message. Probably the E3 is still warming up # error_message = ( # "[INFO] Miner '{}' is still warming up").format(self.ip) # current_app.logger.error(error_message) # flash(error_message, "info") pass if Cs > 0: # flask an info message. Probably the E3 is still warming up # error_message = ( # "[INFO] Miner '{}' is still warming up").format(self.ip) # current_app.logger.error(error_message) # flash(error_message, "info") pass if not self.temperatures: error_message = ("[ERROR] Could not retrieve temperatures " "from miner '{}'.").format(self.ip) # current_app.logger.warning(error_message) # flash(error_message, "error") self.errors.append(error_message) else: if max(self.temperatures) >= 80: error_message = ("[WARNING] High temperatures on " "miner '{}'.").format(self.ip) # current_app.logger.warning(error_message) # flash(error_message, "warning") self.warnings.append(error_message)
def miners(): # Init variables start = time.clock() miners = Miner.query.all() active_miners = [] inactive_miners = [] warnings = [] errors = [] total_hash_rate_per_model = {} miner_objects = [] # lookup table for total_hash_rate_per_model for id, miner in MODELS.items(): total_hash_rate_per_model[id] = {"value": 0, "unit": miner.get('unit')} # create miner objects to pass to executor.map for miner in miners: module = MODELS[miner.model_id]['model_module'] cls = MODELS[miner.model_id]['model_classname'] obj = getattr(sys.modules[module], cls)(miner) miner_objects.append(obj) # pass this method to executor.map to poll the miner def poll(obj): obj.poll() return obj # run with ThreadPoolExecutor with concurrent.futures.ThreadPoolExecutor( max_workers=NUM_THREADS) as executor: results = executor.map(poll, miner_objects) for miner in results: if miner is not None: if miner.is_inactive: inactive_miners.append(miner) else: active_miners.append(miner) for warning in miner.warnings: warnings.append(warning) for error in miner.errors: errors.append(error) total_hash_rate_per_model[ miner.model_id]["value"] += miner.hash_rate_ghs5s # Flash notifications if not miners: error_message = ("[INFO] No miners added yet. " "Please add miners using the above form.") current_app.logger.info(error_message) flash(error_message, "info") elif not errors: error_message = ("[INFO] All miners are operating normal. " "No errors found.") current_app.logger.info(error_message) flash(error_message, "info") for error in errors: current_app.logger.error(error) flash(error, "error") for warning in warnings: current_app.logger.error(warning) flash(warning, "warning") # flash("[INFO] Check chips on your miner", "info") # flash("[SUCCESS] Miner added successfully", "success") # flash("[WARNING] Check temperatures on your miner", "warning") # flash("[ERROR] Check board(s) on your miner", "error") # Convert the total_hash_rate_per_model into a data structure that the # template can consume. total_hash_rate_per_model_temp = {} for key in total_hash_rate_per_model: value, unit = update_unit_and_value( total_hash_rate_per_model[key]["value"], total_hash_rate_per_model[key]["unit"]) if value > 0: total_hash_rate_per_model_temp[key] = "{:3.2f} {}".format( value, unit) end = time.clock() loading_time = end - start return render_template( 'asicminer/home.html', version=current_app.config['__VERSION__'], models=MODELS, errors=errors, warnings=warnings, active_miners=active_miners, inactive_miners=inactive_miners, loading_time=loading_time, total_hash_rate_per_model=total_hash_rate_per_model_temp)
def miners(): # Init variables start = time.clock() miners = Miner.query.all() active_miners = [] inactive_miners = [] warnings = [] errors = [] total_hash_rate_per_model = {} for id, miner in MODELS.items(): total_hash_rate_per_model[id] = {"value": 0, "unit": miner.get('unit')} # running single threaded for miner in miners: antminer = ASIC_ANTMINER(miner) if antminer.is_inactive: inactive_miners.append(antminer) else: active_miners.append(antminer) for warning in antminer.warnings: warnings.append(warning) for error in antminer.errors: errors.append(error) total_hash_rate_per_model[ antminer.model_id]["value"] += antminer.hash_rate_ghs5s # Flash notifications if not miners: error_message = ("[INFO] No miners added yet. " "Please add miners using the above form.") current_app.logger.info(error_message) flash(error_message, "info") elif not errors: error_message = ("[INFO] All miners are operating normal. " "No errors found.") current_app.logger.info(error_message) flash(error_message, "info") for error in errors: current_app.logger.error(error) flash(error, "error") for warning in warnings: current_app.logger.error(warning) flash(warning, "warning") # flash("[INFO] Check chips on your miner", "info") # flash("[SUCCESS] Miner added successfully", "success") # flash("[WARNING] Check temperatures on your miner", "warning") # flash("[ERROR] Check board(s) on your miner", "error") # Convert the total_hash_rate_per_model into a data structure that the # template can consume. total_hash_rate_per_model_temp = {} for key in total_hash_rate_per_model: value, unit = update_unit_and_value( total_hash_rate_per_model[key]["value"], total_hash_rate_per_model[key]["unit"]) if value > 0: total_hash_rate_per_model_temp[key] = "{:3.2f} {}".format( value, unit) end = time.clock() loading_time = end - start return render_template( 'asicminer/home.html', MODELS=MODELS, active_miners=active_miners, inactive_miners=inactive_miners, loading_time=loading_time, total_hash_rate_per_model=total_hash_rate_per_model_temp)