Merge pull request #156 from UpstreamData/dev_dps

This commit is contained in:
Brett Rowan
2024-06-04 17:31:07 -06:00
committed by GitHub
3 changed files with 100 additions and 70 deletions

View File

@@ -18,7 +18,7 @@ from dataclasses import asdict, dataclass, field
from pyasic.config.fans import FanModeConfig from pyasic.config.fans import FanModeConfig
from pyasic.config.mining import MiningModeConfig from pyasic.config.mining import MiningModeConfig
from pyasic.config.pools import PoolConfig 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.config.temperature import TemperatureConfig
from pyasic.misc import merge_dicts from pyasic.misc import merge_dicts
@@ -32,9 +32,7 @@ class MinerConfig:
fan_mode: FanModeConfig = field(default_factory=FanModeConfig.default) fan_mode: FanModeConfig = field(default_factory=FanModeConfig.default)
temperature: TemperatureConfig = field(default_factory=TemperatureConfig.default) temperature: TemperatureConfig = field(default_factory=TemperatureConfig.default)
mining_mode: MiningModeConfig = field(default_factory=MiningModeConfig.default) mining_mode: MiningModeConfig = field(default_factory=MiningModeConfig.default)
power_scaling: PowerScalingConfig = field( scaling: ScalingConfig = field(default_factory=ScalingConfig.default)
default_factory=PowerScalingConfig.default
)
def __getitem__(self, item): def __getitem__(self, item):
try: try:
@@ -54,7 +52,7 @@ class MinerConfig:
**self.mining_mode.as_am_modern(), **self.mining_mode.as_am_modern(),
**self.pools.as_am_modern(user_suffix=user_suffix), **self.pools.as_am_modern(user_suffix=user_suffix),
**self.temperature.as_am_modern(), **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: def as_wm(self, user_suffix: str = None) -> dict:
@@ -64,7 +62,7 @@ class MinerConfig:
**self.mining_mode.as_wm(), **self.mining_mode.as_wm(),
**self.pools.as_wm(user_suffix=user_suffix), **self.pools.as_wm(user_suffix=user_suffix),
**self.temperature.as_wm(), **self.temperature.as_wm(),
**self.power_scaling.as_wm(), **self.scaling.as_wm(),
} }
def as_am_old(self, user_suffix: str = None) -> dict: def as_am_old(self, user_suffix: str = None) -> dict:
@@ -74,7 +72,7 @@ class MinerConfig:
**self.mining_mode.as_am_old(), **self.mining_mode.as_am_old(),
**self.pools.as_am_old(user_suffix=user_suffix), **self.pools.as_am_old(user_suffix=user_suffix),
**self.temperature.as_am_old(), **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: def as_goldshell(self, user_suffix: str = None) -> dict:
@@ -84,7 +82,7 @@ class MinerConfig:
**self.mining_mode.as_goldshell(), **self.mining_mode.as_goldshell(),
**self.pools.as_goldshell(user_suffix=user_suffix), **self.pools.as_goldshell(user_suffix=user_suffix),
**self.temperature.as_goldshell(), **self.temperature.as_goldshell(),
**self.power_scaling.as_goldshell(), **self.scaling.as_goldshell(),
} }
def as_avalon(self, user_suffix: str = None) -> dict: def as_avalon(self, user_suffix: str = None) -> dict:
@@ -94,7 +92,7 @@ class MinerConfig:
**self.mining_mode.as_avalon(), **self.mining_mode.as_avalon(),
**self.pools.as_avalon(user_suffix=user_suffix), **self.pools.as_avalon(user_suffix=user_suffix),
**self.temperature.as_avalon(), **self.temperature.as_avalon(),
**self.power_scaling.as_avalon(), **self.scaling.as_avalon(),
} }
def as_inno(self, user_suffix: str = None) -> dict: def as_inno(self, user_suffix: str = None) -> dict:
@@ -104,7 +102,7 @@ class MinerConfig:
**self.mining_mode.as_inno(), **self.mining_mode.as_inno(),
**self.pools.as_inno(user_suffix=user_suffix), **self.pools.as_inno(user_suffix=user_suffix),
**self.temperature.as_inno(), **self.temperature.as_inno(),
**self.power_scaling.as_inno(), **self.scaling.as_inno(),
} }
def as_bosminer(self, user_suffix: str = None) -> dict: 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()), **merge_dicts(self.fan_mode.as_bosminer(), self.temperature.as_bosminer()),
**self.mining_mode.as_bosminer(), **self.mining_mode.as_bosminer(),
**self.pools.as_bosminer(user_suffix=user_suffix), **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: def as_boser(self, user_suffix: str = None) -> dict:
@@ -123,7 +121,7 @@ class MinerConfig:
**self.temperature.as_boser(), **self.temperature.as_boser(),
**self.mining_mode.as_boser(), **self.mining_mode.as_boser(),
**self.pools.as_boser(user_suffix=user_suffix), **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: 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()), **merge_dicts(self.fan_mode.as_epic(), self.temperature.as_epic()),
**self.mining_mode.as_epic(), **self.mining_mode.as_epic(),
**self.pools.as_epic(user_suffix=user_suffix), **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: def as_auradine(self, user_suffix: str = None) -> dict:
@@ -142,7 +140,7 @@ class MinerConfig:
**self.temperature.as_auradine(), **self.temperature.as_auradine(),
**self.mining_mode.as_auradine(), **self.mining_mode.as_auradine(),
**self.pools.as_auradine(user_suffix=user_suffix), **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: def as_mara(self, user_suffix: str = None) -> dict:
@@ -151,7 +149,7 @@ class MinerConfig:
**self.temperature.as_mara(), **self.temperature.as_mara(),
**self.mining_mode.as_mara(), **self.mining_mode.as_mara(),
**self.pools.as_mara(user_suffix=user_suffix), **self.pools.as_mara(user_suffix=user_suffix),
**self.power_scaling.as_mara(), **self.scaling.as_mara(),
} }
@classmethod @classmethod
@@ -162,7 +160,7 @@ class MinerConfig:
mining_mode=MiningModeConfig.from_dict(dict_conf.get("mining_mode")), mining_mode=MiningModeConfig.from_dict(dict_conf.get("mining_mode")),
fan_mode=FanModeConfig.from_dict(dict_conf.get("fan_mode")), fan_mode=FanModeConfig.from_dict(dict_conf.get("fan_mode")),
temperature=TemperatureConfig.from_dict(dict_conf.get("temperature")), 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 @classmethod
@@ -202,7 +200,7 @@ class MinerConfig:
mining_mode=MiningModeConfig.from_bosminer(toml_conf), mining_mode=MiningModeConfig.from_bosminer(toml_conf),
fan_mode=FanModeConfig.from_bosminer(toml_conf), fan_mode=FanModeConfig.from_bosminer(toml_conf),
temperature=TemperatureConfig.from_bosminer(toml_conf), temperature=TemperatureConfig.from_bosminer(toml_conf),
power_scaling=PowerScalingConfig.from_bosminer(toml_conf), scaling=ScalingConfig.from_bosminer(toml_conf),
) )
@classmethod @classmethod
@@ -213,7 +211,7 @@ class MinerConfig:
mining_mode=MiningModeConfig.from_boser(grpc_miner_conf), mining_mode=MiningModeConfig.from_boser(grpc_miner_conf),
fan_mode=FanModeConfig.from_boser(grpc_miner_conf), fan_mode=FanModeConfig.from_boser(grpc_miner_conf),
temperature=TemperatureConfig.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 @classmethod

