Compare commits

..

22 Commits

Author SHA1 Message Date
Brett Rowan
a62bea33a7 docs: update docs 2025-04-18 16:15:31 -06:00
pre-commit-ci[bot]
406bcd179c [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
2025-04-18 16:12:55 -06:00
Ryan Heideman
aa87ef7d71 nano3s fixes 2025-04-18 16:12:55 -06:00
SKART1
ec88fbf6aa Fix #334 efficiency calculation and add computed fields 2025-04-18 16:12:44 -06:00
pre-commit-ci[bot]
e23c86a944 [pre-commit.ci] pre-commit autoupdate
updates:
- [github.com/python-poetry/poetry: 2.1.1 → 2.1.2](https://github.com/python-poetry/poetry/compare/2.1.1...2.1.2)
2025-04-16 08:41:30 -06:00
Brett Rowan
b81276cb19 version: bump version number 2025-04-16 08:40:36 -06:00
Adrian
8dcc72b1bb T21 working on LuxOS (#331) 2025-04-14 12:55:54 -06:00
Timur Taipov
540572356f feature: add support for S21+ hydro (#326) 2025-04-14 09:15:06 -06:00
Ryan Heideman
83035a869b feature: Add Support for Avalon Nano 3s (#329) 2025-04-12 15:34:45 -06:00
Brett Rowan
4c104a59ff version: bump version number 2025-04-01 09:24:20 -06:00
Brett Rowan
e708ae3728 bug: remove MSKminer web identification 2025-04-01 09:23:51 -06:00
Wilfred Allyn
a4352816ee bug: pass atmset param as bool 2025-04-01 07:48:42 -06:00
Will Jackson
336bd9c002 bug: update set_dps configuration to handle optional power and hashrate parameters (#319)
* bug: update set_dps configuration to handle optional power and hashrate parameters
2025-03-27 11:09:47 -06:00
Wilfred Allyn
e3c917efde feature: set supports_autotuning True for luxminer 2025-03-26 08:06:38 -06:00
Brett Rowan
4d71012ed6 version: bump version number
Closes: #310
2025-03-20 10:46:30 -06:00
Will Jackson
1acdba8ae0 bug: fix set_dps configuration to handle power target parameters correctly (#318)
* bug: fix set_dps configuration to handle power target parameters correctly

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2025-03-20 10:45:48 -06:00
Brett Rowan
5567f26c03 version: bump version number
Closes: #316, #310
2025-03-20 09:20:51 -06:00
Brett Rowan
0027485582 bug: fix set_dps tuple
cc: #310
2025-03-20 09:20:23 -06:00
Brett Rowan
c9bcb7bab6 feature: add support for S21+
cc: #316
2025-03-19 13:28:03 -06:00
John-Paul Compagnone
0ee261930e epic: remove guard on expected_hashboards 2025-03-18 09:35:13 -06:00
John-Paul Compagnone
3cfc8dded9 epic: remove v1 from ELITE miner 2025-03-18 09:35:13 -06:00
John-Paul Compagnone
655cf6d0ac epic: add BlockMiner eLITE, S19k Pro Dualie 2025-03-18 09:35:13 -06:00
31 changed files with 418 additions and 60 deletions

View File

@@ -5,7 +5,7 @@ ci:
- generate-docs - generate-docs
repos: repos:
- repo: https://github.com/python-poetry/poetry - repo: https://github.com/python-poetry/poetry
rev: 2.1.1 rev: 2.1.2
hooks: hooks:
- id: poetry-check - id: poetry-check
- id: poetry-lock - id: poetry-lock

View File

@@ -677,6 +677,19 @@
show_root_heading: false show_root_heading: false
heading_level: 0 heading_level: 0
## S19k Pro Dual (ePIC)
- [x] Shutdowns
- [ ] Power Modes
- [ ] Setpoints
- [ ] Presets
::: pyasic.miners.antminer.epic.X19.S19.ePICS19kProDual
handler: python
options:
show_root_heading: false
heading_level: 0
## S19 (Hive) ## S19 (Hive)
- [ ] Shutdowns - [ ] Shutdowns
@@ -746,7 +759,7 @@
- [x] Shutdowns - [x] Shutdowns
- [ ] Power Modes - [ ] Power Modes
- [ ] Setpoints - [x] Setpoints
- [x] Presets - [x] Presets
::: pyasic.miners.antminer.luxos.X19.S19.LUXMinerS19 ::: pyasic.miners.antminer.luxos.X19.S19.LUXMinerS19
@@ -759,7 +772,7 @@
- [x] Shutdowns - [x] Shutdowns
- [ ] Power Modes - [ ] Power Modes
- [ ] Setpoints - [x] Setpoints
- [x] Presets - [x] Presets
::: pyasic.miners.antminer.luxos.X19.S19.LUXMinerS19Pro ::: pyasic.miners.antminer.luxos.X19.S19.LUXMinerS19Pro
@@ -772,7 +785,7 @@
- [x] Shutdowns - [x] Shutdowns
- [ ] Power Modes - [ ] Power Modes
- [ ] Setpoints - [x] Setpoints
- [x] Presets - [x] Presets
::: pyasic.miners.antminer.luxos.X19.S19.LUXMinerS19XP ::: pyasic.miners.antminer.luxos.X19.S19.LUXMinerS19XP
@@ -785,7 +798,7 @@
- [x] Shutdowns - [x] Shutdowns
- [ ] Power Modes - [ ] Power Modes
- [ ] Setpoints - [x] Setpoints
- [x] Presets - [x] Presets
::: pyasic.miners.antminer.luxos.X19.S19.LUXMinerS19jPro ::: pyasic.miners.antminer.luxos.X19.S19.LUXMinerS19jPro
@@ -798,7 +811,7 @@
- [x] Shutdowns - [x] Shutdowns
- [ ] Power Modes - [ ] Power Modes
- [ ] Setpoints - [x] Setpoints
- [x] Presets - [x] Presets
::: pyasic.miners.antminer.luxos.X19.S19.LUXMinerS19jProPlus ::: pyasic.miners.antminer.luxos.X19.S19.LUXMinerS19jProPlus
@@ -811,7 +824,7 @@
- [x] Shutdowns - [x] Shutdowns
- [ ] Power Modes - [ ] Power Modes
- [ ] Setpoints - [x] Setpoints
- [x] Presets - [x] Presets
::: pyasic.miners.antminer.luxos.X19.S19.LUXMinerS19kPro ::: pyasic.miners.antminer.luxos.X19.S19.LUXMinerS19kPro
@@ -824,7 +837,7 @@
- [x] Shutdowns - [x] Shutdowns
- [ ] Power Modes - [ ] Power Modes
- [ ] Setpoints - [x] Setpoints
- [x] Presets - [x] Presets
::: pyasic.miners.antminer.luxos.X19.T19.LUXMinerT19 ::: pyasic.miners.antminer.luxos.X19.T19.LUXMinerT19

View File

@@ -40,6 +40,32 @@
show_root_heading: false show_root_heading: false
heading_level: 0 heading_level: 0
## S21+ (Stock)
- [x] Shutdowns
- [x] Power Modes
- [ ] Setpoints
- [ ] Presets
::: pyasic.miners.antminer.bmminer.X21.S21.BMMinerS21Plus
handler: python
options:
show_root_heading: false
heading_level: 0
## S21+ Hydro (Stock)
- [x] Shutdowns
- [x] Power Modes
- [ ] Setpoints
- [ ] Presets
::: pyasic.miners.antminer.bmminer.X21.S21.BMMinerS21PlusHydro
handler: python
options:
show_root_heading: false
heading_level: 0
## T21 (Stock) ## T21 (Stock)
- [x] Shutdowns - [x] Shutdowns
@@ -161,7 +187,7 @@
- [x] Shutdowns - [x] Shutdowns
- [ ] Power Modes - [ ] Power Modes
- [ ] Setpoints - [x] Setpoints
- [x] Presets - [x] Presets
::: pyasic.miners.antminer.luxos.X21.S21.LUXMinerS21 ::: pyasic.miners.antminer.luxos.X21.S21.LUXMinerS21
@@ -170,6 +196,19 @@
show_root_heading: false show_root_heading: false
heading_level: 0 heading_level: 0
## T21 (LuxOS)
- [x] Shutdowns
- [ ] Power Modes
- [x] Setpoints
- [x] Presets
::: pyasic.miners.antminer.luxos.X21.T21.LUXMinerT21
handler: python
options:
show_root_heading: false
heading_level: 0
## S21 (MaraFW) ## S21 (MaraFW)
- [ ] Shutdowns - [ ] Shutdowns

View File

@@ -122,7 +122,7 @@
- [x] Shutdowns - [x] Shutdowns
- [ ] Power Modes - [ ] Power Modes
- [ ] Setpoints - [x] Setpoints
- [x] Presets - [x] Presets
::: pyasic.miners.antminer.luxos.X9.S9.LUXMinerS9 ::: pyasic.miners.antminer.luxos.X9.S9.LUXMinerS9

View File

@@ -1,6 +1,19 @@
# pyasic # pyasic
## nano Models ## nano Models
## Avalon Nano 3s (Stock)
- [ ] Shutdowns
- [ ] Power Modes
- [ ] Setpoints
- [ ] Presets
::: pyasic.miners.avalonminer.cgminer.nano.nano3.CGMinerAvalonNano3s
handler: python
options:
show_root_heading: false
heading_level: 0
## Avalon Nano 3 (Stock) ## Avalon Nano 3 (Stock)
- [ ] Shutdowns - [ ] Shutdowns

View File

@@ -27,3 +27,16 @@
show_root_heading: false show_root_heading: false
heading_level: 0 heading_level: 0
## BlockMiner eLITE 1.0 (ePIC)
- [x] Shutdowns
- [ ] Power Modes
- [ ] Setpoints
- [ ] Presets
::: pyasic.miners.blockminer.epic.blockminer.blockminer.ePICBlockMinerELITE1
handler: python
options:
show_root_heading: false
heading_level: 0

View File

@@ -103,6 +103,8 @@ details {
<li><a href="../antminer/X21#s21-stock">S21 (Stock)</a></li> <li><a href="../antminer/X21#s21-stock">S21 (Stock)</a></li>
<li><a href="../antminer/X21#s21-stock">S21 (Stock)</a></li> <li><a href="../antminer/X21#s21-stock">S21 (Stock)</a></li>
<li><a href="../antminer/X21#s21-stock">S21 (Stock)</a></li> <li><a href="../antminer/X21#s21-stock">S21 (Stock)</a></li>
<li><a href="../antminer/X21#s21_1-stock">S21+ (Stock)</a></li>
<li><a href="../antminer/X21#s21_1-hydro-stock">S21+ Hydro (Stock)</a></li>
<li><a href="../antminer/X21#s21-pro-stock">S21 Pro (Stock)</a></li> <li><a href="../antminer/X21#s21-pro-stock">S21 Pro (Stock)</a></li>
<li><a href="../antminer/X21#t21-stock">T21 (Stock)</a></li> <li><a href="../antminer/X21#t21-stock">T21 (Stock)</a></li>
<li><a href="../antminer/X21#s21-hydro-stock">S21 Hydro (Stock)</a></li> <li><a href="../antminer/X21#s21-hydro-stock">S21 Hydro (Stock)</a></li>
@@ -552,6 +554,7 @@ details {
<summary>nano Series:</summary> <summary>nano Series:</summary>
<ul> <ul>
<li><a href="../avalonminer/nano#avalon-nano-3-stock">Avalon Nano 3 (Stock)</a></li> <li><a href="../avalonminer/nano#avalon-nano-3-stock">Avalon Nano 3 (Stock)</a></li>
<li><a href="../avalonminer/nano#avalon-nano-3s-stock">Avalon Nano 3s (Stock)</a></li>
</ul> </ul>
</details> </details>
<details> <details>
@@ -736,6 +739,7 @@ details {
<li><a href="../antminer/X19#s19k-pro-epic">S19k Pro (ePIC)</a></li> <li><a href="../antminer/X19#s19k-pro-epic">S19k Pro (ePIC)</a></li>
<li><a href="../antminer/X19#s19-xp-epic">S19 XP (ePIC)</a></li> <li><a href="../antminer/X19#s19-xp-epic">S19 XP (ePIC)</a></li>
<li><a href="../antminer/X19#s19j-pro-dual-epic">S19j Pro Dual (ePIC)</a></li> <li><a href="../antminer/X19#s19j-pro-dual-epic">S19j Pro Dual (ePIC)</a></li>
<li><a href="../antminer/X19#s19k-pro-dual-epic">S19k Pro Dual (ePIC)</a></li>
</ul> </ul>
</details> </details>
<details> <details>
@@ -751,6 +755,7 @@ details {
<ul> <ul>
<li><a href="../blockminer/blockminer#blockminer-520i-epic">BlockMiner 520i (ePIC)</a></li> <li><a href="../blockminer/blockminer#blockminer-520i-epic">BlockMiner 520i (ePIC)</a></li>
<li><a href="../blockminer/blockminer#blockminer-720i-epic">BlockMiner 720i (ePIC)</a></li> <li><a href="../blockminer/blockminer#blockminer-720i-epic">BlockMiner 720i (ePIC)</a></li>
<li><a href="../blockminer/blockminer#blockminer-elite-1.0-epic">BlockMiner eLITE 1.0 (ePIC)</a></li>
</ul> </ul>
</details> </details>
</ul> </ul>
@@ -811,6 +816,7 @@ details {
<summary>X21 Series:</summary> <summary>X21 Series:</summary>
<ul> <ul>
<li><a href="../antminer/X21#s21-luxos">S21 (LuxOS)</a></li> <li><a href="../antminer/X21#s21-luxos">S21 (LuxOS)</a></li>
<li><a href="../antminer/X21#t21-luxos">T21 (LuxOS)</a></li>
</ul> </ul>
</details> </details>
</ul> </ul>

View File

@@ -258,18 +258,18 @@ class MiningModePowerTune(MinerConfigValue):
sd_cfg = {} sd_cfg = {}
if self.scaling.shutdown is not None: if self.scaling.shutdown is not None:
sd_cfg = self.scaling.shutdown.as_boser() sd_cfg = self.scaling.shutdown.as_boser()
cfg["set_dps"] = ( power_target_kwargs = {}
SetDpsRequest( if self.scaling.step is not None:
enable=True, power_target_kwargs["power_step"] = Power(self.scaling.step)
**sd_cfg, if self.scaling.minimum is not None:
target=DpsTarget( power_target_kwargs["min_power_target"] = Power(self.scaling.minimum)
power_target=DpsPowerTarget( cfg["set_dps"] = SetDpsRequest(
power_step=Power(self.scaling.step), save_action=SaveAction.SAVE_AND_APPLY,
min_power_target=Power(self.scaling.minimum), enable=True,
) **sd_cfg,
), target=DpsTarget(power_target=DpsPowerTarget(**power_target_kwargs)),
),
) )
return cfg return cfg
def as_auradine(self) -> dict: def as_auradine(self) -> dict:
@@ -330,7 +330,6 @@ class MiningModeHashrateTune(MinerConfigValue):
conf["hashrate_target"] = self.hashrate conf["hashrate_target"] = self.hashrate
return {"autotuning": conf} return {"autotuning": conf}
@property
def as_boser(self) -> dict: def as_boser(self) -> dict:
cfg = { cfg = {
"set_performance_mode": SetPerformanceModeRequest( "set_performance_mode": SetPerformanceModeRequest(
@@ -350,18 +349,24 @@ class MiningModeHashrateTune(MinerConfigValue):
sd_cfg = {} sd_cfg = {}
if self.scaling.shutdown is not None: if self.scaling.shutdown is not None:
sd_cfg = self.scaling.shutdown.as_boser() sd_cfg = self.scaling.shutdown.as_boser()
cfg["set_dps"] = ( hashrate_target_kwargs = {}
SetDpsRequest( if self.scaling.step is not None:
enable=True, hashrate_target_kwargs["hashrate_step"] = TeraHashrate(
**sd_cfg, self.scaling.step
target=DpsTarget( )
hashrate_target=DpsHashrateTarget( if self.scaling.minimum is not None:
hashrate_step=TeraHashrate(self.scaling.step), hashrate_target_kwargs["min_hashrate_target"] = TeraHashrate(
min_hashrate_target=TeraHashrate(self.scaling.minimum), self.scaling.minimum
) )
), cfg["set_dps"] = SetDpsRequest(
save_action=SaveAction.SAVE_AND_APPLY,
enable=True,
**sd_cfg,
target=DpsTarget(
hashrate_target=DpsHashrateTarget(**hashrate_target_kwargs)
), ),
) )
return cfg return cfg
def as_auradine(self) -> dict: def as_auradine(self) -> dict:

View File

@@ -284,10 +284,22 @@ class MinerData(BaseModel):
@computed_field # type: ignore[misc] @computed_field # type: ignore[misc]
@property @property
def efficiency(self) -> int | None: def efficiency(self) -> int | None:
efficiency = self._efficiency(0)
if efficiency is None:
return None
else:
return int(efficiency)
@computed_field # type: ignore[misc]
@property
def efficiency_fract(self) -> float | None:
self._efficiency(2)
def _efficiency(self, ndigits: int) -> float | None:
if self.hashrate is None or self.wattage is None: if self.hashrate is None or self.wattage is None:
return None return None
try: try:
return round(self.wattage / float(self.hashrate)) return round(self.wattage / float(self.hashrate), ndigits)
except ZeroDivisionError: except ZeroDivisionError:
return 0 return 0

View File

@@ -28,6 +28,8 @@ class HashBoard(BaseModel):
Attributes: Attributes:
slot: The slot of the board as an int. slot: The slot of the board as an int.
hashrate: The hashrate of the board in TH/s as a float. hashrate: The hashrate of the board in TH/s as a float.
inlet_temp: Inlet temperature for hydro asics as an int
outlet_temp: Outlet temperature for hydro asics as an int
temp: The temperature of the PCB as an int. temp: The temperature of the PCB as an int.
chip_temp: The temperature of the chips as an int. chip_temp: The temperature of the chips as an int.
chips: The chip count of the board as an int. chips: The chip count of the board as an int.
@@ -41,6 +43,8 @@ class HashBoard(BaseModel):
slot: int = 0 slot: int = 0
hashrate: AlgoHashRateType | None = None hashrate: AlgoHashRateType | None = None
inlet_temp: float | None = None
outlet_temp: float | None = None
temp: float | None = None temp: float | None = None
chip_temp: float | None = None chip_temp: float | None = None
chips: int | None = None chips: int | None = None

View File

@@ -58,6 +58,8 @@ class AntminerModels(MinerModelType):
S19jXP = "S19j XP" S19jXP = "S19j XP"
T19 = "T19" T19 = "T19"
S21 = "S21" S21 = "S21"
S21Plus = "S21+"
S21PlusHydro = "S21+ Hydro"
S21Pro = "S21 Pro" S21Pro = "S21 Pro"
S21Hydro = "S21 Hydro" S21Hydro = "S21 Hydro"
T21 = "T21" T21 = "T21"
@@ -450,6 +452,7 @@ class AvalonminerModels(MinerModelType):
Avalon1246 = "Avalon 1246" Avalon1246 = "Avalon 1246"
Avalon1566 = "Avalon 1566" Avalon1566 = "Avalon 1566"
AvalonNano3 = "Avalon Nano 3" AvalonNano3 = "Avalon Nano 3"
AvalonNano3s = "Avalon Nano 3s"
def __str__(self): def __str__(self):
return self.value return self.value
@@ -480,7 +483,9 @@ class GoldshellModels(MinerModelType):
class ePICModels(MinerModelType): class ePICModels(MinerModelType):
BM520i = "BlockMiner 520i" BM520i = "BlockMiner 520i"
BM720i = "BlockMiner 720i" BM720i = "BlockMiner 720i"
eLITE1 = "BlockMiner eLITE 1.0"
S19jProDual = "S19j Pro Dual" S19jProDual = "S19j Pro Dual"
S19kProDual = "S19k Pro Dual"
def __str__(self): def __str__(self):
return self.value return self.value

View File

@@ -15,13 +15,21 @@
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
from pyasic.miners.backends import AntminerModern from pyasic.miners.backends import AntminerModern
from pyasic.miners.device.models import S21, S21Hydro, S21Pro from pyasic.miners.device.models import S21, S21Hydro, S21Plus, S21PlusHydro, S21Pro
class BMMinerS21(AntminerModern, S21): class BMMinerS21(AntminerModern, S21):
pass pass
class BMMinerS21Plus(AntminerModern, S21Plus):
pass
class BMMinerS21PlusHydro(AntminerModern, S21PlusHydro):
pass
class BMMinerS21Pro(AntminerModern, S21Pro): class BMMinerS21Pro(AntminerModern, S21Pro):
pass pass

View File

@@ -13,5 +13,11 @@
# 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 .S21 import BMMinerS21, BMMinerS21Hydro, BMMinerS21Pro from .S21 import (
BMMinerS21,
BMMinerS21Hydro,
BMMinerS21Plus,
BMMinerS21PlusHydro,
BMMinerS21Pro,
)
from .T21 import BMMinerT21 from .T21 import BMMinerT21

View File

@@ -59,3 +59,9 @@ class ePICS19jProDual(ePIC, S19jPro):
raw_model = MinerModel.EPIC.S19jProDual raw_model = MinerModel.EPIC.S19jProDual
expected_fans = S19jPro.expected_fans * 2 expected_fans = S19jPro.expected_fans * 2
expected_hashboards = S19jPro.expected_hashboards * 2 expected_hashboards = S19jPro.expected_hashboards * 2
class ePICS19kProDual(ePIC, S19kPro):
raw_model = MinerModel.EPIC.S19kProDual
expected_fans = S19kPro.expected_fans * 2
expected_hashboards = S19kPro.expected_hashboards * 2

View File

@@ -21,6 +21,7 @@ from .S19 import (
ePICS19jProDual, ePICS19jProDual,
ePICS19jProPlus, ePICS19jProPlus,
ePICS19kPro, ePICS19kPro,
ePICS19kProDual,
ePICS19Pro, ePICS19Pro,
ePICS19XP, ePICS19XP,
) )

View 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 LUXMiner
from pyasic.miners.device.models import S21, T21
class LUXMinerT21(LUXMiner, T21):
pass

View File

@@ -15,3 +15,4 @@
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
from .S21 import LUXMinerS21 from .S21 import LUXMinerS21
from .T21 import LUXMinerT21

View File

@@ -14,4 +14,4 @@
# limitations under the License. - # limitations under the License. -
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
from .nano3 import CGMinerAvalonNano3 from .nano3 import CGMinerAvalonNano3, CGMinerAvalonNano3s

View File

@@ -13,9 +13,11 @@
# 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 typing import Optional from typing import List, Optional
from pyasic import APIError from pyasic import APIError
from pyasic.data.boards import HashBoard
from pyasic.device.algorithm.hashrate import AlgoHashRate
from pyasic.miners.backends import AvalonMiner from pyasic.miners.backends import AvalonMiner
from pyasic.miners.data import ( from pyasic.miners.data import (
DataFunction, DataFunction,
@@ -24,7 +26,7 @@ from pyasic.miners.data import (
RPCAPICommand, RPCAPICommand,
WebAPICommand, WebAPICommand,
) )
from pyasic.miners.device.models import AvalonNano3 from pyasic.miners.device.models import AvalonNano3, AvalonNano3s
from pyasic.web.avalonminer import AvalonMinerWebAPI from pyasic.web.avalonminer import AvalonMinerWebAPI
AVALON_NANO_DATA_LOC = DataLocations( AVALON_NANO_DATA_LOC = DataLocations(
@@ -84,6 +86,63 @@ AVALON_NANO_DATA_LOC = DataLocations(
} }
) )
AVALON_NANO3S_DATA_LOC = DataLocations(
**{
str(DataOptions.MAC): DataFunction(
"_get_mac",
[RPCAPICommand("rpc_version", "version")],
),
str(DataOptions.API_VERSION): DataFunction(
"_get_api_ver",
[RPCAPICommand("rpc_version", "version")],
),
str(DataOptions.FW_VERSION): DataFunction(
"_get_fw_ver",
[RPCAPICommand("rpc_version", "version")],
),
str(DataOptions.HASHRATE): DataFunction(
"_get_hashrate",
[RPCAPICommand("rpc_stats", "stats")],
),
str(DataOptions.EXPECTED_HASHRATE): DataFunction(
"_get_expected_hashrate",
[RPCAPICommand("rpc_stats", "stats")],
),
str(DataOptions.HASHBOARDS): DataFunction(
"_get_hashboards",
[RPCAPICommand("rpc_stats", "stats")],
),
str(DataOptions.ENVIRONMENT_TEMP): DataFunction(
"_get_env_temp",
[RPCAPICommand("rpc_stats", "stats")],
),
str(DataOptions.WATTAGE_LIMIT): DataFunction(
"_get_wattage_limit",
[RPCAPICommand("rpc_stats", "stats")],
),
str(DataOptions.WATTAGE): DataFunction(
"_get_wattage",
[RPCAPICommand("rpc_stats", "stats")],
),
str(DataOptions.FANS): DataFunction(
"_get_fans",
[RPCAPICommand("rpc_stats", "stats")],
),
str(DataOptions.FAULT_LIGHT): DataFunction(
"_get_fault_light",
[RPCAPICommand("rpc_stats", "stats")],
),
str(DataOptions.UPTIME): DataFunction(
"_get_uptime",
[RPCAPICommand("rpc_stats", "stats")],
),
str(DataOptions.POOLS): DataFunction(
"_get_pools",
[RPCAPICommand("rpc_pools", "pools")],
),
}
)
class CGMinerAvalonNano3(AvalonMiner, AvalonNano3): class CGMinerAvalonNano3(AvalonMiner, AvalonNano3):
_web_cls = AvalonMinerWebAPI _web_cls = AvalonMinerWebAPI
@@ -105,3 +164,68 @@ class CGMinerAvalonNano3(AvalonMiner, AvalonNano3):
return mac.upper() return mac.upper()
except (KeyError, ValueError): except (KeyError, ValueError):
pass pass
class CGMinerAvalonNano3s(AvalonMiner, AvalonNano3s):
data_locations = AVALON_NANO3S_DATA_LOC
async def _get_wattage(self, rpc_stats: dict = None) -> Optional[int]:
if rpc_stats is None:
try:
rpc_stats = await self.rpc.stats()
except APIError:
pass
if rpc_stats is not None:
try:
unparsed_stats = rpc_stats["STATS"][0]["MM ID0"]
parsed_stats = self.parse_stats(unparsed_stats)
return int(parsed_stats["PS"][6])
except (IndexError, KeyError, ValueError, TypeError):
pass
async def _get_hashrate(self, rpc_stats: dict = None) -> Optional[AlgoHashRate]:
if rpc_stats is None:
try:
rpc_stats = await self.rpc.stats()
except APIError:
pass
if rpc_stats is not None:
try:
unparsed_stats = rpc_stats["STATS"][0]["MM ID0"]
parsed_stats = self.parse_stats(unparsed_stats)
return self.algo.hashrate(
rate=float(parsed_stats["GHSspd"][0]), unit=self.algo.unit.GH
).into(self.algo.unit.default)
except (IndexError, KeyError, ValueError, TypeError):
pass
async def _get_hashboards(self, rpc_stats: dict = None) -> List[HashBoard]:
hashboards = await AvalonMiner._get_hashboards(self, rpc_stats)
if rpc_stats is None:
try:
rpc_stats = await self.rpc.stats()
except APIError:
pass
if rpc_stats is not None:
try:
unparsed_stats = rpc_stats["STATS"][0]["MM ID0"]
parsed_stats = self.parse_stats(unparsed_stats)
except (IndexError, KeyError, ValueError, TypeError):
return hashboards
for board in range(len(hashboards)):
try:
board_hr = parsed_stats["GHSspd"][board]
hashboards[board].hashrate = self.algo.hashrate(
rate=float(board_hr), unit=self.algo.unit.GH
).into(self.algo.unit.default)
except LookupError:
pass
return hashboards

View File

@@ -272,18 +272,47 @@ class AntminerModern(BMMiner):
rate=board["rate_real"], unit=self.algo.unit.GH rate=board["rate_real"], unit=self.algo.unit.GH
).into(self.algo.unit.default) ).into(self.algo.unit.default)
hashboards[board["index"]].chips = board["asic_num"] hashboards[board["index"]].chips = board["asic_num"]
board_temp_data = list(
filter(lambda x: not x == 0, board["temp_pcb"]) if "S21+ Hyd" in self.model:
) hashboards[board["index"]].inlet_temp = board["temp_pcb"][0]
hashboards[board["index"]].temp = sum(board_temp_data) / len( hashboards[board["index"]].outlet_temp = board["temp_pcb"][2]
board_temp_data hashboards[board["index"]].chip_temp = board["temp_pic"][0]
) board_temp_data = list(
chip_temp_data = list( filter(
filter(lambda x: not x == 0, board["temp_chip"]) lambda x: not x == 0,
) [
hashboards[board["index"]].chip_temp = sum(chip_temp_data) / len( board["temp_pic"][1],
chip_temp_data board["temp_pic"][2],
) board["temp_pic"][3],
board["temp_pcb"][1],
board["temp_pcb"][3],
],
)
)
hashboards[board["index"]].temp = (
sum(board_temp_data) / len(board_temp_data)
if len(board_temp_data) > 0
else 0
)
else:
board_temp_data = list(
filter(lambda x: not x == 0, board["temp_pcb"])
)
hashboards[board["index"]].temp = (
sum(board_temp_data) / len(board_temp_data)
if len(board_temp_data) > 0
else 0
)
chip_temp_data = list(
filter(lambda x: not x == 0, board["temp_chip"])
)
hashboards[board["index"]].chip_temp = (
sum(chip_temp_data) / len(chip_temp_data)
if len(chip_temp_data) > 0
else 0
)
hashboards[board["index"]].serial_number = board["sn"] hashboards[board["index"]].serial_number = board["sn"]
hashboards[board["index"]].missing = False hashboards[board["index"]].missing = False
except LookupError: except LookupError:

View File

@@ -21,7 +21,7 @@ from pyasic.config import MinerConfig
from pyasic.data import Fan, HashBoard from pyasic.data import Fan, HashBoard
from pyasic.data.error_codes import MinerErrorData, X19Error from pyasic.data.error_codes import MinerErrorData, X19Error
from pyasic.data.pools import PoolMetrics, PoolUrl from pyasic.data.pools import PoolMetrics, PoolUrl
from pyasic.device.algorithm import AlgoHashRate from pyasic.device.algorithm import AlgoHashRate, ScryptAlgo
from pyasic.errors import APIError from pyasic.errors import APIError
from pyasic.logger import logger from pyasic.logger import logger
from pyasic.miners.data import DataFunction, DataLocations, DataOptions, WebAPICommand from pyasic.miners.data import DataFunction, DataLocations, DataOptions, WebAPICommand
@@ -138,6 +138,8 @@ class ePIC(ePICFirmware):
await self.web.set_ptune_algo(conf["ptune"]) await self.web.set_ptune_algo(conf["ptune"])
## Pools ## Pools
if self.algo == ScryptAlgo:
conf["pools"]["coin"] = "Ltc"
await self.web.set_pools(conf["pools"]) await self.web.set_pools(conf["pools"])
except APIError: except APIError:
pass pass

View File

@@ -86,6 +86,7 @@ class LUXMiner(LuxOSFirmware):
supports_shutdown = True supports_shutdown = True
supports_presets = True supports_presets = True
supports_autotuning = True
data_locations = LUXMINER_DATA_LOC data_locations = LUXMINER_DATA_LOC
@@ -191,10 +192,10 @@ class LUXMiner(LuxOSFirmware):
try: try:
if await self.atm_enabled(): if await self.atm_enabled():
re_enable_atm = True re_enable_atm = True
await self.rpc.atmset("enabled=false") await self.rpc.atmset(enabled=False)
result = await self.rpc.profileset(new_preset) result = await self.rpc.profileset(new_preset)
if re_enable_atm: if re_enable_atm:
await self.rpc.atmset("enabled=true") await self.rpc.atmset(enabled=True)
except APIError: except APIError:
raise raise
except Exception as e: except Exception as e:

View File

@@ -14,4 +14,4 @@
# limitations under the License. - # limitations under the License. -
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
from .blockminer import ePICBlockMiner520i, ePICBlockMiner720i from .blockminer import *

View File

@@ -15,7 +15,11 @@
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
from pyasic.miners.backends import ePIC from pyasic.miners.backends import ePIC
from pyasic.miners.device.models import BlockMiner520i, BlockMiner720i from pyasic.miners.device.models import (
BlockMiner520i,
BlockMiner720i,
BlockMinerELITE1,
)
class ePICBlockMiner520i(ePIC, BlockMiner520i): class ePICBlockMiner520i(ePIC, BlockMiner520i):
@@ -24,3 +28,7 @@ class ePICBlockMiner520i(ePIC, BlockMiner520i):
class ePICBlockMiner720i(ePIC, BlockMiner720i): class ePICBlockMiner720i(ePIC, BlockMiner720i):
pass pass
class ePICBlockMinerELITE1(ePIC, BlockMinerELITE1):
pass

View File

@@ -27,6 +27,24 @@ class S21(AntMinerMake):
algo = MinerAlgo.SHA256 algo = MinerAlgo.SHA256
class S21Plus(AntMinerMake):
raw_model = MinerModel.ANTMINER.S21Plus
expected_chips = 55
expected_fans = 4
expected_hashboards = 3
algo = MinerAlgo.SHA256
class S21PlusHydro(AntMinerMake):
raw_model = MinerModel.ANTMINER.S21PlusHydro
expected_chips = 95
expected_fans = 0
expected_hashboards = 3
algo = MinerAlgo.SHA256
class S21Pro(AntMinerMake): class S21Pro(AntMinerMake):
raw_model = MinerModel.ANTMINER.S21Pro raw_model = MinerModel.ANTMINER.S21Pro

View File

@@ -14,5 +14,5 @@
# limitations under the License. - # limitations under the License. -
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
from .S21 import S21, S21Hydro, S21Pro from .S21 import S21, S21Hydro, S21Plus, S21PlusHydro, S21Pro
from .T21 import T21 from .T21 import T21

View File

@@ -1 +1 @@
from .nano3 import AvalonNano3 from .nano3 import AvalonNano3, AvalonNano3s

View File

@@ -10,3 +10,12 @@ class AvalonNano3(AvalonMinerMake):
expected_chips = 10 expected_chips = 10
expected_fans = 1 expected_fans = 1
algo = MinerAlgo.SHA256 algo = MinerAlgo.SHA256
class AvalonNano3s(AvalonMinerMake):
raw_model = MinerModel.AVALONMINER.AvalonNano3s
expected_hashboards = 1
expected_chips = 12
expected_fans = 1
algo = MinerAlgo.SHA256

View File

@@ -19,3 +19,12 @@ class BlockMiner720i(ePICMake):
expected_fans = 4 expected_fans = 4
expected_hashboards = 3 expected_hashboards = 3
algo = MinerAlgo.SHA256 algo = MinerAlgo.SHA256
class BlockMinerELITE1(ePICMake):
raw_model = MinerModel.EPIC.eLITE1
expected_chips = 105
expected_fans = 4
expected_hashboards = 3
algo = MinerAlgo.SCRYPT

View File

@@ -120,6 +120,8 @@ MINER_CLASSES = {
"ANTMINER S21": BMMinerS21, "ANTMINER S21": BMMinerS21,
"ANTMINER BHB68601": BMMinerS21, # ??? "ANTMINER BHB68601": BMMinerS21, # ???
"ANTMINER BHB68606": BMMinerS21, # ??? "ANTMINER BHB68606": BMMinerS21, # ???
"ANTMINER S21+": BMMinerS21Plus,
"ANTMINER S21+ HYD.": BMMinerS21PlusHydro,
"ANTMINER S21 PRO": BMMinerS21Pro, "ANTMINER S21 PRO": BMMinerS21Pro,
"ANTMINER T21": BMMinerT21, "ANTMINER T21": BMMinerT21,
"ANTMINER S21 HYD.": BMMinerS21Hydro, "ANTMINER S21 HYD.": BMMinerS21Hydro,
@@ -505,6 +507,7 @@ MINER_CLASSES = {
"AVALONMINER 1166PRO": CGMinerAvalon1166Pro, "AVALONMINER 1166PRO": CGMinerAvalon1166Pro,
"AVALONMINER 1246": CGMinerAvalon1246, "AVALONMINER 1246": CGMinerAvalon1246,
"AVALONMINER NANO3": CGMinerAvalonNano3, "AVALONMINER NANO3": CGMinerAvalonNano3,
"AVALON NANO3S": CGMinerAvalonNano3s,
"AVALONMINER 15-194": CGMinerAvalon1566, "AVALONMINER 15-194": CGMinerAvalon1566,
}, },
MinerTypes.INNOSILICON: { MinerTypes.INNOSILICON: {
@@ -592,8 +595,10 @@ MINER_CLASSES = {
"ANTMINER S21 PRO": ePICS21Pro, "ANTMINER S21 PRO": ePICS21Pro,
"ANTMINER T21": ePICT21, "ANTMINER T21": ePICT21,
"ANTMINER S19J PRO DUAL": ePICS19jProDual, "ANTMINER S19J PRO DUAL": ePICS19jProDual,
"ANTMINER S19K PRO DUAL": ePICS19kProDual,
"BLOCKMINER 520I": ePICBlockMiner520i, "BLOCKMINER 520I": ePICBlockMiner520i,
"BLOCKMINER 720I": ePICBlockMiner720i, "BLOCKMINER 720I": ePICBlockMiner720i,
"BLOCKMINER ELITE 1.0": ePICBlockMinerELITE1,
}, },
MinerTypes.HIVEON: { MinerTypes.HIVEON: {
None: HiveonModern, None: HiveonModern,
@@ -618,6 +623,7 @@ MINER_CLASSES = {
"ANTMINER S19 XP": LUXMinerS19XP, "ANTMINER S19 XP": LUXMinerS19XP,
"ANTMINER T19": LUXMinerT19, "ANTMINER T19": LUXMinerT19,
"ANTMINER S21": LUXMinerS21, "ANTMINER S21": LUXMinerS21,
"ANTMINER T21": LUXMinerT21,
}, },
MinerTypes.AURADINE: { MinerTypes.AURADINE: {
None: type("AuradineUnknown", (Auradine, AuradineMake), {}), None: type("AuradineUnknown", (Auradine, AuradineMake), {}),
@@ -876,8 +882,6 @@ class MinerFactory:
return MinerTypes.INNOSILICON return MinerTypes.INNOSILICON
if "Miner UI" in web_text: if "Miner UI" in web_text:
return MinerTypes.AURADINE return MinerTypes.AURADINE
if "<title>Antminer</title>" in web_text:
return MinerTypes.MSKMINER
async def _get_miner_socket(self, ip: str) -> MinerTypes | None: async def _get_miner_socket(self, ip: str) -> MinerTypes | None:
commands = ["version", "devdetails"] commands = ["version", "devdetails"]

View File

@@ -1,6 +1,6 @@
[project] [project]
name = "pyasic" name = "pyasic"
version = "0.72.1" version = "0.72.7"
description = "A simplified and standardized interface for Bitcoin ASICs." description = "A simplified and standardized interface for Bitcoin ASICs."
authors = [{name = "UpstreamData", email = "brett@upstreamdata.ca"}] authors = [{name = "UpstreamData", email = "brett@upstreamdata.ca"}]