feature: add AM old and modern, and WM config implementation.

This commit is contained in:
UpstreamData
2023-12-08 10:10:21 -07:00
parent 6d75565baf
commit bca81f3bca
7 changed files with 297 additions and 81 deletions

View File

@@ -13,7 +13,7 @@
# See the License for the specific language governing permissions and -
# limitations under the License. -
# ------------------------------------------------------------------------------
from dataclasses import asdict, dataclass
from dataclasses import dataclass
from pyasic.config.fans import FanModeConfig
from pyasic.config.mining import MiningModeConfig
@@ -30,6 +30,48 @@ class MinerConfig:
temperature: TemperatureConfig = TemperatureConfig.default()
power_scaling: PowerScalingConfig = PowerScalingConfig.default()
def as_am_modern(self, user_suffix: str = None):
return {
**self.fan_mode.as_am_modern(),
"freq-level": "100",
**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(),
}
def as_wm(self, user_suffix: str = None):
return {
**self.fan_mode.as_wm(),
**self.mining_mode.as_wm(),
**self.pools.as_wm(user_suffix=user_suffix),
**self.temperature.as_wm(),
**self.power_scaling.as_wm(),
}
def as_am_old(self, user_suffix: str = None):
return {
**self.fan_mode.as_am_old(),
**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(),
}
if __name__ == "__main__":
print(asdict(MinerConfig()))
config = MinerConfig(
pools=PoolConfig.simple(
[
{
"url": "stratum+tcp://stratum.test.io:3333",
"user": "user.test",
"password": "123",
}
]
),
mining_mode=MiningModeConfig.power_tuning(3000),
)
print(config.as_wm())
print(config.as_am_modern())
print(config.as_am_old())

65
pyasic/config/base.py Normal file
View File

@@ -0,0 +1,65 @@
# ------------------------------------------------------------------------------
# Copyright 2022 Upstream Data Inc -
# -
# Licensed under the Apache License, Version 2.0 (the "License"); -
# you may not use this file except in compliance with the License. -
# You may obtain a copy of the License at -
# -
# http://www.apache.org/licenses/LICENSE-2.0 -
# -
# Unless required by applicable law or agreed to in writing, software -
# distributed under the License is distributed on an "AS IS" BASIS, -
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -
# See the License for the specific language governing permissions and -
# limitations under the License. -
# ------------------------------------------------------------------------------
from enum import Enum
class MinerConfigOption(Enum):
def as_am_modern(self) -> dict:
return self.value.as_am_modern()
def as_am_old(self) -> dict:
return self.value.as_am_old()
def as_wm(self) -> dict:
return self.value.as_wm()
def as_inno(self) -> dict:
return self.value.as_inno()
def as_goldshell(self) -> dict:
return self.value.as_goldshell()
def as_avalon(self) -> dict:
return self.value.as_avalon()
def as_bos(self) -> dict:
return self.value.as_bos()
def __call__(self, *args, **kwargs):
return self.value(*args, **kwargs)
class MinerConfigValue:
def as_am_modern(self) -> dict:
return {}
def as_am_old(self) -> dict:
return {}
def as_wm(self) -> dict:
return {}
def as_inno(self) -> dict:
return {}
def as_goldshell(self) -> dict:
return {}
def as_avalon(self) -> dict:
return {}
def as_bos(self) -> dict:
return {}

View File

@@ -14,24 +14,23 @@
# limitations under the License. -
# ------------------------------------------------------------------------------
from dataclasses import dataclass, field
from enum import Enum
from pyasic.config.base import MinerConfigOption, MinerConfigValue
@dataclass
class FanModeNormal:
class FanModeNormal(MinerConfigValue):
mode: str = field(init=False, default="auto")
@staticmethod
def as_am_modern():
def as_am_modern(self):
return {"bitmain-fan-ctrl": False, "bitmain-fan-pwn": "100"}
@staticmethod
def as_bos():
def as_bos(self):
return {"temp_control": {"mode": "auto"}}
@dataclass
class FanModeManual:
class FanModeManual(MinerConfigValue):
mode: str = field(init=False, default="manual")
minimum_fans: int = 1
speed: int = 100
@@ -47,19 +46,17 @@ class FanModeManual:
@dataclass
class FanModeImmersion:
class FanModeImmersion(MinerConfigValue):
mode: str = field(init=False, default="immersion")
@staticmethod
def as_am_modern():
def as_am_modern(self):
return {"bitmain-fan-ctrl": True, "bitmain-fan-pwn": "0"}
@staticmethod
def as_bos():
def as_bos(self):
return {"temp_control": {"mode": "manual"}, "fan_control": {"min_fans": 0}}
class FanModeConfig(Enum):
class FanModeConfig(MinerConfigOption):
normal = FanModeNormal
manual = FanModeManual
immersion = FanModeImmersion
@@ -67,6 +64,3 @@ class FanModeConfig(Enum):
@classmethod
def default(cls):
return cls.normal()
def __call__(self, *args, **kwargs):
return self.value(*args, **kwargs)

