fixed some bugs with differing version of BTMiner and different versions of M30S++ having different chip counts

This commit is contained in:
UpstreamData
2022-05-30 11:13:37 -06:00
parent 5c850a43a9
commit 739126935a
8 changed files with 53 additions and 19 deletions

View File

@@ -98,7 +98,7 @@ If you are sure you want to use this command please use API.send_command("{item}
async def send_command( async def send_command(
self, self,
command: str, command: str or bytes,
parameters: str or int or bool = None, parameters: str or int or bool = None,
ignore_errors: bool = False, ignore_errors: bool = False,
x19_command: bool = False, x19_command: bool = False,

View File

@@ -163,6 +163,7 @@ class BTMinerAPI(BaseMinerAPI):
command: str or bytes, command: str or bytes,
parameters: str or int or bool = None, parameters: str or int or bool = None,
ignore_errors: bool = False, ignore_errors: bool = False,
**kwargs,
) -> dict: ) -> dict:
"""Send a command to the miner API. """Send a command to the miner API.

View File

@@ -125,6 +125,9 @@ class BTMiner(BaseMiner):
summary_data = summary.get("SUMMARY") summary_data = summary.get("SUMMARY")
if summary_data: if summary_data:
if len(summary_data) > 0: if len(summary_data) > 0:
data.fan_1 = summary_data[0]["Fan Speed In"]
data.fan_2 = summary_data[0]["Fan Speed Out"]
hr = summary_data[0].get("MHS 1m") hr = summary_data[0].get("MHS 1m")
if hr: if hr:
data.hashrate = round(hr / 1000000, 2) data.hashrate = round(hr / 1000000, 2)
@@ -136,12 +139,9 @@ class BTMiner(BaseMiner):
if devs: if devs:
temp_data = devs.get("DEVS") temp_data = devs.get("DEVS")
if temp_data: if temp_data:
data.fan_1 = temp_data[0]["Fan Speed In"]
data.fan_2 = temp_data[0]["Fan Speed Out"]
board_map = {0: "left_board", 1: "center_board", 2: "right_board"} board_map = {0: "left_board", 1: "center_board", 2: "right_board"}
for board in temp_data: for board in temp_data:
_id = board["ID"] _id = board["ASC"]
chip_temp = round(board["Chip Temp Avg"]) chip_temp = round(board["Chip Temp Avg"])
board_temp = round(board["Temperature"]) board_temp = round(board["Temperature"])
setattr(data, f"{board_map[_id]}_chip_temp", chip_temp) setattr(data, f"{board_map[_id]}_chip_temp", chip_temp)

View File

@@ -1,10 +1,19 @@
from miners import BaseMiner from miners import BaseMiner
class M30SPlusPlus(BaseMiner): class M30SPlusPlusVG30(BaseMiner):
def __init__(self, ip: str): def __init__(self, ip: str):
super().__init__() super().__init__()
self.ip = ip self.ip = ip
self.model = "M30S++" self.model = "M30S++V30"
self.nominal_chips = 111
self.fan_count = 2
class M30SPlusPlusVG40(BaseMiner):
def __init__(self, ip: str):
super().__init__()
self.ip = ip
self.model = "M30S++V40"
self.nominal_chips = 117 self.nominal_chips = 117
self.fan_count = 2 self.fan_count = 2

View File

@@ -1,6 +1,6 @@
from .M30S import M30S from .M30S import M30S
from .M30S_Plus import M30SPlus from .M30S_Plus import M30SPlus
from .M30S_Plus_Plus import M30SPlusPlus from .M30S_Plus_Plus import M30SPlusPlusVG30, M30SPlusPlusVG40
from .M31S import M31S from .M31S import M31S
from .M31S_Plus import M31SPlus from .M31S_Plus import M31SPlus

View File

@@ -147,8 +147,10 @@ MINER_CLASSES = {
"BTMiner": BTMinerM30SPlus, "BTMiner": BTMinerM30SPlus,
}, },
"M30S++": { "M30S++": {
"Default": BTMinerM30SPlusPlus, "Default": BTMinerM30SPlusPlusVG40,
"BTMiner": BTMinerM30SPlusPlus, "BTMiner": BTMinerM30SPlusPlusVG40,
"40": BTMinerM30SPlusPlusVG40,
"30": BTMinerM30SPlusPlusVG30,
}, },
"M31S": { "M31S": {
"Default": BTMinerM31S, "Default": BTMinerM31S,
@@ -213,12 +215,13 @@ class MinerFactory(metaclass=Singleton):
miner = UnknownMiner(str(ip)) miner = UnknownMiner(str(ip))
api = None api = None
model = None model = None
ver = None
# try to get the API multiple times based on retries # try to get the API multiple times based on retries
for i in range(GET_VERSION_RETRIES): for i in range(GET_VERSION_RETRIES):
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 = 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=PING_TIMEOUT
) )
@@ -227,6 +230,8 @@ class MinerFactory(metaclass=Singleton):
api = new_api api = new_api
if new_model and not model: if new_model and not model:
model = new_model model = new_model
if new_ver and not 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:
@@ -251,6 +256,9 @@ class MinerFactory(metaclass=Singleton):
return miner return miner
if api not in MINER_CLASSES[model].keys(): if api not in MINER_CLASSES[model].keys():
api = "Default" api = "Default"
if ver in MINER_CLASSES[model].keys():
miner = MINER_CLASSES[model][ver](str(ip))
return miner
miner = MINER_CLASSES[model][api](str(ip)) miner = MINER_CLASSES[model][api](str(ip))
# if we cant find a model, check if we found the API # if we cant find a model, check if we found the API
@@ -283,9 +291,10 @@ 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]: ) -> Tuple[str or None, str or None, str or None]:
model = None model = None
api = None api = None
ver = None
devdetails = None devdetails = None
version = None version = None
@@ -332,7 +341,7 @@ class MinerFactory(metaclass=Singleton):
except APIError as e: except APIError as e:
# 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 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:
@@ -363,6 +372,11 @@ class MinerFactory(metaclass=Singleton):
): ):
api = "CGMiner" api = "CGMiner"
elif any(
"BTMiner" in string for string in version["VERSION"][0].keys()
):
api = "BTMiner"
# check if there are any BOSMiner strings in any of the dict keys # check if there are any BOSMiner strings in any of the dict keys
elif any( elif any(
"BOSminer" in string for string in version["VERSION"][0].keys() "BOSminer" in string for string in version["VERSION"][0].keys()
@@ -376,8 +390,8 @@ 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( if version.get("Description") and (
"Description" "whatsminer" in version.get("Description")
): ):
api = "BTMiner" api = "BTMiner"
@@ -400,12 +414,13 @@ class MinerFactory(metaclass=Singleton):
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:
ver = model.split("VG")[1]
model = model.split("V")[0] model = model.split("V")[0]
# don't need "Bitmain", just "Antminer XX" as model # don't need "Bitmain", just "Antminer XX" as model
if "Bitmain " in model: if "Bitmain " in model:
model = model.replace("Bitmain ", "") model = model.replace("Bitmain ", "")
return model, api return model, api, ver
@staticmethod @staticmethod
async def _validate_command(data: dict) -> Tuple[bool, str or None]: async def _validate_command(data: dict) -> Tuple[bool, str or None]:

View File

@@ -1,8 +1,17 @@
from miners._backends import BTMiner # noqa - Ignore access to _module from miners._backends import BTMiner # noqa - Ignore access to _module
from miners._types import M30SPlusPlus # noqa - Ignore access to _module from miners._types import ( # noqa - Ignore access to _module
M30SPlusPlusVG40,
M30SPlusPlusVG30,
)
class BTMinerM30SPlusPlus(BTMiner, M30SPlusPlus): class BTMinerM30SPlusPlusVG40(BTMiner, M30SPlusPlusVG40):
def __init__(self, ip: str) -> None:
super().__init__(ip)
self.ip = ip
class BTMinerM30SPlusPlusVG30(BTMiner, M30SPlusPlusVG30):
def __init__(self, ip: str) -> None: def __init__(self, ip: str) -> None:
super().__init__(ip) super().__init__(ip)
self.ip = ip self.ip = ip

View File

@@ -1,6 +1,6 @@
from .M30S import BTMinerM30S from .M30S import BTMinerM30S
from .M30S_Plus import BTMinerM30SPlus from .M30S_Plus import BTMinerM30SPlus
from .M30S_Plus_Plus import BTMinerM30SPlusPlus from .M30S_Plus_Plus import BTMinerM30SPlusPlusVG40, BTMinerM30SPlusPlusVG30
from .M31S import BTMinerM31S from .M31S import BTMinerM31S
from .M31S_Plus import BTMinerM31SPlus from .M31S_Plus import BTMinerM31SPlus