improved type hinting and formatting in miner factory
This commit is contained in:
@@ -1,12 +1,17 @@
|
|||||||
|
from typing import TypeVar, Iterator, Tuple, List
|
||||||
|
|
||||||
|
|
||||||
|
from miners import BaseMiner
|
||||||
|
|
||||||
from miners.antminer import *
|
from miners.antminer import *
|
||||||
from miners.whatsminer import *
|
from miners.whatsminer import *
|
||||||
from miners.avalonminer import *
|
from miners.avalonminer import *
|
||||||
|
|
||||||
from miners._backends.cgminer import CGMiner
|
from miners._backends.cgminer import CGMiner # noqa - Ignore _module import
|
||||||
from miners._backends.bmminer import BMMiner
|
from miners._backends.bmminer import BMMiner # noqa - Ignore _module import
|
||||||
from miners._backends.bosminer import BOSMiner
|
from miners._backends.bosminer import BOSMiner # noqa - Ignore _module import
|
||||||
from miners._backends.btminer import BTMiner
|
from miners._backends.btminer import BTMiner # noqa - Ignore _module import
|
||||||
from miners._backends.bosminer_old import BOSMinerOld
|
from miners._backends.bosminer_old import BOSMinerOld # noqa - Ignore _module import
|
||||||
|
|
||||||
from miners.unknown import UnknownMiner
|
from miners.unknown import UnknownMiner
|
||||||
|
|
||||||
@@ -22,6 +27,8 @@ from settings import (
|
|||||||
NETWORK_PING_TIMEOUT as PING_TIMEOUT,
|
NETWORK_PING_TIMEOUT as PING_TIMEOUT,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
AnyMiner = TypeVar("AnyMiner", bound=BaseMiner)
|
||||||
|
|
||||||
MINER_CLASSES = {
|
MINER_CLASSES = {
|
||||||
"Antminer S9": {
|
"Antminer S9": {
|
||||||
"Default": BOSMinerS9,
|
"Default": BOSMinerS9,
|
||||||
@@ -170,7 +177,9 @@ class MinerFactory(metaclass=Singleton):
|
|||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.miners = {}
|
self.miners = {}
|
||||||
|
|
||||||
async def get_miner_generator(self, ips: list):
|
async def get_miner_generator(
|
||||||
|
self, ips: List[ipaddress.ip_address or str]
|
||||||
|
) -> Iterator[AnyMiner]:
|
||||||
"""
|
"""
|
||||||
Get Miner objects from ip addresses using an async generator.
|
Get Miner objects from ip addresses using an async generator.
|
||||||
|
|
||||||
@@ -192,7 +201,7 @@ class MinerFactory(metaclass=Singleton):
|
|||||||
for miner in scanned:
|
for miner in scanned:
|
||||||
yield await miner
|
yield await miner
|
||||||
|
|
||||||
async def get_miner(self, ip: ipaddress.ip_address or str):
|
async def get_miner(self, ip: ipaddress.ip_address or str) -> AnyMiner:
|
||||||
"""Decide a miner type using the IP address of the miner."""
|
"""Decide a miner type using the IP address of the miner."""
|
||||||
if isinstance(ip, str):
|
if isinstance(ip, str):
|
||||||
ip = ipaddress.ip_address(ip)
|
ip = ipaddress.ip_address(ip)
|
||||||
@@ -218,7 +227,7 @@ class MinerFactory(metaclass=Singleton):
|
|||||||
if new_model and not model:
|
if new_model and not model:
|
||||||
model = new_model
|
model = new_model
|
||||||
|
|
||||||
# if we find the API and model, dont 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:
|
||||||
@@ -265,15 +274,16 @@ class MinerFactory(metaclass=Singleton):
|
|||||||
# return the miner
|
# return the miner
|
||||||
return miner
|
return miner
|
||||||
|
|
||||||
def clear_cached_miners(self):
|
def clear_cached_miners(self) -> None:
|
||||||
"""Clear the miner factory cache."""
|
"""Clear the miner factory cache."""
|
||||||
# empty out self.miners
|
# empty out self.miners
|
||||||
self.miners = {}
|
self.miners = {}
|
||||||
|
|
||||||
async def _get_miner_type(self, ip: ipaddress.ip_address or str) -> tuple:
|
async def _get_miner_type(
|
||||||
|
self, ip: ipaddress.ip_address or str
|
||||||
|
) -> Tuple[str or None, str or None]:
|
||||||
model = None
|
model = None
|
||||||
api = None
|
api = None
|
||||||
data = None
|
|
||||||
|
|
||||||
devdetails = None
|
devdetails = None
|
||||||
version = None
|
version = None
|
||||||
@@ -288,10 +298,9 @@ class MinerFactory(metaclass=Singleton):
|
|||||||
devdetails = data["devdetails"][0]
|
devdetails = data["devdetails"][0]
|
||||||
version = data["version"][0]
|
version = data["version"][0]
|
||||||
|
|
||||||
except APIError as e:
|
except APIError:
|
||||||
data = None
|
data = None
|
||||||
|
|
||||||
|
|
||||||
if not data:
|
if not data:
|
||||||
try:
|
try:
|
||||||
devdetails = await self._send_api_command(str(ip), "devdetails")
|
devdetails = await self._send_api_command(str(ip), "devdetails")
|
||||||
@@ -350,7 +359,9 @@ class MinerFactory(metaclass=Singleton):
|
|||||||
api = "BOSMiner+"
|
api = "BOSMiner+"
|
||||||
|
|
||||||
# if all that fails, check the Description to see if it is a whatsminer
|
# if all that fails, check the Description to see if it is a whatsminer
|
||||||
if version.get("Description") and "whatsminer" in version.get("Description"):
|
if version.get("Description") and "whatsminer" in version.get(
|
||||||
|
"Description"
|
||||||
|
):
|
||||||
api = "BTMiner"
|
api = "BTMiner"
|
||||||
|
|
||||||
if version and not model:
|
if version and not model:
|
||||||
@@ -364,7 +375,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"
|
||||||
|
|
||||||
|
|
||||||
if model:
|
if model:
|
||||||
if "V" in model:
|
if "V" in model:
|
||||||
model = model.split("V")[0]
|
model = model.split("V")[0]
|
||||||
@@ -373,7 +383,8 @@ class MinerFactory(metaclass=Singleton):
|
|||||||
|
|
||||||
return model, api
|
return model, api
|
||||||
|
|
||||||
async def _validate_command(self, data: dict) -> tuple:
|
@staticmethod
|
||||||
|
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:
|
||||||
@@ -399,7 +410,8 @@ class MinerFactory(metaclass=Singleton):
|
|||||||
return False, data["STATUS"][0]["Msg"]
|
return False, data["STATUS"][0]["Msg"]
|
||||||
return True, None
|
return True, None
|
||||||
|
|
||||||
async def _send_api_command(self, ip: ipaddress.ip_address or str, command: str):
|
@staticmethod
|
||||||
|
async def _send_api_command(ip: ipaddress.ip_address or str, command: str) -> dict:
|
||||||
try:
|
try:
|
||||||
# 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)
|
||||||
@@ -439,12 +451,12 @@ class MinerFactory(metaclass=Singleton):
|
|||||||
str_data = str_data.replace(",}", "}")
|
str_data = str_data.replace(",}", "}")
|
||||||
# fix an error with a btminer return having a newline that breaks json.loads()
|
# fix an error with a btminer return having a newline that breaks json.loads()
|
||||||
str_data = str_data.replace("\n", "")
|
str_data = str_data.replace("\n", "")
|
||||||
# fix an error with a bmminer return not having a specific comma that breaks json.loads()
|
# fix an error with a bmminer return missing a specific comma that breaks json.loads()
|
||||||
str_data = str_data.replace("}{", "},{")
|
str_data = str_data.replace("}{", "},{")
|
||||||
# parse the json
|
# parse the json
|
||||||
data = json.loads(str_data)
|
data = json.loads(str_data)
|
||||||
# handle bad json
|
# handle bad json
|
||||||
except json.decoder.JSONDecodeError as e:
|
except json.decoder.JSONDecodeError:
|
||||||
# raise APIError(f"Decode Error: {data}")
|
# raise APIError(f"Decode Error: {data}")
|
||||||
data = None
|
data = None
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user