Add ePIC send_config and config.as_epic (#101)

* feature: Add epic send_config.

* feature: remove UID from epic config.

* feature: add default for temp configs in epic.
This commit is contained in:
UpstreamData
2024-01-26 12:47:19 -07:00
committed by GitHub
parent 96aa346f00
commit 6c14902484
9 changed files with 163 additions and 18 deletions

View File

@@ -110,10 +110,9 @@ class MinerConfig:
def as_epic(self, user_suffix: str = None) -> dict:
return {
**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.pools.as_epic(),
**self.pools.as_epic(user_suffix=user_suffix),
**self.power_scaling.as_epic(),
}

View File

@@ -50,6 +50,17 @@ class FanModeNormal(MinerConfigValue):
def as_bosminer(self) -> dict:
return {"temp_control": {"mode": "auto"}}
def as_epic(self) -> dict:
return {
"fans": {
"Auto": {
"Idle Speed": self.minimum_speed
if not self.minimum_speed == 0
else 100
}
}
}
@dataclass
class FanModeManual(MinerConfigValue):
@@ -96,6 +107,9 @@ class FanModeManual(MinerConfigValue):
def as_auradine(self) -> dict:
return {"fan": {"percentage": self.speed}}
def as_epic(self) -> dict:
return {"fans": {"Manual": {"speed": self.speed}}}
@dataclass
class FanModeImmersion(MinerConfigValue):

View File

@@ -47,6 +47,9 @@ class MiningModeNormal(MinerConfigValue):
def as_auradine(self) -> dict:
return {"mode": {"mode": self.mode}}
def as_epic(self) -> dict:
return {"ptune": {"enabled": False}}
@dataclass
class MiningModeSleep(MinerConfigValue):
@@ -65,6 +68,9 @@ class MiningModeSleep(MinerConfigValue):
def as_auradine(self) -> dict:
return {"mode": {"sleep": "on"}}
def as_epic(self) -> dict:
return {"ptune": {"algo": "Sleep", "target": 0}}
@dataclass
class MiningModeLPM(MinerConfigValue):
@@ -102,14 +108,52 @@ class MiningModeHPM(MinerConfigValue):
return {"mode": {"mode": "turbo"}}
class StandardPowerTuneAlgo(MinerConfigValue):
mode: str = field(init=False, default="standard")
def as_epic(self):
return VOptPowerTuneAlgo().as_epic()
class VOptPowerTuneAlgo(MinerConfigValue):
mode: str = field(init=False, default="standard")
def as_epic(self):
return "VoltageOptimizer"
class ChipTunePowerTuneAlgo(MinerConfigValue):
mode: str = field(init=False, default="standard")
def as_epic(self):
return "ChipTune"
class PowerTunerAlgo(MinerConfigOption):
standard = StandardPowerTuneAlgo
voltage_optimizer = VOptPowerTuneAlgo
chip_tune = ChipTunePowerTuneAlgo
@classmethod
def default(cls):
return cls.standard()
@dataclass
class MiningModePowerTune(MinerConfigValue):
mode: str = field(init=False, default="power_tuning")
power: int = None
algo: PowerTunerAlgo = PowerTunerAlgo.default()
@classmethod
def from_dict(cls, dict_conf: dict | None) -> "MiningModePowerTune":
return cls(dict_conf.get("power"))
cls_conf = {}
if dict_conf.get("power"):
cls_conf["power"] = dict_conf["power"]
if dict_conf.get("algo"):
cls_conf["algo"] = dict_conf["algo"]
return cls(**cls_conf)
def as_am_modern(self) -> dict:
return {"miner-mode": "0"}
@@ -139,6 +183,9 @@ class MiningModePowerTune(MinerConfigValue):
def as_auradine(self) -> dict:
return {"mode": {"mode": "custom", "tune": "power", "power": self.power}}
def as_epic(self) -> dict:
return {"ptune": {**self.algo.as_epic(), "target": self.power}}
@dataclass
class MiningModeHashrateTune(MinerConfigValue):
@@ -262,20 +309,18 @@ class MiningModeConfig(MinerConfigOption):
@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"
]
tuner_running = web_conf["PerpetualTune"]["Running"]
if tuner_running:
algo_info = web_conf["PerpetualTune"]["Algorithm"]
if algo_info.get("VoltageOptimizer") is not None:
return cls.power_tuning(
power=algo_info["VoltageOptimizer"]["Target"],
algo=PowerTunerAlgo.voltage_optimizer,
)
else:
return cls.hashrate_tuning(
web_conf["PerpetualTune"]["Algorithm"]["ChipTune"]["Target"]
return cls.power_tuning(
power=algo_info["ChipTune"]["Target"],
algo=PowerTunerAlgo.chip_tune,
)
else:
return cls.normal()

View File

@@ -109,6 +109,15 @@ class Pool(MinerConfigValue):
}
return {"url": self.url, "user": self.user, "pass": self.password}
def as_epic(self, user_suffix: str = None):
if user_suffix is not None:
return {
"pool": self.url,
"login": f"{self.user}{user_suffix}",
"password": self.password,
}
return {"pool": self.url, "login": self.user, "password": self.password}
@classmethod
def from_dict(cls, dict_conf: dict | None) -> "Pool":
return cls(
@@ -255,6 +264,17 @@ class PoolGroup(MinerConfigValue):
def as_auradine(self, user_suffix: str = None) -> list:
return [p.as_auradine(user_suffix=user_suffix) for p in self.pools]
def as_epic(self, user_suffix: str = None) -> dict:
if len(self.pools) > 0:
conf = {
"name": self.name,
"pool": [pool.as_epic(user_suffix=user_suffix) for pool in self.pools],
}
if self.quota is not None:
conf["quota"] = self.quota
return conf
return {"name": self.name, "pool": []}
@classmethod
def from_dict(cls, dict_conf: dict | None) -> "PoolGroup":
cls_conf = {}
@@ -396,6 +416,25 @@ class PoolConfig(MinerConfigValue):
}
return {"updatepools": {"pools": PoolGroup().as_auradine()}}
def as_epic(self, user_suffix: str = None) -> dict:
if len(self.groups) > 0:
return {
"pools": {
"coin": "Btc",
"stratum_configs": [
g.as_epic(user_suffix=user_suffix) for g in self.groups
],
"unique_id": False,
}
}
return {
"pools": {
"coin": "Btc",
"stratum_configs": [PoolGroup().as_epic()],
"unique_id": False,
}
}
@classmethod
def from_api(cls, api_pools: dict) -> "PoolConfig":
try:

