Compare commits

...

10 Commits

Author SHA1 Message Date
Brett Rowan
d018724aa4 version: bump version number 2024-12-20 17:07:33 -07:00
Brett Rowan
5b97bed704 bug: fix hashrate sum start value in data 2024-12-20 17:07:11 -07:00
Brett Rowan
55786b154d version: bump version number 2024-12-20 10:16:19 -07:00
Brett Rowan
6ab9681dec feature: add auto unit to hashrates and improve model dump for hashrates 2024-12-20 10:16:01 -07:00
Brett Rowan
89641c6316 version: bump version number 2024-12-20 09:26:16 -07:00
Brett Rowan
136ff6a688 feature: add generic hashrate type for doing sums 2024-12-20 09:25:52 -07:00
Brett Rowan
d918d93f4a version: bump version number 2024-12-20 09:21:32 -07:00
Brett Rowan
8046c532a6 bug: fix some issues with adding hashrate types 2024-12-20 09:21:06 -07:00
Upstream Data
92820a362d version: bump version number 2024-12-17 08:15:37 -07:00
aquariuslt
9fd90031a9 fix: update data.env_temp type to float 2024-12-17 08:14:59 -07:00
5 changed files with 64 additions and 34 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
@@ -96,7 +97,7 @@ class MinerData(BaseModel):
expected_fans: int | None = None expected_fans: int | None = None
# temperature # temperature
env_temp: int | None = None env_temp: float | None = None
# power # power
wattage: int | None = None wattage: int | None = None
@@ -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.device_info.algo.hashrate(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

@@ -1,19 +1,42 @@
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 from .unit.base import AlgoHashRateUnitType, GenericUnit
class AlgoHashRateType(BaseModel, ABC): 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)
@@ -27,36 +50,46 @@ class AlgoHashRateType(BaseModel, ABC):
return round(self.rate, n) return round(self.rate, n)
def __add__(self, other: Self | int | float) -> Self: def __add__(self, other: Self | int | float) -> Self:
if isinstance(other, self.__class__): if isinstance(other, AlgoHashRateType):
return self.__class__( return self.__class__(
rate=self.rate + other.into(self.unit).rate, unit=self.unit rate=self.rate + other.into(self.unit).rate, unit=self.unit
) )
return self.__class__(rate=self.rate + other, unit=self.unit) return self.__class__(rate=self.rate + other, unit=self.unit)
def __sub__(self, other: Self | int | float) -> Self: def __sub__(self, other: Self | int | float) -> Self:
if isinstance(other, self.__class__): if isinstance(other, AlgoHashRateType):
return self.__class__( return self.__class__(
rate=self.rate - other.into(self.unit).rate, unit=self.unit rate=self.rate - other.into(self.unit).rate, unit=self.unit
) )
return self.__class__(rate=self.rate - other, unit=self.unit) return self.__class__(rate=self.rate - other, unit=self.unit)
def __truediv__(self, other: Self | int | float) -> Self: def __truediv__(self, other: Self | int | float) -> Self:
if isinstance(other, self.__class__): if isinstance(other, AlgoHashRateType):
return self.__class__( return self.__class__(
rate=self.rate / other.into(self.unit).rate, unit=self.unit rate=self.rate / other.into(self.unit).rate, unit=self.unit
) )
return self.__class__(rate=self.rate / other, unit=self.unit) return self.__class__(rate=self.rate / other, unit=self.unit)
def __floordiv__(self, other: Self | int | float) -> Self: def __floordiv__(self, other: Self | int | float) -> Self:
if isinstance(other, self.__class__): if isinstance(other, AlgoHashRateType):
return self.__class__( return self.__class__(
rate=self.rate // other.into(self.unit).rate, unit=self.unit rate=self.rate // other.into(self.unit).rate, unit=self.unit
) )
return self.__class__(rate=self.rate // other, unit=self.unit) return self.__class__(rate=self.rate // other, unit=self.unit)
def __mul__(self, other: Self | int | float) -> Self: def __mul__(self, other: Self | int | float) -> Self:
if isinstance(other, self.__class__): if isinstance(other, AlgoHashRateType):
return self.__class__( return self.__class__(
rate=self.rate * other.into(self.unit).rate, unit=self.unit rate=self.rate * other.into(self.unit).rate, unit=self.unit
) )
return self.__class__(rate=self.rate * other, unit=self.unit) return self.__class__(rate=self.rate * other, unit=self.unit)
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
)

View File

@@ -53,3 +53,19 @@ 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):
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 = H

View File

@@ -1,6 +1,6 @@
[tool.poetry] [tool.poetry]
name = "pyasic" name = "pyasic"
version = "0.66.0" version = "0.67.1"
description = "A simplified and standardized interface for Bitcoin ASICs." description = "A simplified and standardized interface for Bitcoin ASICs."
authors = ["UpstreamData <brett@upstreamdata.ca>"] authors = ["UpstreamData <brett@upstreamdata.ca>"]
repository = "https://github.com/UpstreamData/pyasic" repository = "https://github.com/UpstreamData/pyasic"