Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
04bd03b496 | ||
|
|
bc5764c8ff | ||
|
|
1f2e066f4c | ||
|
|
74c457a694 | ||
|
|
4a1c53dfd7 | ||
|
|
81b77f8768 | ||
|
|
3b127b6862 | ||
|
|
2815d2ba11 | ||
|
|
1ff20fc6f0 | ||
|
|
797c847055 | ||
|
|
65c7f2f66f | ||
|
|
577e8df612 | ||
|
|
743823f66e |
@@ -106,7 +106,7 @@
|
||||
show_root_heading: false
|
||||
heading_level: 4
|
||||
|
||||
## S19 Pro+ Hydro
|
||||
## S19K Pro
|
||||
::: pyasic.miners.antminer.bmminer.X19.S19.BMMinerS19KPro
|
||||
handler: python
|
||||
options:
|
||||
|
||||
@@ -8,6 +8,13 @@
|
||||
show_root_heading: false
|
||||
heading_level: 4
|
||||
|
||||
## S21
|
||||
::: pyasic.miners.antminer.bosminer.X21.S21.BOSMinerS21
|
||||
handler: python
|
||||
options:
|
||||
show_root_heading: false
|
||||
heading_level: 4
|
||||
|
||||
## S21 (ePIC)
|
||||
::: pyasic.miners.antminer.epic.X21.S21.ePICS21
|
||||
handler: python
|
||||
|
||||
@@ -81,7 +81,7 @@ details {
|
||||
<li><a href="../antminer/X19#s19-hydro">S19 Hydro</a></li>
|
||||
<li><a href="../antminer/X19#s19-pro-hydro">S19 Pro Hydro</a></li>
|
||||
<li><a href="../antminer/X19#s19-pro_1-hydro">S19 Pro+ Hydro</a></li>
|
||||
<li><a href="../antminer/X19#s19-pro_1-hydro">S19 Pro+ Hydro</a></li>
|
||||
<li><a href="../antminer/X19#s19k-pro">S19K Pro</a></li>
|
||||
<li><a href="../antminer/X19#t19">T19</a></li>
|
||||
</ul>
|
||||
</details>
|
||||
@@ -460,6 +460,12 @@ details {
|
||||
<li><a href="../antminer/X19#t19">T19</a></li>
|
||||
</ul>
|
||||
</details>
|
||||
<details>
|
||||
<summary>X21 Series:</summary>
|
||||
<ul>
|
||||
<li><a href="../antminer/X21#s21">S21</a></li>
|
||||
</ul>
|
||||
</details>
|
||||
</ul>
|
||||
</details>
|
||||
<details>
|
||||
|
||||
@@ -184,7 +184,10 @@ class MiningModePowerTune(MinerConfigValue):
|
||||
return {}
|
||||
|
||||
def as_bosminer(self) -> dict:
|
||||
return {"autotuning": {"enabled": True, "psu_power_limit": self.power}}
|
||||
conf = {"enabled": True, "mode": "power_target"}
|
||||
if self.power is not None:
|
||||
conf["power_target"] = self.power
|
||||
return {"autotuning": conf}
|
||||
|
||||
def as_boser(self) -> dict:
|
||||
return {
|
||||
@@ -219,6 +222,12 @@ class MiningModeHashrateTune(MinerConfigValue):
|
||||
return {"miner-mode": "0"}
|
||||
return {"miner-mode": 0}
|
||||
|
||||
def as_bosminer(self) -> dict:
|
||||
conf = {"enabled": True, "mode": "hashrate_target"}
|
||||
if self.hashrate is not None:
|
||||
conf["hashrate_target"] = self.hashrate
|
||||
return {"autotuning": conf}
|
||||
|
||||
def as_boser(self) -> dict:
|
||||
return {
|
||||
"set_performance_mode": SetPerformanceModeRequest(
|
||||
|
||||
@@ -114,6 +114,8 @@ class PowerScalingEnabled(MinerConfigValue):
|
||||
def from_bosminer(cls, power_scaling_conf: dict) -> "PowerScalingEnabled":
|
||||
power_step = power_scaling_conf.get("power_step")
|
||||
min_power = power_scaling_conf.get("min_psu_power_limit")
|
||||
if min_power is None:
|
||||
min_power = power_scaling_conf.get("min_power_target")
|
||||
sd_mode = PowerScalingShutdown.from_bosminer(power_scaling_conf)
|
||||
|
||||
return cls(
|
||||
@@ -138,12 +140,12 @@ class PowerScalingEnabled(MinerConfigValue):
|
||||
if self.power_step is not None:
|
||||
cfg["power_step"] = self.power_step
|
||||
if self.minimum_power is not None:
|
||||
cfg["min_psu_power_limit"] = self.minimum_power
|
||||
cfg["min_power_target"] = self.minimum_power
|
||||
|
||||
if self.shutdown_enabled is not None:
|
||||
cfg = {**cfg, **self.shutdown_enabled.as_bosminer()}
|
||||
|
||||
return {"power_scaling": cfg}
|
||||
return {"performance_scaling": cfg}
|
||||
|
||||
def as_boser(self) -> dict:
|
||||
return {
|
||||
@@ -189,6 +191,8 @@ class PowerScalingConfig(MinerConfigOption):
|
||||
@classmethod
|
||||
def from_bosminer(cls, toml_conf: dict):
|
||||
power_scaling = toml_conf.get("power_scaling")
|
||||
if power_scaling is None:
|
||||
power_scaling = toml_conf.get("performance_scaling")
|
||||
if power_scaling is not None:
|
||||
enabled = power_scaling.get("enabled")
|
||||
if enabled is not None:
|
||||
|
||||
@@ -94,7 +94,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
|
||||
|
||||
22
pyasic/miners/antminer/bmminer/X21/T21.py
Normal file
22
pyasic/miners/antminer/bmminer/X21/T21.py
Normal file
@@ -0,0 +1,22 @@
|
||||
# ------------------------------------------------------------------------------
|
||||
# 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 pyasic.miners.backends import AntminerModern
|
||||
from pyasic.miners.models import T21
|
||||
|
||||
|
||||
class BMMinerT21(AntminerModern, T21):
|
||||
pass
|
||||
@@ -14,3 +14,4 @@
|
||||
# limitations under the License. -
|
||||
# ------------------------------------------------------------------------------
|
||||
from .S21 import BMMinerS21
|
||||
from .T21 import BMMinerT21
|
||||
|
||||
22
pyasic/miners/antminer/bosminer/X21/S21.py
Normal file
22
pyasic/miners/antminer/bosminer/X21/S21.py
Normal file
@@ -0,0 +1,22 @@
|
||||
# ------------------------------------------------------------------------------
|
||||
# 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 pyasic.miners.backends import BOSer
|
||||
from pyasic.miners.models import S21
|
||||
|
||||
|
||||
class BOSMinerS21(BOSer, S21):
|
||||
pass
|
||||
17
pyasic/miners/antminer/bosminer/X21/__init__.py
Normal file
17
pyasic/miners/antminer/bosminer/X21/__init__.py
Normal file
@@ -0,0 +1,17 @@
|
||||
# ------------------------------------------------------------------------------
|
||||
# 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 .S21 import BOSMinerS21
|
||||
@@ -17,3 +17,4 @@
|
||||
from .X9 import *
|
||||
from .X17 import *
|
||||
from .X19 import *
|
||||
from .X21 import *
|
||||
|
||||
22
pyasic/miners/antminer/epic/X21/T21.py
Normal file
22
pyasic/miners/antminer/epic/X21/T21.py
Normal file
@@ -0,0 +1,22 @@
|
||||
# ------------------------------------------------------------------------------
|
||||
# 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 pyasic.miners.backends import ePIC
|
||||
from pyasic.miners.models import T21
|
||||
|
||||
|
||||
class ePICT21(ePIC, T21):
|
||||
pass
|
||||
@@ -17,3 +17,7 @@
|
||||
from .S21 import (
|
||||
ePICS21,
|
||||
)
|
||||
|
||||
from .T21 import (
|
||||
ePICT21,
|
||||
)
|
||||
|
||||
@@ -181,16 +181,17 @@ class BOSMiner(BaseMiner):
|
||||
|
||||
async def send_config(self, config: MinerConfig, user_suffix: str = None) -> None:
|
||||
self.config = config
|
||||
parsed_cfg = config.as_bosminer(user_suffix=user_suffix)
|
||||
|
||||
toml_conf = toml.dumps(
|
||||
{
|
||||
"format": {
|
||||
"version": "1.2+",
|
||||
"version": "2.0",
|
||||
"generator": "pyasic",
|
||||
"model": f"{self.make.replace('Miner', 'miner')} {self.raw_model.replace('j', 'J')}",
|
||||
"timestamp": int(time.time()),
|
||||
},
|
||||
**config.as_bosminer(user_suffix=user_suffix),
|
||||
**parsed_cfg,
|
||||
}
|
||||
)
|
||||
try:
|
||||
|
||||
@@ -74,6 +74,10 @@ EPIC_DATA_LOC = DataLocations(
|
||||
"_get_uptime",
|
||||
[WebAPICommand("web_summary", "summary")],
|
||||
),
|
||||
str(DataOptions.IS_MINING): DataFunction(
|
||||
"_is_mining",
|
||||
[WebAPICommand("web_summary", "summary")],
|
||||
),
|
||||
}
|
||||
)
|
||||
|
||||
@@ -313,8 +317,18 @@ class ePIC(BaseMiner):
|
||||
hb_list[hb["Index"]].temp = hb["Temperature"]
|
||||
return hb_list
|
||||
|
||||
async def _is_mining(self, *args, **kwargs) -> Optional[bool]:
|
||||
return None
|
||||
async def _is_mining(self, web_summary, *args, **kwargs) -> Optional[bool]:
|
||||
if web_summary is None:
|
||||
try:
|
||||
web_summary = await self.web.summary()
|
||||
except APIError:
|
||||
pass
|
||||
if web_summary is not None:
|
||||
try:
|
||||
op_state = web_summary["Status"]["Operating State"]
|
||||
return not op_state == "Idling"
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
async def _get_uptime(self, web_summary: dict = None) -> Optional[int]:
|
||||
if web_summary is None:
|
||||
|
||||
@@ -225,9 +225,10 @@ class VNish(BMMiner):
|
||||
|
||||
if web_summary is not None:
|
||||
try:
|
||||
is_mining = (
|
||||
not web_summary["miner"]["miner_status"]["miner_state"] == "stopped"
|
||||
)
|
||||
is_mining = not web_summary["miner"]["miner_status"]["miner_state"] in [
|
||||
"stopped",
|
||||
"shutting-down",
|
||||
]
|
||||
return is_mining
|
||||
except LookupError:
|
||||
pass
|
||||
|
||||
@@ -16,4 +16,5 @@
|
||||
|
||||
from .blockminer import (
|
||||
ePICBlockMiner520i,
|
||||
ePICBlockMiner720i,
|
||||
)
|
||||
|
||||
@@ -16,7 +16,12 @@
|
||||
|
||||
from pyasic.miners.backends import ePIC
|
||||
from pyasic.miners.models import BlockMiner520i
|
||||
from pyasic.miners.models import BlockMiner720i
|
||||
|
||||
|
||||
class ePICBlockMiner520i(ePIC, BlockMiner520i):
|
||||
pass
|
||||
|
||||
|
||||
class ePICBlockMiner720i(ePIC, BlockMiner720i):
|
||||
pass
|
||||
|
||||
@@ -105,6 +105,7 @@ MINER_CLASSES = {
|
||||
"ANTMINER S19K PRO": BMMinerS19KPro,
|
||||
"ANTMINER T19": BMMinerT19,
|
||||
"ANTMINER S21": BMMinerS21,
|
||||
"ANTMINER T21": BMMinerT21,
|
||||
},
|
||||
MinerTypes.WHATSMINER: {
|
||||
None: type("WhatsminerUnknown", (BTMiner, WhatsMinerMake), {}),
|
||||
@@ -374,6 +375,7 @@ MINER_CLASSES = {
|
||||
"ANTMINER S19K PRO NOPIC": BOSMinerS19kProNoPIC,
|
||||
"ANTMINER S19 XP": BOSMinerS19XP,
|
||||
"ANTMINER T19": BOSMinerT19,
|
||||
"ANTMINER S21": BOSMinerS21,
|
||||
},
|
||||
MinerTypes.VNISH: {
|
||||
None: VNish,
|
||||
@@ -401,7 +403,9 @@ MINER_CLASSES = {
|
||||
"ANTMINER S19K PRO": ePICS19kPro,
|
||||
"ANTMINER S19 XP": ePICS19XP,
|
||||
"ANTMINER S21": ePICS21,
|
||||
"ANTMINER T21": ePICT21,
|
||||
"BLOCKMINER 520I": ePICBlockMiner520i,
|
||||
"BLOCKMINER 720I": ePICBlockMiner720i,
|
||||
},
|
||||
MinerTypes.HIVEON: {
|
||||
None: Hiveon,
|
||||
|
||||
23
pyasic/miners/models/antminer/X21/T21.py
Normal file
23
pyasic/miners/models/antminer/X21/T21.py
Normal file
@@ -0,0 +1,23 @@
|
||||
# ------------------------------------------------------------------------------
|
||||
# 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 pyasic.miners.makes import AntMinerMake
|
||||
|
||||
|
||||
class T21(AntMinerMake):
|
||||
raw_model = "T21"
|
||||
expected_chips = 108
|
||||
expected_fans = 4
|
||||
@@ -17,3 +17,6 @@
|
||||
from .S21 import (
|
||||
S21,
|
||||
)
|
||||
from .T21 import (
|
||||
T21,
|
||||
)
|
||||
|
||||
@@ -5,3 +5,9 @@ class BlockMiner520i(ePICMake):
|
||||
raw_model = "BlockMiner 520i"
|
||||
expected_chips = 124
|
||||
expected_fans = 4
|
||||
|
||||
|
||||
class BlockMiner720i(ePICMake):
|
||||
raw_model = "BlockMiner 720i"
|
||||
expected_chips = 180
|
||||
expected_fans = 4
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[tool.poetry]
|
||||
name = "pyasic"
|
||||
version = "0.54.11"
|
||||
version = "0.54.15"
|
||||
description = "A simplified and standardized interface for Bitcoin ASICs."
|
||||
authors = ["UpstreamData <brett@upstreamdata.ca>"]
|
||||
repository = "https://github.com/UpstreamData/pyasic"
|
||||
|
||||
@@ -98,7 +98,11 @@ class TestConfig(unittest.TestCase):
|
||||
"dangerous_temp": 120,
|
||||
},
|
||||
"fan_control": {"min_fans": 2, "speed": 90},
|
||||
"autotuning": {"enabled": True, "psu_power_limit": 3000},
|
||||
"autotuning": {
|
||||
"enabled": True,
|
||||
"mode": "power_target",
|
||||
"power_target": 3000,
|
||||
},
|
||||
"group": [
|
||||
{
|
||||
"name": "W91Q1L",
|
||||
@@ -112,10 +116,10 @@ class TestConfig(unittest.TestCase):
|
||||
"quota": 1,
|
||||
}
|
||||
],
|
||||
"power_scaling": {
|
||||
"performance_scaling": {
|
||||
"enabled": True,
|
||||
"power_step": 100,
|
||||
"min_psu_power_limit": 2000,
|
||||
"min_power_target": 2000,
|
||||
"shutdown_enabled": True,
|
||||
"shutdown_duration": 3,
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user