diff --git a/pyasic/config/__init__.py b/pyasic/config/__init__.py index 3962abb1..ebe72ad9 100644 --- a/pyasic/config/__init__.py +++ b/pyasic/config/__init__.py @@ -161,6 +161,15 @@ class MinerConfig: power_scaling=PowerScalingConfig.from_bosminer(toml_conf), ) + @classmethod + def from_epic(cls, web_conf: dict) -> "MinerConfig": + return cls( + pools=PoolConfig.from_epic(web_conf), + fan_mode=FanModeConfig.from_epic(web_conf), + temperature=TemperatureConfig.from_epic(web_conf), + mining_mode=MiningModeConfig.from_epic(web_conf), + ) + def merge(a: dict, b: dict) -> dict: result = deepcopy(a) diff --git a/pyasic/config/fans.py b/pyasic/config/fans.py index 02cb127e..0f6ba357 100644 --- a/pyasic/config/fans.py +++ b/pyasic/config/fans.py @@ -116,6 +116,17 @@ class FanModeConfig(MinerConfigOption): else: return cls.default() + @classmethod + def from_epic(cls, web_conf: dict): + try: + fan_mode = web_conf["Fans"]["Fan Mode"] + if fan_mode.get("Manual") is not None: + return cls.manual(speed=fan_mode.get("Manual")) + else: + return cls.normal() + except KeyError: + return cls.default() + @classmethod def from_bosminer(cls, toml_conf: dict): if toml_conf.get("temp_control") is None: diff --git a/pyasic/config/mining.py b/pyasic/config/mining.py index 010d556e..ccb43fe9 100644 --- a/pyasic/config/mining.py +++ b/pyasic/config/mining.py @@ -186,6 +186,29 @@ class MiningModeConfig(MinerConfigOption): return cls.low() return cls.default() + @classmethod + def from_epic(cls, web_conf: dict): + try: + work_mode = web_conf["PerpetualTune"]["Running"] + if work_mode: + if ( + web_conf["PerpetualTune"]["Algorithm"].get("VoltageOptimizer") + is not None + ): + return cls.hashrate_tuning( + web_conf["PerpetualTune"]["Algorithm"]["VoltageOptimizer"][ + "Target" + ] + ) + else: + return cls.hashrate_tuning( + web_conf["PerpetualTune"]["Algorithm"]["ChipTune"]["Target"] + ) + else: + return cls.normal() + except KeyError: + return cls.default() + @classmethod def from_bosminer(cls, toml_conf: dict): if toml_conf.get("autotuning") is None: diff --git a/pyasic/config/pools.py b/pyasic/config/pools.py index e90c1fa6..ab739d86 100644 --- a/pyasic/config/pools.py +++ b/pyasic/config/pools.py @@ -108,6 +108,12 @@ class Pool(MinerConfigValue): def from_api(cls, api_pool: dict) -> "Pool": return cls(url=api_pool["URL"], user=api_pool["User"], password="x") + @classmethod + def from_epic(cls, api_pool: dict) -> "Pool": + return cls( + url=api_pool["pool"], user=api_pool["login"], password=api_pool["password"] + ) + @classmethod def from_am_modern(cls, web_pool: dict) -> "Pool": return cls( @@ -237,6 +243,13 @@ class PoolGroup(MinerConfigValue): pools.append(Pool.from_api(pool)) return cls(pools=pools) + @classmethod + def from_epic(cls, api_pool_list: list) -> "PoolGroup": + pools = [] + for pool in api_pool_list: + pools.append(Pool.from_epic(pool)) + return cls(pools=pools) + @classmethod def from_am_modern(cls, web_pool_list: list) -> "PoolGroup": pools = [] @@ -334,6 +347,11 @@ class PoolConfig(MinerConfigValue): return cls([PoolGroup.from_api(pool_data)]) + @classmethod + def from_epic(cls, web_conf: dict) -> "PoolConfig": + pool_data = web_conf["StratumConfigs"] + return cls([PoolGroup.from_epic(pool_data)]) + @classmethod def from_am_modern(cls, web_conf: dict) -> "PoolConfig": pool_data = web_conf["pools"] diff --git a/pyasic/config/temperature.py b/pyasic/config/temperature.py index d875104b..816c061f 100644 --- a/pyasic/config/temperature.py +++ b/pyasic/config/temperature.py @@ -56,3 +56,18 @@ class TemperatureConfig(MinerConfigValue): hot=temp_control.get("hot_temp"), danger=temp_control.get("dangerous_temp"), ) + + @classmethod + def from_epic(cls, web_conf: dict) -> "TemperatureConfig": + dangerous_temp = None + try: + hot_temp = web_conf["Misc"]["Shutdown Temp"] + except KeyError: + hot_temp = None + # Need to do this in two blocks to avoid KeyError if one is missing + try: + target_temp = web_conf["Fans"]["Fan Mode"]["Auto"]["Target Temperature"] + except KeyError: + target_temp = None + + return cls(target=target_temp, hot=hot_temp, danger=dangerous_temp) diff --git a/pyasic/data/__init__.py b/pyasic/data/__init__.py index b3d02cf3..15d3ff48 100644 --- a/pyasic/data/__init__.py +++ b/pyasic/data/__init__.py @@ -161,9 +161,9 @@ class MinerData: percent_expected_wattage: float = field(init=False) nominal: bool = field(init=False) config: MinerConfig = None - errors: List[ - Union[WhatsminerError, BraiinsOSError, X19Error, InnosiliconError] - ] = field(default_factory=list) + errors: List[Union[WhatsminerError, BraiinsOSError, X19Error, InnosiliconError]] = ( + field(default_factory=list) + ) fault_light: Union[bool, None] = None efficiency: int = field(init=False) is_mining: bool = True diff --git a/pyasic/miners/backends/bosminer.py b/pyasic/miners/backends/bosminer.py index cc8bc6cf..e949133b 100644 --- a/pyasic/miners/backends/bosminer.py +++ b/pyasic/miners/backends/bosminer.py @@ -537,7 +537,7 @@ class BOSMiner(BaseMiner): pass try: - async with (await self._get_ssh_connection()) as conn: + async with await self._get_ssh_connection() as conn: if conn is not None: data = await conn.run("cat /proc/sys/kernel/hostname") host = data.stdout.strip() diff --git a/pyasic/miners/backends/epic.py b/pyasic/miners/backends/epic.py index f40a93b1..9a40a9d1 100644 --- a/pyasic/miners/backends/epic.py +++ b/pyasic/miners/backends/epic.py @@ -18,6 +18,7 @@ from typing import List, Optional, Tuple, Union from pyasic.data import Fan, HashBoard from pyasic.data.error_codes import MinerErrorData, X19Error +from pyasic.config import MinerConfig, MiningModeConfig from pyasic.errors import APIError from pyasic.logger import logger from pyasic.miners.backends.bmminer import BMMiner @@ -74,6 +75,23 @@ class ePIC(BMMiner): return self.model + " (ePIC)" return "? (ePIC)" + async def get_config(self) -> MinerConfig: + summary = None + try: + summary = await self.web.summary() + except APIError as e: + logger.warning(e) + except LookupError: + pass + + if summary is not None: + cfg = MinerConfig.from_epic(summary) + else: + cfg = MinerConfig() + + self.config = cfg + return self.config + async def restart_backend(self) -> bool: data = await self.web.restart_epic() if data: diff --git a/pyasic/web/bosminer/__init__.py b/pyasic/web/bosminer/__init__.py index aad5de2c..da8ab954 100644 --- a/pyasic/web/bosminer/__init__.py +++ b/pyasic/web/bosminer/__init__.py @@ -189,11 +189,13 @@ class BOSMinerGQLAPI: await client.post( url, json={ - "query": 'mutation{auth{login(username:"' - + "root" - + '", password:"' - + self.pwd - + '"){__typename}}}' + "query": ( + 'mutation{auth{login(username:"' + + "root" + + '", password:"' + + self.pwd + + '"){__typename}}}' + ) }, ) @@ -233,7 +235,9 @@ class BOSMinerLuCIAPI: login = {"luci_username": self.username, "luci_password": self.pwd} url = f"http://{self.ip}/cgi-bin/luci" headers = { - "User-Agent": "BTC Tools v0.1", # only seems to respond if this user-agent is set + "User-Agent": ( + "BTC Tools v0.1" + ), # only seems to respond if this user-agent is set "Content-Type": "application/x-www-form-urlencoded", } await session.post(url, headers=headers, data=login) diff --git a/pyasic/web/bosminer/proto/braiins/bos/v1/__init__.py b/pyasic/web/bosminer/proto/braiins/bos/v1/__init__.py index 5166d971..a9890179 100644 --- a/pyasic/web/bosminer/proto/braiins/bos/v1/__init__.py +++ b/pyasic/web/bosminer/proto/braiins/bos/v1/__init__.py @@ -2357,17 +2357,21 @@ class ActionsServiceBase(ServiceBase): RebootRequest, RebootResponse, ), - "/braiins.bos.v1.ActionsService/SetLocateDeviceStatus": grpclib.const.Handler( - self.__rpc_set_locate_device_status, - grpclib.const.Cardinality.UNARY_UNARY, - SetLocateDeviceStatusRequest, - LocateDeviceStatusResponse, + "/braiins.bos.v1.ActionsService/SetLocateDeviceStatus": ( + grpclib.const.Handler( + self.__rpc_set_locate_device_status, + grpclib.const.Cardinality.UNARY_UNARY, + SetLocateDeviceStatusRequest, + LocateDeviceStatusResponse, + ) ), - "/braiins.bos.v1.ActionsService/GetLocateDeviceStatus": grpclib.const.Handler( - self.__rpc_get_locate_device_status, - grpclib.const.Cardinality.UNARY_UNARY, - GetLocateDeviceStatusRequest, - LocateDeviceStatusResponse, + "/braiins.bos.v1.ActionsService/GetLocateDeviceStatus": ( + grpclib.const.Handler( + self.__rpc_get_locate_device_status, + grpclib.const.Cardinality.UNARY_UNARY, + GetLocateDeviceStatusRequest, + LocateDeviceStatusResponse, + ) ), } @@ -2644,17 +2648,21 @@ class PerformanceServiceBase(ServiceBase): GetTunerStateRequest, GetTunerStateResponse, ), - "/braiins.bos.v1.PerformanceService/ListTargetProfiles": grpclib.const.Handler( - self.__rpc_list_target_profiles, - grpclib.const.Cardinality.UNARY_UNARY, - ListTargetProfilesRequest, - ListTargetProfilesResponse, + "/braiins.bos.v1.PerformanceService/ListTargetProfiles": ( + grpclib.const.Handler( + self.__rpc_list_target_profiles, + grpclib.const.Cardinality.UNARY_UNARY, + ListTargetProfilesRequest, + ListTargetProfilesResponse, + ) ), - "/braiins.bos.v1.PerformanceService/SetDefaultPowerTarget": grpclib.const.Handler( - self.__rpc_set_default_power_target, - grpclib.const.Cardinality.UNARY_UNARY, - SetDefaultPowerTargetRequest, - SetPowerTargetResponse, + "/braiins.bos.v1.PerformanceService/SetDefaultPowerTarget": ( + grpclib.const.Handler( + self.__rpc_set_default_power_target, + grpclib.const.Cardinality.UNARY_UNARY, + SetDefaultPowerTargetRequest, + SetPowerTargetResponse, + ) ), "/braiins.bos.v1.PerformanceService/SetPowerTarget": grpclib.const.Handler( self.__rpc_set_power_target, @@ -2662,41 +2670,53 @@ class PerformanceServiceBase(ServiceBase): SetPowerTargetRequest, SetPowerTargetResponse, ), - "/braiins.bos.v1.PerformanceService/IncrementPowerTarget": grpclib.const.Handler( - self.__rpc_increment_power_target, - grpclib.const.Cardinality.UNARY_UNARY, - IncrementPowerTargetRequest, - SetPowerTargetResponse, + "/braiins.bos.v1.PerformanceService/IncrementPowerTarget": ( + grpclib.const.Handler( + self.__rpc_increment_power_target, + grpclib.const.Cardinality.UNARY_UNARY, + IncrementPowerTargetRequest, + SetPowerTargetResponse, + ) ), - "/braiins.bos.v1.PerformanceService/DecrementPowerTarget": grpclib.const.Handler( - self.__rpc_decrement_power_target, - grpclib.const.Cardinality.UNARY_UNARY, - DecrementPowerTargetRequest, - SetPowerTargetResponse, + "/braiins.bos.v1.PerformanceService/DecrementPowerTarget": ( + grpclib.const.Handler( + self.__rpc_decrement_power_target, + grpclib.const.Cardinality.UNARY_UNARY, + DecrementPowerTargetRequest, + SetPowerTargetResponse, + ) ), - "/braiins.bos.v1.PerformanceService/SetDefaultHashrateTarget": grpclib.const.Handler( - self.__rpc_set_default_hashrate_target, - grpclib.const.Cardinality.UNARY_UNARY, - SetDefaultHashrateTargetRequest, - SetHashrateTargetResponse, + "/braiins.bos.v1.PerformanceService/SetDefaultHashrateTarget": ( + grpclib.const.Handler( + self.__rpc_set_default_hashrate_target, + grpclib.const.Cardinality.UNARY_UNARY, + SetDefaultHashrateTargetRequest, + SetHashrateTargetResponse, + ) ), - "/braiins.bos.v1.PerformanceService/SetHashrateTarget": grpclib.const.Handler( - self.__rpc_set_hashrate_target, - grpclib.const.Cardinality.UNARY_UNARY, - SetHashrateTargetRequest, - SetHashrateTargetResponse, + "/braiins.bos.v1.PerformanceService/SetHashrateTarget": ( + grpclib.const.Handler( + self.__rpc_set_hashrate_target, + grpclib.const.Cardinality.UNARY_UNARY, + SetHashrateTargetRequest, + SetHashrateTargetResponse, + ) ), - "/braiins.bos.v1.PerformanceService/IncrementHashrateTarget": grpclib.const.Handler( - self.__rpc_increment_hashrate_target, - grpclib.const.Cardinality.UNARY_UNARY, - IncrementHashrateTargetRequest, - SetHashrateTargetResponse, + "/braiins.bos.v1.PerformanceService/IncrementHashrateTarget": ( + grpclib.const.Handler( + self.__rpc_increment_hashrate_target, + grpclib.const.Cardinality.UNARY_UNARY, + IncrementHashrateTargetRequest, + SetHashrateTargetResponse, + ) ), - "/braiins.bos.v1.PerformanceService/DecrementHashrateTarget": grpclib.const.Handler( - self.__rpc_decrement_hashrate_target, - grpclib.const.Cardinality.UNARY_UNARY, - DecrementHashrateTargetRequest, - SetHashrateTargetResponse, + "/braiins.bos.v1.PerformanceService/DecrementHashrateTarget": ( + grpclib.const.Handler( + self.__rpc_decrement_hashrate_target, + grpclib.const.Cardinality.UNARY_UNARY, + DecrementHashrateTargetRequest, + SetHashrateTargetResponse, + ) ), "/braiins.bos.v1.PerformanceService/SetDPS": grpclib.const.Handler( self.__rpc_set_dps, @@ -2704,23 +2724,29 @@ class PerformanceServiceBase(ServiceBase): SetDpsRequest, SetDpsResponse, ), - "/braiins.bos.v1.PerformanceService/SetPerformanceMode": grpclib.const.Handler( - self.__rpc_set_performance_mode, - grpclib.const.Cardinality.UNARY_UNARY, - SetPerformanceModeRequest, - PerformanceMode, + "/braiins.bos.v1.PerformanceService/SetPerformanceMode": ( + grpclib.const.Handler( + self.__rpc_set_performance_mode, + grpclib.const.Cardinality.UNARY_UNARY, + SetPerformanceModeRequest, + PerformanceMode, + ) ), - "/braiins.bos.v1.PerformanceService/GetActivePerformanceMode": grpclib.const.Handler( - self.__rpc_get_active_performance_mode, - grpclib.const.Cardinality.UNARY_UNARY, - GetPerformanceModeRequest, - PerformanceMode, + "/braiins.bos.v1.PerformanceService/GetActivePerformanceMode": ( + grpclib.const.Handler( + self.__rpc_get_active_performance_mode, + grpclib.const.Cardinality.UNARY_UNARY, + GetPerformanceModeRequest, + PerformanceMode, + ) ), - "/braiins.bos.v1.PerformanceService/RemoveTunedProfiles": grpclib.const.Handler( - self.__rpc_remove_tuned_profiles, - grpclib.const.Cardinality.UNARY_UNARY, - RemoveTunedProfilesRequest, - RemoveTunedProfilesResponse, + "/braiins.bos.v1.PerformanceService/RemoveTunedProfiles": ( + grpclib.const.Handler( + self.__rpc_remove_tuned_profiles, + grpclib.const.Cardinality.UNARY_UNARY, + RemoveTunedProfilesRequest, + RemoveTunedProfilesResponse, + ) ), } @@ -2836,17 +2862,21 @@ class ConfigurationServiceBase(ServiceBase): def __mapping__(self) -> Dict[str, grpclib.const.Handler]: return { - "/braiins.bos.v1.ConfigurationService/GetMinerConfiguration": grpclib.const.Handler( - self.__rpc_get_miner_configuration, - grpclib.const.Cardinality.UNARY_UNARY, - GetMinerConfigurationRequest, - GetMinerConfigurationResponse, + "/braiins.bos.v1.ConfigurationService/GetMinerConfiguration": ( + grpclib.const.Handler( + self.__rpc_get_miner_configuration, + grpclib.const.Cardinality.UNARY_UNARY, + GetMinerConfigurationRequest, + GetMinerConfigurationResponse, + ) ), - "/braiins.bos.v1.ConfigurationService/GetConstraints": grpclib.const.Handler( - self.__rpc_get_constraints, - grpclib.const.Cardinality.UNARY_UNARY, - GetConstraintsRequest, - GetConstraintsResponse, + "/braiins.bos.v1.ConfigurationService/GetConstraints": ( + grpclib.const.Handler( + self.__rpc_get_constraints, + grpclib.const.Cardinality.UNARY_UNARY, + GetConstraintsRequest, + GetConstraintsResponse, + ) ), }