fixed more bugs with avalonminers

This commit is contained in:
UpstreamData
2022-01-10 13:48:25 -07:00
parent 2610d642fa
commit 01a64e63c6
7 changed files with 106 additions and 75 deletions

View File

@@ -62,7 +62,7 @@ class BaseMinerAPI:
commands = [command for command in user_commands if command in allowed_commands]
for item in list(set(user_commands) - set(commands)):
warnings.warn(f"""Removing incorrect command: {item}
If you are sure you want to use this command please use API.send_command("{item}") instead.""",
If you are sure you want to use this command please use API.send_command("{item}", ignore_errors=True) instead.""",
APIWarning)
# standard multicommand format is "command1+command2"
# doesnt work for S19 which is dealt with in the send command function
@@ -84,7 +84,7 @@ If you are sure you want to use this command please use API.send_command("{item}
if data:
return data
async def send_command(self, command: str, parameters: str or int or bool = None) -> dict:
async def send_command(self, command: str, parameters: str or int or bool = None, ignore_errors: bool = False) -> dict:
"""Send an API command to the miner and return the result."""
try:
# get reader and writer streams
@@ -123,6 +123,8 @@ If you are sure you want to use this command please use API.send_command("{item}
writer.close()
await writer.wait_closed()
# check for if the user wants to allow errors to return
if not ignore_errors:
# validate the command succeeded
validation = self.validate_command_output(data)
if not validation[0]:

View File

@@ -267,20 +267,35 @@ async def scan_and_get_data(network):
async def get_formatted_data(ip: ipaddress.ip_address):
miner = await miner_factory.get_miner(ip)
warnings.filterwarnings('ignore')
miner_data = None
host = await miner.get_hostname()
model = await miner.get_model()
if not model:
model = "Error"
temps = 0
th5s = 0
wattage = 0
user = "?"
try:
miner_data = await miner.api.multicommand("summary", "devs", "temps", "tunerstatus", "pools", "stats")
except APIError:
try:
# no devs command, it will fail in this case
miner_data = await miner.api.multicommand("summary", "temps", "tunerstatus", "pools", "stats")
print(miner_data)
except APIError:
return {'TH/s': 0, 'IP': str(miner.ip), 'model': 'Unknown', 'temp': 0, 'host': 'Unknown', 'user': 'Unknown',
'wattage': 0}
host = await miner.get_hostname()
model = await miner.get_model()
temps = 0
if miner_data:
# get all data from summary
if "summary" in miner_data.keys():
if not miner_data["summary"][0].get("SUMMARY") == []:
# temperature data, this is the idea spot to get this
if "Temperature" in miner_data['summary'][0]['SUMMARY'][0].keys():
if not round(miner_data['summary'][0]['SUMMARY'][0]["Temperature"]) == 0:
temps = miner_data['summary'][0]['SUMMARY'][0]["Temperature"]
# hashrate data, this is the only place to get this for most miners as far as I know
if 'MHS av' in miner_data['summary'][0]['SUMMARY'][0].keys():
th5s = round(await safe_parse_api_data(miner_data, 'summary', 0, 'SUMMARY', 0, 'MHS av') / 1000000, 2)
elif 'GHS av' in miner_data['summary'][0]['SUMMARY'][0].keys():
@@ -288,28 +303,29 @@ async def get_formatted_data(ip: ipaddress.ip_address):
th5s = round(
float(await safe_parse_api_data(miner_data, 'summary', 0, 'SUMMARY', 0, 'GHS av')) / 1000,
2)
else:
th5s = 0
else:
th5s = 0
else:
th5s = 0
if "temps" in miner_data.keys() and not miner_data["temps"][0]['TEMPS'] == []:
# alternate temperature data, for BraiinsOS
if "temps" in miner_data.keys():
if not miner_data["temps"][0]['TEMPS'] == []:
if "Chip" in miner_data["temps"][0]['TEMPS'][0].keys():
for board in miner_data["temps"][0]['TEMPS']:
if board["Chip"] is not None and not board["Chip"] == 0.0:
temps = board["Chip"]
if "devs" in miner_data.keys() and not miner_data["devs"][0]['DEVS'] == []:
# alternate temperature data, for Whatsminers
if "devs" in miner_data.keys():
if not miner_data["devs"][0].get('DEVS') == []:
if "Chip Temp Avg" in miner_data["devs"][0]['DEVS'][0].keys():
for board in miner_data["devs"][0]['DEVS']:
if board['Chip Temp Avg'] is not None and not board['Chip Temp Avg'] == 0.0:
temps = board['Chip Temp Avg']
if "stats" in miner_data.keys() and not miner_data["stats"][0]['STATS'] == []:
# alternate temperature data
if "stats" in miner_data.keys():
if not miner_data["stats"][0]['STATS'] == []:
for temp in ["temp2", "temp1", "temp3"]:
if temp in miner_data["stats"][0]['STATS'][1].keys():
if miner_data["stats"][0]['STATS'][1][temp] is not None and not miner_data["stats"][0]['STATS'][1][
temp] == 0.0:
if miner_data["stats"][0]['STATS'][1][temp] is not None and not miner_data["stats"][0]['STATS'][1][temp] == 0.0:
temps = miner_data["stats"][0]['STATS'][1][temp]
# alternate temperature data, for Avalonminers
miner_data["stats"][0]['STATS'][0].keys()
if any("MM ID" in string for string in miner_data["stats"][0]['STATS'][0].keys()):
temp_all = []
@@ -319,25 +335,20 @@ async def get_formatted_data(ip: ipaddress.ip_address):
temp_all.append(int(value.split("[")[1].replace("]", "")))
temps = round(sum(temp_all) / len(temp_all))
if "pools" not in miner_data.keys():
user = "?"
elif not miner_data['pools'][0]['POOLS'] == []:
# pool information
if "pools" in miner_data.keys():
if not miner_data['pools'][0].get('POOLS') == []:
user = await safe_parse_api_data(miner_data, 'pools', 0, 'POOLS', 0, 'User')
else:
print(miner_data['pools'][0])
user = "Blank"
# braiins tuner status / wattage
if "tunerstatus" in miner_data.keys():
wattage = await safe_parse_api_data(miner_data, "tunerstatus", 0, 'TUNERSTATUS', 0, "PowerLimit")
elif "Power" in miner_data["summary"][0]["SUMMARY"][0].keys():
wattage = await safe_parse_api_data(miner_data, "summary", 0, 'SUMMARY', 0, "Power")
else:
wattage = 0
else:
th5s = 0
user = "Unknown"
wattage = 0
if not model:
model = "Error"
return {'TH/s': th5s, 'IP': str(miner.ip), 'model': model,
'temp': round(temps), 'host': host, 'user': user,
'wattage': wattage}

View File

@@ -1,7 +1,7 @@
from miners.bosminer import BOSminer
from miners.bosminer import BOSMiner
class BOSMinerS9(BOSminer):
class BOSMinerS9(BOSMiner):
def __init__(self, ip: str) -> None:
super().__init__(ip)
self.model = "S9"

View File

@@ -1,7 +1,7 @@
from miners.bosminer import BOSminer
from miners.bosminer import BOSMiner
class BOSMinerX17(BOSminer):
class BOSMinerX17(BOSMiner):
def __init__(self, ip: str) -> None:
super().__init__(ip)
self.api_type = "BOSMiner"

View File

@@ -5,7 +5,7 @@ import toml
from config.bos import bos_config_convert, general_config_convert_bos
class BOSminer(BaseMiner):
class BOSMiner(BaseMiner):
def __init__(self, ip: str) -> None:
api = BOSMinerAPI(ip)
super().__init__(ip, api)

View File

@@ -1,5 +1,6 @@
from miners import BaseMiner
from API.cgminer import CGMinerAPI
from API import APIError
import asyncssh
@@ -18,7 +19,10 @@ class CGMiner(BaseMiner):
async def get_model(self):
if self.model:
return self.model
try:
version_data = await self.api.devdetails()
except APIError:
return None
if version_data:
self.model = version_data["DEVDETAILS"][0]["Model"].replace("Antminer ", "")
return self.model

View File

@@ -17,7 +17,14 @@ from miners.whatsminer.M32 import BTMinerM32
from miners.avalonminer import CGMinerAvalon
from miners.cgminer import CGMiner
from miners.bmminer import BMMiner
from miners.bosminer import BOSMiner
from miners.unknown import UnknownMiner
from API import APIError
import asyncio
import ipaddress
import json
@@ -95,6 +102,14 @@ class MinerFactory:
miner = BTMinerM31(str(ip))
elif "M32" in model:
miner = BTMinerM32(str(ip))
else:
if api:
if "BOSMiner" in api:
miner = BOSMiner(str(ip))
elif "CGMiner" in api:
miner = CGMiner(str(ip))
elif "BMMiner" in api:
miner = BMMiner(str(ip))
self.miners[ip] = miner
return miner
@@ -110,26 +125,26 @@ class MinerFactory:
if data.get("STATUS"):
if not isinstance(data["STATUS"], str):
if data["STATUS"][0].get("STATUS") not in ["I", "S"]:
try:
data = await self._send_api_command(str(ip), "version")
if data:
if data.get("VERSION"):
if data["VERSION"][0].get("Type"):
model = data["VERSION"][0]["Type"]
except:
print(f"Get Model Exception: {ip}")
else:
if not data["DEVDETAILS"][0]["Model"] == "":
model = data["DEVDETAILS"][0]["Model"]
else:
model = data["DEVDETAILS"][0]["Driver"]
else:
try:
data = await self._send_api_command(str(ip), "version")
model = data["VERSION"][0]["Type"]
except:
print(f"Get Model Exception: {ip}")
if model:
return model
except APIError as e:
return None
except OSError as e:
if e.winerror == 121:
print(e)
return None
else:
print(ip, e)
@@ -192,7 +207,6 @@ class MinerFactory:
return data
async def _get_api_type(self, ip: ipaddress.ip_address or str) -> dict or None:
"""Get data on the version of the miner to return the right miner."""
api = None