Merge pull request #137 from UpstreamData/dev_data

feature: Improve timestamp serialization,  add device_data to MinerData, and use enums for device information
This commit is contained in:
Brett Rowan
2024-05-15 14:20:16 -06:00
committed by GitHub
281 changed files with 1807 additions and 990 deletions

View File

@@ -36,6 +36,12 @@ class MinerConfig:
default_factory=PowerScalingConfig.default default_factory=PowerScalingConfig.default
) )
def __getitem__(self, item):
try:
return getattr(self, item)
except AttributeError:
raise KeyError
def as_dict(self) -> dict: def as_dict(self) -> dict:
"""Converts the MinerConfig object to a dictionary.""" """Converts the MinerConfig object to a dictionary."""
return asdict(self) return asdict(self)

View File

@@ -67,6 +67,13 @@ class MinerConfigOption(Enum):
def default(cls): def default(cls):
pass pass
def __getitem__(self, item):
try:
return getattr(self, item)
except AttributeError:
raise KeyError
@dataclass @dataclass
class MinerConfigValue: class MinerConfigValue:
@@ -112,3 +119,9 @@ class MinerConfigValue:
def as_mara(self) -> dict: def as_mara(self) -> dict:
return {} return {}
def __getitem__(self, item):
try:
return getattr(self, item)
except AttributeError:
raise KeyError

View File

@@ -25,8 +25,10 @@ from pyasic.config import MinerConfig
from pyasic.config.mining import MiningModePowerTune from pyasic.config.mining import MiningModePowerTune
from .boards import HashBoard from .boards import HashBoard
from .device import DeviceInfo
from .error_codes import BraiinsOSError, InnosiliconError, WhatsminerError, X19Error from .error_codes import BraiinsOSError, InnosiliconError, WhatsminerError, X19Error
from .fans import Fan from .fans import Fan
from .hashrate import AlgoHashRate, HashUnit
@dataclass @dataclass
@@ -38,8 +40,11 @@ class MinerData:
datetime: The time and date this data was generated. datetime: The time and date this data was generated.
uptime: The uptime of the miner in seconds. uptime: The uptime of the miner in seconds.
mac: The MAC address of the miner as a str. mac: The MAC address of the miner as a str.
device_info: Info about the device, such as model, make, and firmware.
model: The model of the miner as a str. model: The model of the miner as a str.
make: The make of the miner as a str. make: The make of the miner as a str.
firmware: The firmware on the miner as a str.
algo: The mining algorithm of the miner as a str.
api_ver: The current api version on the miner as a str. api_ver: The current api version on the miner as a str.
fw_ver: The current firmware version on the miner as a str. fw_ver: The current firmware version on the miner as a str.
hostname: The network hostname of the miner as a str. hostname: The network hostname of the miner as a str.
@@ -53,6 +58,7 @@ class MinerData:
voltage: Current output voltage of the PSU as an float. voltage: Current output voltage of the PSU as an float.
wattage_limit: Power limit of the miner as an int. wattage_limit: Power limit of the miner as an int.
fans: A list of fans on the miner with their speeds. fans: A list of fans on the miner with their speeds.
expected_fans: The number of fans expected on a miner.
fan_psu: The speed of the PSU on the fan if the miner collects it. fan_psu: The speed of the PSU on the fan if the miner collects it.
total_chips: The total number of chips on all boards. Calculated automatically. total_chips: The total number of chips on all boards. Calculated automatically.
expected_chips: The expected number of chips in the miner as an int. expected_chips: The expected number of chips in the miner as an int.
@@ -67,35 +73,62 @@ class MinerData:
is_mining: Whether the miner is mining. is_mining: Whether the miner is mining.
""" """
# general
ip: str ip: str
datetime: datetime = None _datetime: datetime = field(repr=False, default=None)
uptime: int = None datetime: str = field(init=False)
timestamp: int = field(init=False)
# about
device_info: DeviceInfo = None
make: str = field(init=False)
model: str = field(init=False)
firmware: str = field(init=False)
algo: str = field(init=False)
mac: str = None mac: str = None
model: str = None
make: str = None
api_ver: str = None api_ver: str = None
fw_ver: str = None fw_ver: str = None
hostname: str = None hostname: str = None
hashrate: float = field(init=False)
_hashrate: float = field(repr=False, default=None) # hashrate
hashrate: AlgoHashRate = field(init=False)
_hashrate: AlgoHashRate = field(repr=False, default=None)
# expected
expected_hashrate: float = None expected_hashrate: float = None
hashboards: List[HashBoard] = field(default_factory=list)
expected_hashboards: int = None expected_hashboards: int = None
expected_chips: int = None
expected_fans: int = None
# % expected
percent_expected_chips: float = field(init=False)
percent_expected_hashrate: float = field(init=False)
percent_expected_wattage: float = field(init=False)
# temperature
temperature_avg: int = field(init=False) temperature_avg: int = field(init=False)
env_temp: float = None env_temp: float = None
# power
wattage: int = None wattage: int = None
wattage_limit: int = field(init=False) wattage_limit: int = field(init=False)
voltage: float = None voltage: float = None
_wattage_limit: int = field(repr=False, default=None) _wattage_limit: int = field(repr=False, default=None)
# fans
fans: List[Fan] = field(default_factory=list) fans: List[Fan] = field(default_factory=list)
fan_psu: int = None fan_psu: int = None
# boards
hashboards: List[HashBoard] = field(default_factory=list)
total_chips: int = field(init=False) total_chips: int = field(init=False)
expected_chips: int = None
percent_expected_chips: float = field(init=False)
percent_expected_hashrate: float = field(init=False)
percent_expected_wattage: float = field(init=False)
nominal: bool = field(init=False) nominal: bool = field(init=False)
# config
config: MinerConfig = None config: MinerConfig = None
fault_light: Union[bool, None] = None
# errors
errors: List[ errors: List[
Union[ Union[
WhatsminerError, WhatsminerError,
@@ -104,9 +137,11 @@ class MinerData:
InnosiliconError, InnosiliconError,
] ]
] = field(default_factory=list) ] = field(default_factory=list)
fault_light: Union[bool, None] = None
efficiency: int = field(init=False) # mining state
is_mining: bool = True is_mining: bool = True
uptime: int = None
efficiency: int = field(init=False)
@classmethod @classmethod
def fields(cls): def fields(cls):
@@ -117,7 +152,7 @@ class MinerData:
return {k: v for (k, v) in x if not k.startswith("_")} return {k: v for (k, v) in x if not k.startswith("_")}
def __post_init__(self): def __post_init__(self):
self.datetime = datetime.now(timezone.utc).astimezone() self._datetime = datetime.now(timezone.utc).astimezone()
def get(self, __key: str, default: Any = None): def get(self, __key: str, default: Any = None):
try: try:
@@ -185,7 +220,7 @@ class MinerData:
if item.hashrate is not None: if item.hashrate is not None:
hr_data.append(item.hashrate) hr_data.append(item.hashrate)
if len(hr_data) > 0: if len(hr_data) > 0:
return round(sum(hr_data), 2) return sum(hr_data, start=type(hr_data[0])(0))
return self._hashrate return self._hashrate
@hashrate.setter @hashrate.setter
@@ -244,9 +279,10 @@ class MinerData:
def percent_expected_hashrate(self): # noqa - Skip PyCharm inspection def percent_expected_hashrate(self): # noqa - Skip PyCharm inspection
if self.hashrate is None or self.expected_hashrate is None: if self.hashrate is None or self.expected_hashrate is None:
return None return None
if self.hashrate == 0 or self.expected_hashrate == 0: try:
return round((self.hashrate / self.expected_hashrate) * 100)
except ZeroDivisionError:
return 0 return 0
return round((self.hashrate / self.expected_hashrate) * 100)
@percent_expected_hashrate.setter @percent_expected_hashrate.setter
def percent_expected_hashrate(self, val): def percent_expected_hashrate(self, val):
@@ -256,9 +292,10 @@ class MinerData:
def percent_expected_wattage(self): # noqa - Skip PyCharm inspection def percent_expected_wattage(self): # noqa - Skip PyCharm inspection
if self.wattage_limit is None or self.wattage is None: if self.wattage_limit is None or self.wattage is None:
return None return None
if self.wattage_limit == 0 or self.wattage == 0: try:
return round((self.wattage / self.wattage_limit) * 100)
except ZeroDivisionError:
return 0 return 0
return round((self.wattage / self.wattage_limit) * 100)
@percent_expected_wattage.setter @percent_expected_wattage.setter
def percent_expected_wattage(self, val): def percent_expected_wattage(self, val):
@@ -284,14 +321,70 @@ class MinerData:
def efficiency(self): # noqa - Skip PyCharm inspection def efficiency(self): # noqa - Skip PyCharm inspection
if self.hashrate is None or self.wattage is None: if self.hashrate is None or self.wattage is None:
return None return None
if self.hashrate == 0 or self.wattage == 0: try:
return round(self.wattage / float(self.hashrate))
except ZeroDivisionError:
return 0 return 0
return round(self.wattage / self.hashrate)
@efficiency.setter @efficiency.setter
def efficiency(self, val): def efficiency(self, val):
pass pass
@property
def datetime(self): # noqa - Skip PyCharm inspection
return self._datetime.isoformat()
@datetime.setter
def datetime(self, val):
pass
@property
def timestamp(self): # noqa - Skip PyCharm inspection
return int(time.mktime(self._datetime.timetuple()))
@timestamp.setter
def timestamp(self, val):
pass
@property
def make(self): # noqa - Skip PyCharm inspection
if self.device_info.make is not None:
return str(self.device_info.make)
@make.setter
def make(self, val):
pass
@property
def model(self): # noqa - Skip PyCharm inspection
if self.device_info.model is not None:
return str(self.device_info.model)
@model.setter
def model(self, val):
pass
@property
def firmware(self): # noqa - Skip PyCharm inspection
if self.device_info.firmware is not None:
return str(self.device_info.firmware)
@firmware.setter
def firmware(self, val):
pass
@property
def algo(self): # noqa - Skip PyCharm inspection
if self.device_info.algo is not None:
return str(self.device_info.algo)
@algo.setter
def algo(self, val):
pass
def keys(self) -> list:
return [f.name for f in fields(self)]
def asdict(self) -> dict: def asdict(self) -> dict:
return asdict(self, dict_factory=self.dict_factory) return asdict(self, dict_factory=self.dict_factory)
@@ -309,9 +402,7 @@ class MinerData:
Returns: Returns:
A JSON version of this class. A JSON version of this class.
""" """
data = self.asdict() return json.dumps(self.as_dict())
data["datetime"] = str(int(time.mktime(data["datetime"].timetuple())))
return json.dumps(data)
def as_csv(self) -> str: def as_csv(self) -> str:
"""Get this dataclass as CSV. """Get this dataclass as CSV.
@@ -320,7 +411,6 @@ class MinerData:
A CSV version of this class with no headers. A CSV version of this class with no headers.
""" """
data = self.asdict() data = self.asdict()
data["datetime"] = str(int(time.mktime(data["datetime"].timetuple())))
errs = [] errs = []
for error in data["errors"]: for error in data["errors"]:
errs.append(error["error_message"]) errs.append(error["error_message"])
@@ -385,6 +475,6 @@ class MinerData:
tags_str = ",".join(tag_data) tags_str = ",".join(tag_data)
field_str = ",".join(field_data) field_str = ",".join(field_data)
timestamp = str(int(time.mktime(self.datetime.timetuple()) * 1e9)) timestamp = str(self.timestamp * 1e9)
return " ".join([tags_str, field_str, timestamp]) return " ".join([tags_str, field_str, timestamp])

View File

@@ -17,6 +17,8 @@
from dataclasses import dataclass from dataclasses import dataclass
from typing import Any from typing import Any
from .hashrate import AlgoHashRate
@dataclass @dataclass
class HashBoard: class HashBoard:
@@ -34,7 +36,7 @@ class HashBoard:
""" """
slot: int = 0 slot: int = 0
hashrate: float = None hashrate: AlgoHashRate = None
temp: int = None temp: int = None
chip_temp: int = None chip_temp: int = None
chips: int = None chips: int = None

14
pyasic/data/device.py Normal file
View File

@@ -0,0 +1,14 @@
from dataclasses import dataclass
from pyasic.device.algorithm import MinerAlgo
from pyasic.device.firmware import MinerFirmware
from pyasic.device.makes import MinerMake
from pyasic.device.models import MinerModel
@dataclass
class DeviceInfo:
make: MinerMake = None
model: MinerModel = None
firmware: MinerFirmware = None
algo: MinerAlgo = None

View File

@@ -0,0 +1,15 @@
from enum import Enum
from pyasic.data.hashrate.sha256 import SHA256HashRate
from pyasic.device.algorithm.sha256 import SHA256Unit
class AlgoHashRate(Enum):
SHA256 = SHA256HashRate
def __call__(self, *args, **kwargs):
return self.value(*args, **kwargs)
class HashUnit:
SHA256 = SHA256Unit

View File

