handle for BraiinsOS miners that dont have bosminer running for some reason
This commit is contained in:
@@ -288,9 +288,8 @@ class MinerFactory(metaclass=Singleton):
|
|||||||
try:
|
try:
|
||||||
# get the API type, should be BOSMiner, CGMiner, BMMiner, BTMiner, or None
|
# get the API type, should be BOSMiner, CGMiner, BMMiner, BTMiner, or None
|
||||||
new_model, new_api, new_ver = await asyncio.wait_for(
|
new_model, new_api, new_ver = await asyncio.wait_for(
|
||||||
self._get_miner_type(ip), timeout=PING_TIMEOUT
|
self._get_miner_type(ip), timeout=10
|
||||||
)
|
)
|
||||||
|
|
||||||
# keep track of the API and model we found first
|
# keep track of the API and model we found first
|
||||||
if new_api and not api:
|
if new_api and not api:
|
||||||
api = new_api
|
api = new_api
|
||||||
@@ -298,13 +297,11 @@ class MinerFactory(metaclass=Singleton):
|
|||||||
model = new_model
|
model = new_model
|
||||||
if new_ver and not ver:
|
if new_ver and not ver:
|
||||||
ver = new_ver
|
ver = new_ver
|
||||||
|
|
||||||
# if we find the API and model, don't need to loop anymore
|
# if we find the API and model, don't need to loop anymore
|
||||||
if api and model:
|
if api and model:
|
||||||
break
|
break
|
||||||
except asyncio.TimeoutError:
|
except asyncio.TimeoutError:
|
||||||
pass
|
logging.warning(f"{ip}: Get Miner Timed Out")
|
||||||
|
|
||||||
# make sure we have model information
|
# make sure we have model information
|
||||||
if model:
|
if model:
|
||||||
if not api:
|
if not api:
|
||||||
@@ -312,12 +309,10 @@ class MinerFactory(metaclass=Singleton):
|
|||||||
|
|
||||||
if model not in MINER_CLASSES.keys():
|
if model not in MINER_CLASSES.keys():
|
||||||
if "avalon" in model:
|
if "avalon" in model:
|
||||||
print(model)
|
|
||||||
if model == "avalon10":
|
if model == "avalon10":
|
||||||
miner = CGMinerAvalon1066(str(ip))
|
miner = CGMinerAvalon1066(str(ip))
|
||||||
else:
|
else:
|
||||||
miner = CGMinerAvalon821(str(ip))
|
miner = CGMinerAvalon821(str(ip))
|
||||||
miner = UnknownMiner(str(ip))
|
|
||||||
return miner
|
return miner
|
||||||
if api not in MINER_CLASSES[model].keys():
|
if api not in MINER_CLASSES[model].keys():
|
||||||
api = "Default"
|
api = "Default"
|
||||||
@@ -357,32 +352,26 @@ class MinerFactory(metaclass=Singleton):
|
|||||||
async def _get_miner_type(
|
async def _get_miner_type(
|
||||||
self, ip: ipaddress.ip_address or str
|
self, ip: ipaddress.ip_address or str
|
||||||
) -> Tuple[str or None, str or None, str or None]:
|
) -> Tuple[str or None, str or None, str or None]:
|
||||||
|
data = None
|
||||||
|
|
||||||
model = None
|
model = None
|
||||||
api = None
|
api = None
|
||||||
ver = None
|
ver = None
|
||||||
|
|
||||||
devdetails = None
|
devdetails = None
|
||||||
version = None
|
version = None
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# get device details and version data
|
# get device details and version data
|
||||||
data = await self._send_api_command(str(ip), "devdetails+version")
|
data = await self._send_api_command(str(ip), "devdetails+version")
|
||||||
|
|
||||||
# validate success
|
# validate success
|
||||||
validation = await self._validate_command(data)
|
validation = await self._validate_command(data)
|
||||||
if not validation[0]:
|
if not validation[0]:
|
||||||
raise APIError(validation[1])
|
raise APIError(validation[1])
|
||||||
|
|
||||||
# copy each part of the main command to devdetails and version
|
# copy each part of the main command to devdetails and version
|
||||||
devdetails = data["devdetails"][0]
|
devdetails = data["devdetails"][0]
|
||||||
version = data["version"][0]
|
version = data["version"][0]
|
||||||
|
|
||||||
except APIError:
|
except APIError:
|
||||||
# if getting data fails we need to check again
|
|
||||||
data = None
|
|
||||||
|
|
||||||
# if data is None then get it a slightly different way
|
|
||||||
if not data:
|
|
||||||
try:
|
try:
|
||||||
# try devdetails and version separately (X19s mainly require this)
|
# try devdetails and version separately (X19s mainly require this)
|
||||||
# get devdetails and validate
|
# get devdetails and validate
|
||||||
@@ -407,6 +396,32 @@ class MinerFactory(metaclass=Singleton):
|
|||||||
# catch APIError and let the factory know we cant get data
|
# catch APIError and let the factory know we cant get data
|
||||||
logging.warning(f"{ip}: API Command Error: {e}")
|
logging.warning(f"{ip}: API Command Error: {e}")
|
||||||
return None, None, None
|
return None, None, None
|
||||||
|
except OSError as e:
|
||||||
|
# miner refused connection on API port, we wont be able to get data this way
|
||||||
|
# try ssh
|
||||||
|
try:
|
||||||
|
async with asyncssh.connect(
|
||||||
|
str(ip),
|
||||||
|
known_hosts=None,
|
||||||
|
username="root",
|
||||||
|
password="admin",
|
||||||
|
server_host_key_algs=["ssh-rsa"],
|
||||||
|
) as conn:
|
||||||
|
board_name = None
|
||||||
|
cmd = await conn.run("cat /tmp/sysinfo/board_name")
|
||||||
|
if cmd:
|
||||||
|
board_name = cmd.stdout.strip()
|
||||||
|
|
||||||
|
if board_name:
|
||||||
|
if board_name == "am1-s9":
|
||||||
|
model = "Antminer S9"
|
||||||
|
if board_name == "am2-s17":
|
||||||
|
model = "Antminer S17"
|
||||||
|
api = "BOSMiner+"
|
||||||
|
return model, api, None
|
||||||
|
|
||||||
|
except asyncssh.misc.PermissionDenied:
|
||||||
|
return None, None, None
|
||||||
|
|
||||||
# if we have devdetails, we can get model data from there
|
# if we have devdetails, we can get model data from there
|
||||||
if devdetails:
|
if devdetails:
|
||||||
@@ -488,23 +503,6 @@ class MinerFactory(metaclass=Singleton):
|
|||||||
elif "am2-s17" in version["STATUS"][0]["Description"]:
|
elif "am2-s17" in version["STATUS"][0]["Description"]:
|
||||||
model = "Antminer S17"
|
model = "Antminer S17"
|
||||||
|
|
||||||
# final try on a braiins OS bug with devdetails not returning
|
|
||||||
else:
|
|
||||||
try:
|
|
||||||
async with asyncssh.connect(
|
|
||||||
str(ip),
|
|
||||||
known_hosts=None,
|
|
||||||
username="root",
|
|
||||||
password="admin",
|
|
||||||
server_host_key_algs=["ssh-rsa"],
|
|
||||||
) as conn:
|
|
||||||
cfg = await conn.run("bosminer config --data")
|
|
||||||
if cfg:
|
|
||||||
cfg = json.loads(cfg.stdout)
|
|
||||||
model = cfg.get("data").get("format").get("model")
|
|
||||||
except asyncssh.misc.PermissionDenied:
|
|
||||||
pass
|
|
||||||
|
|
||||||
if model:
|
if model:
|
||||||
# whatsminer have a V in their version string (M20SV41), remove everything after it
|
# whatsminer have a V in their version string (M20SV41), remove everything after it
|
||||||
if "V" in model:
|
if "V" in model:
|
||||||
@@ -521,7 +519,7 @@ class MinerFactory(metaclass=Singleton):
|
|||||||
async def _validate_command(data: dict) -> Tuple[bool, str or None]:
|
async def _validate_command(data: dict) -> Tuple[bool, str or None]:
|
||||||
"""Check if the returned command output is correctly formatted."""
|
"""Check if the returned command output is correctly formatted."""
|
||||||
# check if the data returned is correct or an error
|
# check if the data returned is correct or an error
|
||||||
if not data:
|
if not data or data == {}:
|
||||||
return False, "No API data."
|
return False, "No API data."
|
||||||
# if status isn't a key, it is a multicommand
|
# if status isn't a key, it is a multicommand
|
||||||
if "STATUS" not in data.keys():
|
if "STATUS" not in data.keys():
|
||||||
@@ -550,9 +548,10 @@ class MinerFactory(metaclass=Singleton):
|
|||||||
# get reader and writer streams
|
# get reader and writer streams
|
||||||
reader, writer = await asyncio.open_connection(str(ip), 4028)
|
reader, writer = await asyncio.open_connection(str(ip), 4028)
|
||||||
except OSError as e:
|
except OSError as e:
|
||||||
|
if e.errno in [10061, 22] or e.winerror == 1225:
|
||||||
|
raise e
|
||||||
logging.warning(f"{str(ip)} - Command {command}: {e}")
|
logging.warning(f"{str(ip)} - Command {command}: {e}")
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
# create the command
|
# create the command
|
||||||
cmd = {"command": command}
|
cmd = {"command": command}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user