diff --git a/pyasic/config/__init__.py b/pyasic/config/__init__.py index 79eac9f5..f817664b 100644 --- a/pyasic/config/__init__.py +++ b/pyasic/config/__init__.py @@ -18,7 +18,7 @@ from dataclasses import asdict, dataclass, field from pyasic.config.fans import FanModeConfig from pyasic.config.mining import MiningModeConfig from pyasic.config.pools import PoolConfig -from pyasic.config.power_scaling import PowerScalingConfig +from pyasic.config.scaling import ScalingConfig from pyasic.config.temperature import TemperatureConfig from pyasic.misc import merge_dicts @@ -32,9 +32,7 @@ class MinerConfig: fan_mode: FanModeConfig = field(default_factory=FanModeConfig.default) temperature: TemperatureConfig = field(default_factory=TemperatureConfig.default) mining_mode: MiningModeConfig = field(default_factory=MiningModeConfig.default) - power_scaling: PowerScalingConfig = field( - default_factory=PowerScalingConfig.default - ) + scaling: ScalingConfig = field(default_factory=ScalingConfig.default) def __getitem__(self, item): try: @@ -54,7 +52,7 @@ class MinerConfig: **self.mining_mode.as_am_modern(), **self.pools.as_am_modern(user_suffix=user_suffix), **self.temperature.as_am_modern(), - **self.power_scaling.as_am_modern(), + **self.scaling.as_am_modern(), } def as_wm(self, user_suffix: str = None) -> dict: @@ -64,7 +62,7 @@ class MinerConfig: **self.mining_mode.as_wm(), **self.pools.as_wm(user_suffix=user_suffix), **self.temperature.as_wm(), - **self.power_scaling.as_wm(), + **self.scaling.as_wm(), } def as_am_old(self, user_suffix: str = None) -> dict: @@ -74,7 +72,7 @@ class MinerConfig: **self.mining_mode.as_am_old(), **self.pools.as_am_old(user_suffix=user_suffix), **self.temperature.as_am_old(), - **self.power_scaling.as_am_old(), + **self.scaling.as_am_old(), } def as_goldshell(self, user_suffix: str = None) -> dict: @@ -84,7 +82,7 @@ class MinerConfig: **self.mining_mode.as_goldshell(), **self.pools.as_goldshell(user_suffix=user_suffix), **self.temperature.as_goldshell(), - **self.power_scaling.as_goldshell(), + **self.scaling.as_goldshell(), } def as_avalon(self, user_suffix: str = None) -> dict: @@ -94,7 +92,7 @@ class MinerConfig: **self.mining_mode.as_avalon(), **self.pools.as_avalon(user_suffix=user_suffix), **self.temperature.as_avalon(), - **self.power_scaling.as_avalon(), + **self.scaling.as_avalon(), } def as_inno(self, user_suffix: str = None) -> dict: @@ -104,7 +102,7 @@ class MinerConfig: **self.mining_mode.as_inno(), **self.pools.as_inno(user_suffix=user_suffix), **self.temperature.as_inno(), - **self.power_scaling.as_inno(), + **self.scaling.as_inno(), } def as_bosminer(self, user_suffix: str = None) -> dict: @@ -113,7 +111,7 @@ class MinerConfig: **merge_dicts(self.fan_mode.as_bosminer(), self.temperature.as_bosminer()), **self.mining_mode.as_bosminer(), **self.pools.as_bosminer(user_suffix=user_suffix), - **self.power_scaling.as_bosminer(), + **self.scaling.as_bosminer(), } def as_boser(self, user_suffix: str = None) -> dict: @@ -123,7 +121,7 @@ class MinerConfig: **self.temperature.as_boser(), **self.mining_mode.as_boser(), **self.pools.as_boser(user_suffix=user_suffix), - **self.power_scaling.as_boser(), + **self.scaling.as_boser(), } def as_epic(self, user_suffix: str = None) -> dict: @@ -132,7 +130,7 @@ class MinerConfig: **merge_dicts(self.fan_mode.as_epic(), self.temperature.as_epic()), **self.mining_mode.as_epic(), **self.pools.as_epic(user_suffix=user_suffix), - **self.power_scaling.as_epic(), + **self.scaling.as_epic(), } def as_auradine(self, user_suffix: str = None) -> dict: @@ -142,7 +140,7 @@ class MinerConfig: **self.temperature.as_auradine(), **self.mining_mode.as_auradine(), **self.pools.as_auradine(user_suffix=user_suffix), - **self.power_scaling.as_auradine(), + **self.scaling.as_auradine(), } def as_mara(self, user_suffix: str = None) -> dict: @@ -151,7 +149,7 @@ class MinerConfig: **self.temperature.as_mara(), **self.mining_mode.as_mara(), **self.pools.as_mara(user_suffix=user_suffix), - **self.power_scaling.as_mara(), + **self.scaling.as_mara(), } @classmethod @@ -162,7 +160,7 @@ class MinerConfig: mining_mode=MiningModeConfig.from_dict(dict_conf.get("mining_mode")), fan_mode=FanModeConfig.from_dict(dict_conf.get("fan_mode")), temperature=TemperatureConfig.from_dict(dict_conf.get("temperature")), - power_scaling=PowerScalingConfig.from_dict(dict_conf.get("power_scaling")), + scaling=ScalingConfig.from_dict(dict_conf.get("scaling")), ) @classmethod @@ -202,7 +200,7 @@ class MinerConfig: mining_mode=MiningModeConfig.from_bosminer(toml_conf), fan_mode=FanModeConfig.from_bosminer(toml_conf), temperature=TemperatureConfig.from_bosminer(toml_conf), - power_scaling=PowerScalingConfig.from_bosminer(toml_conf), + scaling=ScalingConfig.from_bosminer(toml_conf), ) @classmethod @@ -213,7 +211,7 @@ class MinerConfig: mining_mode=MiningModeConfig.from_boser(grpc_miner_conf), fan_mode=FanModeConfig.from_boser(grpc_miner_conf), temperature=TemperatureConfig.from_boser(grpc_miner_conf), - power_scaling=PowerScalingConfig.from_boser(grpc_miner_conf), + scaling=ScalingConfig.from_boser(grpc_miner_conf), ) @classmethod diff --git a/pyasic/config/power_scaling.py b/pyasic/config/scaling.py similarity index 65% rename from pyasic/config/power_scaling.py rename to pyasic/config/scaling.py index 362fed06..069dcebf 100644 --- a/pyasic/config/power_scaling.py +++ b/pyasic/config/scaling.py @@ -19,20 +19,22 @@ from dataclasses import dataclass, field from pyasic.config.base import MinerConfigOption, MinerConfigValue from pyasic.web.braiins_os.proto.braiins.bos.v1 import ( + DpsHashrateTarget, DpsPowerTarget, DpsTarget, Power, SetDpsRequest, + TeraHashrate, ) @dataclass -class PowerScalingShutdownEnabled(MinerConfigValue): +class ScalingShutdownEnabled(MinerConfigValue): mode: str = field(init=False, default="enabled") duration: int = None @classmethod - def from_dict(cls, dict_conf: dict | None) -> "PowerScalingShutdownEnabled": + def from_dict(cls, dict_conf: dict | None) -> "ScalingShutdownEnabled": return cls(duration=dict_conf.get("duration")) def as_bosminer(self) -> dict: @@ -48,11 +50,11 @@ class PowerScalingShutdownEnabled(MinerConfigValue): @dataclass -class PowerScalingShutdownDisabled(MinerConfigValue): +class ScalingShutdownDisabled(MinerConfigValue): mode: str = field(init=False, default="disabled") @classmethod - def from_dict(cls, dict_conf: dict | None) -> "PowerScalingShutdownDisabled": + def from_dict(cls, dict_conf: dict | None) -> "ScalingShutdownDisabled": return cls() def as_bosminer(self) -> dict: @@ -62,9 +64,9 @@ class PowerScalingShutdownDisabled(MinerConfigValue): return {"enable_shutdown ": False} -class PowerScalingShutdown(MinerConfigOption): - enabled = PowerScalingShutdownEnabled - disabled = PowerScalingShutdownDisabled +class ScalingShutdown(MinerConfigOption): + enabled = ScalingShutdownEnabled + disabled = ScalingShutdownDisabled @classmethod def from_dict(cls, dict_conf: dict | None): @@ -104,46 +106,42 @@ class PowerScalingShutdown(MinerConfigOption): @dataclass -class PowerScalingEnabled(MinerConfigValue): - mode: str = field(init=False, default="enabled") - power_step: int = None - minimum_power: int = None - shutdown_enabled: PowerScalingShutdownEnabled | PowerScalingShutdownDisabled = None +class PowerScaling(MinerConfigValue): + mode: str = field(init=False, default="power") + step: int = None + minimum: int = None + shutdown: ScalingShutdownEnabled | ScalingShutdownDisabled = None @classmethod - def from_bosminer(cls, power_scaling_conf: dict) -> "PowerScalingEnabled": + def from_bosminer(cls, power_scaling_conf: dict) -> "PowerScaling": power_step = power_scaling_conf.get("power_step") min_power = power_scaling_conf.get("min_psu_power_limit") if min_power is None: min_power = power_scaling_conf.get("min_power_target") - sd_mode = PowerScalingShutdown.from_bosminer(power_scaling_conf) + sd_mode = ScalingShutdown.from_bosminer(power_scaling_conf) - return cls( - power_step=power_step, minimum_power=min_power, shutdown_enabled=sd_mode - ) + return cls(step=power_step, minimum=min_power, shutdown=sd_mode) @classmethod - def from_dict(cls, dict_conf: dict | None) -> "PowerScalingEnabled": + def from_dict(cls, dict_conf: dict | None) -> "PowerScaling": cls_conf = { - "power_step": dict_conf.get("power_step"), - "minimum_power": dict_conf.get("minimum_power"), + "step": dict_conf.get("step"), + "minimum": dict_conf.get("minimum"), } - shutdown_enabled = dict_conf.get("shutdown_enabled") - if shutdown_enabled is not None: - cls_conf["shutdown_enabled"] = PowerScalingShutdown.from_dict( - shutdown_enabled - ) + shutdown = dict_conf.get("shutdown") + if shutdown is not None: + cls_conf["shutdown"] = ScalingShutdown.from_dict(shutdown) return cls(**cls_conf) def as_bosminer(self) -> dict: cfg = {"enabled": True} - if self.power_step is not None: - cfg["power_step"] = self.power_step - if self.minimum_power is not None: - cfg["min_power_target"] = self.minimum_power + if self.step is not None: + cfg["power_step"] = self.step + if self.minimum is not None: + cfg["min_power_target"] = self.minimum - if self.shutdown_enabled is not None: - cfg = {**cfg, **self.shutdown_enabled.as_bosminer()} + if self.shutdown is not None: + cfg = {**cfg, **self.shutdown.as_bosminer()} return {"performance_scaling": cfg} @@ -151,11 +149,11 @@ class PowerScalingEnabled(MinerConfigValue): return { "set_dps": SetDpsRequest( enable=True, - **self.shutdown_enabled.as_boser(), + **self.shutdown.as_boser(), target=DpsTarget( power_target=DpsPowerTarget( - power_step=Power(self.power_step), - min_power_target=Power(self.minimum_power), + power_step=Power(self.step), + min_power_target=Power(self.minimum), ) ), ), @@ -163,13 +161,47 @@ class PowerScalingEnabled(MinerConfigValue): @dataclass -class PowerScalingDisabled(MinerConfigValue): +class HashrateScaling(MinerConfigValue): + mode: str = field(init=False, default="hashrate") + step: int = None + minimum: int = None + shutdown: ScalingShutdownEnabled | ScalingShutdownDisabled = None + + @classmethod + def from_dict(cls, dict_conf: dict | None) -> "HashrateScaling": + cls_conf = { + "step": dict_conf.get("step"), + "minimum": dict_conf.get("minimum"), + } + shutdown = dict_conf.get("shutdown") + if shutdown is not None: + cls_conf["shutdown"] = ScalingShutdown.from_dict(shutdown) + return cls(**cls_conf) + + def as_boser(self) -> dict: + return { + "set_dps": SetDpsRequest( + enable=True, + **self.shutdown.as_boser(), + target=DpsTarget( + hashrate_target=DpsHashrateTarget( + hashrate_step=TeraHashrate(self.step), + min_hashrate_target=TeraHashrate(self.minimum), + ) + ), + ), + } + + +@dataclass +class ScalingDisabled(MinerConfigValue): mode: str = field(init=False, default="disabled") -class PowerScalingConfig(MinerConfigOption): - enabled = PowerScalingEnabled - disabled = PowerScalingDisabled +class ScalingConfig(MinerConfigOption): + power = PowerScaling + hashrate = HashrateScaling + disabled = ScalingDisabled @classmethod def default(cls): @@ -197,7 +229,7 @@ class PowerScalingConfig(MinerConfigOption): enabled = power_scaling.get("enabled") if enabled is not None: if enabled: - return cls.enabled().from_bosminer(power_scaling) + return cls.power().from_bosminer(power_scaling) else: return cls.disabled() @@ -212,10 +244,10 @@ class PowerScalingConfig(MinerConfigOption): except LookupError: return cls.default() - conf = {"shutdown_enabled": PowerScalingShutdown.from_boser(dps_conf)} + conf = {"shutdown_enabled": ScalingShutdown.from_boser(dps_conf)} if dps_conf.get("minPowerTarget") is not None: conf["minimum_power"] = dps_conf["minPowerTarget"]["watt"] if dps_conf.get("powerStep") is not None: conf["power_step"] = dps_conf["powerStep"]["watt"] - return cls.enabled(**conf) + return cls.power(**conf) diff --git a/tests/config_tests/__init__.py b/tests/config_tests/__init__.py index 9c354230..e0a87442 100644 --- a/tests/config_tests/__init__.py +++ b/tests/config_tests/__init__.py @@ -20,10 +20,10 @@ from pyasic.config import ( MinerConfig, MiningModeConfig, PoolConfig, - PowerScalingConfig, + ScalingConfig, TemperatureConfig, ) -from pyasic.config.power_scaling import PowerScalingShutdown +from pyasic.config.scaling import ScalingShutdown class TestConfig(unittest.TestCase): @@ -41,10 +41,10 @@ class TestConfig(unittest.TestCase): fan_mode=FanModeConfig.manual(speed=90, minimum_fans=2), temperature=TemperatureConfig(target=70, danger=120), mining_mode=MiningModeConfig.power_tuning(power=3000), - power_scaling=PowerScalingConfig.enabled( - power_step=100, - minimum_power=2000, - shutdown_enabled=PowerScalingShutdown.enabled(duration=3), + scaling=ScalingConfig.power( + step=100, + minimum=2000, + shutdown=ScalingShutdown.enabled(duration=3), ), ) @@ -77,11 +77,11 @@ class TestConfig(unittest.TestCase): "power": 3000, "algo": {"mode": "standard"}, }, - "power_scaling": { - "mode": "enabled", - "power_step": 100, - "minimum_power": 2000, - "shutdown_enabled": {"mode": "enabled", "duration": 3}, + "scaling": { + "mode": "power", + "step": 100, + "minimum": 2000, + "shutdown": {"mode": "enabled", "duration": 3}, }, }