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 - # See the License for the specific language governing permissions and -
# limitations under the License. - # limitations under the License. -
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
from dataclasses import asdict, dataclass from dataclasses import dataclass
from pyasic.config.fans import FanModeConfig from pyasic.config.fans import FanModeConfig
from pyasic.config.mining import MiningModeConfig from pyasic.config.mining import MiningModeConfig
@@ -30,6 +30,48 @@ class MinerConfig:
temperature: TemperatureConfig = TemperatureConfig.default() temperature: TemperatureConfig = TemperatureConfig.default()
power_scaling: PowerScalingConfig = PowerScalingConfig.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__": 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. - # limitations under the License. -
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
from dataclasses import dataclass, field from dataclasses import dataclass, field
from enum import Enum
from pyasic.config.base import MinerConfigOption, MinerConfigValue
@dataclass @dataclass
class FanModeNormal: class FanModeNormal(MinerConfigValue):
mode: str = field(init=False, default="auto") mode: str = field(init=False, default="auto")
@staticmethod def as_am_modern(self):
def as_am_modern():
return {"bitmain-fan-ctrl": False, "bitmain-fan-pwn": "100"} return {"bitmain-fan-ctrl": False, "bitmain-fan-pwn": "100"}
@staticmethod def as_bos(self):
def as_bos():
return {"temp_control": {"mode": "auto"}} return {"temp_control": {"mode": "auto"}}
@dataclass @dataclass
class FanModeManual: class FanModeManual(MinerConfigValue):
mode: str = field(init=False, default="manual") mode: str = field(init=False, default="manual")
minimum_fans: int = 1 minimum_fans: int = 1
speed: int = 100 speed: int = 100
@@ -47,19 +46,17 @@ class FanModeManual:
@dataclass @dataclass
class FanModeImmersion: class FanModeImmersion(MinerConfigValue):
mode: str = field(init=False, default="immersion") mode: str = field(init=False, default="immersion")
@staticmethod def as_am_modern(self):
def as_am_modern():
return {"bitmain-fan-ctrl": True, "bitmain-fan-pwn": "0"} return {"bitmain-fan-ctrl": True, "bitmain-fan-pwn": "0"}
@staticmethod def as_bos(self):
def as_bos():
return {"temp_control": {"mode": "manual"}, "fan_control": {"min_fans": 0}} return {"temp_control": {"mode": "manual"}, "fan_control": {"min_fans": 0}}
class FanModeConfig(Enum): class FanModeConfig(MinerConfigOption):
normal = FanModeNormal normal = FanModeNormal
manual = FanModeManual manual = FanModeManual
immersion = FanModeImmersion immersion = FanModeImmersion
@@ -67,6 +64,3 @@ class FanModeConfig(Enum):
@classmethod @classmethod
def default(cls): def default(cls):
return cls.normal() return cls.normal()
def __call__(self, *args, **kwargs):
return self.value(*args, **kwargs)

View File

@@ -14,69 +14,97 @@
# limitations under the License. - # limitations under the License. -
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
from dataclasses import dataclass, field from dataclasses import dataclass, field
from enum import Enum
from pyasic.config.base import MinerConfigOption, MinerConfigValue
@dataclass @dataclass
class MiningModeNormal: class MiningModeNormal(MinerConfigValue):
mode: str = field(init=False, default="normal") mode: str = field(init=False, default="normal")
@staticmethod def as_am_modern(self):
def as_am_modern(): 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"} return {"miner-mode": "0"}
@dataclass @dataclass
class MiningModeSleep: class ManualBoardSettings(MinerConfigValue):
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:
freq: float freq: float
volt: float volt: float
def as_am_modern(self):
return {"miner-mode": "0"}
@dataclass @dataclass
class MiningModeManual(MiningModeNormal): class MiningModeManual(MinerConfigValue):
mode: str = field(init=False, default="manual") mode: str = field(init=False, default="manual")
global_freq: float global_freq: float
global_volt: float global_volt: float
boards: dict[int, ManualBoardSettings] = field(default_factory=dict) 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 normal = MiningModeNormal
low = MiningModeLPM low = MiningModeLPM
high = MiningModeHPM high = MiningModeHPM
@@ -88,6 +116,3 @@ class MiningModeConfig(Enum):
@classmethod @classmethod
def default(cls): def default(cls):
return cls.normal() 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 dataclasses import dataclass, field
from typing import Union from typing import Union
from pyasic.config.base import MinerConfigValue
@dataclass @dataclass
class Pool: class Pool(MinerConfigValue):
url: str url: str
user: str user: str
password: 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 @dataclass
class PoolGroup: class PoolGroup(MinerConfigValue):
pools: list[Pool] = field(default_factory=list) pools: list[Pool] = field(default_factory=list)
quota: int = 1 quota: int = 1
name: str = None name: str = None
def __post_init__(self): def __post_init__(self):
if self.group_name is None: if self.name is None:
self.group_name = "".join( self.name = "".join(
random.choice(string.ascii_uppercase + string.digits) for _ in range(6) random.choice(string.ascii_uppercase + string.digits) for _ in range(6)
) # generate random pool group name in case it isn't set ) # 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 @dataclass
class PoolConfig: class PoolConfig(MinerConfigValue):
groups: list[PoolGroup] = field(default_factory=list) groups: list[PoolGroup] = field(default_factory=list)
@classmethod @classmethod
def default(cls): def default(cls):
return 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 = [] group_pools = []
for pool in pools: for pool in pools:
if isinstance(pool, dict): if isinstance(pool, dict):
pool = Pool(**pool) pool = Pool(**pool)
group_pools.append(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. - # limitations under the License. -
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
from dataclasses import dataclass, field from dataclasses import dataclass, field
from enum import Enum
from pyasic.config.base import MinerConfigOption, MinerConfigValue
@dataclass @dataclass
class PowerScalingShutdownEnabled: class PowerScalingShutdownEnabled(MinerConfigValue):
mode: str = field(init=False, default="enabled") mode: str = field(init=False, default="enabled")
duration: int = None duration: int = None
@dataclass @dataclass
class PowerScalingShutdownDisabled: class PowerScalingShutdownDisabled(MinerConfigValue):
mode: str = field(init=False, default="disabled") mode: str = field(init=False, default="disabled")
class PowerScalingShutdown(Enum): class PowerScalingShutdown(MinerConfigOption):
enabled = PowerScalingShutdownEnabled enabled = PowerScalingShutdownEnabled
disabled = PowerScalingShutdownDisabled disabled = PowerScalingShutdownDisabled
@dataclass @dataclass
class PowerScalingEnabled: class PowerScalingEnabled(MinerConfigValue):
mode: str = field(init=False, default="enabled") mode: str = field(init=False, default="enabled")
power_step: int = None power_step: int = None
minimum_power: int = None minimum_power: int = None
@@ -42,17 +43,14 @@ class PowerScalingEnabled:
@dataclass @dataclass
class PowerScalingDisabled: class PowerScalingDisabled(MinerConfigValue):
mode: str = field(init=False, default="disabled") mode: str = field(init=False, default="disabled")
class PowerScalingConfig(Enum): class PowerScalingConfig(MinerConfigOption):
enabled = PowerScalingEnabled enabled = PowerScalingEnabled
disabled = PowerScalingDisabled disabled = PowerScalingDisabled
@classmethod @classmethod
def default(cls): def default(cls):
return cls.disabled() return cls.disabled()
def __call__(self, *args, **kwargs):
return self.value(*args, **kwargs)

View File

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