Merge pull request #24 from UpstreamData/crc

Merge in branch refactoring the hashboard data
This commit is contained in:
Arceris
2022-11-07 19:25:06 -07:00
committed by GitHub
24 changed files with 528 additions and 290 deletions

View File

@@ -230,7 +230,7 @@ These functions are
## [`MinerConfig`][pyasic.config.MinerConfig] and [`MinerData`][pyasic.data.MinerData] ## [`MinerConfig`][pyasic.config.MinerConfig] and [`MinerData`][pyasic.data.MinerData]
Pyasic implements a few dataclasses as helpers to make data return types consistent across different miners and miner APIs. Pyasic implements a few dataclasses as helpers to make data return types consistent across different miners and miner APIs. The different fields of these dataclasses can all be viewed with the classmethod `cls.fields()`.
<br> <br>

View File

@@ -45,10 +45,10 @@ class BMMinerAPI(BaseMinerAPI):
# make sure we can actually run each command, otherwise they will fail # make sure we can actually run each command, otherwise they will fail
commands = self._check_commands(*commands) commands = self._check_commands(*commands)
# standard multicommand format is "command1+command2" # standard multicommand format is "command1+command2"
# doesnt work for S19 which uses the backup _x19_multicommand # doesn't work for S19 which uses the backup _x19_multicommand
command = "+".join(commands) command = "+".join(commands)
try: try:
data = await self.send_command(command, allow_warning=ignore_x19_error) data = await self.send_command(command, allow_warning=not ignore_x19_error)
except APIError: except APIError:
logging.debug(f"{self.ip}: Handling X19 multicommand.") logging.debug(f"{self.ip}: Handling X19 multicommand.")
data = await self._x19_multicommand(*command.split("+")) data = await self._x19_multicommand(*command.split("+"))

View File

@@ -12,7 +12,9 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
from pyasic.API import BaseMinerAPI from pyasic.API import BaseMinerAPI, APIError
import logging
class CGMinerAPI(BaseMinerAPI): class CGMinerAPI(BaseMinerAPI):
@@ -36,6 +38,37 @@ class CGMinerAPI(BaseMinerAPI):
def __init__(self, ip: str, port: int = 4028): def __init__(self, ip: str, port: int = 4028):
super().__init__(ip, port) super().__init__(ip, port)
async def multicommand(
self, *commands: str, ignore_x19_error: bool = False
) -> dict:
logging.debug(f"{self.ip}: Sending multicommand: {[*commands]}")
# make sure we can actually run each command, otherwise they will fail
commands = self._check_commands(*commands)
# standard multicommand format is "command1+command2"
# doesnt work for S19 which uses the backup _x19_multicommand
command = "+".join(commands)
try:
data = await self.send_command(command, allow_warning=ignore_x19_error)
except APIError:
logging.debug(f"{self.ip}: Handling X19 multicommand.")
data = await self._x19_multicommand(*command.split("+"))
logging.debug(f"{self.ip}: Received multicommand data.")
return data
async def _x19_multicommand(self, *commands):
data = None
try:
data = {}
# send all commands individually
for cmd in commands:
data[cmd] = []
data[cmd].append(await self.send_command(cmd, allow_warning=True))
except APIError as e:
raise APIError(e)
except Exception as e:
logging.warning(f"{self.ip}: API Multicommand Error: {e}")
return data
async def version(self) -> dict: async def version(self) -> dict:
"""Get miner version info. """Get miner version info.
<details> <details>

View File