View File

@@ -40,6 +40,16 @@ class TemperatureConfig(MinerConfigValue):
temp_cfg["dangerous_temp"] = self.danger
return {"temp_control": temp_cfg}
def as_epic(self) -> dict:
temps_config = {"temps": {}, "fans": {"Auto": {}}}
if self.target is not None:
temps_config["fans"]["Target Temperature"] = self.target
else:
temps_config["fans"]["Target Temperature"] = 60
if self.danger is not None:
temps_config["temps"]["shutdown"] = self.danger
return temps_config
@classmethod
def from_dict(cls, dict_conf: dict | None) -> "TemperatureConfig":
return cls(

View File

@@ -107,6 +107,30 @@ class ePIC(BaseMiner):
self.config = cfg
return self.config
async def send_config(self, config: MinerConfig, user_suffix: str = None) -> None:
self.config = config
conf = self.config.as_epic(user_suffix=user_suffix)
try:
# Temps
if not conf.get("temps", {}) == {}:
await self.web.set_shutdown_temp(conf["temps"]["shutdown"])
# Fans
if not conf["fans"].get("Manual", {}) == {}:
await self.web.set_fan({"Manual": conf["fans"]["Manual"]})
elif not conf["fans"].get("Auto", {}) == {}:
await self.web.set_fan({"Auto": conf["fans"]["Auto"]})
# Mining Mode -- Need to handle that you may not be able to change while miner is tuning
if conf["ptune"].get("enabled", True):
await self.web.set_ptune_enable(True)
await self.web.set_ptune_algo(**conf["ptune"])
## Pools
await self.web.set_pools(conf["pools"])
except APIError:
pass
async def restart_backend(self) -> bool:
data = await self.web.restart_epic()
if data:

View File

@@ -24,7 +24,6 @@ from pyasic.data.error_codes import MinerErrorData
from pyasic.errors import APIError
from pyasic.logger import logger
from pyasic.miners.data import DataLocations, DataOptions, RPCAPICommand, WebAPICommand
from pyasic.rpc.base import BaseMinerRPCAPI
class MinerProtocol(Protocol):

View File

@@ -94,6 +94,21 @@ class ePICWebAPI(BaseWebAPI):
async def reboot(self) -> dict:
return await self.send_command("reboot", privileged=True)
async def set_shutdown_temp(self, params: int) -> dict:
return await self.send_command("shutdowntemp", parameters=params)
async def set_fan(self, params: dict) -> dict:
return await self.send_command("fanspeed", parameters=params)
async def set_ptune_enable(self, params: bool) -> dict:
return await self.send_command("perpetualtune", parameters=params)
async def set_ptune_algo(self, params: dict) -> dict:
return await self.send_command("perpetualtune/algo", parameters=params)
async def set_pools(self, params: dict) -> dict:
return await self.send_command("coin", parameters=params)
async def pause_mining(self) -> dict:
return await self.send_command("miner", param="Stop")

View File

@@ -72,7 +72,7 @@ class TestConfig(unittest.TestCase):
},
"fan_mode": {"mode": "manual", "speed": 90, "minimum_fans": 2},
"temperature": {"target": 70, "hot": None, "danger": 120},
"mining_mode": {"mode": "power_tuning", "power": 3000},
"mining_mode": {"mode": "power_tuning", "power": 3000, "algo": {}},
"power_scaling": {
"mode": "enabled",
"power_step": 100,