View File

@@ -14,69 +14,97 @@
# limitations under the License. -
# ------------------------------------------------------------------------------
from dataclasses import dataclass, field
from enum import Enum
from pyasic.config.base import MinerConfigOption, MinerConfigValue
@dataclass
class MiningModeNormal:
class MiningModeNormal(MinerConfigValue):
mode: str = field(init=False, default="normal")
@staticmethod
def as_am_modern():
def as_am_modern(self):
return {"miner-mode": "0"}
def as_wm(self):
return {"mode": self.mode}
@dataclass
class MiningModeSleep(MinerConfigValue):
mode: str = field(init=False, default="sleep")
def as_am_modern(self):
return {"miner-mode": "1"}
def as_wm(self):
return {"mode": self.mode}
@dataclass
class MiningModeLPM(MinerConfigValue):
mode: str = field(init=False, default="low")
def as_am_modern(self):
return {"miner-mode": "3"}
def as_wm(self):
return {"mode": self.mode}
@dataclass
class MiningModeHPM(MinerConfigValue):
mode: str = field(init=False, default="high")
def as_am_modern(self):
return {"miner-mode": "0"}
def as_wm(self):
return {"mode": self.mode}
@dataclass
class MiningModePowerTune(MinerConfigValue):
mode: str = field(init=False, default="power_tuning")
power: int
def as_am_modern(self):
return {"miner-mode": "0"}
def as_wm(self):
return {"mode": self.mode, self.mode: {"wattage": self.power}}
@dataclass
class MiningModeHashrateTune(MinerConfigValue):
mode: str = field(init=False, default="hashrate_tuning")
hashrate: int
def as_am_modern(self):
return {"miner-mode": "0"}
@dataclass
class MiningModeSleep:
mode: str = field(init=False, default="sleep")
@staticmethod
def as_am_modern():
return {"miner-mode": "1"}
@dataclass
class MiningModeLPM:
mode: str = field(init=False, default="low")
@staticmethod
def as_am_modern():
return {"miner-mode": "3"}
@dataclass
class MiningModeHPM(MiningModeNormal):
mode: str = field(init=False, default="high")
@dataclass
class MiningModePowerTune(MiningModeNormal):
mode: str = field(init=False, default="power_tuning")
power: int
@dataclass
class MiningModeHashrateTune(MiningModeNormal):
mode: str = field(init=False, default="hashrate_tuning")
hashrate: int
@dataclass
class ManualBoardSettings:
class ManualBoardSettings(MinerConfigValue):
freq: float
volt: float
def as_am_modern(self):
return {"miner-mode": "0"}
@dataclass
class MiningModeManual(MiningModeNormal):
class MiningModeManual(MinerConfigValue):
mode: str = field(init=False, default="manual")
global_freq: float
global_volt: float
boards: dict[int, ManualBoardSettings] = field(default_factory=dict)
def as_am_modern(self):
return {"miner-mode": "0"}
class MiningModeConfig(Enum):
class MiningModeConfig(MinerConfigOption):
normal = MiningModeNormal
low = MiningModeLPM
high = MiningModeHPM
@@ -88,6 +116,3 @@ class MiningModeConfig(Enum):
@classmethod
def default(cls):
return cls.normal()
def __call__(self, *args, **kwargs):
return self.value(*args, **kwargs)

View File