@@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
from dataclasses import dataclass, asdict from dataclasses import dataclass, asdict, fields
from typing import Literal, List from typing import Literal, List
import random import random
import string import string
@@ -37,6 +37,10 @@ class _Pool:
username: str = "" username: str = ""
password: str = "" password: str = ""
@classmethod
def fields(cls):
return fields(cls)
def from_dict(self, data: dict): def from_dict(self, data: dict):
"""Convert raw pool data as a dict to usable data and save it to this class. """Convert raw pool data as a dict to usable data and save it to this class.
@@ -136,6 +140,10 @@ class _PoolGroup:
group_name: str = None group_name: str = None
pools: List[_Pool] = None pools: List[_Pool] = None
@classmethod
def fields(cls):
return fields(cls)
def __post_init__(self): def __post_init__(self):
if not self.group_name: if not self.group_name:
self.group_name = "".join( self.group_name = "".join(
@@ -263,6 +271,10 @@ class MinerConfig:
dps_shutdown_enabled: bool = None dps_shutdown_enabled: bool = None
dps_shutdown_duration: float = None dps_shutdown_duration: float = None
@classmethod
def fields(cls):
return fields(cls)
def as_dict(self) -> dict: def as_dict(self) -> dict:
"""Convert the data in this class to a dict.""" """Convert the data in this class to a dict."""
data_dict = asdict(self) data_dict = asdict(self)

View File

@@ -13,8 +13,9 @@
# limitations under the License. # limitations under the License.
from typing import Union, List from typing import Union, List
from dataclasses import dataclass, field, asdict from dataclasses import dataclass, field, asdict, fields
from datetime import datetime, timezone from datetime import datetime, timezone
from functools import reduce
import time import time
import json import json
import copy import copy
@@ -22,6 +23,17 @@ import copy
from .error_codes import X19Error, WhatsminerError, BraiinsOSError, InnosiliconError from .error_codes import X19Error, WhatsminerError, BraiinsOSError, InnosiliconError
@dataclass
class HashBoard:
slot: int = 0
hashrate: float = 0.0
temp: int = -1
chip_temp: int = -1
chips: int = 0
expected_chips: int = 0
missing: bool = True
@dataclass @dataclass
class MinerData: class MinerData:
"""A Dataclass to standardize data returned from miners (specifically `AnyMiner().get_data()`) """A Dataclass to standardize data returned from miners (specifically `AnyMiner().get_data()`)
@@ -73,17 +85,19 @@ class MinerData:
model: str = "Unknown" model: str = "Unknown"
hostname: str = "Unknown" hostname: str = "Unknown"
hashrate: float = 0 hashrate: float = 0
left_board_hashrate: float = 0.0 hashboards: List[HashBoard] = field(default_factory=list)
center_board_hashrate: float = 0.0 ideal_hashboards: int = 1
right_board_hashrate: float = 0.0 left_board_hashrate: float = field(init=False)
center_board_hashrate: float = field(init=False)
right_board_hashrate: float = field(init=False)
temperature_avg: int = field(init=False) temperature_avg: int = field(init=False)
env_temp: float = -1.0 env_temp: float = -1.0
left_board_temp: int = -1 left_board_temp: int = field(init=False)
left_board_chip_temp: int = -1 left_board_chip_temp: int = field(init=False)
center_board_temp: int = -1 center_board_temp: int = field(init=False)
center_board_chip_temp: int = -1 center_board_chip_temp: int = field(init=False)
right_board_temp: int = -1 right_board_temp: int = field(init=False)
right_board_chip_temp: int = -1 right_board_chip_temp: int = field(init=False)
wattage: int = -1 wattage: int = -1
wattage_limit: int = -1 wattage_limit: int = -1
fan_1: int = -1 fan_1: int = -1
@@ -91,9 +105,9 @@ class MinerData:
fan_3: int = -1 fan_3: int = -1
fan_4: int = -1 fan_4: int = -1
fan_psu: int = -1 fan_psu: int = -1
left_chips: int = 0 left_chips: int = field(init=False)
center_chips: int = 0 center_chips: int = field(init=False)
right_chips: int = 0 right_chips: int = field(init=False)
total_chips: int = field(init=False) total_chips: int = field(init=False)
ideal_chips: int = 1 ideal_chips: int = 1
percent_ideal: float = field(init=False) percent_ideal: float = field(init=False)
@@ -109,6 +123,11 @@ class MinerData:
fault_light: Union[bool, None] = None fault_light: Union[bool, None] = None
efficiency: int = field(init=False) efficiency: int = field(init=False)
@classmethod
def fields(cls):
return [f.name for f in fields(cls)]
def __post_init__(self): def __post_init__(self):
self.datetime = datetime.now(timezone.utc).astimezone() self.datetime = datetime.now(timezone.utc).astimezone()
@@ -163,12 +182,148 @@ class MinerData:
@property @property
def total_chips(self): # noqa - Skip PyCharm inspection def total_chips(self): # noqa - Skip PyCharm inspection
return self.right_chips + self.center_chips + self.left_chips return sum([hb.chips for hb in self.hashboards])
@total_chips.setter @total_chips.setter
def total_chips(self, val): def total_chips(self, val):
pass pass
@property
def left_chips(self): # noqa - Skip PyCharm inspection
if len(self.hashboards) in [2, 3]:
return self.hashboards[0].chips
return 0
@left_chips.setter
def left_chips(self, val):
pass
@property
def center_chips(self): # noqa - Skip PyCharm inspection
if len(self.hashboards) == 1:
return self.hashboards[0].chips
if len(self.hashboards) == 3:
return self.hashboards[1].chips
return 0
@center_chips.setter
def center_chips(self, val):
pass
@property
def right_chips(self): # noqa - Skip PyCharm inspection
if len(self.hashboards) == 2:
return self.hashboards[1].chips
if len(self.hashboards) == 3:
return self.hashboards[2].chips
return 0
@right_chips.setter
def right_chips(self, val):
pass
@property
def left_board_hashrate(self): # noqa - Skip PyCharm inspection
if len(self.hashboards) in [2, 3]:
return self.hashboards[0].hashrate
return 0
@left_board_hashrate.setter
def left_board_hashrate(self, val):
pass
@property
def center_board_hashrate(self): # noqa - Skip PyCharm inspection
if len(self.hashboards) == 1:
return self.hashboards[0].hashrate
if len(self.hashboards) == 3:
return self.hashboards[1].hashrate
return 0
@center_board_hashrate.setter
def center_board_hashrate(self, val):
pass
@property
def right_board_hashrate(self): # noqa - Skip PyCharm inspection
if len(self.hashboards) == 2:
return self.hashboards[1].hashrate
if len(self.hashboards) == 3:
return self.hashboards[2].hashrate
return 0
@right_board_hashrate.setter
def right_board_hashrate(self, val):
pass
@property
def left_board_temp(self): # noqa - Skip PyCharm inspection
if len(self.hashboards) in [2, 3]:
return self.hashboards[0].temp
return 0
@left_board_temp.setter
def left_board_temp(self, val):
pass
@property
def center_board_temp(self): # noqa - Skip PyCharm inspection
if len(self.hashboards) == 1:
return self.hashboards[0].temp
if len(self.hashboards) == 3:
return self.hashboards[1].temp
return 0
@center_board_temp.setter
def center_board_temp(self, val):
pass
@property
def right_board_temp(self): # noqa - Skip PyCharm inspection
if len(self.hashboards) == 2:
return self.hashboards[1].temp
if len(self.hashboards) == 3:
return self.hashboards[2].temp
return 0
@right_board_temp.setter
def right_board_temp(self, val):
pass
@property
def left_board_chip_temp(self): # noqa - Skip PyCharm inspection
if len(self.hashboards) in [2, 3]:
return self.hashboards[0].chip_temp
return 0
@left_board_chip_temp.setter
def left_board_chip_temp(self, val):
pass
@property
def center_board_chip_temp(self): # noqa - Skip PyCharm inspection
if len(self.hashboards) == 1:
return self.hashboards[0].chip_temp
if len(self.hashboards) == 3:
return self.hashboards[1].chip_temp
return 0
@center_board_chip_temp.setter
def center_board_chip_temp(self, val):
pass
@property
def right_board_chip_temp(self): # noqa - Skip PyCharm inspection
if len(self.hashboards) == 2:
return self.hashboards[1].chip_temp
if len(self.hashboards) == 3:
return self.hashboards[2].chip_temp
return 0
@right_board_chip_temp.setter
def right_board_chip_temp(self, val):
pass
@property @property
def nominal(self): # noqa - Skip PyCharm inspection def nominal(self): # noqa - Skip PyCharm inspection
return self.ideal_chips == self.total_chips return self.ideal_chips == self.total_chips
@@ -189,13 +344,9 @@ class MinerData:
def temperature_avg(self): # noqa - Skip PyCharm inspection def temperature_avg(self): # noqa - Skip PyCharm inspection
total_temp = 0 total_temp = 0
temp_count = 0 temp_count = 0
for temp in [ for hb in self.hashboards:
self.left_board_chip_temp, if hb.temp and not hb.temp == -1:
self.center_board_chip_temp, total_temp += hb.temp
self.right_board_chip_temp,
]:
if temp and not temp == -1:
total_temp += temp
temp_count += 1 temp_count += 1
if not temp_count > 0: if not temp_count > 0:
return 0 return 0

View File

@@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
from dataclasses import dataclass, asdict from dataclasses import dataclass, asdict, fields
@dataclass @dataclass
@@ -21,9 +21,15 @@ class X19Error:
Attributes: Attributes:
error_message: The error message as a string. error_message: The error message as a string.
error_code: The error code as an int. 0 if the message is not assigned a code.
""" """
error_message: str error_message: str
error_code: int = 0
@classmethod
def fields(cls):
return fields(cls)
def asdict(self): def asdict(self):
return asdict(self) return asdict(self)

View File

@@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
from dataclasses import dataclass, asdict from dataclasses import dataclass, asdict, fields
@dataclass @dataclass
@@ -21,9 +21,16 @@ class BraiinsOSError:
Attributes: Attributes:
error_message: The error message as a string. error_message: The error message as a string.
error_code: The error code as an int. 0 if the message is not assigned a code.
""" """
error_message: str error_message: str
error_code: int = 0
@classmethod
def fields(cls):
return fields(cls)
def asdict(self): def asdict(self):
return asdict(self) return asdict(self)

View File

@@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
from dataclasses import dataclass, field, asdict from dataclasses import dataclass, field, asdict, fields
@dataclass @dataclass
@@ -27,6 +27,11 @@ class InnosiliconError:
error_code: int error_code: int
error_message: str = field(init=False) error_message: str = field(init=False)
@classmethod
def fields(cls):
return fields(cls)
@property @property
def error_message(self): # noqa - Skip PyCharm inspection def error_message(self): # noqa - Skip PyCharm inspection
if self.error_code in ERROR_CODES: if self.error_code in ERROR_CODES:

View File

@@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
from dataclasses import dataclass, field, asdict from dataclasses import dataclass, field, asdict, fields
@dataclass @dataclass
@@ -27,6 +27,11 @@ class WhatsminerError:
error_code: int error_code: int
error_message: str = field(init=False) error_message: str = field(init=False)
@classmethod
def fields(cls):
return fields(cls)
@property @property
def error_message(self): # noqa - Skip PyCharm inspection def error_message(self): # noqa - Skip PyCharm inspection
if self.error_code in ERROR_CODES: if self.error_code in ERROR_CODES:

View File

@@ -20,7 +20,7 @@ from typing import Union, List
from pyasic.API.bmminer import BMMinerAPI from pyasic.API.bmminer import BMMinerAPI
from pyasic.miners.base import BaseMiner from pyasic.miners.base import BaseMiner
from pyasic.data import MinerData from pyasic.data import MinerData, HashBoard
from pyasic.config import MinerConfig from pyasic.config import MinerConfig
from pyasic.data.error_codes import MinerErrorData from pyasic.data.error_codes import MinerErrorData
@@ -191,7 +191,11 @@ class BMMiner(BaseMiner):
Returns: Returns:
A [`MinerData`][pyasic.data.MinerData] instance containing the miners data. A [`MinerData`][pyasic.data.MinerData] instance containing the miners data.
""" """
data = MinerData(ip=str(self.ip), ideal_chips=self.nominal_chips * 3) data = MinerData(
ip=str(self.ip),
ideal_chips=self.nominal_chips * self.ideal_hashboards,
ideal_hashboards=self.ideal_hashboards,
)
board_offset = -1 board_offset = -1
fan_offset = -1 fan_offset = -1
@@ -242,7 +246,7 @@ class BMMiner(BaseMiner):
if stats: if stats:
boards = stats.get("STATS") boards = stats.get("STATS")
if boards: if boards:
if len(boards) > 0: if len(boards) > 1:
for board_num in range(1, 16, 5): for board_num in range(1, 16, 5):
for _b_num in range(5): for _b_num in range(5):
b = boards[1].get(f"chain_acn{board_num + _b_num}") b = boards[1].get(f"chain_acn{board_num + _b_num}")
@@ -252,30 +256,38 @@ class BMMiner(BaseMiner):
if board_offset == -1: if board_offset == -1:
board_offset = 1 board_offset = 1
data.left_chips = boards[1].get(f"chain_acn{board_offset}") env_temp_list = []
data.center_chips = boards[1].get(f"chain_acn{board_offset+1}") for i in range(board_offset, board_offset + self.ideal_hashboards):
data.right_chips = boards[1].get(f"chain_acn{board_offset+2}") hashboard = HashBoard(
slot=i - board_offset, expected_chips=self.nominal_chips
)
try: chip_temp = boards[1].get(f"temp{i}")
data.left_board_hashrate = round( if chip_temp:
float(boards[1].get(f"chain_rate{board_offset}")) / 1000, 2 hashboard.chip_temp = round(chip_temp)
)
except ValueError as e: temp = boards[1].get(f"temp2_{i}")
data.left_board_hashrate = round(0.00, 2) if temp:
try: hashboard.temp = round(temp)
data.center_board_hashrate = round(
float(boards[1].get(f"chain_rate{board_offset+1}")) / 1000, hashrate = boards[1].get(f"chain_rate{i}")
2, if hashrate:
) hashboard.hashrate = round(float(hashrate) / 1000, 2)
except ValueError as e:
data.center_board_hashrate = round(0.00, 2) chips = boards[1].get(f"chain_acn{i}")
try: if chips:
data.right_board_hashrate = round( hashboard.chips = chips
float(boards[1].get(f"chain_rate{board_offset+2}")) / 1000, hashboard.missing = False
2, if (not chips) or (not chips > 0):
) hashboard.missing = True
except ValueError as e: data.hashboards.append(hashboard)
data.right_board_hashrate = round(0.00, 2)
if f"temp_pcb{i}" in boards[1].keys():
env_temp = boards[1][f"temp_pcb{i}"].split("-")[0]
if not env_temp == 0:
env_temp_list.append(int(env_temp))
if not env_temp_list == []:
data.env_temp = round(sum(env_temp_list) / len(env_temp_list))
if stats: if stats:
temp = stats.get("STATS") temp = stats.get("STATS")
@@ -293,20 +305,6 @@ class BMMiner(BaseMiner):
data, f"fan_{fan + 1}", temp[1].get(f"fan{fan_offset+fan}") data, f"fan_{fan + 1}", temp[1].get(f"fan{fan_offset+fan}")
) )
board_map = {0: "left_board", 1: "center_board", 2: "right_board"}
env_temp_list = []
for item in range(3):
board_temp = temp[1].get(f"temp{item + board_offset}")
chip_temp = temp[1].get(f"temp2_{item + board_offset}")
setattr(data, f"{board_map[item]}_chip_temp", chip_temp)
setattr(data, f"{board_map[item]}_temp", board_temp)
if f"temp_pcb{item}" in temp[1].keys():
env_temp = temp[1][f"temp_pcb{item}"].split("-")[0]
if not env_temp == 0:
env_temp_list.append(int(env_temp))
if not env_temp_list == []:
data.env_temp = sum(env_temp_list) / len(env_temp_list)
if pools: if pools:
pool_1 = None pool_1 = None
pool_2 = None pool_2 = None