@@ -0,0 +1,54 @@
from __future__ import annotations
from dataclasses import dataclass
from pyasic.device.algorithm import MinerAlgo
from pyasic.device.algorithm.sha256 import SHA256Unit
@dataclass
class SHA256HashRate:
rate: float
unit: SHA256Unit = MinerAlgo.SHA256.unit.default
def __float__(self):
return float(self.rate)
def __int__(self):
return int(self.rate)
def __repr__(self):
return f"{self.rate} {str(self.unit)}"
def __round__(self, n: int = None):
return round(self.rate, n)
def __add__(self, other: SHA256HashRate | int | float) -> SHA256HashRate:
if isinstance(other, SHA256HashRate):
return SHA256HashRate(self.rate + other.into(self.unit).rate, self.unit)
return SHA256HashRate(self.rate + other, self.unit)
def __sub__(self, other: SHA256HashRate | int | float) -> SHA256HashRate:
if isinstance(other, SHA256HashRate):
return SHA256HashRate(self.rate - other.into(self.unit).rate, self.unit)
return SHA256HashRate(self.rate - other, self.unit)
def __truediv__(self, other: SHA256HashRate | int | float):
if isinstance(other, SHA256HashRate):
return SHA256HashRate(self.rate / other.into(self.unit).rate, self.unit)
return SHA256HashRate(self.rate / other, self.unit)
def __floordiv__(self, other: SHA256HashRate | int | float):
if isinstance(other, SHA256HashRate):
return SHA256HashRate(self.rate // other.into(self.unit).rate, self.unit)
return SHA256HashRate(self.rate // other, self.unit)
def __mul__(self, other: SHA256HashRate | int | float):
if isinstance(other, SHA256HashRate):
return SHA256HashRate(self.rate * other.into(self.unit).rate, self.unit)
return SHA256HashRate(self.rate * other, self.unit)
def into(self, other: SHA256Unit) -> SHA256HashRate:
return SHA256HashRate(
rate=self.rate / (other.value / self.unit.value), unit=other
)

View File

@@ -0,0 +1,4 @@
from .algorithm import MinerAlgo
from .firmware import MinerFirmware
from .makes import MinerMake
from .models import MinerModel

View File

@@ -0,0 +1,5 @@
from pyasic.device.algorithm.sha256 import SHA256Algo
class MinerAlgo:
SHA256 = SHA256Algo

View File

@@ -0,0 +1,68 @@
from __future__ import annotations
from enum import IntEnum
class SHA256Unit(IntEnum):
H = 1
KH = int(H) * 1000
MH = int(KH) * 1000
GH = int(MH) * 1000
TH = int(GH) * 1000
PH = int(TH) * 1000
EH = int(PH) * 1000
ZH = int(EH) * 1000
default = TH
def __str__(self):
if self.value == self.H:
return "H/s"
if self.value == self.KH:
return "KH/s"
if self.value == self.MH:
return "MH/s"
if self.value == self.GH:
return "GH/s"
if self.value == self.TH:
return "TH/s"
if self.value == self.PH:
return "PH/s"
if self.value == self.EH:
return "EH/s"
if self.value == self.ZH:
return "ZH/s"
@classmethod
def from_str(cls, value: str):
if value == "H":
return cls.H
elif value == "KH":
return cls.KH
elif value == "MH":
return cls.MH
elif value == "GH":
return cls.GH
elif value == "TH":
return cls.TH
elif value == "PH":
return cls.PH
elif value == "EH":
return cls.EH
elif value == "ZH":
return cls.ZH
return cls.default
def __repr__(self):
return str(self)
# make this json serializable
class _SHA256Algo(str):
unit = SHA256Unit
def __repr__(self):
return "SHA256Algo"
SHA256Algo = _SHA256Algo("SHA256")

27
pyasic/device/firmware.py Normal file
View File

@@ -0,0 +1,27 @@
# ------------------------------------------------------------------------------
# Copyright 2022 Upstream Data Inc -
# -
# Licensed under the Apache License, Version 2.0 (the "License"); -
# you may not use this file except in compliance with the License. -
# You may obtain a copy of the License at -
# -
# http://www.apache.org/licenses/LICENSE-2.0 -
# -
# Unless required by applicable law or agreed to in writing, software -
# distributed under the License is distributed on an "AS IS" BASIS, -
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -
# See the License for the specific language governing permissions and -
# limitations under the License. -
# ------------------------------------------------------------------------------
from enum import StrEnum
class MinerFirmware(StrEnum):
STOCK = "Stock"
BRAIINS_OS = "BOS+"
VNISH = "VNish"
EPIC = "ePIC"
HIVEON = "Hive"
LUXOS = "LuxOS"
MARATHON = "MaraFW"

27
pyasic/device/makes.py Normal file
View File

@@ -0,0 +1,27 @@
# ------------------------------------------------------------------------------
# Copyright 2022 Upstream Data Inc -
# -
# Licensed under the Apache License, Version 2.0 (the "License"); -
# you may not use this file except in compliance with the License. -
# You may obtain a copy of the License at -
# -
# http://www.apache.org/licenses/LICENSE-2.0 -
# -
# Unless required by applicable law or agreed to in writing, software -
# distributed under the License is distributed on an "AS IS" BASIS, -
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -
# See the License for the specific language governing permissions and -
# limitations under the License. -
# ------------------------------------------------------------------------------
from enum import StrEnum
class MinerMake(StrEnum):
WHATSMINER = "WhatsMiner"
ANTMINER = "AntMiner"
AVALONMINER = "AvalonMiner"
INNOSILICON = "Innosilicon"
GOLDSHELL = "Goldshell"
AURADINE = "Auradine"
EPIC = "ePIC"

318
pyasic/device/models.py Normal file
View File

@@ -0,0 +1,318 @@
from enum import StrEnum
class AntminerModels(StrEnum):
D3 = "D3"
HS3 = "HS3"
L3Plus = "L3+"
DR5 = "DR5"
L7 = "L7"
E9Pro = "E9Pro"
S9 = "S9"
S9i = "S9i"
S9j = "S9j"
T9 = "T9"
Z15 = "Z15"
S17 = "S17"
S17Plus = "S17+"
S17Pro = "S17 Pro"
S17e = "S17e"
T17 = "T17"
T17Plus = "T17+"
T17e = "T17e"
S19 = "S19"
S19NoPIC = "S19 No PIC"
S19L = "S19L"
S19Pro = "S19 Pro"
S19j = "S19j"
S19i = "S19i"
S19Plus = "S19+"
S19jNoPIC = "S19j No PIC"
S19ProPlus = "S19 Pro+"
S19jPro = "S19j Pro"
S19jProNoPIC = "S19j Pro No PIC"
S19jProPlus = "S19j Pro+"
S19jProPlusNoPIC = "S19j Pro+ No PIC"
S19XP = "S19 XP"
S19a = "S19a"
S19aPro = "S19a Pro"
S19Hydro = "S19 Hydro"
S19ProHydro = "S19 Pro Hydro"
S19ProPlusHydro = "S19 Pro+ Hydro"
S19KPro = "S19K Pro"
S19kPro = "S19k Pro"
S19kProNoPIC = "S19k Pro No PIC"
T19 = "T19"
S21 = "S21"
T21 = "T21"
class WhatsminerModels(StrEnum):
M20V10 = "M20 V10"
M20SV10 = "M20S V10"
M20SV20 = "M20S V20"
M20SV30 = "M20S V30"
M20PV10 = "M20P V10"
M20PV30 = "M20P V30"
M20SPlusV30 = "M20S+ V30"
M21V10 = "M21 V10"
M21SV20 = "M21S V20"
M21SV60 = "M21S V60"
M21SV70 = "M21S V70"
M21SPlusV20 = "M21S+ V20"
M29V10 = "M29 V10"
M30V10 = "M30 V10"
M30V20 = "M30 V20"
M30KV10 = "M30K V10"
M30LV10 = "M30L V10"
M30SV10 = "M30S V10"
M30SV20 = "M30S V20"
M30SV30 = "M30S V30"
M30SV40 = "M30S V40"
M30SV50 = "M30S V50"
M30SV60 = "M30S V60"
M30SV70 = "M30S V70"
M30SV80 = "M30S V80"
M30SVE10 = "M30S VE10"
M30SVE20 = "M30S VE20"
M30SVE30 = "M30S VE30"
M30SVE40 = "M30S VE40"
M30SVE50 = "M30S VE50"
M30SVE60 = "M30S VE60"
M30SVE70 = "M30S VE70"
M30SVF10 = "M30S VF10"
M30SVF20 = "M30S VF20"
M30SVF30 = "M30S VF30"
M30SVG10 = "M30S VG10"
M30SVG20 = "M30S VG20"
M30SVG30 = "M30S VG30"
M30SVG40 = "M30S VG40"
M30SVH10 = "M30S VH10"
M30SVH20 = "M30S VH20"
M30SVH30 = "M30S VH30"
M30SVH40 = "M30S VH40"
M30SVH50 = "M30S VH50"
M30SVH60 = "M30S VH60"
M30SVI20 = "M30S VI20"
M30SPlusV10 = "M30S+ V10"
M30SPlusV20 = "M30S+ V20"
M30SPlusV30 = "M30S+ V30"
M30SPlusV40 = "M30S+ V40"
M30SPlusV50 = "M30S+ V50"
M30SPlusV60 = "M30S+ V60"
M30SPlusV70 = "M30S+ V70"
M30SPlusV80 = "M30S+ V80"
M30SPlusV90 = "M30S+ V90"
M30SPlusV100 = "M30S+ V100"
M30SPlusVE30 = "M30S+ VE30"
M30SPlusVE40 = "M30S+ VE40"
M30SPlusVE50 = "M30S+ VE50"
M30SPlusVE60 = "M30S+ VE60"
M30SPlusVE70 = "M30S+ VE70"
M30SPlusVE80 = "M30S+ VE80"
M30SPlusVE90 = "M30S+ VE90"
M30SPlusVE100 = "M30S+ VE100"
M30SPlusVF20 = "M30S+ VF20"
M30SPlusVF30 = "M30S+ VF30"
M30SPlusVG20 = "M30S+ VG20"
M30SPlusVG30 = "M30S+ VG30"
M30SPlusVG40 = "M30S+ VG40"
M30SPlusVG50 = "M30S+ VG50"
M30SPlusVG60 = "M30S+ VG60"
M30SPlusVH10 = "M30S+ VH10"
M30SPlusVH20 = "M30S+ VH20"
M30SPlusVH30 = "M30S+ VH30"
M30SPlusVH40 = "M30S+ VH40"
M30SPlusVH50 = "M30S+ VH50"
M30SPlusVH60 = "M30S+ VH60"
M30SPlusPlusV10 = "M30S++ V10"
M30SPlusPlusV20 = "M30S++ V20"
M30SPlusPlusVE30 = "M30S++ VE30"
M30SPlusPlusVE40 = "M30S++ VE40"
M30SPlusPlusVE50 = "M30S++ VE50"
M30SPlusPlusVF40 = "M30S++ VF40"
M30SPlusPlusVG30 = "M30S++ VG30"
M30SPlusPlusVG40 = "M30S++ VG40"
M30SPlusPlusVG50 = "M30S++ VG50"
M30SPlusPlusVH10 = "M30S++ VH10"
M30SPlusPlusVH20 = "M30S++ VH20"
M30SPlusPlusVH30 = "M30S++ VH30"
M30SPlusPlusVH40 = "M30S++ VH40"
M30SPlusPlusVH50 = "M30S++ VH50"
M30SPlusPlusVH60 = "M30S++ VH60"
M30SPlusPlusVH70 = "M30S++ VH70"
M30SPlusPlusVH80 = "M30S++ VH80"
M30SPlusPlusVH90 = "M30S++ VH90"
M30SPlusPlusVH100 = "M30S++ VH100"
M30SPlusPlusVJ20 = "M30S++ VJ20"
M30SPlusPlusVJ30 = "M30S++ VJ30"
M31V10 = "M31 V10"
M31V20 = "M31 V20"
M31HV10 = "M31H V10"
M31HV40 = "M31H V40"
M31LV10 = "M30L V10"
M31SV10 = "M31S V10"
M31SV20 = "M31S V20"
M31SV30 = "M31S V30"
M31SV40 = "M31S V40"
M31SV50 = "M31S V50"
M31SV60 = "M31S V60"
M31SV70 = "M31S V70"
M31SV80 = "M31S V80"
M31SV90 = "M31S V90"
M31SVE10 = "M31S VE10"
M31SVE20 = "M31S VE20"
M31SVE30 = "M31S VE30"
M31SEV10 = "M31SE V10"
M31SEV20 = "M31SE V20"
M31SEV30 = "M31SE V30"
M31SPlusV10 = "M31S+ V10"
M31SPlusV20 = "M31S+ V20"
M31SPlusV30 = "M31S+ V30"
M31SPlusV40 = "M31S+ V40"
M31SPlusV50 = "M31S+ V50"
M31SPlusV60 = "M31S+ V60"
M31SPlusV80 = "M31S+ V80"
M31SPlusV90 = "M31S+ V90"
M31SPlusV100 = "M31S+ V100"
M31SPlusVE10 = "M31S+ VE10"
M31SPlusVE20 = "M31S+ VE20"
M31SPlusVE30 = "M31S+ VE30"
M31SPlusVE40 = "M31S+ VE40"
M31SPlusVE50 = "M31S+ VE50"
M31SPlusVE60 = "M31S+ VE60"
M31SPlusVE80 = "M31S+ VE80"
M31SPlusVF20 = "M31S+ VF20"
M31SPlusVF30 = "M31S+ VF30"
M31SPlusVG20 = "M31S+ VG20"
M31SPlusVG30 = "M31S+ VG30"
M32V10 = "M32 V10"
M32V20 = "M32 V20"
M32S = "M32S"
M33V10 = "M33 V10"
M33V20 = "M33 V20"
M33V30 = "M33 V30"
M33SVG30 = "M33S VG30"
M33SPlusVG20 = "M33S+ VG20"
M33SPlusVH20 = "M33S+ VH20"
M33SPlusVH30 = "M33S+ VH30"
M33SPlusPlusVH20 = "M33S++ VH20"
M33SPlusPlusVH30 = "M33S++ VH30"
M33SPlusPlusVG40 = "M33S++ VG40"
M34SPlusVE10 = "M34S+ VE10"
M36SVE10 = "M36S VE10"
M36SPlusVG30 = "M36S+ VG30"
M36SPlusPlusVH30 = "M36S++ VH30"
M39V10 = "M39 V10"
M39V20 = "M39 V20"
M39V30 = "M39 V30"
M50VE30 = "M50 VE30"
M50VG30 = "M50 VG30"
M50VH10 = "M50 VH10"
M50VH20 = "M50 VH20"
M50VH30 = "M50 VH30"
M50VH40 = "M50 VH40"
M50VH50 = "M50 VH50"
M50VH60 = "M50 VH60"
M50VH70 = "M50 VH70"
M50VH80 = "M50 VH80"
M50VJ10 = "M50 VJ10"
M50VJ20 = "M50 VJ20"
M50VJ30 = "M50 VJ30"
M50SVJ10 = "M50S VJ10"
M50SVJ20 = "M50S VJ20"
M50SVJ30 = "M50S VJ30"
M50SVH10 = "M50S VH10"
M50SVH20 = "M50S VH20"
M50SVH30 = "M50S VH30"
M50SVH40 = "M50S VH40"
M50SVH50 = "M50S VH50"
M50SPlusVH30 = "M50S+ VH30"
M50SPlusVH40 = "M50S+ VH40"
M50SPlusVJ30 = "M50S+ VJ30"
M50SPlusVK20 = "M50S+ VK20"
M50SPlusPlusVK10 = "M50S++ VK10"
M50SPlusPlusVK20 = "M50S++ VK20"
M50SPlusPlusVK30 = "M50S++ VK30"
M53VH30 = "M53 VH30"
M53SVH30 = "M53S VH30"
M53SVJ40 = "M53S VJ40"
M53SPlusVJ30 = "M53S+ VJ30"
M53SPlusPlusVK10 = "M53S++ VK10"
M56VH30 = "M56 VH30"
M56SVH30 = "M56S VH30"
M56SPlusVJ30 = "M56S+ VJ30"
M59VH30 = "M59 VH30"
M60VK10 = "M60 VK10"
M60VK20 = "M60 VK20"
M60VK30 = "M60 VK30"
M60VK40 = "M60 VK40"
M60SVK10 = "M60S VK10"
M60SVK20 = "M60S VK20"
M60SVK30 = "M60S VK30"
M60SVK40 = "M60S VK40"
M63VK10 = "M63 VK10"
M63VK20 = "M63 VK20"
M63VK30 = "M63 VK30"
M63SVK10 = "M63S VK10"
M63SVK20 = "M63S VK20"
M63SVK30 = "M63S VK30"
M66VK20 = "M66 VK20"
M66VK30 = "M66 VK30"
M66SVK20 = "M66S VK20"
M66SVK30 = "M66S VK30"
M66SVK40 = "M66S VK40"
class AvalonminerModels(StrEnum):
Avalon721 = "Avalon 721"
Avalon741 = "Avalon 741"
Avalon761 = "Avalon 761"
Avalon821 = "Avalon 821"
Avalon841 = "Avalon 841"
Avalon851 = "Avalon 851"
Avalon921 = "Avalon 921"
Avalon1026 = "Avalon 1026"
Avalon1047 = "Avalon 1047"
Avalon1066 = "Avalon 1066"
Avalon1166Pro = "Avalon 1166 Pro"
Avalon1246 = "Avalon 1246"
class InnosiliconModels(StrEnum):
T3HPlus = "T3H+"
A10X = "A10X"
class GoldshellModels(StrEnum):
CK5 = "CK5"
HS5 = "HS5"
KD5 = "KD5"
KDMax = "KD Max"
KDBoxII = "KD Box II"
KDBoxPro = "KD Box Pro"
class ePICModels(StrEnum):
BM520i = "BlockMiner 520i"
BM720i = "BlockMiner 720i"
class AuradineModels(StrEnum):
AT1500 = "AT1500"
AT2860 = "AT2860"
AT2880 = "AT2880"
AI2500 = "AI2500"
AI3680 = "AI3680"
AD2500 = "AD2500"
AD3500 = "AD3500"
class MinerModel:
ANTMINER = AntminerModels
WHATSMINER = WhatsminerModels
AVALONMINER = AvalonminerModels
INNOSILICON = InnosiliconModels
GOLDSHELL = GoldshellModels
AURADINE = AuradineModels
EPIC = ePICModels

View File

@@ -20,7 +20,16 @@ from typing import List, Union
from pyasic.errors import APIError from pyasic.errors import APIError
from pyasic.miners import AnyMiner from pyasic.miners import AnyMiner
from pyasic.miners.backends import AntminerModern, BOSMiner, BTMiner from pyasic.miners.backends import AntminerModern, BOSMiner, BTMiner
from pyasic.miners.models import S9, S17, T17, S17e, S17Plus, S17Pro, T17e, T17Plus from pyasic.miners.device.models import (
S9,
S17,
T17,
S17e,
S17Plus,
S17Pro,
T17e,
T17Plus,
)
FAN_USAGE = 50 # 50 W per fan FAN_USAGE = 50 # 50 W per fan

View File

@@ -15,7 +15,7 @@
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
from pyasic.miners.backends import AntminerOld from pyasic.miners.backends import AntminerOld
from pyasic.miners.models import S17, S17e, S17Plus, S17Pro from pyasic.miners.device.models import S17, S17e, S17Plus, S17Pro
class BMMinerS17(AntminerOld, S17): class BMMinerS17(AntminerOld, S17):

View File

@@ -15,7 +15,7 @@
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
from pyasic.miners.backends import AntminerOld from pyasic.miners.backends import AntminerOld
from pyasic.miners.models import T17, T17e, T17Plus from pyasic.miners.device.models import T17, T17e, T17Plus
class BMMinerT17(AntminerOld, T17): class BMMinerT17(AntminerOld, T17):

View File

@@ -15,7 +15,7 @@
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
from pyasic.miners.backends import AntminerModern from pyasic.miners.backends import AntminerModern
from pyasic.miners.models import ( from pyasic.miners.device.models import (
S19, S19,
S19L, S19L,
S19XP, S19XP,
@@ -26,12 +26,12 @@ from pyasic.miners.models import (
S19j, S19j,
S19jNoPIC, S19jNoPIC,
S19jPro, S19jPro,
S19KPro,
S19Plus, S19Plus,
S19Pro, S19Pro,
S19ProHydro, S19ProHydro,
S19ProPlus, S19ProPlus,
S19ProPlusHydro, S19ProPlusHydro,
S19KPro,
) )

View File

@@ -15,7 +15,7 @@
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
from pyasic.miners.backends import AntminerModern from pyasic.miners.backends import AntminerModern
from pyasic.miners.models import T19 from pyasic.miners.device.models import T19
class BMMinerT19(AntminerModern, T19): class BMMinerT19(AntminerModern, T19):

View File

@@ -15,7 +15,7 @@
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
from pyasic.miners.backends import AntminerModern from pyasic.miners.backends import AntminerModern
from pyasic.miners.models import S21 from pyasic.miners.device.models import S21
class BMMinerS21(AntminerModern, S21): class BMMinerS21(AntminerModern, S21):

View File

@@ -15,7 +15,7 @@
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
from pyasic.miners.backends import AntminerModern from pyasic.miners.backends import AntminerModern
from pyasic.miners.models import T21 from pyasic.miners.device.models import T21
class BMMinerT21(AntminerModern, T21): class BMMinerT21(AntminerModern, T21):

View File

@@ -15,7 +15,7 @@
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
from pyasic.miners.backends import AntminerModern from pyasic.miners.backends import AntminerModern
from pyasic.miners.models import HS3 from pyasic.miners.device.models import HS3
class BMMinerHS3(AntminerModern, HS3): class BMMinerHS3(AntminerModern, HS3):

View File

@@ -15,7 +15,7 @@
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
from pyasic.miners.backends import AntminerOld from pyasic.miners.backends import AntminerOld
from pyasic.miners.models import L3Plus from pyasic.miners.device.models import L3Plus
class BMMinerL3Plus(AntminerOld, L3Plus): class BMMinerL3Plus(AntminerOld, L3Plus):

View File

@@ -14,7 +14,7 @@
# limitations under the License. - # limitations under the License. -
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
from pyasic.miners.backends import AntminerModern from pyasic.miners.backends import AntminerModern
from pyasic.miners.models import L7 from pyasic.miners.device.models import L7
class BMMinerL7(AntminerModern, L7): class BMMinerL7(AntminerModern, L7):

View File

@@ -15,7 +15,7 @@
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
from pyasic.miners.backends import AntminerModern from pyasic.miners.backends import AntminerModern
from pyasic.miners.models import E9Pro from pyasic.miners.device.models import E9Pro
class BMMinerE9Pro(AntminerModern, E9Pro): class BMMinerE9Pro(AntminerModern, E9Pro):

View File

@@ -15,7 +15,7 @@
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
from pyasic.miners.backends import BMMiner from pyasic.miners.backends import BMMiner
from pyasic.miners.models import S9, S9i, S9j from pyasic.miners.device.models import S9, S9i, S9j
class BMMinerS9(BMMiner, S9): class BMMinerS9(BMMiner, S9):

View File

@@ -15,7 +15,7 @@
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
from pyasic.miners.backends import BMMiner from pyasic.miners.backends import BMMiner
from pyasic.miners.models import T9 from pyasic.miners.device.models import T9
class BMMinerT9(BMMiner, T9): class BMMinerT9(BMMiner, T9):

View File

@@ -15,7 +15,7 @@
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
from pyasic.miners.backends import BOSMiner from pyasic.miners.backends import BOSMiner
from pyasic.miners.models import S17, S17e, S17Plus, S17Pro from pyasic.miners.device.models import S17, S17e, S17Plus, S17Pro
class BOSMinerS17(BOSMiner, S17): class BOSMinerS17(BOSMiner, S17):

View File

@@ -15,7 +15,7 @@
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
from pyasic.miners.backends import BOSMiner from pyasic.miners.backends import BOSMiner
from pyasic.miners.models import T17, T17e, T17Plus from pyasic.miners.device.models import T17, T17e, T17Plus
class BOSMinerT17(BOSMiner, T17): class BOSMinerT17(BOSMiner, T17):

View File

@@ -15,7 +15,7 @@
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
from pyasic.miners.backends import BOSer from pyasic.miners.backends import BOSer
from pyasic.miners.models import ( from pyasic.miners.device.models import (
S19, S19,
S19XP, S19XP,
S19a, S19a,

View File

@@ -15,7 +15,7 @@
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
from pyasic.miners.backends import BOSer from pyasic.miners.backends import BOSer
from pyasic.miners.models import T19 from pyasic.miners.device.models import T19
class BOSMinerT19(BOSer, T19): class BOSMinerT19(BOSer, T19):

View File

@@ -15,7 +15,7 @@
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
from pyasic.miners.backends import BOSer from pyasic.miners.backends import BOSer
from pyasic.miners.models import S21 from pyasic.miners.device.models import S21
class BOSMinerS21(BOSer, S21): class BOSMinerS21(BOSer, S21):

View File

@@ -15,7 +15,7 @@
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
from pyasic.miners.backends import BOSMiner from pyasic.miners.backends import BOSMiner
from pyasic.miners.models import S9 from pyasic.miners.device.models import S9
class BOSMinerS9(BOSMiner, S9): class BOSMinerS9(BOSMiner, S9):

View File

@@ -15,7 +15,7 @@
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
from pyasic.miners.backends import AntminerOld from pyasic.miners.backends import AntminerOld
from pyasic.miners.models import Z15 from pyasic.miners.device.models import Z15
class CGMinerZ15(AntminerOld, Z15): class CGMinerZ15(AntminerOld, Z15):

View File

@@ -14,7 +14,7 @@
# limitations under the License. - # limitations under the License. -
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
from pyasic.miners.backends import AntminerOld from pyasic.miners.backends import AntminerOld
from pyasic.miners.models import D3 from pyasic.miners.device.models import D3
class CGMinerD3(AntminerOld, D3): class CGMinerD3(AntminerOld, D3):

View File

@@ -15,7 +15,7 @@
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
from pyasic.miners.backends import AntminerOld from pyasic.miners.backends import AntminerOld
from pyasic.miners.models import DR5 from pyasic.miners.device.models import DR5
class CGMinerDR5(AntminerOld, DR5): class CGMinerDR5(AntminerOld, DR5):

View File

@@ -15,7 +15,15 @@
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
from pyasic.miners.backends import ePIC from pyasic.miners.backends import ePIC
from pyasic.miners.models import S19, S19XP, S19j, S19jPro, S19jProPlus, S19kPro, S19Pro from pyasic.miners.device.models import (
S19,
S19XP,
S19j,
S19jPro,
S19jProPlus,
S19kPro,
S19Pro,
)
class ePICS19(ePIC, S19): class ePICS19(ePIC, S19):

View File

@@ -15,7 +15,7 @@
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
from pyasic.miners.backends import ePIC from pyasic.miners.backends import ePIC
from pyasic.miners.models import S21 from pyasic.miners.device.models import S21
class ePICS21(ePIC, S21): class ePICS21(ePIC, S21):

View File

@@ -15,7 +15,7 @@
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
from pyasic.miners.backends import ePIC from pyasic.miners.backends import ePIC
from pyasic.miners.models import T21 from pyasic.miners.device.models import T21
class ePICT21(ePIC, T21): class ePICT21(ePIC, T21):

View File

@@ -18,11 +18,11 @@ from typing import List, Optional
import asyncssh import asyncssh
from pyasic.data import HashBoard from pyasic.data import AlgoHashRate, HashBoard, HashUnit
from pyasic.errors import APIError from pyasic.errors import APIError
from pyasic.miners.backends import Hiveon from pyasic.miners.backends import Hiveon
from pyasic.miners.data import DataFunction, DataLocations, DataOptions, RPCAPICommand from pyasic.miners.data import DataFunction, DataLocations, DataOptions, RPCAPICommand
from pyasic.miners.models import T9 from pyasic.miners.device.models import T9
HIVEON_T9_DATA_LOC = DataLocations( HIVEON_T9_DATA_LOC = DataLocations(
**{ **{
@@ -121,7 +121,9 @@ class HiveonT9(Hiveon, T9):
chips += rpc_stats["STATS"][1][f"chain_acn{chipset}"] chips += rpc_stats["STATS"][1][f"chain_acn{chipset}"]
except (KeyError, IndexError): except (KeyError, IndexError):
pass pass
hashboards[board].hashrate = round(hashrate / 1000, 2) hashboards[board].hashrate = AlgoHashRate.SHA256(
hashrate, HashUnit.SHA256.GH
).into(self.algo.unit.default)
hashboards[board].chips = chips hashboards[board].chips = chips
return hashboards return hashboards

View File

@@ -15,7 +15,14 @@
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
from pyasic.miners.backends import LUXMiner from pyasic.miners.backends import LUXMiner
from pyasic.miners.models import S19, S19XP, S19jPro, S19jProPlus, S19kPro, S19Pro from pyasic.miners.device.models import (
S19,
S19XP,
S19jPro,
S19jProPlus,
S19kPro,
S19Pro,
)
class LUXMinerS19(LUXMiner, S19): class LUXMinerS19(LUXMiner, S19):

View File

@@ -15,7 +15,7 @@
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
from pyasic.miners.backends import LUXMiner from pyasic.miners.backends import LUXMiner
from pyasic.miners.models import T19 from pyasic.miners.device.models import T19
class LUXMinerT19(LUXMiner, T19): class LUXMinerT19(LUXMiner, T19):

View File

@@ -15,7 +15,7 @@
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
from pyasic.miners.backends import LUXMiner from pyasic.miners.backends import LUXMiner
from pyasic.miners.models import S21 from pyasic.miners.device.models import S21
class LUXMinerS21(LUXMiner, S21): class LUXMinerS21(LUXMiner, S21):

View File

@@ -15,7 +15,7 @@
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
from pyasic.miners.backends import LUXMiner from pyasic.miners.backends import LUXMiner
from pyasic.miners.models import S9 from pyasic.miners.device.models import S9
class LUXMinerS9(LUXMiner, S9): class LUXMinerS9(LUXMiner, S9):

View File

@@ -15,7 +15,15 @@
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
from pyasic.miners.backends import MaraMiner from pyasic.miners.backends import MaraMiner
from pyasic.miners.models import S19, S19XP, S19j, S19jNoPIC, S19jPro, S19KPro, S19Pro from pyasic.miners.device.models import (
S19,
S19XP,
S19j,
S19jNoPIC,
S19jPro,
S19KPro,
S19Pro,
)
class MaraS19(MaraMiner, S19): class MaraS19(MaraMiner, S19):

View File

@@ -15,7 +15,7 @@
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
from pyasic.miners.backends import MaraMiner from pyasic.miners.backends import MaraMiner
from pyasic.miners.models import S21 from pyasic.miners.device.models import S21
class MaraS21(MaraMiner, S21): class MaraS21(MaraMiner, S21):

View File

@@ -15,7 +15,7 @@
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
from pyasic.miners.backends import MaraMiner from pyasic.miners.backends import MaraMiner
from pyasic.miners.models import T21 from pyasic.miners.device.models import T21
class MaraT21(MaraMiner, T21): class MaraT21(MaraMiner, T21):

View File

@@ -14,7 +14,7 @@
# limitations under the License. - # limitations under the License. -
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
from pyasic.miners.backends import VNish from pyasic.miners.backends import VNish
from pyasic.miners.models import S17Plus, S17Pro from pyasic.miners.device.models import S17Plus, S17Pro
class VNishS17Plus(VNish, S17Plus): class VNishS17Plus(VNish, S17Plus):

View File

@@ -15,7 +15,7 @@
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
from pyasic.miners.backends import VNish from pyasic.miners.backends import VNish
from pyasic.miners.models import ( from pyasic.miners.device.models import (
S19, S19,
S19XP, S19XP,
S19a, S19a,

View File

@@ -15,7 +15,7 @@
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
from pyasic.miners.backends import VNish from pyasic.miners.backends import VNish
from pyasic.miners.models import T19 from pyasic.miners.device.models import T19
class VNishT19(VNish, T19): class VNishT19(VNish, T19):

View File

@@ -15,7 +15,7 @@
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
from pyasic.miners.backends import VNish from pyasic.miners.backends import VNish
from pyasic.miners.models import L3Plus from pyasic.miners.device.models import L3Plus
class VnishL3Plus(VNish, L3Plus): class VnishL3Plus(VNish, L3Plus):

View File

@@ -15,7 +15,7 @@
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
from pyasic.miners.backends import VNish from pyasic.miners.backends import VNish
from pyasic.miners.models import L7 from pyasic.miners.device.models import L7
class VnishL7(VNish, L7): class VnishL7(VNish, L7):

View File

@@ -1,5 +1,5 @@
from pyasic.miners.backends import Auradine from pyasic.miners.backends import Auradine
from pyasic.miners.models import AuradineAT1500 from pyasic.miners.device.models import AuradineAT1500
class AuradineFluxAT1500(AuradineAT1500, Auradine): class AuradineFluxAT1500(AuradineAT1500, Auradine):

View File

@@ -1,5 +1,5 @@
from pyasic.miners.backends import Auradine from pyasic.miners.backends import Auradine
from pyasic.miners.models import AuradineAT2860, AuradineAT2880 from pyasic.miners.device.models import AuradineAT2860, AuradineAT2880
class AuradineFluxAT2860(AuradineAT2860, Auradine): class AuradineFluxAT2860(AuradineAT2860, Auradine):

View File

@@ -1,5 +1,5 @@
from pyasic.miners.backends import Auradine from pyasic.miners.backends import Auradine
from pyasic.miners.models import AuradineAI2500 from pyasic.miners.device.models import AuradineAI2500
class AuradineFluxAI2500(AuradineAI2500, Auradine): class AuradineFluxAI2500(AuradineAI2500, Auradine):

View File

@@ -1,5 +1,5 @@
from pyasic.miners.backends import Auradine from pyasic.miners.backends import Auradine
from pyasic.miners.models import AuradineAI3680 from pyasic.miners.device.models import AuradineAI3680
class AuradineFluxAI3680(AuradineAI3680, Auradine): class AuradineFluxAI3680(AuradineAI3680, Auradine):

View File

@@ -1,5 +1,5 @@
from pyasic.miners.backends import Auradine from pyasic.miners.backends import Auradine
from pyasic.miners.models import AuradineAD2500 from pyasic.miners.device.models import AuradineAD2500
class AuradineFluxAD2500(AuradineAD2500, Auradine): class AuradineFluxAD2500(AuradineAD2500, Auradine):

View File

@@ -1,5 +1,5 @@
from pyasic.miners.backends import Auradine from pyasic.miners.backends import Auradine
from pyasic.miners.models import AuradineAD3500 from pyasic.miners.device.models import AuradineAD3500
class AuradineFluxAD3500(AuradineAD3500, Auradine): class AuradineFluxAD3500(AuradineAD3500, Auradine):

View File

@@ -15,7 +15,7 @@
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
from pyasic.miners.backends import AvalonMiner from pyasic.miners.backends import AvalonMiner
from pyasic.miners.models import Avalon1026 from pyasic.miners.device.models import Avalon1026
class CGMinerAvalon1026(AvalonMiner, Avalon1026): class CGMinerAvalon1026(AvalonMiner, Avalon1026):

View File

@@ -15,7 +15,7 @@
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
from pyasic.miners.backends import AvalonMiner from pyasic.miners.backends import AvalonMiner
from pyasic.miners.models import Avalon1047 from pyasic.miners.device.models import Avalon1047
class CGMinerAvalon1047(AvalonMiner, Avalon1047): class CGMinerAvalon1047(AvalonMiner, Avalon1047):

View File

@@ -15,7 +15,7 @@
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
from pyasic.miners.backends import AvalonMiner from pyasic.miners.backends import AvalonMiner
from pyasic.miners.models import Avalon1066 from pyasic.miners.device.models import Avalon1066
class CGMinerAvalon1066(AvalonMiner, Avalon1066): class CGMinerAvalon1066(AvalonMiner, Avalon1066):

View File

@@ -15,7 +15,7 @@
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
from pyasic.miners.backends import AvalonMiner from pyasic.miners.backends import AvalonMiner
from pyasic.miners.models import Avalon1166Pro from pyasic.miners.device.models import Avalon1166Pro
class CGMinerAvalon1166Pro(AvalonMiner, Avalon1166Pro): class CGMinerAvalon1166Pro(AvalonMiner, Avalon1166Pro):

View File

@@ -15,7 +15,7 @@
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
from pyasic.miners.backends import AvalonMiner from pyasic.miners.backends import AvalonMiner
from pyasic.miners.models import Avalon1246 from pyasic.miners.device.models import Avalon1246
class CGMinerAvalon1246(AvalonMiner, Avalon1246): class CGMinerAvalon1246(AvalonMiner, Avalon1246):

View File

@@ -15,7 +15,7 @@
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
from pyasic.miners.backends import AvalonMiner from pyasic.miners.backends import AvalonMiner
from pyasic.miners.models import Avalon721 from pyasic.miners.device.models import Avalon721
class CGMinerAvalon721(AvalonMiner, Avalon721): class CGMinerAvalon721(AvalonMiner, Avalon721):

View File

@@ -15,7 +15,7 @@
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
from pyasic.miners.backends import AvalonMiner from pyasic.miners.backends import AvalonMiner
from pyasic.miners.models import Avalon741 from pyasic.miners.device.models import Avalon741
class CGMinerAvalon741(AvalonMiner, Avalon741): class CGMinerAvalon741(AvalonMiner, Avalon741):

View File

@@ -15,7 +15,7 @@
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
from pyasic.miners.backends import AvalonMiner from pyasic.miners.backends import AvalonMiner
from pyasic.miners.models import Avalon761 from pyasic.miners.device.models import Avalon761
class CGMinerAvalon761(AvalonMiner, Avalon761): class CGMinerAvalon761(AvalonMiner, Avalon761):

View File

@@ -15,7 +15,7 @@
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
from pyasic.miners.backends import AvalonMiner from pyasic.miners.backends import AvalonMiner
from pyasic.miners.models import Avalon821 from pyasic.miners.device.models import Avalon821
class CGMinerAvalon821(AvalonMiner, Avalon821): class CGMinerAvalon821(AvalonMiner, Avalon821):

View File

@@ -15,7 +15,7 @@
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
from pyasic.miners.backends import AvalonMiner from pyasic.miners.backends import AvalonMiner
from pyasic.miners.models import Avalon841 from pyasic.miners.device.models import Avalon841
class CGMinerAvalon841(AvalonMiner, Avalon841): class CGMinerAvalon841(AvalonMiner, Avalon841):

View File

@@ -15,7 +15,7 @@
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
from pyasic.miners.backends import AvalonMiner from pyasic.miners.backends import AvalonMiner
from pyasic.miners.models import Avalon851 from pyasic.miners.device.models import Avalon851
class CGMinerAvalon851(AvalonMiner, Avalon851): class CGMinerAvalon851(AvalonMiner, Avalon851):

View File

@@ -15,7 +15,7 @@
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
from pyasic.miners.backends import AvalonMiner from pyasic.miners.backends import AvalonMiner
from pyasic.miners.models import Avalon921 from pyasic.miners.device.models import Avalon921
class CGMinerAvalon921(AvalonMiner, Avalon921): class CGMinerAvalon921(AvalonMiner, Avalon921):

View File

@@ -17,12 +17,11 @@
from typing import List, Optional, Union from typing import List, Optional, Union
from pyasic.config import MinerConfig, MiningModeConfig from pyasic.config import MinerConfig, MiningModeConfig
from pyasic.data import Fan, HashBoard from pyasic.data import AlgoHashRate, Fan, HashBoard, HashUnit
from pyasic.data.error_codes import MinerErrorData, X19Error from pyasic.data.error_codes import MinerErrorData, X19Error
from pyasic.errors import APIError from pyasic.errors import APIError
from pyasic.miners.backends.bmminer import BMMiner from pyasic.miners.backends.bmminer import BMMiner
from pyasic.miners.backends.cgminer import CGMiner from pyasic.miners.backends.cgminer import CGMiner
from pyasic.miners.base import BaseMiner
from pyasic.miners.data import ( from pyasic.miners.data import (
DataFunction, DataFunction,
DataLocations, DataLocations,
@@ -219,9 +218,9 @@ class AntminerModern(BMMiner):
if rpc_stats is not None: if rpc_stats is not None:
try: try:
for board in rpc_stats["STATS"][0]["chain"]: for board in rpc_stats["STATS"][0]["chain"]:
hashboards[board["index"]].hashrate = round( hashboards[board["index"]].hashrate = AlgoHashRate.SHA256(
board["rate_real"] / 1000, 2 board["rate_real"], HashUnit.SHA256.GH
) ).into(self.algo.unit.default)
hashboards[board["index"]].chips = board["asic_num"] hashboards[board["index"]].chips = board["asic_num"]
board_temp_data = list( board_temp_data = list(
filter(lambda x: not x == 0, board["temp_pcb"]) filter(lambda x: not x == 0, board["temp_pcb"])
@@ -274,12 +273,9 @@ class AntminerModern(BMMiner):
rate_unit = rpc_stats["STATS"][1]["rate_unit"] rate_unit = rpc_stats["STATS"][1]["rate_unit"]
except KeyError: except KeyError:
rate_unit = "GH" rate_unit = "GH"
if rate_unit == "GH": return AlgoHashRate.SHA256(
return round(expected_rate / 1000, 2) expected_rate, HashUnit.SHA256.from_str(rate_unit)
if rate_unit == "MH": ).int(self.algo.unit.default)
return round(expected_rate / 1000000, 2)
else:
return round(expected_rate, 2)
except LookupError: except LookupError:
pass pass
@@ -553,7 +549,9 @@ class AntminerOld(CGMiner):
hashrate = boards[1].get(f"chain_rate{i}") hashrate = boards[1].get(f"chain_rate{i}")
if hashrate: if hashrate:
hashboard.hashrate = round(float(hashrate) / 1000, 2) hashboard.hashrate = AlgoHashRate.SHA256(
hashrate, HashUnit.SHA256.GH
).into(self.algo.unit.default)
chips = boards[1].get(f"chain_acn{i}") chips = boards[1].get(f"chain_acn{i}")
if chips: if chips:

View File

@@ -18,9 +18,8 @@ from enum import Enum
from typing import List, Optional from typing import List, Optional
from pyasic.config import MinerConfig from pyasic.config import MinerConfig
from pyasic.data import Fan, HashBoard from pyasic.data import AlgoHashRate, Fan, HashBoard, HashUnit
from pyasic.errors import APIError from pyasic.errors import APIError
from pyasic.miners.base import BaseMiner
from pyasic.miners.data import ( from pyasic.miners.data import (
DataFunction, DataFunction,
DataLocations, DataLocations,
@@ -28,6 +27,7 @@ from pyasic.miners.data import (
RPCAPICommand, RPCAPICommand,
WebAPICommand, WebAPICommand,
) )
from pyasic.miners.device.firmware import StockFirmware
from pyasic.rpc.gcminer import GCMinerRPCAPI from pyasic.rpc.gcminer import GCMinerRPCAPI
from pyasic.web.auradine import AuradineWebAPI from pyasic.web.auradine import AuradineWebAPI
@@ -113,7 +113,7 @@ class AuradineLEDCodes(Enum):
return self.value return self.value
class Auradine(BaseMiner): class Auradine(StockFirmware):
"""Base handler for Auradine miners""" """Base handler for Auradine miners"""
_rpc_cls = GCMinerRPCAPI _rpc_cls = GCMinerRPCAPI
@@ -245,9 +245,9 @@ class Auradine(BaseMiner):
if rpc_summary is not None: if rpc_summary is not None:
try: try:
return round( return AlgoHashRate.SHA256(
float(float(rpc_summary["SUMMARY"][0]["MHS 5s"]) / 1000000), 2 rpc_summary["SUMMARY"][0]["MHS 5s"], HashUnit.SHA256.MH
) ).into(self.algo.unit.default)
except (LookupError, ValueError, TypeError): except (LookupError, ValueError, TypeError):
pass pass
@@ -274,9 +274,9 @@ class Auradine(BaseMiner):
try: try:
for board in rpc_devs["DEVS"]: for board in rpc_devs["DEVS"]:
b_id = board["ID"] - 1 b_id = board["ID"] - 1
hashboards[b_id].hashrate = round( hashboards[b_id].hashrate = AlgoHashRate.SHA256(
float(float(board["MHS 5s"]) / 1000000), 2 board["MHS 5s"], HashUnit.SHA256.MH
) ).into(self.algo.unit.default)
hashboards[b_id].temp = round(float(float(board["Temperature"])), 2) hashboards[b_id].temp = round(float(float(board["Temperature"])), 2)
hashboards[b_id].missing = False hashboards[b_id].missing = False
except LookupError: except LookupError:

View File

@@ -17,7 +17,7 @@
import re import re
from typing import List, Optional from typing import List, Optional
from pyasic.data import Fan, HashBoard from pyasic.data import AlgoHashRate, Fan, HashBoard, HashUnit
from pyasic.errors import APIError from pyasic.errors import APIError
from pyasic.miners.backends.cgminer import CGMiner from pyasic.miners.backends.cgminer import CGMiner
from pyasic.miners.data import DataFunction, DataLocations, DataOptions, RPCAPICommand from pyasic.miners.data import DataFunction, DataLocations, DataOptions, RPCAPICommand
@@ -182,7 +182,9 @@ class AvalonMiner(CGMiner):
if rpc_devs is not None: if rpc_devs is not None:
try: try:
return round(float(rpc_devs["DEVS"][0]["MHS 1m"] / 1000000), 2) return AlgoHashRate.SHA256(
rpc_devs["DEVS"][0]["MHS 1m"], HashUnit.SHA256.MH
).into(self.algo.unit.default)
except (KeyError, IndexError, ValueError, TypeError): except (KeyError, IndexError, ValueError, TypeError):
pass pass
@@ -213,7 +215,9 @@ class AvalonMiner(CGMiner):
try: try:
board_hr = parsed_stats["MGHS"][board] board_hr = parsed_stats["MGHS"][board]
hashboards[board].hashrate = round(float(board_hr) / 1000, 2) hashboards[board].hashrate = AlgoHashRate.SHA256(
board_hr, HashUnit.SHA256.GH
).into(self.algo.unit.default)
except LookupError: except LookupError:
pass pass
@@ -245,7 +249,9 @@ class AvalonMiner(CGMiner):
try: try:
unparsed_stats = rpc_stats["STATS"][0]["MM ID0"] unparsed_stats = rpc_stats["STATS"][0]["MM ID0"]
parsed_stats = self.parse_stats(unparsed_stats) parsed_stats = self.parse_stats(unparsed_stats)
return round(float(parsed_stats["GHSmm"]) / 1000, 2) return AlgoHashRate.SHA256(
parsed_stats["GHSmm"], HashUnit.SHA256.GH
).int(self.algo.unit.default)
except (IndexError, KeyError, ValueError, TypeError): except (IndexError, KeyError, ValueError, TypeError):
pass pass

View File

@@ -17,10 +17,10 @@
from typing import List, Optional from typing import List, Optional
from pyasic.config import MinerConfig from pyasic.config import MinerConfig
from pyasic.data import Fan, HashBoard from pyasic.data import AlgoHashRate, Fan, HashBoard, HashUnit
from pyasic.errors import APIError from pyasic.errors import APIError
from pyasic.miners.base import BaseMiner
from pyasic.miners.data import DataFunction, DataLocations, DataOptions, RPCAPICommand from pyasic.miners.data import DataFunction, DataLocations, DataOptions, RPCAPICommand
from pyasic.miners.device.firmware import StockFirmware
from pyasic.rpc.bfgminer import BFGMinerRPCAPI from pyasic.rpc.bfgminer import BFGMinerRPCAPI
BFGMINER_DATA_LOC = DataLocations( BFGMINER_DATA_LOC = DataLocations(
@@ -53,7 +53,7 @@ BFGMINER_DATA_LOC = DataLocations(
) )
class BFGMiner(BaseMiner): class BFGMiner(StockFirmware):
"""Base handler for BFGMiner based miners.""" """Base handler for BFGMiner based miners."""
_rpc_cls = BFGMinerRPCAPI _rpc_cls = BFGMinerRPCAPI
@@ -115,7 +115,9 @@ class BFGMiner(BaseMiner):
if rpc_summary is not None: if rpc_summary is not None:
try: try:
return round(float(rpc_summary["SUMMARY"][0]["MHS 20s"] / 1000000), 2) return AlgoHashRate.SHA256(
rpc_summary["SUMMARY"][0]["MHS 20s"], HashUnit.SHA256.MH
).into(self.algo.unit.default)
except (LookupError, ValueError, TypeError): except (LookupError, ValueError, TypeError):
pass pass
@@ -159,7 +161,9 @@ class BFGMiner(BaseMiner):
hashrate = boards[1].get(f"chain_rate{i}") hashrate = boards[1].get(f"chain_rate{i}")
if hashrate: if hashrate:
hashboard.hashrate = round(float(hashrate) / 1000, 2) hashboard.hashrate = AlgoHashRate.SHA256(
hashrate, HashUnit.SHA256.GH
).into(self.algo.unit.default)
chips = boards[1].get(f"chain_acn{i}") chips = boards[1].get(f"chain_acn{i}")
if chips: if chips:
@@ -218,11 +222,8 @@ class BFGMiner(BaseMiner):
rate_unit = rpc_stats["STATS"][1]["rate_unit"] rate_unit = rpc_stats["STATS"][1]["rate_unit"]
except KeyError: except KeyError:
rate_unit = "GH" rate_unit = "GH"
if rate_unit == "GH": return AlgoHashRate.SHA256(
return round(expected_rate / 1000, 2) expected_rate, HashUnit.SHA256.from_str(rate_unit)
if rate_unit == "MH": ).int(self.algo.unit.default)
return round(expected_rate / 1000000, 2)
else:
return round(expected_rate, 2)
except LookupError: except LookupError:
pass pass

View File

@@ -17,10 +17,10 @@
from typing import List, Optional from typing import List, Optional
from pyasic.config import MinerConfig from pyasic.config import MinerConfig
from pyasic.data import Fan, HashBoard from pyasic.data import AlgoHashRate, Fan, HashBoard, HashUnit
from pyasic.errors import APIError from pyasic.errors import APIError
from pyasic.miners.base import BaseMiner
from pyasic.miners.data import DataFunction, DataLocations, DataOptions, RPCAPICommand from pyasic.miners.data import DataFunction, DataLocations, DataOptions, RPCAPICommand
from pyasic.miners.device.firmware import StockFirmware
from pyasic.rpc.bmminer import BMMinerRPCAPI from pyasic.rpc.bmminer import BMMinerRPCAPI
BMMINER_DATA_LOC = DataLocations( BMMINER_DATA_LOC = DataLocations(
@@ -57,7 +57,7 @@ BMMINER_DATA_LOC = DataLocations(
) )
class BMMiner(BaseMiner): class BMMiner(StockFirmware):
"""Base handler for BMMiner based miners.""" """Base handler for BMMiner based miners."""
_rpc_cls = BMMinerRPCAPI _rpc_cls = BMMinerRPCAPI
@@ -119,7 +119,9 @@ class BMMiner(BaseMiner):
if rpc_summary is not None: if rpc_summary is not None:
try: try:
return round(float(rpc_summary["SUMMARY"][0]["GHS 5s"] / 1000), 2) return AlgoHashRate.SHA256(
rpc_summary["SUMMARY"][0]["GHS 5s"], HashUnit.SHA256.GH
).into(self.algo.unit.default)
except (LookupError, ValueError, TypeError): except (LookupError, ValueError, TypeError):
pass pass
@@ -176,7 +178,9 @@ class BMMiner(BaseMiner):
hashrate = boards[1].get(f"chain_rate{i}") hashrate = boards[1].get(f"chain_rate{i}")
if hashrate: if hashrate:
hashboard.hashrate = round(float(hashrate) / 1000, 2) hashboard.hashrate = AlgoHashRate.SHA256(
hashrate, HashUnit.SHA256.GH
).into(self.algo.unit.default)
chips = boards[1].get(f"chain_acn{i}") chips = boards[1].get(f"chain_acn{i}")
if chips: if chips:
@@ -234,12 +238,9 @@ class BMMiner(BaseMiner):
rate_unit = rpc_stats["STATS"][1]["rate_unit"] rate_unit = rpc_stats["STATS"][1]["rate_unit"]
except KeyError: except KeyError:
rate_unit = "GH" rate_unit = "GH"
if rate_unit == "GH": return AlgoHashRate.SHA256(
return round(expected_rate / 1000, 2) expected_rate, HashUnit.SHA256.from_str(rate_unit)
if rate_unit == "MH": ).int(self.algo.unit.default)
return round(expected_rate / 1000000, 2)
else:
return round(expected_rate, 2)
except LookupError: except LookupError:
pass pass

View File

@@ -21,10 +21,9 @@ import toml
from pyasic.config import MinerConfig from pyasic.config import MinerConfig
from pyasic.config.mining import MiningModePowerTune from pyasic.config.mining import MiningModePowerTune
from pyasic.data import Fan, HashBoard from pyasic.data import AlgoHashRate, Fan, HashBoard, HashUnit
from pyasic.data.error_codes import BraiinsOSError, MinerErrorData from pyasic.data.error_codes import BraiinsOSError, MinerErrorData
from pyasic.errors import APIError from pyasic.errors import APIError
from pyasic.miners.base import BaseMiner
from pyasic.miners.data import ( from pyasic.miners.data import (
DataFunction, DataFunction,
DataLocations, DataLocations,
@@ -32,6 +31,7 @@ from pyasic.miners.data import (
RPCAPICommand, RPCAPICommand,
WebAPICommand, WebAPICommand,
) )
from pyasic.miners.device.firmware import BraiinsOSFirmware
from pyasic.rpc.bosminer import BOSMinerRPCAPI from pyasic.rpc.bosminer import BOSMinerRPCAPI
from pyasic.ssh.braiins_os import BOSMinerSSH from pyasic.ssh.braiins_os import BOSMinerSSH
from pyasic.web.braiins_os import BOSerWebAPI, BOSMinerWebAPI from pyasic.web.braiins_os import BOSerWebAPI, BOSMinerWebAPI
@@ -95,7 +95,7 @@ BOSMINER_DATA_LOC = DataLocations(
) )
class BOSMiner(BaseMiner): class BOSMiner(BraiinsOSFirmware):
"""Handler for old versions of BraiinsOS+ (pre-gRPC)""" """Handler for old versions of BraiinsOS+ (pre-gRPC)"""
_rpc_cls = BOSMinerRPCAPI _rpc_cls = BOSMinerRPCAPI
@@ -105,8 +105,6 @@ class BOSMiner(BaseMiner):
_ssh_cls = BOSMinerSSH _ssh_cls = BOSMinerSSH
ssh: BOSMinerSSH ssh: BOSMinerSSH
firmware = "BOS+"
data_locations = BOSMINER_DATA_LOC data_locations = BOSMINER_DATA_LOC
supports_shutdown = True supports_shutdown = True
@@ -352,7 +350,9 @@ class BOSMiner(BaseMiner):
if rpc_summary is not None: if rpc_summary is not None:
try: try:
return round(float(rpc_summary["SUMMARY"][0]["MHS 1m"] / 1000000), 2) return AlgoHashRate.SHA256(
rpc_summary["SUMMARY"][0]["MHS 1m"], HashUnit.SHA256.MH
).into(self.algo.unit.default)
except (KeyError, IndexError, ValueError, TypeError): except (KeyError, IndexError, ValueError, TypeError):
pass pass
@@ -422,8 +422,9 @@ class BOSMiner(BaseMiner):
for board in rpc_devs["DEVS"]: for board in rpc_devs["DEVS"]:
_id = board["ID"] - offset _id = board["ID"] - offset
hashrate = round(float(board["MHS 1m"] / 1000000), 2) hashboards[_id].hashrate = AlgoHashRate.SHA256(
hashboards[_id].hashrate = hashrate board["MHS 1m"], HashUnit.SHA256.MH
).into(self.algo.unit.default)
except (IndexError, KeyError): except (IndexError, KeyError):
pass pass
@@ -531,11 +532,12 @@ class BOSMiner(BaseMiner):
expected_hashrate = round(float(board["Nominal MHS"] / 1000000), 2) expected_hashrate = round(float(board["Nominal MHS"] / 1000000), 2)
if expected_hashrate: if expected_hashrate:
hr_list.append(expected_hashrate) hr_list.append(expected_hashrate)
if len(hr_list) == 0: if len(hr_list) == 0:
return 0 return AlgoHashRate.SHA256(0)
else: else:
return round( return AlgoHashRate.SHA256(
(sum(hr_list) / len(hr_list)) * self.expected_hashboards, 2 (sum(hr_list) / len(hr_list)) * self.expected_hashboards
) )
except (IndexError, KeyError): except (IndexError, KeyError):
pass pass
@@ -635,7 +637,7 @@ BOSER_DATA_LOC = DataLocations(
) )
class BOSer(BaseMiner): class BOSer(BraiinsOSFirmware):
"""Handler for new versions of BraiinsOS+ (post-gRPC)""" """Handler for new versions of BraiinsOS+ (post-gRPC)"""
_rpc_cls = BOSMinerRPCAPI _rpc_cls = BOSMinerRPCAPI
@@ -643,8 +645,6 @@ class BOSer(BaseMiner):
_web_cls = BOSerWebAPI _web_cls = BOSerWebAPI
web: BOSerWebAPI web: BOSerWebAPI
firmware = "BOS+"
data_locations = BOSER_DATA_LOC data_locations = BOSER_DATA_LOC
supports_autotuning = True supports_autotuning = True
@@ -788,7 +788,9 @@ class BOSer(BaseMiner):
if rpc_summary is not None: if rpc_summary is not None:
try: try:
return round(float(rpc_summary["SUMMARY"][0]["MHS 1m"] / 1000000), 2) return AlgoHashRate.SHA256(
rpc_summary["SUMMARY"][0]["MHS 1m"], HashUnit.SHA256.MH
).into(self.algo.unit.default)
except (KeyError, IndexError, ValueError, TypeError): except (KeyError, IndexError, ValueError, TypeError):
pass pass
@@ -803,7 +805,10 @@ class BOSer(BaseMiner):
if grpc_miner_details is not None: if grpc_miner_details is not None:
try: try:
return grpc_miner_details["stickerHashrate"]["gigahashPerSecond"] / 1000 return AlgoHashRate.SHA256(
grpc_miner_details["stickerHashrate"]["gigahashPerSecond"],
HashUnit.SHA256.GH,
).into(self.algo.unit.default)
except LookupError: except LookupError:
pass pass
@@ -832,13 +837,12 @@ class BOSer(BaseMiner):
] ]
if board.get("stats") is not None: if board.get("stats") is not None:
if not board["stats"]["realHashrate"]["last5S"] == {}: if not board["stats"]["realHashrate"]["last5S"] == {}:
hashboards[idx].hashrate = round( hashboards[idx].hashrate = AlgoHashRate.SHA256(
board["stats"]["realHashrate"]["last5S"][ board["stats"]["realHashrate"]["last5S"][
"gigahashPerSecond" "gigahashPerSecond"
] ],
/ 1000, HashUnit.SHA256.GH,
2, ).into(self.algo.unit.default)
)
hashboards[idx].missing = False hashboards[idx].missing = False
return hashboards return hashboards

View File

@@ -18,11 +18,11 @@ import logging
from typing import List, Optional from typing import List, Optional
from pyasic.config import MinerConfig, MiningModeConfig from pyasic.config import MinerConfig, MiningModeConfig
from pyasic.data import Fan, HashBoard from pyasic.data import AlgoHashRate, Fan, HashBoard, HashUnit
from pyasic.data.error_codes import MinerErrorData, WhatsminerError from pyasic.data.error_codes import MinerErrorData, WhatsminerError
from pyasic.errors import APIError from pyasic.errors import APIError
from pyasic.miners.base import BaseMiner
from pyasic.miners.data import DataFunction, DataLocations, DataOptions, RPCAPICommand from pyasic.miners.data import DataFunction, DataLocations, DataOptions, RPCAPICommand
from pyasic.miners.device.firmware import StockFirmware
from pyasic.rpc.btminer import BTMinerRPCAPI from pyasic.rpc.btminer import BTMinerRPCAPI
BTMINER_DATA_LOC = DataLocations( BTMINER_DATA_LOC = DataLocations(
@@ -110,7 +110,7 @@ BTMINER_DATA_LOC = DataLocations(
) )
class BTMiner(BaseMiner): class BTMiner(StockFirmware):
"""Base handler for BTMiner based miners.""" """Base handler for BTMiner based miners."""
_rpc_cls = BTMinerRPCAPI _rpc_cls = BTMinerRPCAPI
@@ -395,7 +395,9 @@ class BTMiner(BaseMiner):
if rpc_summary is not None: if rpc_summary is not None:
try: try:
return round(float(rpc_summary["SUMMARY"][0]["MHS 1m"] / 1000000), 2) return AlgoHashRate.SHA256(
rpc_summary["SUMMARY"][0]["MHS 1m"], HashUnit.SHA256.MH
).into(self.algo.unit.default)
except LookupError: except LookupError:
pass pass
@@ -423,9 +425,9 @@ class BTMiner(BaseMiner):
self.expected_hashboards += 1 self.expected_hashboards += 1
hashboards[board["ASC"]].chip_temp = round(board["Chip Temp Avg"]) hashboards[board["ASC"]].chip_temp = round(board["Chip Temp Avg"])
hashboards[board["ASC"]].temp = round(board["Temperature"]) hashboards[board["ASC"]].temp = round(board["Temperature"])
hashboards[board["ASC"]].hashrate = round( hashboards[board["ASC"]].hashrate = AlgoHashRate.SHA256(
float(board["MHS 1m"] / 1000000), 2 board["MHS 1m"], HashUnit.SHA256.MH
) ).into(self.algo.unit.default)
hashboards[board["ASC"]].chips = board["Effective Chips"] hashboards[board["ASC"]].chips = board["Effective Chips"]
hashboards[board["ASC"]].serial_number = board["PCB SN"] hashboards[board["ASC"]].serial_number = board["PCB SN"]
hashboards[board["ASC"]].missing = False hashboards[board["ASC"]].missing = False
@@ -571,7 +573,10 @@ class BTMiner(BaseMiner):
try: try:
expected_hashrate = rpc_summary["SUMMARY"][0]["Factory GHS"] expected_hashrate = rpc_summary["SUMMARY"][0]["Factory GHS"]
if expected_hashrate: if expected_hashrate:
return round(expected_hashrate / 1000, 2) return AlgoHashRate.SHA256(
expected_hashrate, HashUnit.SHA256.GH
).int(self.algo.unit.default)
except LookupError: except LookupError:
pass pass

View File

@@ -17,9 +17,10 @@
from typing import Optional from typing import Optional
from pyasic.config import MinerConfig from pyasic.config import MinerConfig
from pyasic.data import AlgoHashRate, HashUnit
from pyasic.errors import APIError from pyasic.errors import APIError
from pyasic.miners.base import BaseMiner
from pyasic.miners.data import DataFunction, DataLocations, DataOptions, RPCAPICommand from pyasic.miners.data import DataFunction, DataLocations, DataOptions, RPCAPICommand
from pyasic.miners.device.firmware import StockFirmware
from pyasic.rpc.cgminer import CGMinerRPCAPI from pyasic.rpc.cgminer import CGMinerRPCAPI
CGMINER_DATA_LOC = DataLocations( CGMINER_DATA_LOC = DataLocations(
@@ -56,7 +57,7 @@ CGMINER_DATA_LOC = DataLocations(
) )
class CGMiner(BaseMiner): class CGMiner(StockFirmware):
"""Base handler for CGMiner based miners""" """Base handler for CGMiner based miners"""
_rpc_cls = CGMinerRPCAPI _rpc_cls = CGMinerRPCAPI
@@ -117,9 +118,9 @@ class CGMiner(BaseMiner):
if rpc_summary is not None: if rpc_summary is not None:
try: try:
return round( return AlgoHashRate.SHA256(
float(float(rpc_summary["SUMMARY"][0]["GHS 5s"]) / 1000), 2 rpc_summary["SUMMARY"][0]["GHS 5s"], HashUnit.SHA256.GH
) ).into(self.algo.unit.default)
except (LookupError, ValueError, TypeError): except (LookupError, ValueError, TypeError):
pass pass

View File

@@ -17,12 +17,12 @@
from typing import List, Optional from typing import List, Optional
from pyasic.config import MinerConfig from pyasic.config import MinerConfig
from pyasic.data import Fan, HashBoard from pyasic.data import AlgoHashRate, Fan, HashBoard, HashUnit
from pyasic.data.error_codes import MinerErrorData, X19Error from pyasic.data.error_codes import MinerErrorData, X19Error
from pyasic.errors import APIError from pyasic.errors import APIError
from pyasic.logger import logger from pyasic.logger import logger
from pyasic.miners.base import BaseMiner
from pyasic.miners.data import DataFunction, DataLocations, DataOptions, WebAPICommand from pyasic.miners.data import DataFunction, DataLocations, DataOptions, WebAPICommand
from pyasic.miners.device.firmware import ePICFirmware
from pyasic.web.epic import ePICWebAPI from pyasic.web.epic import ePICWebAPI
EPIC_DATA_LOC = DataLocations( EPIC_DATA_LOC = DataLocations(
@@ -86,14 +86,12 @@ EPIC_DATA_LOC = DataLocations(
) )
class ePIC(BaseMiner): class ePIC(ePICFirmware):
"""Handler for miners with the ePIC board""" """Handler for miners with the ePIC board"""
_web_cls = ePICWebAPI _web_cls = ePICWebAPI
web: ePICWebAPI web: ePICWebAPI
firmware = "ePIC"
data_locations = EPIC_DATA_LOC data_locations = EPIC_DATA_LOC
supports_shutdown = True supports_shutdown = True
@@ -248,7 +246,9 @@ class ePIC(BaseMiner):
if web_summary["HBs"] is not None: if web_summary["HBs"] is not None:
for hb in web_summary["HBs"]: for hb in web_summary["HBs"]:
hashrate += hb["Hashrate"][0] hashrate += hb["Hashrate"][0]
return round(float(float(hashrate / 1000000)), 2) return AlgoHashRate.SHA256(hashrate, HashUnit.SHA256.MH).into(
HashUnit.SHA256.TH
)
except (LookupError, ValueError, TypeError): except (LookupError, ValueError, TypeError):
pass pass
@@ -270,7 +270,9 @@ class ePIC(BaseMiner):
ideal = hb["Hashrate"][1] / 100 ideal = hb["Hashrate"][1] / 100
hashrate += hb["Hashrate"][0] / ideal hashrate += hb["Hashrate"][0] / ideal
return round(float(float(hashrate / 1000000)), 2) return AlgoHashRate.SHA256(hashrate, HashUnit.SHA256.GH).int(
self.algo.unit.default
)
except (LookupError, ValueError, TypeError): except (LookupError, ValueError, TypeError):
pass pass
@@ -342,7 +344,9 @@ class ePIC(BaseMiner):
hashrate = hb["Hashrate"][0] hashrate = hb["Hashrate"][0]
# Update the Hashboard object # Update the Hashboard object
hb_list[hb["Index"]].missing = False hb_list[hb["Index"]].missing = False
hb_list[hb["Index"]].hashrate = round(hashrate / 1000000, 2) hb_list[hb["Index"]].hashrate = AlgoHashRate.SHA256(
hashrate, HashUnit.SHA256.MH
).into(self.algo.unit.default)
hb_list[hb["Index"]].chips = num_of_chips hb_list[hb["Index"]].chips = num_of_chips
hb_list[hb["Index"]].temp = hb["Temperature"] hb_list[hb["Index"]].temp = hb["Temperature"]
return hb_list return hb_list

View File

@@ -16,7 +16,7 @@
from typing import List from typing import List
from pyasic.config import MinerConfig, MiningModeConfig from pyasic.config import MinerConfig, MiningModeConfig
from pyasic.data import HashBoard from pyasic.data import AlgoHashRate, HashBoard, HashUnit
from pyasic.errors import APIError from pyasic.errors import APIError
from pyasic.logger import logger from pyasic.logger import logger
from pyasic.miners.backends import BFGMiner from pyasic.miners.backends import BFGMiner
@@ -158,9 +158,9 @@ class GoldshellMiner(BFGMiner):
if board.get("ID") is not None: if board.get("ID") is not None:
try: try:
b_id = board["ID"] b_id = board["ID"]
hashboards[b_id].hashrate = round( hashboards[b_id].hashrate = AlgoHashRate.SHA256(
board["MHS 20s"] / 1000000, 2 board["MHS 20s"], HashUnit.SHA256.MH
) ).into(self.algo.unit.default)
hashboards[b_id].temp = board["tstemp-2"] hashboards[b_id].temp = board["tstemp-2"]
hashboards[b_id].missing = False hashboards[b_id].missing = False
except KeyError: except KeyError:

View File

@@ -15,7 +15,8 @@
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
from pyasic.miners.backends import BMMiner from pyasic.miners.backends import BMMiner
from pyasic.miners.device.firmware import HiveonFirmware
class Hiveon(BMMiner): class Hiveon(BMMiner, HiveonFirmware):
firmware = "Hive" pass

View File

@@ -16,7 +16,7 @@
from typing import List, Optional from typing import List, Optional
from pyasic.config import MinerConfig from pyasic.config import MinerConfig
from pyasic.data import Fan, HashBoard from pyasic.data import AlgoHashRate, Fan, HashBoard, HashUnit
from pyasic.data.error_codes import MinerErrorData from pyasic.data.error_codes import MinerErrorData
from pyasic.data.error_codes.innosilicon import InnosiliconError from pyasic.data.error_codes.innosilicon import InnosiliconError
from pyasic.errors import APIError from pyasic.errors import APIError
@@ -182,20 +182,21 @@ class Innosilicon(CGMiner):
if web_get_all is not None: if web_get_all is not None:
try: try:
if "Hash Rate H" in web_get_all["total_hash"].keys(): if "Hash Rate H" in web_get_all["total_hash"].keys():
return round( return AlgoHashRate.SHA256(
float(web_get_all["total_hash"]["Hash Rate H"] / 1000000000000), web_get_all["total_hash"]["Hash Rate H"], HashUnit.SHA256.H
2, ).into(self.algo.unit.default)
)
elif "Hash Rate" in web_get_all["total_hash"].keys(): elif "Hash Rate" in web_get_all["total_hash"].keys():
return round( return AlgoHashRate.SHA256(
float(web_get_all["total_hash"]["Hash Rate"] / 1000000), 5 web_get_all["total_hash"]["Hash Rate"], HashUnit.SHA256.MH
) ).into(self.algo.unit.default)
except KeyError: except KeyError:
pass pass
if rpc_summary is not None: if rpc_summary is not None:
try: try:
return round(float(rpc_summary["SUMMARY"][0]["MHS 1m"] / 1000000), 2) return AlgoHashRate.SHA256(
rpc_summary["SUMMARY"][0]["MHS 1m"], HashUnit.SHA256.MH
).into(self.algo.unit.default)
except (KeyError, IndexError): except (KeyError, IndexError):
pass pass
@@ -247,9 +248,9 @@ class Innosilicon(CGMiner):
hashrate = board.get("Hash Rate H") hashrate = board.get("Hash Rate H")
if hashrate: if hashrate:
hashboards[idx].hashrate = round( hashboards[idx].hashrate = AlgoHashRate.SHA256(
hashrate / 1000000000000, 2 hashrate, HashUnit.SHA256.H
) ).into(self.algo.unit.default)
chip_temp = board.get("Temp max") chip_temp = board.get("Temp max")
if chip_temp: if chip_temp:

View File

@@ -16,10 +16,10 @@
from typing import List, Optional from typing import List, Optional
from pyasic.config import MinerConfig from pyasic.config import MinerConfig
from pyasic.data import Fan, HashBoard from pyasic.data import AlgoHashRate, Fan, HashBoard, HashUnit
from pyasic.errors import APIError from pyasic.errors import APIError
from pyasic.miners.base import BaseMiner
from pyasic.miners.data import DataFunction, DataLocations, DataOptions, RPCAPICommand from pyasic.miners.data import DataFunction, DataLocations, DataOptions, RPCAPICommand
from pyasic.miners.device.firmware import LuxOSFirmware
from pyasic.rpc.luxminer import LUXMinerRPCAPI from pyasic.rpc.luxminer import LUXMinerRPCAPI
LUXMINER_DATA_LOC = DataLocations( LUXMINER_DATA_LOC = DataLocations(
@@ -55,14 +55,12 @@ LUXMINER_DATA_LOC = DataLocations(
) )
class LUXMiner(BaseMiner): class LUXMiner(LuxOSFirmware):
"""Handler for LuxOS miners""" """Handler for LuxOS miners"""
_rpc_cls = LUXMinerRPCAPI _rpc_cls = LUXMinerRPCAPI
rpc: LUXMinerRPCAPI rpc: LUXMinerRPCAPI
firmware = "LuxOS"
data_locations = LUXMINER_DATA_LOC data_locations = LUXMINER_DATA_LOC
async def _get_session(self) -> Optional[str]: async def _get_session(self) -> Optional[str]:
@@ -173,7 +171,9 @@ class LUXMiner(BaseMiner):
if rpc_summary is not None: if rpc_summary is not None:
try: try:
return round(float(rpc_summary["SUMMARY"][0]["GHS 5s"] / 1000), 2) return AlgoHashRate.SHA256(
rpc_summary["SUMMARY"][0]["GHS 5s"], HashUnit.SHA256.GH
).into(self.algo.unit.default)
except (LookupError, ValueError, TypeError): except (LookupError, ValueError, TypeError):
pass pass
@@ -217,7 +217,9 @@ class LUXMiner(BaseMiner):
hashrate = boards[1].get(f"chain_rate{i}") hashrate = boards[1].get(f"chain_rate{i}")
if hashrate: if hashrate:
hashboard.hashrate = round(float(hashrate) / 1000, 2) hashboard.hashrate = AlgoHashRate.SHA256(
hashrate, HashUnit.SHA256.GH
).into(self.algo.unit.default)
chips = boards[1].get(f"chain_acn{i}") chips = boards[1].get(f"chain_acn{i}")
if chips: if chips:
@@ -275,12 +277,9 @@ class LUXMiner(BaseMiner):
rate_unit = rpc_stats["STATS"][1]["rate_unit"] rate_unit = rpc_stats["STATS"][1]["rate_unit"]
except KeyError: except KeyError:
rate_unit = "GH" rate_unit = "GH"
if rate_unit == "GH": return AlgoHashRate.SHA256(
return round(expected_rate / 1000, 2) expected_rate, HashUnit.SHA256.from_str(rate_unit)
if rate_unit == "MH": ).int(self.algo.unit.default)
return round(expected_rate / 1000000, 2)
else:
return round(expected_rate, 2)
except LookupError: except LookupError:
pass pass

View File

@@ -2,10 +2,10 @@ from typing import List, Optional
from pyasic import MinerConfig from pyasic import MinerConfig
from pyasic.config import MiningModeConfig from pyasic.config import MiningModeConfig
from pyasic.data import Fan, HashBoard from pyasic.data import AlgoHashRate, Fan, HashBoard, HashUnit
from pyasic.errors import APIError from pyasic.errors import APIError
from pyasic.miners.base import BaseMiner
from pyasic.miners.data import DataFunction, DataLocations, DataOptions, WebAPICommand from pyasic.miners.data import DataFunction, DataLocations, DataOptions, WebAPICommand
from pyasic.miners.device.firmware import MaraFirmware
from pyasic.misc import merge_dicts from pyasic.misc import merge_dicts
from pyasic.web.marathon import MaraWebAPI from pyasic.web.marathon import MaraWebAPI
@@ -63,14 +63,12 @@ MARA_DATA_LOC = DataLocations(
) )
class MaraMiner(BaseMiner): class MaraMiner(MaraFirmware):
_web_cls = MaraWebAPI _web_cls = MaraWebAPI
web: MaraWebAPI web: MaraWebAPI
data_locations = MARA_DATA_LOC data_locations = MARA_DATA_LOC
firmware = "MaraFW"
async def fault_light_off(self) -> bool: async def fault_light_off(self) -> bool:
res = await self.web.set_locate_miner(blinking=False) res = await self.web.set_locate_miner(blinking=False)
return res.get("blinking") is False return res.get("blinking") is False
@@ -172,7 +170,9 @@ class MaraMiner(BaseMiner):
try: try:
for hb in web_hashboards["hashboards"]: for hb in web_hashboards["hashboards"]:
idx = hb["index"] idx = hb["index"]
hashboards[idx].hashrate = round(hb["hashrate_average"] / 1000, 2) hashboards[idx].hashrate = AlgoHashRate.SHA256(
hb["hashrate_average"], HashUnit.SHA256.GH
).into(self.algo.unit.default)
hashboards[idx].temp = round( hashboards[idx].temp = round(
sum(hb["temperature_pcb"]) / len(hb["temperature_pcb"]), 2 sum(hb["temperature_pcb"]) / len(hb["temperature_pcb"]), 2
) )
@@ -234,7 +234,9 @@ class MaraMiner(BaseMiner):
if web_brief is not None: if web_brief is not None:
try: try:
return round(web_brief["hashrate_realtime"], 2) return AlgoHashRate.SHA256(
web_brief["hashrate_realtime"], HashUnit.SHA256.TH
).into(self.algo.unit.default)
except LookupError: except LookupError:
pass pass
@@ -278,7 +280,9 @@ class MaraMiner(BaseMiner):
if web_brief is not None: if web_brief is not None:
try: try:
return round(web_brief["hashrate_ideal"] / 1000, 2) return AlgoHashRate.SHA256(
web_brief["hashrate_ideal"], HashUnit.SHA256.GH
).int(self.algo.unit.default)
except LookupError: except LookupError:
pass pass

View File

@@ -17,6 +17,7 @@
from typing import Optional from typing import Optional
from pyasic import MinerConfig from pyasic import MinerConfig
from pyasic.data import AlgoHashRate, HashUnit
from pyasic.errors import APIError from pyasic.errors import APIError
from pyasic.miners.backends.bmminer import BMMiner from pyasic.miners.backends.bmminer import BMMiner
from pyasic.miners.data import ( from pyasic.miners.data import (
@@ -26,6 +27,7 @@ from pyasic.miners.data import (
RPCAPICommand, RPCAPICommand,
WebAPICommand, WebAPICommand,
) )
from pyasic.miners.device.firmware import VNishFirmware
from pyasic.web.vnish import VNishWebAPI from pyasic.web.vnish import VNishWebAPI
VNISH_DATA_LOC = DataLocations( VNISH_DATA_LOC = DataLocations(
@@ -82,7 +84,7 @@ VNISH_DATA_LOC = DataLocations(
) )
class VNish(BMMiner): class VNish(BMMiner, VNishFirmware):
"""Handler for VNish miners""" """Handler for VNish miners"""
_web_cls = VNishWebAPI _web_cls = VNishWebAPI
@@ -90,8 +92,6 @@ class VNish(BMMiner):
supports_shutdown = True supports_shutdown = True
firmware = "VNish"
data_locations = VNISH_DATA_LOC data_locations = VNISH_DATA_LOC
async def restart_backend(self) -> bool: async def restart_backend(self) -> bool:
@@ -187,9 +187,9 @@ class VNish(BMMiner):
if rpc_summary is not None: if rpc_summary is not None:
try: try:
return round( return AlgoHashRate.SHA256(
float(float(rpc_summary["SUMMARY"][0]["GHS 5s"]) / 1000), 2 rpc_summary["SUMMARY"][0]["GHS 5s"], HashUnit.SHA256.GH
) ).into(self.algo.unit.default)
except (LookupError, ValueError, TypeError): except (LookupError, ValueError, TypeError):
pass pass

View File

@@ -20,7 +20,12 @@ from typing import List, Optional, Protocol, Tuple, Type, TypeVar, Union
from pyasic.config import MinerConfig from pyasic.config import MinerConfig
from pyasic.data import Fan, HashBoard, MinerData from pyasic.data import Fan, HashBoard, MinerData
from pyasic.data.device import DeviceInfo
from pyasic.data.error_codes import MinerErrorData from pyasic.data.error_codes import MinerErrorData
from pyasic.device import MinerModel
from pyasic.device.algorithm import MinerAlgo
from pyasic.device.firmware import MinerFirmware
from pyasic.device.makes import MinerMake
from pyasic.errors import APIError from pyasic.errors import APIError
from pyasic.logger import logger from pyasic.logger import logger
from pyasic.miners.data import DataLocations, DataOptions, RPCAPICommand, WebAPICommand from pyasic.miners.data import DataLocations, DataOptions, RPCAPICommand, WebAPICommand
@@ -36,9 +41,10 @@ class MinerProtocol(Protocol):
web: _web_cls = None web: _web_cls = None
ssh: _ssh_cls = None ssh: _ssh_cls = None
make: str = None make: MinerMake = None
raw_model: str = None raw_model: MinerModel = None
firmware: str = None firmware: MinerFirmware = None
algo = MinerAlgo.SHA256
expected_hashboards: int = 3 expected_hashboards: int = 3
expected_chips: int = None expected_chips: int = None
@@ -79,6 +85,12 @@ class MinerProtocol(Protocol):
model_data.append(f"({self.firmware})") model_data.append(f"({self.firmware})")
return " ".join(model_data) return " ".join(model_data)
@property
def device_info(self) -> DeviceInfo:
return DeviceInfo(
make=self.make, model=self.raw_model, firmware=self.firmware, algo=self.algo
)
@property @property
def api(self): def api(self):
return self.rpc return self.rpc
@@ -183,6 +195,14 @@ class MinerProtocol(Protocol):
""" """
return self.model return self.model
async def get_device_info(self) -> Optional[DeviceInfo]:
"""Get device information, including model, make, and firmware.
Returns:
A dataclass containing device information.
"""
return self.device_info
async def get_api_ver(self) -> Optional[str]: async def get_api_ver(self) -> Optional[str]:
"""Get the API version of the miner and is as a string. """Get the API version of the miner and is as a string.
@@ -476,14 +496,14 @@ class MinerProtocol(Protocol):
""" """
data = MinerData( data = MinerData(
ip=str(self.ip), ip=str(self.ip),
make=self.make, device_info=self.device_info,
model=self.model,
expected_chips=( expected_chips=(
self.expected_chips * self.expected_hashboards self.expected_chips * self.expected_hashboards
if self.expected_chips is not None if self.expected_chips is not None
else 0 else 0
), ),
expected_hashboards=self.expected_hashboards, expected_hashboards=self.expected_hashboards,
expected_fans=self.expected_fans,
hashboards=[ hashboards=[
HashBoard(slot=i, expected_chips=self.expected_chips) HashBoard(slot=i, expected_chips=self.expected_chips)
for i in range(self.expected_hashboards) for i in range(self.expected_hashboards)

View File

@@ -15,8 +15,7 @@
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
from pyasic.miners.backends import ePIC from pyasic.miners.backends import ePIC
from pyasic.miners.models import BlockMiner520i from pyasic.miners.device.models import BlockMiner520i, BlockMiner720i
from pyasic.miners.models import BlockMiner720i
class ePICBlockMiner520i(ePIC, BlockMiner520i): class ePICBlockMiner520i(ePIC, BlockMiner520i):

View File

View File

@@ -0,0 +1,46 @@
# ------------------------------------------------------------------------------
# Copyright 2022 Upstream Data Inc -
# -
# Licensed under the Apache License, Version 2.0 (the "License"); -
# you may not use this file except in compliance with the License. -
# You may obtain a copy of the License at -
# -
# http://www.apache.org/licenses/LICENSE-2.0 -
# -
# Unless required by applicable law or agreed to in writing, software -
# distributed under the License is distributed on an "AS IS" BASIS, -
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -
# See the License for the specific language governing permissions and -
# limitations under the License. -
# ------------------------------------------------------------------------------
from pyasic.device.firmware import MinerFirmware
from pyasic.miners.base import BaseMiner
class StockFirmware(BaseMiner):
firmware = MinerFirmware.STOCK
class BraiinsOSFirmware(BaseMiner):
firmware = MinerFirmware.BRAIINS_OS
class VNishFirmware(BaseMiner):
firmware = MinerFirmware.VNISH
class ePICFirmware(BaseMiner):
firmware = MinerFirmware.EPIC
class HiveonFirmware(BaseMiner):
firmware = MinerFirmware.HIVEON
class LuxOSFirmware(BaseMiner):
firmware = MinerFirmware.LUXOS
class MaraFirmware(BaseMiner):
firmware = MinerFirmware.MARATHON

View File

@@ -14,32 +14,33 @@
# limitations under the License. - # limitations under the License. -
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
from pyasic.device.makes import MinerMake
from pyasic.miners.base import BaseMiner from pyasic.miners.base import BaseMiner
class WhatsMinerMake(BaseMiner): class WhatsMinerMake(BaseMiner):
make = "WhatsMiner" make = MinerMake.WHATSMINER
class AntMinerMake(BaseMiner): class AntMinerMake(BaseMiner):
make = "AntMiner" make = MinerMake.ANTMINER
class AvalonMinerMake(BaseMiner): class AvalonMinerMake(BaseMiner):
make = "AvalonMiner" make = MinerMake.AVALONMINER
class InnosiliconMake(BaseMiner): class InnosiliconMake(BaseMiner):
make = "Innosilicon" make = MinerMake.INNOSILICON
class GoldshellMake(BaseMiner): class GoldshellMake(BaseMiner):
make = "Goldshell" make = MinerMake.GOLDSHELL
class AuradineMake(BaseMiner): class AuradineMake(BaseMiner):
make = "Auradine" make = MinerMake.AURADINE
class ePICMake(BaseMiner): class ePICMake(BaseMiner):
make = "ePIC" make = MinerMake.EPIC

View File

@@ -17,7 +17,7 @@
from .antminer import * from .antminer import *
from .auradine import * from .auradine import *
from .avalonminer import * from .avalonminer import *
from .epic import *
from .goldshell import * from .goldshell import *
from .innosilicon import * from .innosilicon import *
from .whatsminer import * from .whatsminer import *
from .epic import *

View File

@@ -13,11 +13,11 @@
# 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.device.models import MinerModel
from pyasic.miners.makes import AntMinerMake from pyasic.miners.device.makes import AntMinerMake
class Z15(AntMinerMake): class Z15(AntMinerMake):
raw_model = "Z15" raw_model = MinerModel.ANTMINER.Z15
expected_chips = 3 expected_chips = 3
expected_fans = 2

View File

@@ -13,29 +13,33 @@
# 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.device.models import MinerModel
from pyasic.miners.makes import AntMinerMake from pyasic.miners.device.makes import AntMinerMake
class S17(AntMinerMake): class S17(AntMinerMake):
raw_model = "S17" raw_model = MinerModel.ANTMINER.S17
expected_chips = 48 expected_chips = 48
expected_fans = 4 expected_fans = 4
class S17Plus(AntMinerMake): class S17Plus(AntMinerMake):
raw_model = "S17+" raw_model = MinerModel.ANTMINER.S17Plus
expected_chips = 65 expected_chips = 65
expected_fans = 4 expected_fans = 4
class S17Pro(AntMinerMake): class S17Pro(AntMinerMake):
raw_model = "S17 Pro" raw_model = MinerModel.ANTMINER.S17Pro
expected_chips = 48 expected_chips = 48
expected_fans = 4 expected_fans = 4
class S17e(AntMinerMake): class S17e(AntMinerMake):
raw_model = "S17e" raw_model = MinerModel.ANTMINER.S17e
expected_chips = 135 expected_chips = 135
expected_fans = 4 expected_fans = 4

View File

@@ -13,23 +13,26 @@
# 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.device.models import MinerModel
from pyasic.miners.makes import AntMinerMake from pyasic.miners.device.makes import AntMinerMake
class T17(AntMinerMake): class T17(AntMinerMake):
raw_model = "T17" raw_model = MinerModel.ANTMINER.T17
expected_chips = 30 expected_chips = 30
expected_fans = 4 expected_fans = 4
class T17Plus(AntMinerMake): class T17Plus(AntMinerMake):
raw_model = "T17+" raw_model = MinerModel.ANTMINER.T17Plus
expected_chips = 44 expected_chips = 44
expected_fans = 4 expected_fans = 4
class T17e(AntMinerMake): class T17e(AntMinerMake):
raw_model = "T17e" raw_model = MinerModel.ANTMINER.T17e
expected_chips = 78 expected_chips = 78
expected_fans = 4 expected_fans = 4

View File

@@ -13,140 +13,162 @@
# 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.device.models import MinerModel
from pyasic.miners.makes import AntMinerMake from pyasic.miners.device.makes import AntMinerMake
class S19(AntMinerMake): class S19(AntMinerMake):
raw_model = "S19" raw_model = MinerModel.ANTMINER.S19
expected_chips = 76 expected_chips = 76
expected_fans = 4 expected_fans = 4
class S19NoPIC(AntMinerMake): class S19NoPIC(AntMinerMake):
raw_model = "S19 No PIC" raw_model = MinerModel.ANTMINER.S19NoPIC
expected_chips = 88 expected_chips = 88
expected_fans = 4 expected_fans = 4
class S19Pro(AntMinerMake): class S19Pro(AntMinerMake):
raw_model = "S19 Pro" raw_model = MinerModel.ANTMINER.S19Pro
expected_chips = 114 expected_chips = 114
expected_fans = 4 expected_fans = 4
class S19i(AntMinerMake): class S19i(AntMinerMake):
raw_model = "S19i" raw_model = MinerModel.ANTMINER.S19i
expected_chips = 80 expected_chips = 80
expected_fans = 4 expected_fans = 4
class S19Plus(AntMinerMake): class S19Plus(AntMinerMake):
raw_model = "S19+" raw_model = MinerModel.ANTMINER.S19Plus
expected_chips = 80 expected_chips = 80
expected_fans = 4 expected_fans = 4
class S19ProPlus(AntMinerMake): class S19ProPlus(AntMinerMake):
raw_model = "S19 Pro+" raw_model = MinerModel.ANTMINER.S19ProPlus
expected_chips = 120 expected_chips = 120
expected_fans = 4 expected_fans = 4
class S19XP(AntMinerMake): class S19XP(AntMinerMake):
raw_model = "S19 XP" raw_model = MinerModel.ANTMINER.S19XP
expected_chips = 110 expected_chips = 110
expected_fans = 4 expected_fans = 4
class S19a(AntMinerMake): class S19a(AntMinerMake):
raw_model = "S19a" raw_model = MinerModel.ANTMINER.S19a
expected_chips = 72 expected_chips = 72
expected_fans = 4 expected_fans = 4
class S19aPro(AntMinerMake): class S19aPro(AntMinerMake):
raw_model = "S19a Pro" raw_model = MinerModel.ANTMINER.S19aPro
expected_chips = 100 expected_chips = 100
expected_fans = 4 expected_fans = 4
class S19j(AntMinerMake): class S19j(AntMinerMake):
raw_model = "S19j" raw_model = MinerModel.ANTMINER.S19j
expected_chips = 114 expected_chips = 114
expected_fans = 4 expected_fans = 4
class S19jNoPIC(AntMinerMake): class S19jNoPIC(AntMinerMake):
raw_model = "S19j No PIC" raw_model = MinerModel.ANTMINER.S19jNoPIC
expected_chips = 88 expected_chips = 88
expected_fans = 4 expected_fans = 4
class S19jPro(AntMinerMake): class S19jPro(AntMinerMake):
raw_model = "S19j Pro" raw_model = MinerModel.ANTMINER.S19jPro
expected_chips = 126 expected_chips = 126
expected_fans = 4 expected_fans = 4
class S19jProNoPIC(AntMinerMake): class S19jProNoPIC(AntMinerMake):
raw_model = "S19j Pro No PIC" raw_model = MinerModel.ANTMINER.S19jProNoPIC
expected_chips = 126 expected_chips = 126
expected_fans = 4 expected_fans = 4
class S19jProPlus(AntMinerMake): class S19jProPlus(AntMinerMake):
raw_model = "S19j Pro+" raw_model = MinerModel.ANTMINER.S19jProPlus
expected_chips = 120 expected_chips = 120
expected_fans = 4 expected_fans = 4
class S19jProPlusNoPIC(AntMinerMake): class S19jProPlusNoPIC(AntMinerMake):
raw_model = "S19j Pro+ No PIC" raw_model = MinerModel.ANTMINER.S19jProPlusNoPIC
expected_chips = 120 expected_chips = 120
expected_fans = 4 expected_fans = 4
class S19kPro(AntMinerMake): class S19kPro(AntMinerMake):
raw_model = "S19k Pro" raw_model = MinerModel.ANTMINER.S19kPro
expected_chips = 77
expected_fans = 4
class S19kProNoPIC(AntMinerMake):
raw_model = MinerModel.ANTMINER.S19kProNoPIC
expected_chips = 77 expected_chips = 77
expected_fans = 4 expected_fans = 4
class S19L(AntMinerMake): class S19L(AntMinerMake):
raw_model = "S19L" raw_model = MinerModel.ANTMINER.S19L
expected_chips = 76 expected_chips = 76
expected_fans = 4 expected_fans = 4
class S19kProNoPIC(AntMinerMake):
raw_model = "S19k Pro No PIC"
expected_chips = 77
expected_fans = 4
class S19Hydro(AntMinerMake): class S19Hydro(AntMinerMake):
raw_model = "S19 Hydro" raw_model = MinerModel.ANTMINER.S19Hydro
expected_chips = 104 expected_chips = 104
expected_hashboards = 4 expected_hashboards = 4
expected_fans = 0 expected_fans = 0
class S19ProHydro(AntMinerMake): class S19ProHydro(AntMinerMake):
raw_model = "S19 Pro Hydro" raw_model = MinerModel.ANTMINER.S19ProHydro
expected_chips = 180 expected_chips = 180
expected_hashboards = 4 expected_hashboards = 4
expected_fans = 0 expected_fans = 0
class S19ProPlusHydro(AntMinerMake): class S19ProPlusHydro(AntMinerMake):
raw_model = "S19 Pro+ Hydro" raw_model = MinerModel.ANTMINER.S19ProPlusHydro
expected_chips = 180 expected_chips = 180
expected_hashboards = 4 expected_hashboards = 4
expected_fans = 0 expected_fans = 0
class S19KPro(AntMinerMake): class S19KPro(AntMinerMake):
raw_model = "S19K Pro" raw_model = MinerModel.ANTMINER.S19KPro
expected_chips = 77 expected_chips = 77
expected_fans = 4 expected_fans = 4

View File

@@ -13,11 +13,12 @@
# 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.device.models import MinerModel
from pyasic.miners.makes import AntMinerMake from pyasic.miners.device.makes import AntMinerMake
class T19(AntMinerMake): class T19(AntMinerMake):
raw_model = "T19" raw_model = MinerModel.ANTMINER.T19
expected_chips = 76 expected_chips = 76
expected_fans = 4 expected_fans = 4

View File

@@ -13,11 +13,12 @@
# 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.device.models import MinerModel
from pyasic.miners.makes import AntMinerMake from pyasic.miners.device.makes import AntMinerMake
class S21(AntMinerMake): class S21(AntMinerMake):
raw_model = "S21" raw_model = MinerModel.ANTMINER.S21
expected_chips = 108 expected_chips = 108
expected_fans = 4 expected_fans = 4

View File

@@ -13,11 +13,12 @@
# 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.device.models import MinerModel
from pyasic.miners.makes import AntMinerMake from pyasic.miners.device.makes import AntMinerMake
class T21(AntMinerMake): class T21(AntMinerMake):
raw_model = "T21" raw_model = MinerModel.ANTMINER.T21
expected_chips = 108 expected_chips = 108
expected_fans = 4 expected_fans = 4

Some files were not shown because too many files have changed in this diff Show More