feature: add bos to config miner types.

This commit is contained in:
UpstreamData
2023-12-09 13:24:44 -07:00
parent d7d1b845a7
commit 5eaf876c6d
6 changed files with 86 additions and 7 deletions

View File

@@ -15,6 +15,8 @@
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
from dataclasses import dataclass from dataclasses import dataclass
import toml
from pyasic.config.fans import FanModeConfig from pyasic.config.fans import FanModeConfig
from pyasic.config.mining import MiningModeConfig from pyasic.config.mining import MiningModeConfig
from pyasic.config.pools import PoolConfig from pyasic.config.pools import PoolConfig
@@ -85,11 +87,41 @@ class MinerConfig:
**self.power_scaling.as_inno(), **self.power_scaling.as_inno(),
} }
def as_bosminer(self, user_suffix: str = None):
return {
**merge(self.fan_mode.as_bosminer(), self.temperature.as_bosminer()),
**self.mining_mode.as_bosminer(),
**self.pools.as_bosminer(user_suffix=user_suffix),
**self.power_scaling.as_bosminer(),
}
@classmethod @classmethod
def from_api(cls, api_pools: dict): def from_api(cls, api_pools: dict):
return cls(pools=PoolConfig.from_api(api_pools)) return cls(pools=PoolConfig.from_api(api_pools))
def merge(a: dict, b: dict):
ret = {}
for k in a:
v = a[k]
if k in b.keys():
if isinstance(v, dict):
ret[k] = merge(a[k], b[k])
elif isinstance(v, list):
ret[k] = [*v, *b[k]]
else:
ret[k] = v
else:
ret[k] = v
for k in b:
v = b[k]
if k not in ret.keys():
ret[k] = v
return ret
if __name__ == "__main__": if __name__ == "__main__":
config = MinerConfig( config = MinerConfig(
pools=PoolConfig.simple( pools=PoolConfig.simple(
@@ -102,6 +134,8 @@ if __name__ == "__main__":
] ]
), ),
mining_mode=MiningModeConfig.power_tuning(3000), mining_mode=MiningModeConfig.power_tuning(3000),
temperature=TemperatureConfig(hot=100),
fan_mode=FanModeConfig.manual(minimum_fans=2, speed=70),
) )
print("WM:", config.as_wm()) print("WM:", config.as_wm())
print("AM Modern:", config.as_am_modern()) print("AM Modern:", config.as_am_modern())
@@ -109,3 +143,6 @@ if __name__ == "__main__":
print("GS:", config.as_goldshell()) print("GS:", config.as_goldshell())
print("Avalon:", config.as_avalon()) print("Avalon:", config.as_avalon())
print("Inno:", config.as_inno()) print("Inno:", config.as_inno())
print("BOS+ .toml:", config.as_bosminer())
print("BOS+ .toml as toml:")
print(toml.dumps(config.as_bosminer()))

View File

@@ -35,7 +35,7 @@ class MinerConfigOption(Enum):
def as_avalon(self) -> dict: def as_avalon(self) -> dict:
return self.value.as_avalon() return self.value.as_avalon()
def as_bos(self) -> dict: def as_bosminer(self) -> dict:
return self.value.as_bos() return self.value.as_bos()
def __call__(self, *args, **kwargs): def __call__(self, *args, **kwargs):
@@ -61,5 +61,5 @@ class MinerConfigValue:
def as_avalon(self) -> dict: def as_avalon(self) -> dict:
return {} return {}
def as_bos(self) -> dict: def as_bosminer(self) -> dict:
return {} return {}

View File