View File

@@ -25,7 +25,7 @@ from pyasic.API.bosminer import BOSMinerAPI
from pyasic.errors import APIError from pyasic.errors import APIError
from pyasic.data.error_codes import BraiinsOSError, MinerErrorData from pyasic.data.error_codes import BraiinsOSError, MinerErrorData
from pyasic.data import MinerData from pyasic.data import MinerData, HashBoard
from pyasic.config import MinerConfig from pyasic.config import MinerConfig
@@ -266,7 +266,10 @@ class BOSMiner(BaseMiner):
logging.warning(e) logging.warning(e)
if tunerstatus: if tunerstatus:
tuner = tunerstatus[0].get("TUNERSTATUS") try:
tuner = tunerstatus[0].get("TUNERSTATUS")
except KeyError:
tuner = tunerstatus.get("TUNERSTATUS")
if tuner: if tuner:
if len(tuner) > 0: if len(tuner) > 0:
chain_status = tuner[0].get("TunerChainStatus") chain_status = tuner[0].get("TunerChainStatus")
@@ -300,7 +303,15 @@ class BOSMiner(BaseMiner):
Returns: Returns:
A [`MinerData`][pyasic.data.MinerData] instance containing the miners data. A [`MinerData`][pyasic.data.MinerData] instance containing the miners data.
""" """
data = MinerData(ip=str(self.ip), ideal_chips=self.nominal_chips * 3) data = MinerData(
ip=str(self.ip),
ideal_chips=self.nominal_chips * self.ideal_hashboards,
ideal_hashboards=self.ideal_hashboards,
hashboards=[
HashBoard(slot=i, expected_chips=self.nominal_chips)
for i in range(self.ideal_hashboards)
],
)
board_offset = -1 board_offset = -1
fan_offset = -1 fan_offset = -1
@@ -361,14 +372,13 @@ class BOSMiner(BaseMiner):
temp = temps[0].get("TEMPS") temp = temps[0].get("TEMPS")
if temp: if temp:
if len(temp) > 0: if len(temp) > 0:
board_map = {0: "left_board", 1: "center_board", 2: "right_board"}
offset = 6 if temp[0]["ID"] in [6, 7, 8] else temp[0]["ID"] offset = 6 if temp[0]["ID"] in [6, 7, 8] else temp[0]["ID"]
for board in temp: for board in temp:
_id = board["ID"] - offset _id = board["ID"] - offset
chip_temp = round(board["Chip"]) chip_temp = round(board["Chip"])
board_temp = round(board["Board"]) board_temp = round(board["Board"])
setattr(data, f"{board_map[_id]}_chip_temp", chip_temp) data.hashboards[_id].chip_temp = chip_temp
setattr(data, f"{board_map[_id]}_temp", board_temp) data.hashboards[_id].temp = board_temp
if fans: if fans:
fan_data = fans[0].get("FANS") fan_data = fans[0].get("FANS")
@@ -461,27 +471,25 @@ class BOSMiner(BaseMiner):
boards = devdetails[0].get("DEVDETAILS") boards = devdetails[0].get("DEVDETAILS")
if boards: if boards:
if len(boards) > 0: if len(boards) > 0:
board_map = {0: "left_chips", 1: "center_chips", 2: "right_chips"}
offset = 6 if boards[0]["ID"] in [6, 7, 8] else boards[0]["ID"] offset = 6 if boards[0]["ID"] in [6, 7, 8] else boards[0]["ID"]
for board in boards: for board in boards:
_id = board["ID"] - offset _id = board["ID"] - offset
chips = board["Chips"] chips = board["Chips"]
setattr(data, board_map[_id], chips) data.hashboards[_id].chips = chips
if chips > 0:
data.hashboards[_id].missing = False
else:
data.hashboards[_id].missing = True
if devs: if devs:
boards = devs[0].get("DEVS") boards = devs[0].get("DEVS")
if boards: if boards:
if len(boards) > 0: if len(boards) > 0:
board_map = {
0: "left_board_hashrate",
1: "center_board_hashrate",
2: "right_board_hashrate",
}
offset = 6 if boards[0]["ID"] in [6, 7, 8] else boards[0]["ID"] offset = 6 if boards[0]["ID"] in [6, 7, 8] else boards[0]["ID"]
for board in boards: for board in boards:
_id = board["ID"] - offset _id = board["ID"] - offset
hashrate = round(board["MHS 1m"] / 1000000, 2) hashrate = round(board["MHS 1m"] / 1000000, 2)
setattr(data, board_map[_id], hashrate) data.hashboards[_id].hashrate = hashrate
return data return data
async def get_mac(self): async def get_mac(self):

