feature: add custom hashrate types and conversion.
This commit is contained in:
@@ -28,6 +28,7 @@ from .boards import HashBoard
|
||||
from .device import DeviceInfo
|
||||
from .error_codes import BraiinsOSError, InnosiliconError, WhatsminerError, X19Error
|
||||
from .fans import Fan
|
||||
from .hashrate import AlgoHashRate, HashUnit
|
||||
|
||||
|
||||
@dataclass
|
||||
@@ -40,6 +41,10 @@ class MinerData:
|
||||
uptime: The uptime of the miner in seconds.
|
||||
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.
|
||||
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.
|
||||
fw_ver: The current firmware version on the miner as a str.
|
||||
hostname: The network hostname of the miner as a str.
|
||||
@@ -79,14 +84,15 @@ class MinerData:
|
||||
make: str = field(init=False)
|
||||
model: str = field(init=False)
|
||||
firmware: str = field(init=False)
|
||||
algo: str = field(init=False)
|
||||
mac: str = None
|
||||
api_ver: str = None
|
||||
fw_ver: str = None
|
||||
hostname: str = None
|
||||
|
||||
# hashrate
|
||||
hashrate: float = field(init=False)
|
||||
_hashrate: float = field(repr=False, default=None)
|
||||
hashrate: AlgoHashRate = field(init=False)
|
||||
_hashrate: AlgoHashRate = field(repr=False, default=None)
|
||||
|
||||
# expected
|
||||
expected_hashrate: float = None
|
||||
@@ -214,7 +220,7 @@ class MinerData:
|
||||
if item.hashrate is not None:
|
||||
hr_data.append(item.hashrate)
|
||||
if len(hr_data) > 0:
|
||||
return round(sum(hr_data), 2)
|
||||
return sum(hr_data, start=type(hr_data[0])(0))
|
||||
return self._hashrate
|
||||
|
||||
@hashrate.setter
|
||||
@@ -315,7 +321,7 @@ class MinerData:
|
||||
return None
|
||||
if self.hashrate == 0 or self.wattage == 0:
|
||||
return 0
|
||||
return round(self.wattage / self.hashrate)
|
||||
return round(self.wattage / float(self.hashrate))
|
||||
|
||||
@efficiency.setter
|
||||
def efficiency(self, val):
|
||||
@@ -364,6 +370,15 @@ class MinerData:
|
||||
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 asdict(self) -> dict:
|
||||
return asdict(self, dict_factory=self.dict_factory)
|
||||
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
from dataclasses import dataclass
|
||||
from typing import Any
|
||||
|
||||
from .hashrate import AlgoHashRate
|
||||
|
||||
|
||||
@dataclass
|
||||
class HashBoard:
|
||||
@@ -34,7 +36,7 @@ class HashBoard:
|
||||
"""
|
||||
|
||||
slot: int = 0
|
||||
hashrate: float = None
|
||||
hashrate: AlgoHashRate = None
|
||||
temp: int = None
|
||||
chip_temp: int = None
|
||||
chips: int = None
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
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
|
||||
@@ -10,3 +11,4 @@ class DeviceInfo:
|
||||
make: MinerMake = None
|
||||
model: MinerModel = None
|
||||
firmware: MinerFirmware = None
|
||||
algo: MinerAlgo = None
|
||||
|
||||
15
pyasic/data/hashrate/__init__.py
Normal file
15
pyasic/data/hashrate/__init__.py
Normal 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
|
||||
54
pyasic/data/hashrate/sha256.py
Normal file
54
pyasic/data/hashrate/sha256.py
Normal 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
|
||||
)
|
||||
@@ -1,3 +1,4 @@
|
||||
from .algorithm import MinerAlgo
|
||||
from .firmware import MinerFirmware
|
||||
from .makes import MinerMake
|
||||
from .models import MinerModel
|
||||
|
||||
5
pyasic/device/algorithm/__init__.py
Normal file
5
pyasic/device/algorithm/__init__.py
Normal file
@@ -0,0 +1,5 @@
|
||||
from pyasic.device.algorithm.sha256 import SHA256Algo
|
||||
|
||||
|
||||
class MinerAlgo:
|
||||
SHA256 = SHA256Algo
|
||||
69
pyasic/device/algorithm/sha256.py
Normal file
69
pyasic/device/algorithm/sha256.py
Normal file
@@ -0,0 +1,69 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass
|
||||
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")
|
||||
@@ -18,7 +18,7 @@ from typing import List, Optional
|
||||
|
||||
import asyncssh
|
||||
|
||||
from pyasic.data import HashBoard
|
||||
from pyasic.data import AlgoHashRate, HashBoard, HashUnit
|
||||
from pyasic.errors import APIError
|
||||
from pyasic.miners.backends import Hiveon
|
||||
from pyasic.miners.data import DataFunction, DataLocations, DataOptions, RPCAPICommand
|
||||
@@ -121,7 +121,9 @@ class HiveonT9(Hiveon, T9):
|
||||
chips += rpc_stats["STATS"][1][f"chain_acn{chipset}"]
|
||||
except (KeyError, IndexError):
|
||||
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
|
||||
|
||||
return hashboards
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
from typing import List, Optional, Union
|
||||
|
||||
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.errors import APIError
|
||||
from pyasic.miners.backends.bmminer import BMMiner
|
||||
@@ -218,9 +218,9 @@ class AntminerModern(BMMiner):
|
||||
if rpc_stats is not None:
|
||||
try:
|
||||
for board in rpc_stats["STATS"][0]["chain"]:
|
||||
hashboards[board["index"]].hashrate = round(
|
||||
board["rate_real"] / 1000, 2
|
||||
)
|
||||
hashboards[board["index"]].hashrate = AlgoHashRate.SHA256(
|
||||
board["rate_real"], HashUnit.SHA256.GH
|
||||
).into(self.algo.unit.default)
|
||||
hashboards[board["index"]].chips = board["asic_num"]
|
||||
board_temp_data = list(
|
||||
filter(lambda x: not x == 0, board["temp_pcb"])
|
||||
@@ -273,12 +273,9 @@ class AntminerModern(BMMiner):
|
||||
rate_unit = rpc_stats["STATS"][1]["rate_unit"]
|
||||
except KeyError:
|
||||
rate_unit = "GH"
|
||||
if rate_unit == "GH":
|
||||
return round(expected_rate / 1000, 2)
|
||||
if rate_unit == "MH":
|
||||
return round(expected_rate / 1000000, 2)
|
||||
else:
|
||||
return round(expected_rate, 2)
|
||||
return AlgoHashRate.SHA256(
|
||||
expected_rate, HashUnit.SHA256.from_str(rate_unit)
|
||||
).int(self.algo.unit.default)
|
||||
except LookupError:
|
||||
pass
|
||||
|
||||
@@ -552,7 +549,9 @@ class AntminerOld(CGMiner):
|
||||
|
||||
hashrate = boards[1].get(f"chain_rate{i}")
|
||||
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}")
|
||||
if chips:
|
||||
|
||||
@@ -18,7 +18,7 @@ from enum import Enum
|
||||
from typing import List, Optional
|
||||
|
||||
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.miners.data import (
|
||||
DataFunction,
|
||||
@@ -245,9 +245,9 @@ class Auradine(StockFirmware):
|
||||
|
||||
if rpc_summary is not None:
|
||||
try:
|
||||
return round(
|
||||
float(float(rpc_summary["SUMMARY"][0]["MHS 5s"]) / 1000000), 2
|
||||
)
|
||||
return AlgoHashRate.SHA256(
|
||||
rpc_summary["SUMMARY"][0]["MHS 5s"], HashUnit.SHA256.MH
|
||||
).into(self.algo.unit.default)
|
||||
except (LookupError, ValueError, TypeError):
|
||||
pass
|
||||
|
||||
@@ -274,9 +274,9 @@ class Auradine(StockFirmware):
|
||||
try:
|
||||
for board in rpc_devs["DEVS"]:
|
||||
b_id = board["ID"] - 1
|
||||
hashboards[b_id].hashrate = round(
|
||||
float(float(board["MHS 5s"]) / 1000000), 2
|
||||
)
|
||||
hashboards[b_id].hashrate = AlgoHashRate.SHA256(
|
||||
board["MHS 5s"], HashUnit.SHA256.MH
|
||||
).into(self.algo.unit.default)
|
||||
hashboards[b_id].temp = round(float(float(board["Temperature"])), 2)
|
||||
hashboards[b_id].missing = False
|
||||
except LookupError:
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
import re
|
||||
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.miners.backends.cgminer import CGMiner
|
||||
from pyasic.miners.data import DataFunction, DataLocations, DataOptions, RPCAPICommand
|
||||
@@ -182,7 +182,9 @@ class AvalonMiner(CGMiner):
|
||||
|
||||
if rpc_devs is not None:
|
||||
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):
|
||||
pass
|
||||
|
||||
@@ -213,7 +215,9 @@ class AvalonMiner(CGMiner):
|
||||
|
||||
try:
|
||||
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:
|
||||
pass
|
||||
|
||||
@@ -245,7 +249,9 @@ class AvalonMiner(CGMiner):
|
||||
try:
|
||||
unparsed_stats = rpc_stats["STATS"][0]["MM ID0"]
|
||||
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):
|
||||
pass
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
from typing import List, Optional
|
||||
|
||||
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.miners.data import DataFunction, DataLocations, DataOptions, RPCAPICommand
|
||||
from pyasic.miners.device.firmware import StockFirmware
|
||||
@@ -115,7 +115,9 @@ class BFGMiner(StockFirmware):
|
||||
|
||||
if rpc_summary is not None:
|
||||
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):
|
||||
pass
|
||||
|
||||
@@ -159,7 +161,9 @@ class BFGMiner(StockFirmware):
|
||||
|
||||
hashrate = boards[1].get(f"chain_rate{i}")
|
||||
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}")
|
||||
if chips:
|
||||
@@ -218,11 +222,8 @@ class BFGMiner(StockFirmware):
|
||||
rate_unit = rpc_stats["STATS"][1]["rate_unit"]
|
||||
except KeyError:
|
||||
rate_unit = "GH"
|
||||
if rate_unit == "GH":
|
||||
return round(expected_rate / 1000, 2)
|
||||
if rate_unit == "MH":
|
||||
return round(expected_rate / 1000000, 2)
|
||||
else:
|
||||
return round(expected_rate, 2)
|
||||
return AlgoHashRate.SHA256(
|
||||
expected_rate, HashUnit.SHA256.from_str(rate_unit)
|
||||
).int(self.algo.unit.default)
|
||||
except LookupError:
|
||||
pass
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
from typing import List, Optional
|
||||
|
||||
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.miners.data import DataFunction, DataLocations, DataOptions, RPCAPICommand
|
||||
from pyasic.miners.device.firmware import StockFirmware
|
||||
@@ -119,7 +119,9 @@ class BMMiner(StockFirmware):
|
||||
|
||||
if rpc_summary is not None:
|
||||
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):
|
||||
pass
|
||||
|
||||
@@ -176,7 +178,9 @@ class BMMiner(StockFirmware):
|
||||
|
||||
hashrate = boards[1].get(f"chain_rate{i}")
|
||||
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}")
|
||||
if chips:
|
||||
@@ -234,12 +238,9 @@ class BMMiner(StockFirmware):
|
||||
rate_unit = rpc_stats["STATS"][1]["rate_unit"]
|
||||
except KeyError:
|
||||
rate_unit = "GH"
|
||||
if rate_unit == "GH":
|
||||
return round(expected_rate / 1000, 2)
|
||||
if rate_unit == "MH":
|
||||
return round(expected_rate / 1000000, 2)
|
||||
else:
|
||||
return round(expected_rate, 2)
|
||||
return AlgoHashRate.SHA256(
|
||||
expected_rate, HashUnit.SHA256.from_str(rate_unit)
|
||||
).int(self.algo.unit.default)
|
||||
except LookupError:
|
||||
pass
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ import toml
|
||||
|
||||
from pyasic.config import MinerConfig
|
||||
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.errors import APIError
|
||||
from pyasic.miners.data import (
|
||||
@@ -350,7 +350,9 @@ class BOSMiner(BraiinsOSFirmware):
|
||||
|
||||
if rpc_summary is not None:
|
||||
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):
|
||||
pass
|
||||
|
||||
@@ -420,8 +422,9 @@ class BOSMiner(BraiinsOSFirmware):
|
||||
|
||||
for board in rpc_devs["DEVS"]:
|
||||
_id = board["ID"] - offset
|
||||
hashrate = round(float(board["MHS 1m"] / 1000000), 2)
|
||||
hashboards[_id].hashrate = hashrate
|
||||
hashboards[_id].hashrate = AlgoHashRate.SHA256(
|
||||
board["MHS 1m"], HashUnit.SHA256.MH
|
||||
).into(self.algo.unit.default)
|
||||
except (IndexError, KeyError):
|
||||
pass
|
||||
|
||||
@@ -529,11 +532,12 @@ class BOSMiner(BraiinsOSFirmware):
|
||||
expected_hashrate = round(float(board["Nominal MHS"] / 1000000), 2)
|
||||
if expected_hashrate:
|
||||
hr_list.append(expected_hashrate)
|
||||
|
||||
if len(hr_list) == 0:
|
||||
return 0
|
||||
return AlgoHashRate.SHA256(0)
|
||||
else:
|
||||
return round(
|
||||
(sum(hr_list) / len(hr_list)) * self.expected_hashboards, 2
|
||||
return AlgoHashRate.SHA256(
|
||||
(sum(hr_list) / len(hr_list)) * self.expected_hashboards
|
||||
)
|
||||
except (IndexError, KeyError):
|
||||
pass
|
||||
@@ -784,7 +788,9 @@ class BOSer(BraiinsOSFirmware):
|
||||
|
||||
if rpc_summary is not None:
|
||||
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):
|
||||
pass
|
||||
|
||||
@@ -799,7 +805,10 @@ class BOSer(BraiinsOSFirmware):
|
||||
|
||||
if grpc_miner_details is not None:
|
||||
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:
|
||||
pass
|
||||
|
||||
@@ -828,13 +837,12 @@ class BOSer(BraiinsOSFirmware):
|
||||
]
|
||||
if board.get("stats") is not None:
|
||||
if not board["stats"]["realHashrate"]["last5S"] == {}:
|
||||
hashboards[idx].hashrate = round(
|
||||
hashboards[idx].hashrate = AlgoHashRate.SHA256(
|
||||
board["stats"]["realHashrate"]["last5S"][
|
||||
"gigahashPerSecond"
|
||||
]
|
||||
/ 1000,
|
||||
2,
|
||||
)
|
||||
],
|
||||
HashUnit.SHA256.GH,
|
||||
).into(self.algo.unit.default)
|
||||
hashboards[idx].missing = False
|
||||
|
||||
return hashboards
|
||||
|
||||
@@ -18,7 +18,7 @@ import logging
|
||||
from typing import List, Optional
|
||||
|
||||
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.errors import APIError
|
||||
from pyasic.miners.data import DataFunction, DataLocations, DataOptions, RPCAPICommand
|
||||
@@ -395,7 +395,9 @@ class BTMiner(StockFirmware):
|
||||
|
||||
if rpc_summary is not None:
|
||||
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:
|
||||
pass
|
||||
|
||||
@@ -423,9 +425,9 @@ class BTMiner(StockFirmware):
|
||||
self.expected_hashboards += 1
|
||||
hashboards[board["ASC"]].chip_temp = round(board["Chip Temp Avg"])
|
||||
hashboards[board["ASC"]].temp = round(board["Temperature"])
|
||||
hashboards[board["ASC"]].hashrate = round(
|
||||
float(board["MHS 1m"] / 1000000), 2
|
||||
)
|
||||
hashboards[board["ASC"]].hashrate = AlgoHashRate.SHA256(
|
||||
board["MHS 1m"], HashUnit.SHA256.MH
|
||||
).into(self.algo.unit.default)
|
||||
hashboards[board["ASC"]].chips = board["Effective Chips"]
|
||||
hashboards[board["ASC"]].serial_number = board["PCB SN"]
|
||||
hashboards[board["ASC"]].missing = False
|
||||
@@ -571,7 +573,10 @@ class BTMiner(StockFirmware):
|
||||
try:
|
||||
expected_hashrate = rpc_summary["SUMMARY"][0]["Factory GHS"]
|
||||
if expected_hashrate:
|
||||
return round(expected_hashrate / 1000, 2)
|
||||
return AlgoHashRate.SHA256(
|
||||
expected_hashrate, HashUnit.SHA256.GH
|
||||
).int(self.algo.unit.default)
|
||||
|
||||
except LookupError:
|
||||
pass
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
from typing import Optional
|
||||
|
||||
from pyasic.config import MinerConfig
|
||||
from pyasic.data import AlgoHashRate, HashUnit
|
||||
from pyasic.errors import APIError
|
||||
from pyasic.miners.data import DataFunction, DataLocations, DataOptions, RPCAPICommand
|
||||
from pyasic.miners.device.firmware import StockFirmware
|
||||
@@ -117,9 +118,9 @@ class CGMiner(StockFirmware):
|
||||
|
||||
if rpc_summary is not None:
|
||||
try:
|
||||
return round(
|
||||
float(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):
|
||||
pass
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
from typing import List, Optional
|
||||
|
||||
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.errors import APIError
|
||||
from pyasic.logger import logger
|
||||
@@ -246,7 +246,9 @@ class ePIC(ePICFirmware):
|
||||
if web_summary["HBs"] is not None:
|
||||
for hb in web_summary["HBs"]:
|
||||
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):
|
||||
pass
|
||||
|
||||
@@ -268,7 +270,9 @@ class ePIC(ePICFirmware):
|
||||
ideal = hb["Hashrate"][1] / 100
|
||||
|
||||
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):
|
||||
pass
|
||||
|
||||
@@ -340,7 +344,9 @@ class ePIC(ePICFirmware):
|
||||
hashrate = hb["Hashrate"][0]
|
||||
# Update the Hashboard object
|
||||
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"]].temp = hb["Temperature"]
|
||||
return hb_list
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
from typing import List
|
||||
|
||||
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.logger import logger
|
||||
from pyasic.miners.backends import BFGMiner
|
||||
@@ -158,9 +158,9 @@ class GoldshellMiner(BFGMiner):
|
||||
if board.get("ID") is not None:
|
||||
try:
|
||||
b_id = board["ID"]
|
||||
hashboards[b_id].hashrate = round(
|
||||
board["MHS 20s"] / 1000000, 2
|
||||
)
|
||||
hashboards[b_id].hashrate = AlgoHashRate.SHA256(
|
||||
board["MHS 20s"], HashUnit.SHA256.MH
|
||||
).into(self.algo.unit.default)
|
||||
hashboards[b_id].temp = board["tstemp-2"]
|
||||
hashboards[b_id].missing = False
|
||||
except KeyError:
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
from typing import List, Optional
|
||||
|
||||
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.innosilicon import InnosiliconError
|
||||
from pyasic.errors import APIError
|
||||
@@ -182,20 +182,21 @@ class Innosilicon(CGMiner):
|
||||
if web_get_all is not None:
|
||||
try:
|
||||
if "Hash Rate H" in web_get_all["total_hash"].keys():
|
||||
return round(
|
||||
float(web_get_all["total_hash"]["Hash Rate H"] / 1000000000000),
|
||||
2,
|
||||
)
|
||||
return AlgoHashRate.SHA256(
|
||||
web_get_all["total_hash"]["Hash Rate H"], HashUnit.SHA256.H
|
||||
).into(self.algo.unit.default)
|
||||
elif "Hash Rate" in web_get_all["total_hash"].keys():
|
||||
return round(
|
||||
float(web_get_all["total_hash"]["Hash Rate"] / 1000000), 5
|
||||
)
|
||||
return AlgoHashRate.SHA256(
|
||||
web_get_all["total_hash"]["Hash Rate"], HashUnit.SHA256.MH
|
||||
).into(self.algo.unit.default)
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
if rpc_summary is not None:
|
||||
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):
|
||||
pass
|
||||
|
||||
@@ -247,9 +248,9 @@ class Innosilicon(CGMiner):
|
||||
|
||||
hashrate = board.get("Hash Rate H")
|
||||
if hashrate:
|
||||
hashboards[idx].hashrate = round(
|
||||
hashrate / 1000000000000, 2
|
||||
)
|
||||
hashboards[idx].hashrate = AlgoHashRate.SHA256(
|
||||
hashrate, HashUnit.SHA256.H
|
||||
).into(self.algo.unit.default)
|
||||
|
||||
chip_temp = board.get("Temp max")
|
||||
if chip_temp:
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
from typing import List, Optional
|
||||
|
||||
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.miners.data import DataFunction, DataLocations, DataOptions, RPCAPICommand
|
||||
from pyasic.miners.device.firmware import LuxOSFirmware
|
||||
@@ -171,7 +171,9 @@ class LUXMiner(LuxOSFirmware):
|
||||
|
||||
if rpc_summary is not None:
|
||||
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):
|
||||
pass
|
||||
|
||||
@@ -215,7 +217,9 @@ class LUXMiner(LuxOSFirmware):
|
||||
|
||||
hashrate = boards[1].get(f"chain_rate{i}")
|
||||
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}")
|
||||
if chips:
|
||||
@@ -273,12 +277,9 @@ class LUXMiner(LuxOSFirmware):
|
||||
rate_unit = rpc_stats["STATS"][1]["rate_unit"]
|
||||
except KeyError:
|
||||
rate_unit = "GH"
|
||||
if rate_unit == "GH":
|
||||
return round(expected_rate / 1000, 2)
|
||||
if rate_unit == "MH":
|
||||
return round(expected_rate / 1000000, 2)
|
||||
else:
|
||||
return round(expected_rate, 2)
|
||||
return AlgoHashRate.SHA256(
|
||||
expected_rate, HashUnit.SHA256.from_str(rate_unit)
|
||||
).int(self.algo.unit.default)
|
||||
except LookupError:
|
||||
pass
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ from typing import List, Optional
|
||||
|
||||
from pyasic import MinerConfig
|
||||
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.miners.data import DataFunction, DataLocations, DataOptions, WebAPICommand
|
||||
from pyasic.miners.device.firmware import MaraFirmware
|
||||
@@ -170,7 +170,9 @@ class MaraMiner(MaraFirmware):
|
||||
try:
|
||||
for hb in web_hashboards["hashboards"]:
|
||||
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(
|
||||
sum(hb["temperature_pcb"]) / len(hb["temperature_pcb"]), 2
|
||||
)
|
||||
@@ -232,7 +234,9 @@ class MaraMiner(MaraFirmware):
|
||||
|
||||
if web_brief is not None:
|
||||
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:
|
||||
pass
|
||||
|
||||
@@ -276,7 +280,9 @@ class MaraMiner(MaraFirmware):
|
||||
|
||||
if web_brief is not None:
|
||||
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:
|
||||
pass
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
from typing import Optional
|
||||
|
||||
from pyasic import MinerConfig
|
||||
from pyasic.data import AlgoHashRate, HashUnit
|
||||
from pyasic.errors import APIError
|
||||
from pyasic.miners.backends.bmminer import BMMiner
|
||||
from pyasic.miners.data import (
|
||||
@@ -186,9 +187,9 @@ class VNish(BMMiner, VNishFirmware):
|
||||
|
||||
if rpc_summary is not None:
|
||||
try:
|
||||
return round(
|
||||
float(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):
|
||||
pass
|
||||
|
||||
|
||||
@@ -22,6 +22,8 @@ from pyasic.config import MinerConfig
|
||||
from pyasic.data import Fan, HashBoard, MinerData
|
||||
from pyasic.data.device import DeviceInfo
|
||||
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
|
||||
@@ -40,8 +42,9 @@ class MinerProtocol(Protocol):
|
||||
ssh: _ssh_cls = None
|
||||
|
||||
make: MinerMake = None
|
||||
raw_model: str = None
|
||||
raw_model: MinerModel = None
|
||||
firmware: MinerFirmware = None
|
||||
algo = MinerAlgo.SHA256
|
||||
|
||||
expected_hashboards: int = 3
|
||||
expected_chips: int = None
|
||||
@@ -84,7 +87,9 @@ class MinerProtocol(Protocol):
|
||||
|
||||
@property
|
||||
def device_info(self) -> DeviceInfo:
|
||||
return DeviceInfo(make=self.make, model=self.raw_model, firmware=self.firmware)
|
||||
return DeviceInfo(
|
||||
make=self.make, model=self.raw_model, firmware=self.firmware, algo=self.algo
|
||||
)
|
||||
|
||||
@property
|
||||
def api(self):
|
||||
|
||||
Reference in New Issue
Block a user