diff --git a/pyasic/config/__init__.py b/pyasic/config/__init__.py index ebe72ad9..c3ba16d4 100644 --- a/pyasic/config/__init__.py +++ b/pyasic/config/__init__.py @@ -170,6 +170,15 @@ class MinerConfig: mining_mode=MiningModeConfig.from_epic(web_conf), ) + @classmethod + def from_vnish(cls, web_settings: dict) -> "MinerConfig": + return cls( + pools=PoolConfig.from_vnish(web_settings), + fan_mode=FanModeConfig.from_vnish(web_settings), + temperature=TemperatureConfig.from_vnish(web_settings), + mining_mode=MiningModeConfig.from_vnish(web_settings), + ) + def merge(a: dict, b: dict) -> dict: result = deepcopy(a) diff --git a/pyasic/config/base.py b/pyasic/config/base.py index 3e430890..3f38adeb 100644 --- a/pyasic/config/base.py +++ b/pyasic/config/base.py @@ -50,6 +50,9 @@ class MinerConfigOption(Enum): def as_epic(self) -> dict: return self.value.as_epic() + def as_vnish(self) -> dict: + return self.value.as_vnish() + def __call__(self, *args, **kwargs): return self.value(*args, **kwargs) @@ -93,3 +96,6 @@ class MinerConfigValue: def as_epic(self) -> dict: return {} + + def as_vnish(self) -> dict: + return {} diff --git a/pyasic/config/fans.py b/pyasic/config/fans.py index 0f6ba357..5d93bcd0 100644 --- a/pyasic/config/fans.py +++ b/pyasic/config/fans.py @@ -22,10 +22,26 @@ from pyasic.config.base import MinerConfigOption, MinerConfigValue @dataclass class FanModeNormal(MinerConfigValue): mode: str = field(init=False, default="normal") + minimum_fans: int = 1 + minimum_speed: int = 0 @classmethod def from_dict(cls, dict_conf: Union[dict, None]) -> "FanModeNormal": - return cls() + cls_conf = {} + if dict_conf.get("minimum_fans") is not None: + cls_conf["minimum_fans"] = dict_conf["minimum_fans"] + if dict_conf.get("minimum_speed") is not None: + cls_conf["minimum_speed"] = dict_conf["minimum_speed"] + return cls(**cls_conf) + + @classmethod + def from_vnish(cls, web_cooling_settings: dict): + cls_conf = {} + if web_cooling_settings.get("fan_min_count") is not None: + cls_conf["minimum_fans"] = web_cooling_settings["fan_min_count"] + if web_cooling_settings.get("fan_min_duty") is not None: + cls_conf["minimum_speed"] = web_cooling_settings["fan_min_duty"] + return cls(**cls_conf) def as_am_modern(self) -> dict: return {"bitmain-fan-ctrl": False, "bitmain-fan-pwn": "100"} @@ -58,6 +74,15 @@ class FanModeManual(MinerConfigValue): cls_conf["speed"] = toml_fan_conf["speed"] return cls(**cls_conf) + @classmethod + def from_vnish(cls, web_cooling_settings: dict) -> "FanModeManual": + cls_conf = {} + if web_cooling_settings.get("fan_min_count") is not None: + cls_conf["minimum_fans"] = web_cooling_settings["fan_min_count"] + if web_cooling_settings["mode"].get("param") is not None: + cls_conf["speed"] = web_cooling_settings["mode"]["param"] + return cls(**cls_conf) + def as_am_modern(self) -> dict: return {"bitmain-fan-ctrl": True, "bitmain-fan-pwn": str(self.speed)} @@ -143,3 +168,17 @@ class FanModeConfig(MinerConfigOption): return cls.manual() elif mode == "disabled": return cls.immersion() + + @classmethod + def from_vnish(cls, web_settings: dict): + try: + mode = web_settings["miner"]["cooling"]["mode"]["name"] + except LookupError: + return cls.default() + + if mode == "auto": + return cls.normal().from_vnish(web_settings["miner"]["cooling"]) + elif mode == "manual": + return cls.manual().from_vnish(web_settings["miner"]["cooling"]) + elif mode == "immers": + return cls.immersion() diff --git a/pyasic/config/mining.py b/pyasic/config/mining.py index 38ca847c..1b9a7eb3 100644 --- a/pyasic/config/mining.py +++ b/pyasic/config/mining.py @@ -145,6 +145,20 @@ class MiningModeManual(MinerConfigValue): def as_am_modern(self) -> dict: return {"miner-mode": "0"} + @classmethod + def from_vnish(cls, web_overclock_settings: dict) -> "MiningModeManual": + # will raise KeyError if it cant find the settings, values cannot be empty + voltage = web_overclock_settings["globals"]["volt"] + freq = web_overclock_settings["globals"]["freq"] + boards = { + idx: ManualBoardSettings( + freq=board["freq"], + volt=voltage if not board["freq"] == 0 else 0, + ) + for idx, board in enumerate(web_overclock_settings["chains"]) + } + return cls(global_freq=freq, global_volt=voltage, boards=boards) + class MiningModeConfig(MinerConfigOption): normal = MiningModeNormal @@ -234,3 +248,15 @@ class MiningModeConfig(MinerConfigOption): if autotuning_conf.get("hashrate_target") is not None: return cls.hashrate_tuning(autotuning_conf["hashrate_target"]) return cls.hashrate_tuning() + + @classmethod + def from_vnish(cls, web_settings: dict): + try: + mode_settings = web_settings["miner"]["overclock"] + except KeyError: + return cls.default() + + if mode_settings["preset"] == "disabled": + return MiningModeManual.from_vnish(mode_settings) + else: + return cls.power_tuning(int(mode_settings["preset"])) diff --git a/pyasic/config/pools.py b/pyasic/config/pools.py index c6b330b2..b2d10fb5 100644 --- a/pyasic/config/pools.py +++ b/pyasic/config/pools.py @@ -141,6 +141,14 @@ class Pool(MinerConfigValue): password=toml_pool_conf["password"], ) + @classmethod + def from_vnish(cls, web_pool: dict) -> "Pool": + return cls( + url=web_pool["url"], + user=web_pool["user"], + password=web_pool["pass"], + ) + @dataclass class PoolGroup(MinerConfigValue): @@ -275,6 +283,10 @@ class PoolGroup(MinerConfigValue): ) return cls() + @classmethod + def from_vnish(cls, web_settings_pools: dict) -> "PoolGroup": + return cls([Pool.from_vnish(p) for p in web_settings_pools]) + @dataclass class PoolConfig(MinerConfigValue): @@ -375,3 +387,10 @@ class PoolConfig(MinerConfigValue): return cls() return cls([PoolGroup.from_bosminer(g) for g in toml_conf["group"]]) + + @classmethod + def from_vnish(cls, web_settings: dict) -> "PoolConfig": + try: + return cls([PoolGroup.from_vnish(web_settings["miner"]["pools"])]) + except LookupError: + return cls() diff --git a/pyasic/config/temperature.py b/pyasic/config/temperature.py index 816c061f..07ec4f60 100644 --- a/pyasic/config/temperature.py +++ b/pyasic/config/temperature.py @@ -71,3 +71,12 @@ class TemperatureConfig(MinerConfigValue): target_temp = None return cls(target=target_temp, hot=hot_temp, danger=dangerous_temp) + + @classmethod + def from_vnish(cls, web_settings: dict): + try: + if web_settings["miner"]["cooling"]["mode"]["name"] == "auto": + return cls(target=web_settings["miner"]["cooling"]["mode"]["param"]) + except KeyError: + pass + return cls() diff --git a/pyasic/miners/backends/vnish.py b/pyasic/miners/backends/vnish.py index 30e24810..0df888a6 100644 --- a/pyasic/miners/backends/vnish.py +++ b/pyasic/miners/backends/vnish.py @@ -16,6 +16,7 @@ from typing import Optional +from pyasic import MinerConfig from pyasic.errors import APIError from pyasic.logger import logger from pyasic.miners.backends.bmminer import BMMiner @@ -219,3 +220,11 @@ class VNish(BMMiner): async def get_uptime(self, *args, **kwargs) -> Optional[int]: return None + + async def get_config(self) -> MinerConfig: + try: + web_settings = await self.web.settings() + except APIError: + return self.config + self.config = MinerConfig.from_vnish(web_settings) + return self.config