View File

@@ -21,7 +21,7 @@ from pyasic.API.btminer import BTMinerAPI
from pyasic.miners.base import BaseMiner from pyasic.miners.base import BaseMiner
from pyasic.errors import APIError from pyasic.errors import APIError
from pyasic.data import MinerData from pyasic.data import MinerData, HashBoard
from pyasic.data.error_codes import WhatsminerError, MinerErrorData from pyasic.data.error_codes import WhatsminerError, MinerErrorData
from pyasic.config import MinerConfig from pyasic.config import MinerConfig
@@ -109,7 +109,6 @@ class BTMiner(BaseMiner):
if "Code" in data.keys(): if "Code" in data.keys():
if data["Code"] == 131: if data["Code"] == 131:
return True return True
print(data)
return False return False
async def check_light(self) -> bool: async def check_light(self) -> bool:
@@ -166,28 +165,22 @@ class BTMiner(BaseMiner):
for err in err_data["Msg"]["error_code"]: for err in err_data["Msg"]["error_code"]:
if isinstance(err, dict): if isinstance(err, dict):
for code in err: for code in err:
data.append( data.append(WhatsminerError(error_code=int(code)))
WhatsminerError(
error_code=int(code)
)
)
else: else:
data.append( data.append(WhatsminerError(error_code=int(err)))
WhatsminerError(
error_code=int(err)
)
)
except APIError: except APIError:
summary_data = await self.api.summary() summary_data = await self.api.summary()
if summary_data[0].get("Error Code Count"): if summary_data.get("SUMMARY"):
for i in range(summary_data[0]["Error Code Count"]): summary_data = summary_data["SUMMARY"]
if summary_data[0].get(f"Error Code {i}"): if summary_data[0].get("Error Code Count"):
if not summary_data[0][f"Error Code {i}"] == "": for i in range(summary_data[0]["Error Code Count"]):
data.append( if summary_data[0].get(f"Error Code {i}"):
WhatsminerError( if not summary_data[0][f"Error Code {i}"] == "":
error_code=summary_data[0][f"Error Code {i}"] data.append(
WhatsminerError(
error_code=summary_data[0][f"Error Code {i}"]
)
) )
)
return data return data
@@ -254,7 +247,11 @@ class BTMiner(BaseMiner):
Returns: Returns:
A [`MinerData`][pyasic.data.MinerData] instance containing the miners data. A [`MinerData`][pyasic.data.MinerData] instance containing the miners data.
""" """
data = MinerData(ip=str(self.ip), ideal_chips=self.nominal_chips * 3) data = MinerData(
ip=str(self.ip),
ideal_chips=self.nominal_chips * self.ideal_hashboards,
ideal_hashboards=self.ideal_hashboards,
)
mac = None mac = None
@@ -361,44 +358,25 @@ class BTMiner(BaseMiner):
if isinstance(err, dict): if isinstance(err, dict):
for code in err: for code in err:
data.errors.append( data.errors.append(
WhatsminerError( WhatsminerError(error_code=int(code))
error_code=int(code)
)
) )
else: else:
data.errors.append( data.errors.append(WhatsminerError(error_code=int(err)))
WhatsminerError(
error_code=int(err)
)
)
if devs: if devs:
temp_data = devs.get("DEVS") dev_data = devs.get("DEVS")
if temp_data: if dev_data:
board_map = {0: "left_board", 1: "center_board", 2: "right_board"} for board in dev_data:
for board in temp_data: temp_board = HashBoard(
_id = board["ASC"] slot=board["ASC"],
chip_temp = round(board["Chip Temp Avg"]) chip_temp=round(board["Chip Temp Avg"]),
board_temp = round(board["Temperature"]) temp=round(board["Temperature"]),
hashrate = round(board["MHS 1m"] / 1000000, 2) hashrate=round(board["MHS 1m"] / 1000000, 2),
setattr(data, f"{board_map[_id]}_chip_temp", chip_temp) chips=board["Effective Chips"],
setattr(data, f"{board_map[_id]}_temp", board_temp) missing=False if board["Effective Chips"] > 0 else True,
setattr(data, f"{board_map[_id]}_hashrate", hashrate) expected_chips=self.nominal_chips,
)
if devs: data.hashboards.append(temp_board)
boards = devs.get("DEVS")
if boards:
if len(boards) > 0:
board_map = {0: "left_chips", 1: "center_chips", 2: "right_chips"}
if "ID" in boards[0].keys():
id_key = "ID"
else:
id_key = "ASC"
offset = boards[0][id_key]
for board in boards:
_id = board[id_key] - offset
chips = board["Effective Chips"]
setattr(data, board_map[_id], chips)
if pools: if pools:
pool_1 = None pool_1 = None