View File

@@ -19,20 +19,22 @@ from dataclasses import dataclass, field
from pyasic.config.base import MinerConfigOption, MinerConfigValue from pyasic.config.base import MinerConfigOption, MinerConfigValue
from pyasic.web.braiins_os.proto.braiins.bos.v1 import ( from pyasic.web.braiins_os.proto.braiins.bos.v1 import (
DpsHashrateTarget,
DpsPowerTarget, DpsPowerTarget,
DpsTarget, DpsTarget,
Power, Power,
SetDpsRequest, SetDpsRequest,
TeraHashrate,
) )
@dataclass @dataclass
class PowerScalingShutdownEnabled(MinerConfigValue): class ScalingShutdownEnabled(MinerConfigValue):
mode: str = field(init=False, default="enabled") mode: str = field(init=False, default="enabled")
duration: int = None duration: int = None
@classmethod @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")) return cls(duration=dict_conf.get("duration"))
def as_bosminer(self) -> dict: def as_bosminer(self) -> dict:
@@ -48,11 +50,11 @@ class PowerScalingShutdownEnabled(MinerConfigValue):
@dataclass @dataclass
class PowerScalingShutdownDisabled(MinerConfigValue): class ScalingShutdownDisabled(MinerConfigValue):
mode: str = field(init=False, default="disabled") mode: str = field(init=False, default="disabled")
@classmethod @classmethod
def from_dict(cls, dict_conf: dict | None) -> "PowerScalingShutdownDisabled": def from_dict(cls, dict_conf: dict | None) -> "ScalingShutdownDisabled":
return cls() return cls()
def as_bosminer(self) -> dict: def as_bosminer(self) -> dict:
@@ -62,9 +64,9 @@ class PowerScalingShutdownDisabled(MinerConfigValue):
return {"enable_shutdown ": False} return {"enable_shutdown ": False}
class PowerScalingShutdown(MinerConfigOption): class ScalingShutdown(MinerConfigOption):
enabled = PowerScalingShutdownEnabled enabled = ScalingShutdownEnabled
disabled = PowerScalingShutdownDisabled disabled = ScalingShutdownDisabled
@classmethod @classmethod
def from_dict(cls, dict_conf: dict | None): def from_dict(cls, dict_conf: dict | None):
@@ -104,46 +106,42 @@ class PowerScalingShutdown(MinerConfigOption):
@dataclass @dataclass
class PowerScalingEnabled(MinerConfigValue): class PowerScaling(MinerConfigValue):
mode: str = field(init=False, default="enabled") mode: str = field(init=False, default="power")
power_step: int = None step: int = None
minimum_power: int = None minimum: int = None
shutdown_enabled: PowerScalingShutdownEnabled | PowerScalingShutdownDisabled = None shutdown: ScalingShutdownEnabled | ScalingShutdownDisabled = None
@classmethod @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") power_step = power_scaling_conf.get("power_step")
min_power = power_scaling_conf.get("min_psu_power_limit") min_power = power_scaling_conf.get("min_psu_power_limit")
if min_power is None: if min_power is None:
min_power = power_scaling_conf.get("min_power_target") 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( return cls(step=power_step, minimum=min_power, shutdown=sd_mode)
power_step=power_step, minimum_power=min_power, shutdown_enabled=sd_mode
)
@classmethod @classmethod
def from_dict(cls, dict_conf: dict | None) -> "PowerScalingEnabled": def from_dict(cls, dict_conf: dict | None) -> "PowerScaling":
cls_conf = { cls_conf = {
"power_step": dict_conf.get("power_step"), "step": dict_conf.get("step"),
"minimum_power": dict_conf.get("minimum_power"), "minimum": dict_conf.get("minimum"),
} }
shutdown_enabled = dict_conf.get("shutdown_enabled") shutdown = dict_conf.get("shutdown")
if shutdown_enabled is not None: if shutdown is not None:
cls_conf["shutdown_enabled"] = PowerScalingShutdown.from_dict( cls_conf["shutdown"] = ScalingShutdown.from_dict(shutdown)
shutdown_enabled
)
return cls(**cls_conf) return cls(**cls_conf)
def as_bosminer(self) -> dict: def as_bosminer(self) -> dict:
cfg = {"enabled": True} cfg = {"enabled": True}
if self.power_step is not None: if self.step is not None:
cfg["power_step"] = self.power_step cfg["power_step"] = self.step
if self.minimum_power is not None: if self.minimum is not None:
cfg["min_power_target"] = self.minimum_power cfg["min_power_target"] = self.minimum
if self.shutdown_enabled is not None: if self.shutdown is not None:
cfg = {**cfg, **self.shutdown_enabled.as_bosminer()} cfg = {**cfg, **self.shutdown.as_bosminer()}
return {"performance_scaling": cfg} return {"performance_scaling": cfg}
@@ -151,11 +149,11 @@ class PowerScalingEnabled(MinerConfigValue):
return { return {
"set_dps": SetDpsRequest( "set_dps": SetDpsRequest(
enable=True, enable=True,
**self.shutdown_enabled.as_boser(), **self.shutdown.as_boser(),
target=DpsTarget( target=DpsTarget(
power_target=DpsPowerTarget( power_target=DpsPowerTarget(
power_step=Power(self.power_step), power_step=Power(self.step),
min_power_target=Power(self.minimum_power), min_power_target=Power(self.minimum),
) )
), ),
), ),
@@ -163,13 +161,47 @@ class PowerScalingEnabled(MinerConfigValue):
@dataclass @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") mode: str = field(init=False, default="disabled")
class PowerScalingConfig(MinerConfigOption): class ScalingConfig(MinerConfigOption):
enabled = PowerScalingEnabled power = PowerScaling
disabled = PowerScalingDisabled hashrate = HashrateScaling
disabled = ScalingDisabled
@classmethod @classmethod
def default(cls): def default(cls):
@@ -197,7 +229,7 @@ class PowerScalingConfig(MinerConfigOption):
enabled = power_scaling.get("enabled") enabled = power_scaling.get("enabled")
if enabled is not None: if enabled is not None:
if enabled: if enabled:
return cls.enabled().from_bosminer(power_scaling) return cls.power().from_bosminer(power_scaling)
else: else:
return cls.disabled() return cls.disabled()
@@ -212,10 +244,10 @@ class PowerScalingConfig(MinerConfigOption):
except LookupError: except LookupError:
return cls.default() 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: if dps_conf.get("minPowerTarget") is not None:
conf["minimum_power"] = dps_conf["minPowerTarget"]["watt"] conf["minimum_power"] = dps_conf["minPowerTarget"]["watt"]
if dps_conf.get("powerStep") is not None: if dps_conf.get("powerStep") is not None:
conf["power_step"] = dps_conf["powerStep"]["watt"] conf["power_step"] = dps_conf["powerStep"]["watt"]
return cls.enabled(**conf) return cls.power(**conf)

View File

@@ -20,10 +20,10 @@ from pyasic.config import (
MinerConfig, MinerConfig,
MiningModeConfig, MiningModeConfig,
PoolConfig, PoolConfig,
PowerScalingConfig, ScalingConfig,
TemperatureConfig, TemperatureConfig,
) )
from pyasic.config.power_scaling import PowerScalingShutdown from pyasic.config.scaling import ScalingShutdown
class TestConfig(unittest.TestCase): class TestConfig(unittest.TestCase):
@@ -41,10 +41,10 @@ class TestConfig(unittest.TestCase):
fan_mode=FanModeConfig.manual(speed=90, minimum_fans=2), fan_mode=FanModeConfig.manual(speed=90, minimum_fans=2),
temperature=TemperatureConfig(target=70, danger=120), temperature=TemperatureConfig(target=70, danger=120),
mining_mode=MiningModeConfig.power_tuning(power=3000), mining_mode=MiningModeConfig.power_tuning(power=3000),
power_scaling=PowerScalingConfig.enabled( scaling=ScalingConfig.power(
power_step=100, step=100,
minimum_power=2000, minimum=2000,
shutdown_enabled=PowerScalingShutdown.enabled(duration=3), shutdown=ScalingShutdown.enabled(duration=3),
), ),
) )
@@ -77,11 +77,11 @@ class TestConfig(unittest.TestCase):
"power": 3000, "power": 3000,
"algo": {"mode": "standard"}, "algo": {"mode": "standard"},
}, },
"power_scaling": { "scaling": {
"mode": "enabled", "mode": "power",
"power_step": 100, "step": 100,
"minimum_power": 2000, "minimum": 2000,
"shutdown_enabled": {"mode": "enabled", "duration": 3}, "shutdown": {"mode": "enabled", "duration": 3},
}, },
} }