def summary(ip):
    output = get_summary(ip)
    return jsonify(output)
    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)
예제 #3
0
def miners():
    # Init variables
    start = time.clock()
    miners = Miner.query.all()
    models = MinerModel.query.all()
    active_miners = []
    inactive_miners = []
    workers = {}
    miner_chips = {}
    temperatures = {}
    fans = {}
    hash_rates = {}
    hw_error_rates = {}
    uptimes = {}
    total_hash_rate_per_model = {
        "L3+": {
            "value": 0,
            "unit": "MH/s"
        },
        "S7": {
            "value": 0,
            "unit": "GH/s"
        },
        "S9": {
            "value": 0,
            "unit": "GH/s"
        },
        "D3": {
            "value": 0,
            "unit": "MH/s"
        },
        "T9": {
            "value": 0,
            "unit": "GH/s"
        },
        "T9+": {
            "value": 0,
            "unit": "GH/s"
        },
        "A3": {
            "value": 0,
            "unit": "GH/s"
        },
        "L3": {
            "value": 0,
            "unit": "MH/s"
        },
        "R4": {
            "value": 0,
            "unit": "TH/s"
        },
        "V9": {
            "value": 0,
            "unit": "GH/s"
        },
        "X3": {
            "value": 0,
            "unit": "KH/s"
        },
        "Z9 mini": {
            "value": 0,
            "unit": "KSol/s"
        },
        "E3": {
            "value": 0,
            "unit": "MH/s"
        },
    }

    errors = False
    miner_errors = {}

    for miner in miners:
        miner_stats = get_stats(miner.ip)
        # if miner not accessible
        if miner_stats['STATUS'][0]['STATUS'] == 'error':
            errors = True
            inactive_miners.append(miner)
        else:
            # Get worker name
            miner_pools = get_pools(miner.ip)
            active_pool = [
                pool for pool in miner_pools['POOLS'] if pool['Stratum Active']
            ]
            try:
                worker = active_pool[0]['User']
            except KeyError as k:
                worker = ""
            except ValueError as v:
                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(miner.model.chips).split(',')]
            total_chips = sum(chips_list)
            # Get the temperatures of the miner according to miner's model
            temps = [
                int(miner_stats['STATS'][1][temp])
                for temp in sorted(miner_stats['STATS'][1].keys(),
                                   key=lambda x: str(x))
                if re.search(miner.model.temp_keys + '[0-9]', temp)
                if miner_stats['STATS'][1][temp] != 0
            ]
            # Get fan speeds
            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:
                ghs5s = float(str(miner_stats['STATS'][1]['GHS 5s']))
            except ValueError as v:
                ghs5s = 0
            except KeyError as k:
                miner_summary = get_summary(miner.ip)
                ghs5s = float(str(miner_summary['SUMAMRY'][0]['GHS 5s']))
            # Get HW Errors
            try:
                hw_error_rate = miner_stats['STATS'][1]['Device Hardware%']
            except KeyError as k:
                # Probably the miner is an Antminer E3
                miner_summary = get_summary(miner.ip)
                hw_error_rate = miner_summary['SUMMARY'][0]['Device Hardware%']
            except ValueError as v:
                hw_error_rate = 0
            # Get uptime
            uptime = timedelta(seconds=miner_stats['STATS'][1]['Elapsed'])
            #
            workers.update({miner.ip: worker})
            miner_chips.update({
                miner.ip: {
                    'status': {
                        'Os': Os,
                        'Xs': Xs,
                        '-': _dash_chips
                    },
                    'total': total_chips,
                }
            })
            temperatures.update({miner.ip: temps})
            fans.update({miner.ip: {"speeds": fan_speeds}})
            value, unit = update_unit_and_value(
                ghs5s, total_hash_rate_per_model[miner.model.model]['unit'])
            hash_rates.update({miner.ip: "{:3.2f} {}".format(value, unit)})
            hw_error_rates.update({miner.ip: hw_error_rate})
            uptimes.update({miner.ip: uptime})
            total_hash_rate_per_model[miner.model.model]["value"] += ghs5s
            active_miners.append(miner)

            # Flash error messages
            if Xs > 0:
                error_message = ("[WARNING] '{}' chips are defective on "
                                 "miner '{}'.").format(Xs, miner.ip)
                current_app.logger.warning(error_message)
                flash(error_message, "warning")
                errors = True
                miner_errors.update({miner.ip: error_message})
            if Os + Xs < total_chips:
                error_message = (
                    "[ERROR] ASIC chips are missing from miner "
                    "'{}'. Your Antminer '{}' has '{}/{} chips'.").format(
                        miner.ip, miner.model.model, Os + Xs, total_chips)
                current_app.logger.error(error_message)
                flash(error_message, "error")
                errors = True
                miner_errors.update({miner.ip: 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(miner.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(miner.ip)
                # current_app.logger.error(error_message)
                # flash(error_message, "info")
                pass
            if temps:
                if max(temps) >= 80:
                    error_message = ("[WARNING] High temperatures on "
                                     "miner '{}'.").format(miner.ip)
                    current_app.logger.warning(error_message)
                    flash(error_message, "warning")
            if not temps:
                temperatures.update({miner.ip: 0})
                error_message = ("[ERROR] Could not retrieve temperatures "
                                 "from miner '{}'.").format(miner.ip)
                current_app.logger.warning(error_message)
                flash(error_message, "error")

    # Flash success/info message
    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")

    # 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,
        active_miners=active_miners,
        inactive_miners=inactive_miners,
        workers=workers,
        miner_chips=miner_chips,
        temperatures=temperatures,
        fans=fans,
        hash_rates=hash_rates,
        hw_error_rates=hw_error_rates,
        uptimes=uptimes,
        total_hash_rate_per_model=total_hash_rate_per_model_temp,
        loading_time=loading_time,
        miner_errors=miner_errors,
    )