View File

@@ -22,7 +22,7 @@ from pyasic.miners.base import BaseMiner
from pyasic.errors import APIError from pyasic.errors import APIError
from pyasic.config import MinerConfig from pyasic.config import MinerConfig
from pyasic.data import MinerData from pyasic.data import MinerData, HashBoard
from pyasic.data.error_codes import MinerErrorData from pyasic.data.error_codes import MinerErrorData
from pyasic.settings import PyasicSettings from pyasic.settings import PyasicSettings
@@ -179,7 +179,11 @@ class CGMiner(BaseMiner):
Returns: Returns:
A [`MinerData`][pyasic.data.MinerData] instance containing the miners data. A [`MinerData`][pyasic.data.MinerData] instance containing the miners data.
""" """
data = MinerData(ip=str(self.ip), ideal_chips=self.nominal_chips * 3) data = MinerData(
ip=str(self.ip),
ideal_chips=self.nominal_chips * self.ideal_hashboards,
ideal_hashboards=self.ideal_hashboards,
)
board_offset = -1 board_offset = -1
fan_offset = -1 fan_offset = -1
@@ -202,7 +206,7 @@ class CGMiner(BaseMiner):
miner_data = None miner_data = None
for i in range(PyasicSettings().miner_get_data_retries): for i in range(PyasicSettings().miner_get_data_retries):
miner_data = await self.api.multicommand( miner_data = await self.api.multicommand(
"summary", "pools", "stats", ignore_x19_error=True "summary", "pools", "stats",
) )
if miner_data: if miner_data:
break break
@@ -235,19 +239,38 @@ class CGMiner(BaseMiner):
if board_offset == -1: if board_offset == -1:
board_offset = 1 board_offset = 1
data.left_chips = boards[1].get(f"chain_acn{board_offset}") env_temp_list = []
data.center_chips = boards[1].get(f"chain_acn{board_offset+1}") for i in range(board_offset, board_offset + self.ideal_hashboards):
data.right_chips = boards[1].get(f"chain_acn{board_offset+2}") hashboard = HashBoard(
slot=i - board_offset, expected_chips=self.nominal_chips
)
data.left_board_hashrate = round( chip_temp = boards[1].get(f"temp{i}")
float(boards[1].get(f"chain_rate{board_offset}")) / 1000, 2 if chip_temp:
) hashboard.chip_temp = round(chip_temp)
data.center_board_hashrate = round(
float(boards[1].get(f"chain_rate{board_offset+1}")) / 1000, 2 temp = boards[1].get(f"temp2_{i}")
) if temp:
data.right_board_hashrate = round( hashboard.temp = round(temp)
float(boards[1].get(f"chain_rate{board_offset+2}")) / 1000, 2
) hashrate = boards[1].get(f"chain_rate{i}")
if hashrate:
hashboard.hashrate = round(float(hashrate) / 1000, 2)
chips = boards[1].get(f"chain_acn{i}")
if chips:
hashboard.chips = chips
hashboard.missing = False
if (not chips) or (not chips > 0):
hashboard.missing = True
data.hashboards.append(hashboard)
if f"temp_pcb{i}" in boards[1].keys():
env_temp = boards[1][f"temp_pcb{i}"].split("-")[0]
if not env_temp == 0:
env_temp_list.append(int(env_temp))
if not env_temp_list == []:
data.env_temp = round(sum(env_temp_list) / len(env_temp_list))
if stats: if stats:
temp = stats.get("STATS") temp = stats.get("STATS")
@@ -265,19 +288,6 @@ class CGMiner(BaseMiner):
data, f"fan_{fan + 1}", temp[1].get(f"fan{fan_offset+fan}") data, f"fan_{fan + 1}", temp[1].get(f"fan{fan_offset+fan}")
) )
board_map = {0: "left_board", 1: "center_board", 2: "right_board"}
env_temp_list = []
for item in range(3):
board_temp = temp[1].get(f"temp{item + board_offset}")
chip_temp = temp[1].get(f"temp2_{item + board_offset}")
setattr(data, f"{board_map[item]}_chip_temp", chip_temp)
setattr(data, f"{board_map[item]}_temp", board_temp)
if f"temp_pcb{item}" in temp[1].keys():
env_temp = temp[1][f"temp_pcb{item}"].split("-")[0]
if not env_temp == 0:
env_temp_list.append(int(env_temp))
data.env_temp = sum(env_temp_list) / len(env_temp_list)
if pools: if pools:
pool_1 = None pool_1 = None
pool_2 = None pool_2 = None

