diff --git a/pyasic/data/__init__.py b/pyasic/data/__init__.py index 337813be..7e412116 100644 --- a/pyasic/data/__init__.py +++ b/pyasic/data/__init__.py @@ -13,19 +13,20 @@ # See the License for the specific language governing permissions and - # limitations under the License. - # ------------------------------------------------------------------------------ - import copy import time from datetime import datetime, timezone 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.mining import MiningModePowerTune from pyasic.data.pools import PoolMetrics, Scheme 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 .device import DeviceInfo from .error_codes import BraiinsOSError, InnosiliconError, WhatsminerError, X19Error @@ -135,9 +136,6 @@ class MinerData(BaseModel): def fields(cls): 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): try: val = self.__getitem__(__key) @@ -198,35 +196,23 @@ class MinerData(BaseModel): @computed_field # type: ignore[misc] @property - def hashrate(self) -> AlgoHashRateType: + def hashrate(self) -> AlgoHashRateType | None: if len(self.hashboards) > 0: hr_data = [] for item in self.hashboards: if item.hashrate is not None: hr_data.append(item.hashrate) 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 - @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 def hashrate(self, val): self.raw_hashrate = val @computed_field # type: ignore[misc] @property - def wattage_limit(self) -> int: + def wattage_limit(self) -> int | None: if self.config is not None: if isinstance(self.config.mining_mode, MiningModePowerTune): return self.config.mining_mode.power diff --git a/pyasic/data/boards.py b/pyasic/data/boards.py index e619c5b1..ad0b79ec 100644 --- a/pyasic/data/boards.py +++ b/pyasic/data/boards.py @@ -51,11 +51,6 @@ class HashBoard(BaseModel): active: bool | 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): try: val = self.__getitem__(__key) diff --git a/pyasic/device/algorithm/hashrate/base.py b/pyasic/device/algorithm/hashrate/base.py index 206edb0a..bb81ba34 100644 --- a/pyasic/device/algorithm/hashrate/base.py +++ b/pyasic/device/algorithm/hashrate/base.py @@ -2,7 +2,7 @@ from __future__ import annotations from abc import ABC, abstractmethod -from pydantic import BaseModel +from pydantic import BaseModel, field_serializer from typing_extensions import Self from .unit.base import AlgoHashRateUnitType, GenericUnit @@ -12,10 +12,31 @@ class AlgoHashRateType(BaseModel, ABC): unit: AlgoHashRateUnitType rate: float + @field_serializer("unit") + def serialize_unit(self, unit: AlgoHashRateUnitType): + return unit.model_dump() + @abstractmethod def into(self, other: "AlgoHashRateUnitType"): 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): return float(self.rate) @@ -65,6 +86,9 @@ class AlgoHashRateType(BaseModel, ABC): class GenericHashrate(AlgoHashRateType): + rate: float = 0 + unit: GenericUnit = GenericUnit.H + def into(self, other: GenericUnit): return self.__class__( rate=self.rate / (other.value / self.unit.value), unit=other diff --git a/pyasic/device/algorithm/hashrate/unit/base.py b/pyasic/device/algorithm/hashrate/unit/base.py index f7b39d66..2a358d02 100644 --- a/pyasic/device/algorithm/hashrate/unit/base.py +++ b/pyasic/device/algorithm/hashrate/unit/base.py @@ -54,6 +54,9 @@ class AlgoHashRateUnitType(IntEnum): def __repr__(self): return str(self) + def model_dump(self): + return {"value": self.value, "suffix": str(self)} + class GenericUnit(AlgoHashRateUnitType): H = 1