@@ -18,39 +18,129 @@ import string
from dataclasses import dataclass, field
from typing import Union
from pyasic.config.base import MinerConfigValue
@dataclass
class Pool:
class Pool(MinerConfigValue):
url: str
user: str
password: str
def as_am_modern(self, user_suffix: str = None):
if user_suffix is not None:
return {
"url": self.url,
"user": f"{self.user}{user_suffix}",
"pass": self.password,
}
return {"url": self.url, "user": self.user, "pass": self.password}
def as_wm(self, idx: int, user_suffix: str = None):
if user_suffix is not None:
return {
f"pool_{idx}": self.url,
f"worker_{idx}": f"{self.user}{user_suffix}",
f"passwd_{idx}": self.password,
}
return {
f"pool_{idx}": self.url,
f"worker_{idx}": self.user,
f"passwd_{idx}": self.password,
}
def as_am_old(self, idx: int, user_suffix: str = None):
if user_suffix is not None:
return {
f"_ant_pool{idx}url": self.url,
f"_ant_pool{idx}user": f"{self.user}{user_suffix}",
f"_ant_pool{idx}pw": self.password,
}
return {
f"_ant_pool{idx}url": self.url,
f"_ant_pool{idx}user": self.user,
f"_ant_pool{idx}pw": self.password,
}
@dataclass
class PoolGroup:
class PoolGroup(MinerConfigValue):
pools: list[Pool] = field(default_factory=list)
quota: int = 1
name: str = None
def __post_init__(self):
if self.group_name is None:
self.group_name = "".join(
if self.name is None:
self.name = "".join(
random.choice(string.ascii_uppercase + string.digits) for _ in range(6)
) # generate random pool group name in case it isn't set
def as_am_modern(self, user_suffix: str = None):
pools = []
idx = 0
while idx < 3:
if len(self.pools) > idx:
pools.append(self.pools[idx].as_am_modern(user_suffix=user_suffix))
else:
pools.append(Pool("", "", "").as_am_modern())
idx += 1
return pools
def as_wm(self, user_suffix: str = None):
pools = {}
idx = 0
while idx < 3:
if len(self.pools) > idx:
pools.update(
**self.pools[idx].as_wm(idx=idx + 1, user_suffix=user_suffix)
)
else:
pools.update(**Pool("", "", "").as_wm(idx=idx + 1))
idx += 1
return pools
def as_am_old(self, user_suffix: str = None):
pools = {}
idx = 0
while idx < 3:
if len(self.pools) > idx:
pools.update(
**self.pools[idx].as_am_old(idx=idx + 1, user_suffix=user_suffix)
)
else:
pools.update(**Pool("", "", "").as_am_old(idx=idx + 1))
idx += 1
return pools
@dataclass
class PoolConfig:
class PoolConfig(MinerConfigValue):
groups: list[PoolGroup] = field(default_factory=list)
@classmethod
def default(cls):
return cls()
def simple(self, pools: list[Union[Pool, dict[str, str]]]):
@classmethod
def simple(cls, pools: list[Union[Pool, dict[str, str]]]):
group_pools = []
for pool in pools:
if isinstance(pool, dict):
pool = Pool(**pool)
group_pools.append(pool)
self.groups = [PoolGroup(pools=group_pools)]
return cls(groups=[PoolGroup(pools=group_pools)])
def as_am_modern(self, user_suffix: str = None):
if len(self.groups) > 0:
return {"pools": self.groups[0].as_am_modern(user_suffix=user_suffix)}
return {"pools": PoolGroup().as_am_modern()}
def as_wm(self, user_suffix: str = None):
if len(self.groups) > 0:
return {"pools": self.groups[0].as_wm(user_suffix=user_suffix)}
return {"pools": PoolGroup().as_wm()}
def as_am_old(self, user_suffix: str = None):
if len(self.groups) > 0:
return self.groups[0].as_am_old(user_suffix=user_suffix)
return PoolGroup().as_am_old()

View File

@@ -14,27 +14,28 @@
# limitations under the License. -
# ------------------------------------------------------------------------------
from dataclasses import dataclass, field
from enum import Enum
from pyasic.config.base import MinerConfigOption, MinerConfigValue
@dataclass
class PowerScalingShutdownEnabled:
class PowerScalingShutdownEnabled(MinerConfigValue):
mode: str = field(init=False, default="enabled")
duration: int = None
@dataclass
class PowerScalingShutdownDisabled:
class PowerScalingShutdownDisabled(MinerConfigValue):
mode: str = field(init=False, default="disabled")
class PowerScalingShutdown(Enum):
class PowerScalingShutdown(MinerConfigOption):
enabled = PowerScalingShutdownEnabled
disabled = PowerScalingShutdownDisabled
@dataclass
class PowerScalingEnabled:
class PowerScalingEnabled(MinerConfigValue):
mode: str = field(init=False, default="enabled")
power_step: int = None
minimum_power: int = None
@@ -42,17 +43,14 @@ class PowerScalingEnabled:
@dataclass
class PowerScalingDisabled:
class PowerScalingDisabled(MinerConfigValue):
mode: str = field(init=False, default="disabled")
class PowerScalingConfig(Enum):
class PowerScalingConfig(MinerConfigOption):
enabled = PowerScalingEnabled
disabled = PowerScalingDisabled
@classmethod
def default(cls):
return cls.disabled()
def __call__(self, *args, **kwargs):
return self.value(*args, **kwargs)

View File

@@ -15,9 +15,11 @@
# ------------------------------------------------------------------------------
from dataclasses import dataclass
from pyasic.config.base import MinerConfigValue
@dataclass
class TemperatureConfig:
class TemperatureConfig(MinerConfigValue):
target: int = None
hot: int = None
danger: int = None