View File

@@ -20,9 +20,9 @@ class M34SPlus(BaseMiner):
super().__init__() super().__init__()
self.ip = ip self.ip = ip
self.model = "M34S+" self.model = "M34S+"
# TODO: has 4 boards instead of 3 self.ideal_hashboards = 4
self.nominal_chips = 464 self.nominal_chips = 116
self.fan_count = 2 self.fan_count = 0
class M34SPlusVE10(BaseMiner): class M34SPlusVE10(BaseMiner):
@@ -30,5 +30,6 @@ class M34SPlusVE10(BaseMiner):
super().__init__() super().__init__()
self.ip = ip self.ip = ip
self.model = "M34S+ VE10" self.model = "M34S+ VE10"
self.nominal_chips = 464 self.ideal_hashboards = 4
self.fan_count = 2 self.nominal_chips = 116
self.fan_count = 0

View File

@@ -14,4 +14,4 @@
from .M2X import * from .M2X import *
from .M3X import * from .M3X import *
from .M5X import * from .M5X import *

View File

@@ -15,7 +15,7 @@
from pyasic.miners._backends import Hiveon # noqa - Ignore access to _module from pyasic.miners._backends import Hiveon # noqa - Ignore access to _module
from pyasic.miners._types import T9 # noqa - Ignore access to _module from pyasic.miners._types import T9 # noqa - Ignore access to _module
from pyasic.data import MinerData from pyasic.data import MinerData, HashBoard
from pyasic.settings import PyasicSettings from pyasic.settings import PyasicSettings
@@ -39,7 +39,11 @@ class HiveonT9(Hiveon, T9):
Returns: Returns:
A [`MinerData`][pyasic.data.MinerData] instance containing the miners data. A [`MinerData`][pyasic.data.MinerData] instance containing the miners data.
""" """
data = MinerData(ip=str(self.ip), ideal_chips=self.nominal_chips * 3) data = MinerData(
ip=str(self.ip),
ideal_chips=self.nominal_chips * self.ideal_hashboards,
ideal_hashboards=self.ideal_hashboards,
)
board_offset = -1 board_offset = -1
fan_offset = -1 fan_offset = -1
@@ -97,14 +101,17 @@ class HiveonT9(Hiveon, T9):
) )
board_map = { board_map = {
"left": [2, 9, 10], 0: [2, 9, 10],
"center": [3, 11, 12], 1: [3, 11, 12],
"right": [4, 13, 14], 2: [4, 13, 14],
} }
env_temp_list = [] env_temp_list = []
for board in board_map.keys(): for board in board_map.keys():
hashboard = HashBoard(
slot=board, expected_chips=self.nominal_chips
)
chips = 0 chips = 0
hashrate = 0 hashrate = 0
chip_temp = 0 chip_temp = 0
@@ -121,10 +128,15 @@ class HiveonT9(Hiveon, T9):
hashrate += boards[1][f"chain_rate{chipset}"] hashrate += boards[1][f"chain_rate{chipset}"]
chips += boards[1][f"chain_acn{chipset}"] chips += boards[1][f"chain_acn{chipset}"]
setattr(data, f"{board}_chips", chips) hashboard.hashrate = hashrate
setattr(data, f"{board}_board_hashrate", hashrate) hashboard.chips = chips
setattr(data, f"{board}_board_temp", board_temp) hashboard.temp = board_temp
setattr(data, f"{board}_board_chip_temp", chip_temp) hashboard.chip_temp = chip_temp
hashboard.missing = True
if chips and chips > 0:
hashboard.missing = False
data.hashboards.append(hashboard)
if not env_temp_list == []: if not env_temp_list == []:
data.env_temp = sum(env_temp_list) / len(env_temp_list) data.env_temp = sum(env_temp_list) / len(env_temp_list)

View File

@@ -81,7 +81,15 @@ class CGMinerA10X(CGMiner):
return mac return mac
async def get_data(self): async def get_data(self):
data = MinerData(ip=str(self.ip), ideal_chips=self.nominal_chips * 3) data = MinerData(
ip=str(self.ip),
ideal_chips=self.nominal_chips * self.ideal_hashboards,
ideal_hashboards=self.ideal_hashboards,
hashboards=[
HashBoard(slot=i, expected_chips=self.nominal_chips)
for i in range(self.ideal_hashboards)
],
)
model = await self.get_model() model = await self.get_model()
mac = None mac = None
@@ -145,27 +153,20 @@ class CGMinerA10X(CGMiner):
f"fan_{fan+1}", f"fan_{fan+1}",
int(raw_data[f"Fan{fan+1}"]), int(raw_data[f"Fan{fan+1}"]),
) )
if "MTmax" in raw_data.keys(): for board in range(self.ideal_hashboards):
data.left_board_chip_temp = int(raw_data["MTmax"][0]) chip_temp = raw_data.get("MTmax")
data.center_board_chip_temp = int(raw_data["MTmax"][1]) if chip_temp:
data.right_board_chip_temp = int(raw_data["MTmax"][2]) data.hashboards[board].chip_temp = chip_temp[board]
if "MTavg" in raw_data.keys():
data.left_board_temp = int(raw_data["MTavg"][0])
data.center_board_temp = int(raw_data["MTavg"][1])
data.right_board_temp = int(raw_data["MTavg"][2])
if "PVT_T0" in raw_data: temp = raw_data.get("MTavg")
data.left_chips = len( if temp:
[item for item in raw_data["PVT_T0"] if not item == "0"] data.hashboards[board].temp = temp[board]
)
if "PVT_T1" in raw_data: chips = raw_data.get(f"PVT_T{board}")
data.center_chips = len( if chips:
[item for item in raw_data["PVT_T1"] if not item == "0"] data.hashboards[board].chips = len(
) [item for item in chips if not item == "0"]
if "PVT_T2" in raw_data: )
data.right_chips = len(
[item for item in raw_data["PVT_T2"] if not item == "0"]
)
if pools: if pools:
pool_1 = None pool_1 = None