@@ -25,7 +25,7 @@ class FanModeNormal(MinerConfigValue):
def as_am_modern(self): def as_am_modern(self):
return {"bitmain-fan-ctrl": False, "bitmain-fan-pwn": "100"} return {"bitmain-fan-ctrl": False, "bitmain-fan-pwn": "100"}
def as_bos(self): def as_bosminer(self):
return {"temp_control": {"mode": "auto"}} return {"temp_control": {"mode": "auto"}}
@@ -38,7 +38,7 @@ class FanModeManual(MinerConfigValue):
def as_am_modern(self): def as_am_modern(self):
return {"bitmain-fan-ctrl": True, "bitmain-fan-pwn": str(self.speed)} return {"bitmain-fan-ctrl": True, "bitmain-fan-pwn": str(self.speed)}
def as_bos(self): def as_bosminer(self):
return { return {
"temp_control": {"mode": "manual"}, "temp_control": {"mode": "manual"},
"fan_control": {"min_fans": self.minimum_fans, "speed": self.speed}, "fan_control": {"min_fans": self.minimum_fans, "speed": self.speed},
@@ -52,8 +52,8 @@ class FanModeImmersion(MinerConfigValue):
def as_am_modern(self): def as_am_modern(self):
return {"bitmain-fan-ctrl": True, "bitmain-fan-pwn": "0"} return {"bitmain-fan-ctrl": True, "bitmain-fan-pwn": "0"}
def as_bos(self): def as_bosminer(self):
return {"temp_control": {"mode": "manual"}, "fan_control": {"min_fans": 0}} return {"temp_control": {"mode": "disabled"}}
class FanModeConfig(MinerConfigOption): class FanModeConfig(MinerConfigOption):

View File

@@ -73,6 +73,9 @@ class MiningModePowerTune(MinerConfigValue):
def as_wm(self): def as_wm(self):
return {"mode": self.mode, self.mode: {"wattage": self.power}} return {"mode": self.mode, self.mode: {"wattage": self.power}}
def as_bosminer(self) -> dict:
return {"autotuning": {"enabled": True, "psu_power_limit": self.power}}
@dataclass @dataclass
class MiningModeHashrateTune(MinerConfigValue): class MiningModeHashrateTune(MinerConfigValue):

View File

@@ -93,6 +93,16 @@ class Pool(MinerConfigValue):
def from_api(cls, api_pool: dict): def from_api(cls, api_pool: dict):
return cls(url=api_pool["URL"], user=api_pool["User"], password="x") return cls(url=api_pool["URL"], user=api_pool["User"], password="x")
def as_bosminer(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}
@dataclass @dataclass
class PoolGroup(MinerConfigValue): class PoolGroup(MinerConfigValue):
pools: list[Pool] = field(default_factory=list) pools: list[Pool] = field(default_factory=list)
@@ -178,6 +188,18 @@ class PoolGroup(MinerConfigValue):
pools.append(Pool.from_api(pool)) pools.append(Pool.from_api(pool))
return cls(pools=pools) return cls(pools=pools)
def as_bosminer(self, user_suffix: str = None) -> dict:
if len(self.pools) > 0:
return {
"name": self.name,
"quota": self.quota,
"pool": [
pool.as_bosminer(user_suffix=user_suffix) for pool in self.pools
],
}
return {"name": "Group", "quota": 1, "pool": [Pool.as_bosminer()]}
@dataclass @dataclass
class PoolConfig(MinerConfigValue): class PoolConfig(MinerConfigValue):
groups: list[PoolGroup] = field(default_factory=list) groups: list[PoolGroup] = field(default_factory=list)
@@ -231,3 +253,10 @@ class PoolConfig(MinerConfigValue):
pool_data = sorted(pool_data, key=lambda x: int(x["POOL"])) pool_data = sorted(pool_data, key=lambda x: int(x["POOL"]))
return cls([PoolGroup.from_api(pool_data)]) return cls([PoolGroup.from_api(pool_data)])
def as_bosminer(self, user_suffix: str = None) -> dict:
if len(self.groups) > 0:
return {
"group": [g.as_bosminer(user_suffix=user_suffix) for g in self.groups]
}
return {"group": [PoolGroup().as_bosminer()]}

View File

@@ -27,3 +27,13 @@ class TemperatureConfig(MinerConfigValue):
@classmethod @classmethod
def default(cls): def default(cls):
return cls() return cls()
def as_bosminer(self) -> dict:
temp_cfg = {}
if self.target is not None:
temp_cfg["target_temp"] = self.target
if self.hot is not None:
temp_cfg["hot_temp"] = self.hot
if self.danger is not None:
temp_cfg["dangerous_temp"] = self.danger
return {"temp_control": temp_cfg}