feature: add auto unit to hashrates and improve model dump for hashrates

This commit is contained in:
Brett Rowan
2024-12-20 10:16:01 -07:00
parent 89641c6316
commit 6ab9681dec
4 changed files with 34 additions and 26 deletions

View File

@@ -13,19 +13,20 @@
# 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. -
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
import copy import copy
import time import time
from datetime import datetime, timezone from datetime import datetime, timezone
from typing import Any, List, Union from typing import Any, List, Union
from pydantic import BaseModel, Field, computed_field, field_serializer from pydantic import BaseModel, Field, computed_field
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.pools import PoolMetrics, Scheme from pyasic.data.pools import PoolMetrics, Scheme
from pyasic.device.algorithm.hashrate import AlgoHashRateType from pyasic.device.algorithm.hashrate import AlgoHashRateType
from pyasic.device.algorithm.hashrate.base import GenericHashrate
from ..device.algorithm.hashrate.unit.base import GenericUnit
from .boards import HashBoard from .boards import HashBoard
from .device import DeviceInfo from .device import DeviceInfo
from .error_codes import BraiinsOSError, InnosiliconError, WhatsminerError, X19Error from .error_codes import BraiinsOSError, InnosiliconError, WhatsminerError, X19Error
@@ -135,9 +136,6 @@ class MinerData(BaseModel):
def fields(cls): def fields(cls):
return list(cls.model_fields.keys()) return list(cls.model_fields.keys())
def __post_init__(self):
self.raw_datetime = datetime.now(timezone.utc).astimezone()
def get(self, __key: str, default: Any = None): def get(self, __key: str, default: Any = None):
try: try:
val = self.__getitem__(__key) val = self.__getitem__(__key)
@@ -198,35 +196,23 @@ class MinerData(BaseModel):
@computed_field # type: ignore[misc] @computed_field # type: ignore[misc]
@property @property
def hashrate(self) -> AlgoHashRateType: def hashrate(self) -> AlgoHashRateType | None:
if len(self.hashboards) > 0: if len(self.hashboards) > 0:
hr_data = [] hr_data = []
for item in self.hashboards: for item in self.hashboards:
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 sum(hr_data, start=type(hr_data[0])(rate=0)) return sum(hr_data, start=self.hashboards[0].hashrate.__class__(rate=0))
return self.raw_hashrate return self.raw_hashrate
@field_serializer("hashrate")
def serialize_hashrate(self, hashrate: AlgoHashRateType | None) -> float:
if hashrate is not None:
return float(hashrate)
@field_serializer("expected_hashrate")
def serialize_expected_hashrate(
self, expected_hashrate: AlgoHashRateType | None, _info
) -> float:
if expected_hashrate is not None:
return float(expected_hashrate)
@hashrate.setter @hashrate.setter
def hashrate(self, val): def hashrate(self, val):
self.raw_hashrate = val self.raw_hashrate = val
@computed_field # type: ignore[misc] @computed_field # type: ignore[misc]
@property @property
def wattage_limit(self) -> int: def wattage_limit(self) -> int | None:
if self.config is not None: if self.config is not None:
if isinstance(self.config.mining_mode, MiningModePowerTune): if isinstance(self.config.mining_mode, MiningModePowerTune):
return self.config.mining_mode.power return self.config.mining_mode.power

View File

@@ -51,11 +51,6 @@ class HashBoard(BaseModel):
active: bool | None = None active: bool | None = None
voltage: float | None = None voltage: float | None = None
@field_serializer("hashrate")
def serialize_hashrate(self, hashrate: AlgoHashRateType | None) -> float:
if hashrate is not None:
return float(hashrate)
def get(self, __key: str, default: Any = None): def get(self, __key: str, default: Any = None):
try: try:
val = self.__getitem__(__key) val = self.__getitem__(__key)

View File

@@ -2,7 +2,7 @@ from __future__ import annotations
from abc import ABC, abstractmethod from abc import ABC, abstractmethod
from pydantic import BaseModel from pydantic import BaseModel, field_serializer
from typing_extensions import Self from typing_extensions import Self
from .unit.base import AlgoHashRateUnitType, GenericUnit from .unit.base import AlgoHashRateUnitType, GenericUnit
@@ -12,10 +12,31 @@ class AlgoHashRateType(BaseModel, ABC):
unit: AlgoHashRateUnitType unit: AlgoHashRateUnitType
rate: float rate: float
@field_serializer("unit")
def serialize_unit(self, unit: AlgoHashRateUnitType):
return unit.model_dump()
@abstractmethod @abstractmethod
def into(self, other: "AlgoHashRateUnitType"): def into(self, other: "AlgoHashRateUnitType"):
pass pass
def auto_unit(self):
if 1 < self.rate // int(self.unit.H) < 1000:
return self.into(self.unit.H)
if 1 < self.rate // int(self.unit.MH) < 1000:
return self.into(self.unit.MH)
if 1 < self.rate // int(self.unit.GH) < 1000:
return self.into(self.unit.GH)
if 1 < self.rate // int(self.unit.TH) < 1000:
return self.into(self.unit.TH)
if 1 < self.rate // int(self.unit.PH) < 1000:
return self.into(self.unit.PH)
if 1 < self.rate // int(self.unit.EH) < 1000:
return self.into(self.unit.EH)
if 1 < self.rate // int(self.unit.ZH) < 1000:
return self.into(self.unit.ZH)
return self
def __float__(self): def __float__(self):
return float(self.rate) return float(self.rate)
@@ -65,6 +86,9 @@ class AlgoHashRateType(BaseModel, ABC):
class GenericHashrate(AlgoHashRateType): class GenericHashrate(AlgoHashRateType):
rate: float = 0
unit: GenericUnit = GenericUnit.H
def into(self, other: GenericUnit): def into(self, other: GenericUnit):
return self.__class__( return self.__class__(
rate=self.rate / (other.value / self.unit.value), unit=other rate=self.rate / (other.value / self.unit.value), unit=other

View File

@@ -54,6 +54,9 @@ class AlgoHashRateUnitType(IntEnum):
def __repr__(self): def __repr__(self):
return str(self) return str(self)
def model_dump(self):
return {"value": self.value, "suffix": str(self)}
class GenericUnit(AlgoHashRateUnitType): class GenericUnit(AlgoHashRateUnitType):
H = 1 H = 1