View File

@@ -14,7 +14,7 @@
from pyasic.miners._backends import CGMiner # noqa - Ignore access to _module from pyasic.miners._backends import CGMiner # noqa - Ignore access to _module
from pyasic.data import MinerData from pyasic.data import MinerData, HashBoard
from pyasic.settings import PyasicSettings from pyasic.settings import PyasicSettings
import re import re
from pyasic.config import MinerConfig from pyasic.config import MinerConfig
@@ -81,7 +81,15 @@ class CGMinerA7X(CGMiner):
return mac return mac
async def get_data(self): async def get_data(self):
data = MinerData(ip=str(self.ip), ideal_chips=self.nominal_chips * 3) data = MinerData(
ip=str(self.ip),
ideal_chips=self.nominal_chips * self.ideal_hashboards,
ideal_hashboards=self.ideal_hashboards,
hashboards=[
HashBoard(slot=i, expected_chips=self.nominal_chips)
for i in range(self.ideal_hashboards)
],
)
model = await self.get_model() model = await self.get_model()
mac = None mac = None
@@ -145,27 +153,20 @@ class CGMinerA7X(CGMiner):
f"fan_{fan+1}", f"fan_{fan+1}",
int(raw_data[f"Fan{fan+1}"]), int(raw_data[f"Fan{fan+1}"]),
) )
if "MTmax" in raw_data.keys(): for board in range(self.ideal_hashboards):
data.left_board_chip_temp = int(raw_data["MTmax"][0]) chip_temp = raw_data.get("MTmax")
data.center_board_chip_temp = int(raw_data["MTmax"][1]) if chip_temp:
data.right_board_chip_temp = int(raw_data["MTmax"][2]) data.hashboards[board].chip_temp = chip_temp[board]
if "MTavg" in raw_data.keys():
data.left_board_temp = int(raw_data["MTavg"][0])
data.center_board_temp = int(raw_data["MTavg"][1])
data.right_board_temp = int(raw_data["MTavg"][2])
if "PVT_T0" in raw_data: temp = raw_data.get("MTavg")
data.left_chips = len( if temp:
[item for item in raw_data["PVT_T0"] if not item == "0"] data.hashboards[board].temp = temp[board]
)
if "PVT_T1" in raw_data: chips = raw_data.get(f"PVT_T{board}")
data.center_chips = len( if chips:
[item for item in raw_data["PVT_T1"] if not item == "0"] data.hashboards[board].chips = len(
) [item for item in chips if not item == "0"]
if "PVT_T2" in raw_data: )
data.right_chips = len(
[item for item in raw_data["PVT_T2"] if not item == "0"]
)
if pools: if pools:
pool_1 = None pool_1 = None

View File

@@ -14,7 +14,7 @@
from pyasic.miners._backends import CGMiner # noqa - Ignore access to _module from pyasic.miners._backends import CGMiner # noqa - Ignore access to _module
from pyasic.data import MinerData from pyasic.data import MinerData, HashBoard
from pyasic.settings import PyasicSettings from pyasic.settings import PyasicSettings
import re import re
from pyasic.config import MinerConfig from pyasic.config import MinerConfig
@@ -81,7 +81,15 @@ class CGMinerA8X(CGMiner):
return mac return mac
async def get_data(self): async def get_data(self):
data = MinerData(ip=str(self.ip), ideal_chips=self.nominal_chips * 3) data = MinerData(
ip=str(self.ip),
ideal_chips=self.nominal_chips * self.ideal_hashboards,
ideal_hashboards=self.ideal_hashboards,
hashboards=[
HashBoard(slot=i, expected_chips=self.nominal_chips)
for i in range(self.ideal_hashboards)
],
)
model = await self.get_model() model = await self.get_model()
mac = None mac = None
@@ -145,27 +153,20 @@ class CGMinerA8X(CGMiner):
f"fan_{fan+1}", f"fan_{fan+1}",
int(raw_data[f"Fan{fan+1}"]), int(raw_data[f"Fan{fan+1}"]),
) )
if "MTmax" in raw_data.keys(): for board in range(self.ideal_hashboards):
data.left_board_chip_temp = int(raw_data["MTmax"][0]) chip_temp = raw_data.get("MTmax")
data.center_board_chip_temp = int(raw_data["MTmax"][1]) if chip_temp:
data.right_board_chip_temp = int(raw_data["MTmax"][2]) data.hashboards[board].chip_temp = chip_temp[board]
if "MTavg" in raw_data.keys():
data.left_board_temp = int(raw_data["MTavg"][0])
data.center_board_temp = int(raw_data["MTavg"][1])
data.right_board_temp = int(raw_data["MTavg"][2])
if "PVT_T0" in raw_data: temp = raw_data.get("MTavg")
data.left_chips = len( if temp:
[item for item in raw_data["PVT_T0"] if not item == "0"] data.hashboards[board].temp = temp[board]
)
if "PVT_T1" in raw_data: chips = raw_data.get(f"PVT_T{board}")
data.center_chips = len( if chips:
[item for item in raw_data["PVT_T1"] if not item == "0"] data.hashboards[board].chips = len(
) [item for item in chips if not item == "0"]
if "PVT_T2" in raw_data: )
data.right_chips = len(
[item for item in raw_data["PVT_T2"] if not item == "0"]
)
if pools: if pools:
pool_1 = None pool_1 = None

View File

@@ -15,7 +15,7 @@
from pyasic.miners._backends import CGMiner # noqa - Ignore access to _module from pyasic.miners._backends import CGMiner # noqa - Ignore access to _module
from pyasic.miners._types import Avalon921 # noqa - Ignore access to _module from pyasic.miners._types import Avalon921 # noqa - Ignore access to _module
from pyasic.data import MinerData from pyasic.data import MinerData, HashBoard
from pyasic.settings import PyasicSettings from pyasic.settings import PyasicSettings
import re import re
from pyasic.config import MinerConfig from pyasic.config import MinerConfig
@@ -82,7 +82,15 @@ class CGMinerAvalon921(CGMiner, Avalon921):
return mac return mac
async def get_data(self): async def get_data(self):
data = MinerData(ip=str(self.ip), ideal_chips=self.nominal_chips * 3) data = MinerData(
ip=str(self.ip),
ideal_chips=self.nominal_chips * self.ideal_hashboards,
ideal_hashboards=self.ideal_hashboards,
hashboards=[
HashBoard(slot=i, expected_chips=self.nominal_chips)
for i in range(self.ideal_hashboards)
],
)
model = await self.get_model() model = await self.get_model()
mac = None mac = None
@@ -146,27 +154,20 @@ class CGMinerAvalon921(CGMiner, Avalon921):
f"fan_{fan+1}", f"fan_{fan+1}",
int(raw_data[f"Fan{fan+1}"]), int(raw_data[f"Fan{fan+1}"]),
) )
if "MTmax" in raw_data.keys(): for board in range(self.ideal_hashboards):
data.left_board_chip_temp = int(raw_data["MTmax"][0]) chip_temp = raw_data.get("MTmax")
data.center_board_chip_temp = int(raw_data["MTmax"][1]) if chip_temp:
data.right_board_chip_temp = int(raw_data["MTmax"][2]) data.hashboards[board].chip_temp = chip_temp[board]
if "MTavg" in raw_data.keys():
data.left_board_temp = int(raw_data["MTavg"][0])
data.center_board_temp = int(raw_data["MTavg"][1])
data.right_board_temp = int(raw_data["MTavg"][2])
if "PVT_T0" in raw_data: temp = raw_data.get("MTavg")
data.left_chips = len( if temp:
[item for item in raw_data["PVT_T0"] if not item == "0"] data.hashboards[board].temp = temp[board]
)
if "PVT_T1" in raw_data: chips = raw_data.get(f"PVT_T{board}")
data.center_chips = len( if chips:
[item for item in raw_data["PVT_T1"] if not item == "0"] data.hashboards[board].chips = len(
) [item for item in chips if not item == "0"]
if "PVT_T2" in raw_data: )
data.right_chips = len(
[item for item in raw_data["PVT_T2"] if not item == "0"]
)
if pools: if pools:
pool_1 = None pool_1 = None

View File

@@ -43,6 +43,7 @@ class BaseMiner(ABC):
self.version = None self.version = None
self.fan_count = 2 self.fan_count = 2
self.config = None self.config = None
self.ideal_hashboards = 3
def __new__(cls, *args, **kwargs): def __new__(cls, *args, **kwargs):
if cls is BaseMiner: if cls is BaseMiner:

View File

@@ -14,7 +14,7 @@
from pyasic.miners._backends import CGMiner # noqa - Ignore access to _module from pyasic.miners._backends import CGMiner # noqa - Ignore access to _module
from pyasic.miners._types import InnosiliconT3HPlus # noqa - Ignore access to _module from pyasic.miners._types import InnosiliconT3HPlus # noqa - Ignore access to _module
from pyasic.data import MinerData from pyasic.data import MinerData, HashBoard
from pyasic.data.error_codes import InnosiliconError, MinerErrorData from pyasic.data.error_codes import InnosiliconError, MinerErrorData
from pyasic.settings import PyasicSettings from pyasic.settings import PyasicSettings
from pyasic.config import MinerConfig from pyasic.config import MinerConfig
@@ -158,7 +158,15 @@ class CGMinerInnosiliconT3HPlus(CGMiner, InnosiliconT3HPlus):
return errors return errors
async def get_data(self) -> MinerData: async def get_data(self) -> MinerData:
data = MinerData(ip=str(self.ip), ideal_chips=self.nominal_chips * 3) data = MinerData(
ip=str(self.ip),
ideal_chips=self.nominal_chips * self.ideal_hashboards,
ideal_hashboards=self.ideal_hashboards,
hashboards=[
HashBoard(slot=i, expected_chips=self.nominal_chips)
for i in range(self.ideal_hashboards)
],
)
board_offset = -1 board_offset = -1
fan_offset = -1 fan_offset = -1
@@ -215,32 +223,31 @@ class CGMinerInnosiliconT3HPlus(CGMiner, InnosiliconT3HPlus):
if stats: if stats:
stats = stats[0] stats = stats[0]
if stats.get("STATS"): if stats.get("STATS"):
board_map = {0: "left", 1: "center", 2: "right"}
for idx, board in enumerate(stats["STATS"]): for idx, board in enumerate(stats["STATS"]):
data.hashboards[idx].missing = True
chips = board.get("Num active chips") chips = board.get("Num active chips")
if chips: if chips:
setattr(data, f"{board_map[idx]}_chips", chips) data.hashboards[idx].chips = chips
temp = board.get("Temp") if chips > 0:
if temp: data.hashboards[idx].missing = False
setattr(data, f"{board_map[idx]}_board_chip_temp", temp)
if all_data: if all_data:
if all_data.get("chain"): if all_data.get("chain"):
board_map = {0: "left", 1: "center", 2: "right"}
for idx, board in enumerate(all_data["chain"]): for idx, board in enumerate(all_data["chain"]):
temp = board.get("Temp max") temp = board.get("Temp min")
if temp: if temp:
setattr(data, f"{board_map[idx]}_board_chip_temp", temp) data.hashboards[idx].temp = round(temp)
temp_board = board.get("Temp min")
if temp_board: hashrate = board.get("Hash Rate H")
setattr(data, f"{board_map[idx]}_board_temp", temp_board) if hashrate:
hr = board.get("Hash Rate H") data.hashboards[idx].hashrate = round(
if hr: hashrate / 1000000000000, 2
setattr(
data,
f"{board_map[idx]}_board_hashrate",
round(hr / 1000000000000, 2),
) )
chip_temp = board.get("Temp max")
if chip_temp:
data.hashboards[idx].chip_temp = round(chip_temp)
if all_data.get("fansSpeed"): if all_data.get("fansSpeed"):
speed = round((all_data["fansSpeed"] * 6000) / 100) speed = round((all_data["fansSpeed"] * 6000) / 100)
for fan in range(self.fan_count): for fan in range(self.fan_count):

View File

@@ -15,4 +15,4 @@
from .M50 import ( from .M50 import (
BTMinerM50, BTMinerM50,
BTMinerM50VH50, BTMinerM50VH50,
) )

View File

@@ -14,4 +14,4 @@
from .M2X import * from .M2X import *
from .M3X import * from .M3X import *
from .M5X import * from .M5X import *