Compare commits

...

24 Commits

Author SHA1 Message Date
Brett Rowan
75056cfff5 version: bump version number 2025-09-19 14:18:36 -06:00
James Hilliard
7fbcb0dbd2 Fix race condition in BOSer multicommand causing CancelledError
The multicommand method was double-awaiting tasks - first via
asyncio.gather() with return_exceptions=True, then trying to await
the same tasks again. This caused CancelledError when gRPC connections
were lost.

Changed to properly use the results from gather() instead of
re-awaiting completed tasks, preventing the race condition and
properly handling exceptions.

Fixes StreamTerminatedError occurring in pyasic/web/braiins_os/boser.py:91
2025-09-19 14:17:59 -06:00
Brett Rowan
7329aeace2 version: bump version number 2025-09-17 19:18:51 -06:00
Brett Rowan
e8c3953106 bug: fix btminer V3 password 2025-09-17 19:18:27 -06:00
James Hilliard
a1a7562bdb Handle invalid unicode in json response 2025-09-17 19:11:31 -06:00
Brett Rowan
b2726c77a0 version: bump version number 2025-09-09 08:13:09 -06:00
Ryan Heideman
68299fa54d Avalon Nano3s Fixes (#374)
* Avalon Nano3s Fixes

* Fix to handle both cases

* [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-08-30 22:04:58 -06:00
UpstreamData
1466039e08 version: bump version number 2025-08-28 21:43:00 -06:00
Ryan Heideman
0aa72c6c85 Fix Byte Folder Names (#376) 2025-08-26 21:18:57 -06:00
Ryan Heideman
24134a5991 Goldshell Mini Doge Support (#375)
* Docs for Mini Doge

* Mini Doge Recognition Support

* Loading fixes

* Fix for number of fans

* Fixed expected_hashrate

* Fixes for hashboards

* Implemented uptime

* Fixed uptime

* Doc fixes

* Fixes for byte

* Copyright update

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

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

* Typo fix

* File renames

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2025-08-26 21:06:10 -06:00
Brett Rowan
038208efa6 version: bump version number 2025-08-16 10:25:55 -06:00
Brett Rowan
7e319b79df feature: add misidentified L7_i 2025-08-16 10:25:40 -06:00
Brett Rowan
a0fdec3ce5 version: bump version number 2025-08-16 10:06:58 -06:00
Brett Rowan
1a8928de18 feature: add retries to elphapex 2025-08-16 10:06:46 -06:00
Brett Rowan
bce0058930 version: bump version number 2025-08-16 09:38:24 -06:00
Brett Rowan
850656fce4 bug: fix elphapex hashboard parsing 2025-08-16 09:38:06 -06:00
Brett Rowan
8bb35d6d7c version: bump version number 2025-08-16 09:24:17 -06:00
Brett Rowan
e85f06dbc2 feature: add misidentified L9_i 2025-08-16 09:23:12 -06:00
Brett Rowan
a566801316 feature: add chip count for IceRiver KS5M 2025-08-16 09:16:07 -06:00
Brett Rowan
e1a9cc5d19 bug: fix some issues with whatsminer BTMinerV3 implementation 2025-08-16 09:14:11 -06:00
Brett Rowan
27bb06de2b version: bump version number 2025-08-15 14:36:04 -06:00
Brett Rowan
debd4d2d4d feature: add BTMiner V3 configuration 2025-08-15 14:35:32 -06:00
Brett Rowan
56ad6cbc6f feature: add dynamic version selection for whatsminers 2025-08-15 14:35:32 -06:00
Brett Rowan
3fa54213bf bug: handle vnish S19 pro hydro alternate naming 2025-08-15 14:35:15 -06:00
50 changed files with 1143 additions and 554 deletions

View File

@@ -0,0 +1,16 @@
# pyasic
## Q Models
## Avalon Q Home (Stock)
- [ ] Shutdowns
- [ ] Power Modes
- [ ] Setpoints
- [ ] Presets
::: pyasic.miners.avalonminer.cgminer.Q.Q.CGMinerAvalonQHome
handler: python
options:
show_root_heading: false
heading_level: 0

View File

@@ -1,14 +1,14 @@
# pyasic # pyasic
## Byte Models ## byte Models
## Byte (Stock) ## Byte (Stock)
- [x] Shutdowns - [ ] Shutdowns
- [x] Power Modes - [ ] Power Modes
- [ ] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.goldshell.bfgminer.Byte.Byte.GoldshellByte ::: pyasic.miners.goldshell.bfgminer.byte.byte.GoldshellByte
handler: python handler: python
options: options:
show_root_heading: false show_root_heading: false

View File

@@ -0,0 +1,16 @@
# pyasic
## Mini Doge Models
## Mini Doge (Stock)
- [ ] Shutdowns
- [ ] Power Modes
- [ ] Setpoints
- [ ] Presets
::: pyasic.miners.goldshell.bfgminer.MiniDoge.MiniDoge.GoldshellMiniDoge
handler: python
options:
show_root_heading: false
heading_level: 0

View File

@@ -0,0 +1,16 @@
# pyasic
## mini_doge Models
## Mini Doge (Stock)
- [ ] Shutdowns
- [ ] Power Modes
- [ ] Setpoints
- [ ] Presets
::: pyasic.miners.goldshell.bfgminer.mini_doge.mini_doge.GoldshellMiniDoge
handler: python
options:
show_root_heading: false
heading_level: 0

View File

@@ -0,0 +1,16 @@
# pyasic
## ALX Models
## AL3 (Stock)
- [ ] Shutdowns
- [ ] Power Modes
- [ ] Setpoints
- [ ] Presets
::: pyasic.miners.iceriver.iceminer.ALX.AL3.IceRiverAL3
handler: python
options:
show_root_heading: false
heading_level: 0

View File

@@ -38,6 +38,7 @@ details {
<details> <details>
<summary>X7 Series:</summary> <summary>X7 Series:</summary>
<ul> <ul>
<li><a href="../antminer/X7#l7-stock">L7 (Stock)</a></li>
<li><a href="../antminer/X7#l7-stock">L7 (Stock)</a></li> <li><a href="../antminer/X7#l7-stock">L7 (Stock)</a></li>
<li><a href="../antminer/X7#k7-stock">K7 (Stock)</a></li> <li><a href="../antminer/X7#k7-stock">K7 (Stock)</a></li>
<li><a href="../antminer/X7#d7-stock">D7 (Stock)</a></li> <li><a href="../antminer/X7#d7-stock">D7 (Stock)</a></li>
@@ -53,6 +54,7 @@ details {
<li><a href="../antminer/X9#s9j-stock">S9j (Stock)</a></li> <li><a href="../antminer/X9#s9j-stock">S9j (Stock)</a></li>
<li><a href="../antminer/X9#t9-stock">T9 (Stock)</a></li> <li><a href="../antminer/X9#t9-stock">T9 (Stock)</a></li>
<li><a href="../antminer/X9#l9-stock">L9 (Stock)</a></li> <li><a href="../antminer/X9#l9-stock">L9 (Stock)</a></li>
<li><a href="../antminer/X9#l9-stock">L9 (Stock)</a></li>
</ul> </ul>
</details> </details>
<details> <details>
@@ -623,9 +625,15 @@ details {
</ul> </ul>
</details> </details>
<details> <details>
<summary>Byte Series:</summary> <summary>byte Series:</summary>
<ul> <ul>
<li><a href="../goldshell/Byte#byte-stock">Byte (Stock)</a></li> <li><a href="../goldshell/byte#byte-stock">Byte (Stock)</a></li>
</ul>
</details>
<details>
<summary>mini_doge Series:</summary>
<ul>
<li><a href="../goldshell/mini_doge#mini-doge-stock">Mini Doge (Stock)</a></li>
</ul> </ul>
</details> </details>
</ul> </ul>
@@ -741,6 +749,7 @@ details {
<li><a href="../antminer/X19#s19a-pro-vnish">S19a Pro (VNish)</a></li> <li><a href="../antminer/X19#s19a-pro-vnish">S19a Pro (VNish)</a></li>
<li><a href="../antminer/X19#s19-pro-a-vnish">S19 Pro A (VNish)</a></li> <li><a href="../antminer/X19#s19-pro-a-vnish">S19 Pro A (VNish)</a></li>
<li><a href="../antminer/X19#s19-pro-hydro-vnish">S19 Pro Hydro (VNish)</a></li> <li><a href="../antminer/X19#s19-pro-hydro-vnish">S19 Pro Hydro (VNish)</a></li>
<li><a href="../antminer/X19#s19-pro-hydro-vnish">S19 Pro Hydro (VNish)</a></li>
<li><a href="../antminer/X19#s19k-pro-vnish">S19k Pro (VNish)</a></li> <li><a href="../antminer/X19#s19k-pro-vnish">S19k Pro (VNish)</a></li>
<li><a href="../antminer/X19#t19-vnish">T19 (VNish)</a></li> <li><a href="../antminer/X19#t19-vnish">T19 (VNish)</a></li>
</ul> </ul>

File diff suppressed because it is too large Load Diff

View File

@@ -5,7 +5,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M5X.M50S_Plus_Plus.BTMinerM50SPlusPlusVK10 ::: pyasic.miners.whatsminer.btminer.M5X.M50S_Plus_Plus.BTMinerM50SPlusPlusVK10
@@ -18,7 +18,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M5X.M50S_Plus_Plus.BTMinerM50SPlusPlusVK20 ::: pyasic.miners.whatsminer.btminer.M5X.M50S_Plus_Plus.BTMinerM50SPlusPlusVK20
@@ -31,7 +31,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M5X.M50S_Plus_Plus.BTMinerM50SPlusPlusVK30 ::: pyasic.miners.whatsminer.btminer.M5X.M50S_Plus_Plus.BTMinerM50SPlusPlusVK30
@@ -44,7 +44,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M5X.M50S_Plus_Plus.BTMinerM50SPlusPlusVK40 ::: pyasic.miners.whatsminer.btminer.M5X.M50S_Plus_Plus.BTMinerM50SPlusPlusVK40
@@ -57,7 +57,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M5X.M50S_Plus_Plus.BTMinerM50SPlusPlusVK50 ::: pyasic.miners.whatsminer.btminer.M5X.M50S_Plus_Plus.BTMinerM50SPlusPlusVK50
@@ -70,7 +70,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M5X.M50S_Plus_Plus.BTMinerM50SPlusPlusVK60 ::: pyasic.miners.whatsminer.btminer.M5X.M50S_Plus_Plus.BTMinerM50SPlusPlusVK60
@@ -83,7 +83,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M5X.M50S_Plus_Plus.BTMinerM50SPlusPlusVL20 ::: pyasic.miners.whatsminer.btminer.M5X.M50S_Plus_Plus.BTMinerM50SPlusPlusVL20
@@ -96,7 +96,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M5X.M50S_Plus_Plus.BTMinerM50SPlusPlusVL30 ::: pyasic.miners.whatsminer.btminer.M5X.M50S_Plus_Plus.BTMinerM50SPlusPlusVL30
@@ -109,7 +109,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M5X.M50S_Plus_Plus.BTMinerM50SPlusPlusVL40 ::: pyasic.miners.whatsminer.btminer.M5X.M50S_Plus_Plus.BTMinerM50SPlusPlusVL40
@@ -122,7 +122,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M5X.M50S_Plus_Plus.BTMinerM50SPlusPlusVL50 ::: pyasic.miners.whatsminer.btminer.M5X.M50S_Plus_Plus.BTMinerM50SPlusPlusVL50
@@ -135,7 +135,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M5X.M50S_Plus_Plus.BTMinerM50SPlusPlusVL60 ::: pyasic.miners.whatsminer.btminer.M5X.M50S_Plus_Plus.BTMinerM50SPlusPlusVL60
@@ -148,7 +148,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M5X.M50S_Plus.BTMinerM50SPlusVH30 ::: pyasic.miners.whatsminer.btminer.M5X.M50S_Plus.BTMinerM50SPlusVH30
@@ -161,7 +161,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M5X.M50S_Plus.BTMinerM50SPlusVH40 ::: pyasic.miners.whatsminer.btminer.M5X.M50S_Plus.BTMinerM50SPlusVH40
@@ -174,7 +174,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M5X.M50S_Plus.BTMinerM50SPlusVJ30 ::: pyasic.miners.whatsminer.btminer.M5X.M50S_Plus.BTMinerM50SPlusVJ30
@@ -187,7 +187,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M5X.M50S_Plus.BTMinerM50SPlusVJ40 ::: pyasic.miners.whatsminer.btminer.M5X.M50S_Plus.BTMinerM50SPlusVJ40
@@ -200,7 +200,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M5X.M50S_Plus.BTMinerM50SPlusVJ60 ::: pyasic.miners.whatsminer.btminer.M5X.M50S_Plus.BTMinerM50SPlusVJ60
@@ -213,7 +213,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M5X.M50S_Plus.BTMinerM50SPlusVK10 ::: pyasic.miners.whatsminer.btminer.M5X.M50S_Plus.BTMinerM50SPlusVK10
@@ -226,7 +226,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M5X.M50S_Plus.BTMinerM50SPlusVK20 ::: pyasic.miners.whatsminer.btminer.M5X.M50S_Plus.BTMinerM50SPlusVK20
@@ -239,7 +239,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M5X.M50S_Plus.BTMinerM50SPlusVK30 ::: pyasic.miners.whatsminer.btminer.M5X.M50S_Plus.BTMinerM50SPlusVK30
@@ -252,7 +252,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M5X.M50S_Plus.BTMinerM50SPlusVL10 ::: pyasic.miners.whatsminer.btminer.M5X.M50S_Plus.BTMinerM50SPlusVL10
@@ -265,7 +265,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M5X.M50S_Plus.BTMinerM50SPlusVL20 ::: pyasic.miners.whatsminer.btminer.M5X.M50S_Plus.BTMinerM50SPlusVL20
@@ -278,7 +278,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M5X.M50S_Plus.BTMinerM50SPlusVL30 ::: pyasic.miners.whatsminer.btminer.M5X.M50S_Plus.BTMinerM50SPlusVL30
@@ -291,7 +291,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M5X.M50S.BTMinerM50SVH10 ::: pyasic.miners.whatsminer.btminer.M5X.M50S.BTMinerM50SVH10
@@ -304,7 +304,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M5X.M50S.BTMinerM50SVH20 ::: pyasic.miners.whatsminer.btminer.M5X.M50S.BTMinerM50SVH20
@@ -317,7 +317,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M5X.M50S.BTMinerM50SVH30 ::: pyasic.miners.whatsminer.btminer.M5X.M50S.BTMinerM50SVH30
@@ -330,7 +330,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M5X.M50S.BTMinerM50SVH40 ::: pyasic.miners.whatsminer.btminer.M5X.M50S.BTMinerM50SVH40
@@ -343,7 +343,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M5X.M50S.BTMinerM50SVH50 ::: pyasic.miners.whatsminer.btminer.M5X.M50S.BTMinerM50SVH50
@@ -356,7 +356,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M5X.M50S.BTMinerM50SVJ10 ::: pyasic.miners.whatsminer.btminer.M5X.M50S.BTMinerM50SVJ10
@@ -369,7 +369,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M5X.M50S.BTMinerM50SVJ20 ::: pyasic.miners.whatsminer.btminer.M5X.M50S.BTMinerM50SVJ20
@@ -382,7 +382,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M5X.M50S.BTMinerM50SVJ30 ::: pyasic.miners.whatsminer.btminer.M5X.M50S.BTMinerM50SVJ30
@@ -395,7 +395,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M5X.M50S.BTMinerM50SVJ40 ::: pyasic.miners.whatsminer.btminer.M5X.M50S.BTMinerM50SVJ40
@@ -408,7 +408,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M5X.M50S.BTMinerM50SVJ50 ::: pyasic.miners.whatsminer.btminer.M5X.M50S.BTMinerM50SVJ50
@@ -421,7 +421,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M5X.M50S.BTMinerM50SVK10 ::: pyasic.miners.whatsminer.btminer.M5X.M50S.BTMinerM50SVK10
@@ -434,7 +434,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M5X.M50S.BTMinerM50SVK20 ::: pyasic.miners.whatsminer.btminer.M5X.M50S.BTMinerM50SVK20
@@ -447,7 +447,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M5X.M50S.BTMinerM50SVK30 ::: pyasic.miners.whatsminer.btminer.M5X.M50S.BTMinerM50SVK30
@@ -460,7 +460,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M5X.M50S.BTMinerM50SVK50 ::: pyasic.miners.whatsminer.btminer.M5X.M50S.BTMinerM50SVK50
@@ -473,7 +473,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M5X.M50S.BTMinerM50SVK60 ::: pyasic.miners.whatsminer.btminer.M5X.M50S.BTMinerM50SVK60
@@ -486,7 +486,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M5X.M50S.BTMinerM50SVK70 ::: pyasic.miners.whatsminer.btminer.M5X.M50S.BTMinerM50SVK70
@@ -499,7 +499,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M5X.M50S.BTMinerM50SVK80 ::: pyasic.miners.whatsminer.btminer.M5X.M50S.BTMinerM50SVK80
@@ -512,7 +512,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M5X.M50S.BTMinerM50SVL20 ::: pyasic.miners.whatsminer.btminer.M5X.M50S.BTMinerM50SVL20
@@ -525,7 +525,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M5X.M50S.BTMinerM50SVL30 ::: pyasic.miners.whatsminer.btminer.M5X.M50S.BTMinerM50SVL30
@@ -538,7 +538,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M5X.M50.BTMinerM50VE30 ::: pyasic.miners.whatsminer.btminer.M5X.M50.BTMinerM50VE30
@@ -551,7 +551,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M5X.M50.BTMinerM50VG30 ::: pyasic.miners.whatsminer.btminer.M5X.M50.BTMinerM50VG30
@@ -564,7 +564,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M5X.M50.BTMinerM50VH10 ::: pyasic.miners.whatsminer.btminer.M5X.M50.BTMinerM50VH10
@@ -577,7 +577,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M5X.M50.BTMinerM50VH20 ::: pyasic.miners.whatsminer.btminer.M5X.M50.BTMinerM50VH20
@@ -590,7 +590,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M5X.M50.BTMinerM50VH30 ::: pyasic.miners.whatsminer.btminer.M5X.M50.BTMinerM50VH30
@@ -603,7 +603,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M5X.M50.BTMinerM50VH40 ::: pyasic.miners.whatsminer.btminer.M5X.M50.BTMinerM50VH40
@@ -616,7 +616,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M5X.M50.BTMinerM50VH50 ::: pyasic.miners.whatsminer.btminer.M5X.M50.BTMinerM50VH50
@@ -629,7 +629,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M5X.M50.BTMinerM50VH60 ::: pyasic.miners.whatsminer.btminer.M5X.M50.BTMinerM50VH60
@@ -642,7 +642,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M5X.M50.BTMinerM50VH70 ::: pyasic.miners.whatsminer.btminer.M5X.M50.BTMinerM50VH70
@@ -655,7 +655,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M5X.M50.BTMinerM50VH80 ::: pyasic.miners.whatsminer.btminer.M5X.M50.BTMinerM50VH80
@@ -668,7 +668,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M5X.M50.BTMinerM50VH90 ::: pyasic.miners.whatsminer.btminer.M5X.M50.BTMinerM50VH90
@@ -681,7 +681,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M5X.M50.BTMinerM50VJ10 ::: pyasic.miners.whatsminer.btminer.M5X.M50.BTMinerM50VJ10
@@ -694,7 +694,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M5X.M50.BTMinerM50VJ20 ::: pyasic.miners.whatsminer.btminer.M5X.M50.BTMinerM50VJ20
@@ -707,7 +707,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M5X.M50.BTMinerM50VJ30 ::: pyasic.miners.whatsminer.btminer.M5X.M50.BTMinerM50VJ30
@@ -720,7 +720,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M5X.M50.BTMinerM50VJ40 ::: pyasic.miners.whatsminer.btminer.M5X.M50.BTMinerM50VJ40
@@ -733,7 +733,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M5X.M50.BTMinerM50VJ60 ::: pyasic.miners.whatsminer.btminer.M5X.M50.BTMinerM50VJ60
@@ -746,7 +746,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M5X.M50.BTMinerM50VK40 ::: pyasic.miners.whatsminer.btminer.M5X.M50.BTMinerM50VK40
@@ -759,7 +759,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M5X.M50.BTMinerM50VK50 ::: pyasic.miners.whatsminer.btminer.M5X.M50.BTMinerM50VK50
@@ -772,7 +772,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M5X.M52S_Plus_Plus.BTMinerM52SPlusPlusVL10 ::: pyasic.miners.whatsminer.btminer.M5X.M52S_Plus_Plus.BTMinerM52SPlusPlusVL10
@@ -785,7 +785,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M5X.M52S.BTMinerM52SVK30 ::: pyasic.miners.whatsminer.btminer.M5X.M52S.BTMinerM52SVK30
@@ -798,7 +798,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M5X.M53H.BTMinerM53HVH10 ::: pyasic.miners.whatsminer.btminer.M5X.M53H.BTMinerM53HVH10
@@ -811,7 +811,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M5X.M53S_Plus_Plus.BTMinerM53SPlusPlusVK10 ::: pyasic.miners.whatsminer.btminer.M5X.M53S_Plus_Plus.BTMinerM53SPlusPlusVK10
@@ -824,7 +824,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M5X.M53S_Plus_Plus.BTMinerM53SPlusPlusVK20 ::: pyasic.miners.whatsminer.btminer.M5X.M53S_Plus_Plus.BTMinerM53SPlusPlusVK20
@@ -837,7 +837,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M5X.M53S_Plus_Plus.BTMinerM53SPlusPlusVK30 ::: pyasic.miners.whatsminer.btminer.M5X.M53S_Plus_Plus.BTMinerM53SPlusPlusVK30
@@ -850,7 +850,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M5X.M53S_Plus_Plus.BTMinerM53SPlusPlusVK50 ::: pyasic.miners.whatsminer.btminer.M5X.M53S_Plus_Plus.BTMinerM53SPlusPlusVK50
@@ -863,7 +863,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M5X.M53S_Plus_Plus.BTMinerM53SPlusPlusVL10 ::: pyasic.miners.whatsminer.btminer.M5X.M53S_Plus_Plus.BTMinerM53SPlusPlusVL10
@@ -876,7 +876,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M5X.M53S_Plus_Plus.BTMinerM53SPlusPlusVL30 ::: pyasic.miners.whatsminer.btminer.M5X.M53S_Plus_Plus.BTMinerM53SPlusPlusVL30
@@ -889,7 +889,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M5X.M53S_Plus.BTMinerM53SPlusVJ30 ::: pyasic.miners.whatsminer.btminer.M5X.M53S_Plus.BTMinerM53SPlusVJ30
@@ -902,7 +902,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M5X.M53S_Plus.BTMinerM53SPlusVJ40 ::: pyasic.miners.whatsminer.btminer.M5X.M53S_Plus.BTMinerM53SPlusVJ40
@@ -915,7 +915,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M5X.M53S_Plus.BTMinerM53SPlusVJ50 ::: pyasic.miners.whatsminer.btminer.M5X.M53S_Plus.BTMinerM53SPlusVJ50
@@ -928,7 +928,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M5X.M53S_Plus.BTMinerM53SPlusVK30 ::: pyasic.miners.whatsminer.btminer.M5X.M53S_Plus.BTMinerM53SPlusVK30
@@ -941,7 +941,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M5X.M53S.BTMinerM53SVH20 ::: pyasic.miners.whatsminer.btminer.M5X.M53S.BTMinerM53SVH20
@@ -954,7 +954,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M5X.M53S.BTMinerM53SVH30 ::: pyasic.miners.whatsminer.btminer.M5X.M53S.BTMinerM53SVH30
@@ -967,7 +967,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M5X.M53S.BTMinerM53SVJ30 ::: pyasic.miners.whatsminer.btminer.M5X.M53S.BTMinerM53SVJ30
@@ -980,7 +980,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M5X.M53S.BTMinerM53SVJ40 ::: pyasic.miners.whatsminer.btminer.M5X.M53S.BTMinerM53SVJ40
@@ -993,7 +993,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M5X.M53S.BTMinerM53SVK30 ::: pyasic.miners.whatsminer.btminer.M5X.M53S.BTMinerM53SVK30
@@ -1006,7 +1006,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M5X.M53.BTMinerM53VH30 ::: pyasic.miners.whatsminer.btminer.M5X.M53.BTMinerM53VH30
@@ -1019,7 +1019,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M5X.M53.BTMinerM53VH40 ::: pyasic.miners.whatsminer.btminer.M5X.M53.BTMinerM53VH40
@@ -1032,7 +1032,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M5X.M53.BTMinerM53VH50 ::: pyasic.miners.whatsminer.btminer.M5X.M53.BTMinerM53VH50
@@ -1045,7 +1045,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M5X.M53.BTMinerM53VK30 ::: pyasic.miners.whatsminer.btminer.M5X.M53.BTMinerM53VK30
@@ -1058,7 +1058,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M5X.M53.BTMinerM53VK60 ::: pyasic.miners.whatsminer.btminer.M5X.M53.BTMinerM53VK60
@@ -1071,7 +1071,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M5X.M54S_Plus_Plus.BTMinerM54SPlusPlusVK30 ::: pyasic.miners.whatsminer.btminer.M5X.M54S_Plus_Plus.BTMinerM54SPlusPlusVK30
@@ -1084,7 +1084,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M5X.M54S_Plus_Plus.BTMinerM54SPlusPlusVL30 ::: pyasic.miners.whatsminer.btminer.M5X.M54S_Plus_Plus.BTMinerM54SPlusPlusVL30
@@ -1097,7 +1097,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M5X.M54S_Plus_Plus.BTMinerM54SPlusPlusVL40 ::: pyasic.miners.whatsminer.btminer.M5X.M54S_Plus_Plus.BTMinerM54SPlusPlusVL40
@@ -1110,7 +1110,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M5X.M56S_Plus_Plus.BTMinerM56SPlusPlusVK10 ::: pyasic.miners.whatsminer.btminer.M5X.M56S_Plus_Plus.BTMinerM56SPlusPlusVK10
@@ -1123,7 +1123,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M5X.M56S_Plus_Plus.BTMinerM56SPlusPlusVK30 ::: pyasic.miners.whatsminer.btminer.M5X.M56S_Plus_Plus.BTMinerM56SPlusPlusVK30
@@ -1136,7 +1136,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M5X.M56S_Plus_Plus.BTMinerM56SPlusPlusVK40 ::: pyasic.miners.whatsminer.btminer.M5X.M56S_Plus_Plus.BTMinerM56SPlusPlusVK40
@@ -1149,7 +1149,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M5X.M56S_Plus_Plus.BTMinerM56SPlusPlusVK50 ::: pyasic.miners.whatsminer.btminer.M5X.M56S_Plus_Plus.BTMinerM56SPlusPlusVK50
@@ -1162,7 +1162,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M5X.M56S_Plus.BTMinerM56SPlusVJ30 ::: pyasic.miners.whatsminer.btminer.M5X.M56S_Plus.BTMinerM56SPlusVJ30
@@ -1175,7 +1175,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M5X.M56S_Plus.BTMinerM56SPlusVK30 ::: pyasic.miners.whatsminer.btminer.M5X.M56S_Plus.BTMinerM56SPlusVK30
@@ -1188,7 +1188,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M5X.M56S_Plus.BTMinerM56SPlusVK40 ::: pyasic.miners.whatsminer.btminer.M5X.M56S_Plus.BTMinerM56SPlusVK40
@@ -1201,7 +1201,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M5X.M56S_Plus.BTMinerM56SPlusVK50 ::: pyasic.miners.whatsminer.btminer.M5X.M56S_Plus.BTMinerM56SPlusVK50
@@ -1214,7 +1214,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M5X.M56S.BTMinerM56SVH30 ::: pyasic.miners.whatsminer.btminer.M5X.M56S.BTMinerM56SVH30
@@ -1227,7 +1227,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M5X.M56S.BTMinerM56SVJ30 ::: pyasic.miners.whatsminer.btminer.M5X.M56S.BTMinerM56SVJ30
@@ -1240,7 +1240,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M5X.M56S.BTMinerM56SVJ40 ::: pyasic.miners.whatsminer.btminer.M5X.M56S.BTMinerM56SVJ40
@@ -1253,7 +1253,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M5X.M56.BTMinerM56VH30 ::: pyasic.miners.whatsminer.btminer.M5X.M56.BTMinerM56VH30
@@ -1266,7 +1266,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M5X.M59.BTMinerM59VH30 ::: pyasic.miners.whatsminer.btminer.M5X.M59.BTMinerM59VH30

View File

@@ -5,7 +5,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M6X.M60S_Plus_Plus.BTMinerM60SPlusPlusVL30 ::: pyasic.miners.whatsminer.btminer.M6X.M60S_Plus_Plus.BTMinerM60SPlusPlusVL30
@@ -18,7 +18,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M6X.M60S_Plus_Plus.BTMinerM60SPlusPlusVL40 ::: pyasic.miners.whatsminer.btminer.M6X.M60S_Plus_Plus.BTMinerM60SPlusPlusVL40
@@ -31,7 +31,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M6X.M60S_Plus.BTMinerM60SPlusVK30 ::: pyasic.miners.whatsminer.btminer.M6X.M60S_Plus.BTMinerM60SPlusVK30
@@ -44,7 +44,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M6X.M60S_Plus.BTMinerM60SPlusVK40 ::: pyasic.miners.whatsminer.btminer.M6X.M60S_Plus.BTMinerM60SPlusVK40
@@ -57,7 +57,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M6X.M60S_Plus.BTMinerM60SPlusVK50 ::: pyasic.miners.whatsminer.btminer.M6X.M60S_Plus.BTMinerM60SPlusVK50
@@ -70,7 +70,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M6X.M60S_Plus.BTMinerM60SPlusVK60 ::: pyasic.miners.whatsminer.btminer.M6X.M60S_Plus.BTMinerM60SPlusVK60
@@ -83,7 +83,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M6X.M60S_Plus.BTMinerM60SPlusVK70 ::: pyasic.miners.whatsminer.btminer.M6X.M60S_Plus.BTMinerM60SPlusVK70
@@ -96,7 +96,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M6X.M60S_Plus.BTMinerM60SPlusVL10 ::: pyasic.miners.whatsminer.btminer.M6X.M60S_Plus.BTMinerM60SPlusVL10
@@ -109,7 +109,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M6X.M60S_Plus.BTMinerM60SPlusVL30 ::: pyasic.miners.whatsminer.btminer.M6X.M60S_Plus.BTMinerM60SPlusVL30
@@ -122,7 +122,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M6X.M60S_Plus.BTMinerM60SPlusVL40 ::: pyasic.miners.whatsminer.btminer.M6X.M60S_Plus.BTMinerM60SPlusVL40
@@ -135,7 +135,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M6X.M60S_Plus.BTMinerM60SPlusVL50 ::: pyasic.miners.whatsminer.btminer.M6X.M60S_Plus.BTMinerM60SPlusVL50
@@ -148,7 +148,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M6X.M60S_Plus.BTMinerM60SPlusVL60 ::: pyasic.miners.whatsminer.btminer.M6X.M60S_Plus.BTMinerM60SPlusVL60
@@ -161,7 +161,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M6X.M60S.BTMinerM60SVK10 ::: pyasic.miners.whatsminer.btminer.M6X.M60S.BTMinerM60SVK10
@@ -174,7 +174,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M6X.M60S.BTMinerM60SVK20 ::: pyasic.miners.whatsminer.btminer.M6X.M60S.BTMinerM60SVK20
@@ -187,7 +187,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M6X.M60S.BTMinerM60SVK30 ::: pyasic.miners.whatsminer.btminer.M6X.M60S.BTMinerM60SVK30
@@ -200,7 +200,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M6X.M60S.BTMinerM60SVK40 ::: pyasic.miners.whatsminer.btminer.M6X.M60S.BTMinerM60SVK40
@@ -213,7 +213,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M6X.M60S.BTMinerM60SVL10 ::: pyasic.miners.whatsminer.btminer.M6X.M60S.BTMinerM60SVL10
@@ -226,7 +226,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M6X.M60S.BTMinerM60SVL20 ::: pyasic.miners.whatsminer.btminer.M6X.M60S.BTMinerM60SVL20
@@ -239,7 +239,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M6X.M60S.BTMinerM60SVL30 ::: pyasic.miners.whatsminer.btminer.M6X.M60S.BTMinerM60SVL30
@@ -252,7 +252,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M6X.M60S.BTMinerM60SVL40 ::: pyasic.miners.whatsminer.btminer.M6X.M60S.BTMinerM60SVL40
@@ -265,7 +265,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M6X.M60S.BTMinerM60SVL50 ::: pyasic.miners.whatsminer.btminer.M6X.M60S.BTMinerM60SVL50
@@ -278,7 +278,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M6X.M60S.BTMinerM60SVL60 ::: pyasic.miners.whatsminer.btminer.M6X.M60S.BTMinerM60SVL60
@@ -291,7 +291,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M6X.M60S.BTMinerM60SVL70 ::: pyasic.miners.whatsminer.btminer.M6X.M60S.BTMinerM60SVL70
@@ -304,7 +304,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M6X.M60.BTMinerM60VK10 ::: pyasic.miners.whatsminer.btminer.M6X.M60.BTMinerM60VK10
@@ -317,7 +317,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M6X.M60.BTMinerM60VK20 ::: pyasic.miners.whatsminer.btminer.M6X.M60.BTMinerM60VK20
@@ -330,7 +330,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M6X.M60.BTMinerM60VK30 ::: pyasic.miners.whatsminer.btminer.M6X.M60.BTMinerM60VK30
@@ -343,7 +343,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M6X.M60.BTMinerM60VK40 ::: pyasic.miners.whatsminer.btminer.M6X.M60.BTMinerM60VK40
@@ -356,7 +356,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M6X.M60.BTMinerM60VK6A ::: pyasic.miners.whatsminer.btminer.M6X.M60.BTMinerM60VK6A
@@ -369,7 +369,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M6X.M60.BTMinerM60VL10 ::: pyasic.miners.whatsminer.btminer.M6X.M60.BTMinerM60VL10
@@ -382,7 +382,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M6X.M60.BTMinerM60VL20 ::: pyasic.miners.whatsminer.btminer.M6X.M60.BTMinerM60VL20
@@ -395,7 +395,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M6X.M60.BTMinerM60VL30 ::: pyasic.miners.whatsminer.btminer.M6X.M60.BTMinerM60VL30
@@ -408,7 +408,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M6X.M60.BTMinerM60VL40 ::: pyasic.miners.whatsminer.btminer.M6X.M60.BTMinerM60VL40
@@ -421,7 +421,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M6X.M60.BTMinerM60VL50 ::: pyasic.miners.whatsminer.btminer.M6X.M60.BTMinerM60VL50
@@ -434,7 +434,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M6X.M61S_Plus.BTMinerM61SPlusVL30 ::: pyasic.miners.whatsminer.btminer.M6X.M61S_Plus.BTMinerM61SPlusVL30
@@ -447,7 +447,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M6X.M61S.BTMinerM61SVL10 ::: pyasic.miners.whatsminer.btminer.M6X.M61S.BTMinerM61SVL10
@@ -460,7 +460,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M6X.M61S.BTMinerM61SVL20 ::: pyasic.miners.whatsminer.btminer.M6X.M61S.BTMinerM61SVL20
@@ -473,7 +473,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M6X.M61S.BTMinerM61SVL30 ::: pyasic.miners.whatsminer.btminer.M6X.M61S.BTMinerM61SVL30
@@ -486,7 +486,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M6X.M61.BTMinerM61VK10 ::: pyasic.miners.whatsminer.btminer.M6X.M61.BTMinerM61VK10
@@ -499,7 +499,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M6X.M61.BTMinerM61VK20 ::: pyasic.miners.whatsminer.btminer.M6X.M61.BTMinerM61VK20
@@ -512,7 +512,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M6X.M61.BTMinerM61VK30 ::: pyasic.miners.whatsminer.btminer.M6X.M61.BTMinerM61VK30
@@ -525,7 +525,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M6X.M61.BTMinerM61VK40 ::: pyasic.miners.whatsminer.btminer.M6X.M61.BTMinerM61VK40
@@ -538,7 +538,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M6X.M61.BTMinerM61VL10 ::: pyasic.miners.whatsminer.btminer.M6X.M61.BTMinerM61VL10
@@ -551,7 +551,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M6X.M61.BTMinerM61VL30 ::: pyasic.miners.whatsminer.btminer.M6X.M61.BTMinerM61VL30
@@ -564,7 +564,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M6X.M61.BTMinerM61VL40 ::: pyasic.miners.whatsminer.btminer.M6X.M61.BTMinerM61VL40
@@ -577,7 +577,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M6X.M61.BTMinerM61VL50 ::: pyasic.miners.whatsminer.btminer.M6X.M61.BTMinerM61VL50
@@ -590,7 +590,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M6X.M61.BTMinerM61VL60 ::: pyasic.miners.whatsminer.btminer.M6X.M61.BTMinerM61VL60
@@ -603,7 +603,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M6X.M62S_Plus.BTMinerM62SPlusVK30 ::: pyasic.miners.whatsminer.btminer.M6X.M62S_Plus.BTMinerM62SPlusVK30
@@ -616,7 +616,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M6X.M63S_Plus_Plus.BTMinerM63SPlusPlusVL20 ::: pyasic.miners.whatsminer.btminer.M6X.M63S_Plus_Plus.BTMinerM63SPlusPlusVL20
@@ -629,7 +629,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M6X.M63S_Plus.BTMinerM63SPlusVK30 ::: pyasic.miners.whatsminer.btminer.M6X.M63S_Plus.BTMinerM63SPlusVK30
@@ -642,7 +642,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M6X.M63S_Plus.BTMinerM63SPlusVL10 ::: pyasic.miners.whatsminer.btminer.M6X.M63S_Plus.BTMinerM63SPlusVL10
@@ -655,7 +655,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M6X.M63S_Plus.BTMinerM63SPlusVL20 ::: pyasic.miners.whatsminer.btminer.M6X.M63S_Plus.BTMinerM63SPlusVL20
@@ -668,7 +668,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M6X.M63S_Plus.BTMinerM63SPlusVL30 ::: pyasic.miners.whatsminer.btminer.M6X.M63S_Plus.BTMinerM63SPlusVL30
@@ -681,7 +681,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M6X.M63S_Plus.BTMinerM63SPlusVL50 ::: pyasic.miners.whatsminer.btminer.M6X.M63S_Plus.BTMinerM63SPlusVL50
@@ -694,7 +694,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M6X.M63S.BTMinerM63SVK10 ::: pyasic.miners.whatsminer.btminer.M6X.M63S.BTMinerM63SVK10
@@ -707,7 +707,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M6X.M63S.BTMinerM63SVK20 ::: pyasic.miners.whatsminer.btminer.M6X.M63S.BTMinerM63SVK20
@@ -720,7 +720,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M6X.M63S.BTMinerM63SVK30 ::: pyasic.miners.whatsminer.btminer.M6X.M63S.BTMinerM63SVK30
@@ -733,7 +733,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M6X.M63S.BTMinerM63SVK60 ::: pyasic.miners.whatsminer.btminer.M6X.M63S.BTMinerM63SVK60
@@ -746,7 +746,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M6X.M63S.BTMinerM63SVL10 ::: pyasic.miners.whatsminer.btminer.M6X.M63S.BTMinerM63SVL10
@@ -759,7 +759,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M6X.M63S.BTMinerM63SVL50 ::: pyasic.miners.whatsminer.btminer.M6X.M63S.BTMinerM63SVL50
@@ -772,7 +772,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M6X.M63S.BTMinerM63SVL60 ::: pyasic.miners.whatsminer.btminer.M6X.M63S.BTMinerM63SVL60
@@ -785,7 +785,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M6X.M63.BTMinerM63VK10 ::: pyasic.miners.whatsminer.btminer.M6X.M63.BTMinerM63VK10
@@ -798,7 +798,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M6X.M63.BTMinerM63VK20 ::: pyasic.miners.whatsminer.btminer.M6X.M63.BTMinerM63VK20
@@ -811,7 +811,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M6X.M63.BTMinerM63VK30 ::: pyasic.miners.whatsminer.btminer.M6X.M63.BTMinerM63VK30
@@ -824,7 +824,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M6X.M63.BTMinerM63VL10 ::: pyasic.miners.whatsminer.btminer.M6X.M63.BTMinerM63VL10
@@ -837,7 +837,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M6X.M63.BTMinerM63VL30 ::: pyasic.miners.whatsminer.btminer.M6X.M63.BTMinerM63VL30
@@ -850,7 +850,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M6X.M64S.BTMinerM64SVL30 ::: pyasic.miners.whatsminer.btminer.M6X.M64S.BTMinerM64SVL30
@@ -863,7 +863,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M6X.M64.BTMinerM64VL30 ::: pyasic.miners.whatsminer.btminer.M6X.M64.BTMinerM64VL30
@@ -876,7 +876,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M6X.M64.BTMinerM64VL40 ::: pyasic.miners.whatsminer.btminer.M6X.M64.BTMinerM64VL40
@@ -889,7 +889,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M6X.M65S_Plus.BTMinerM65SPlusVK30 ::: pyasic.miners.whatsminer.btminer.M6X.M65S_Plus.BTMinerM65SPlusVK30
@@ -902,7 +902,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M6X.M65S.BTMinerM65SVK20 ::: pyasic.miners.whatsminer.btminer.M6X.M65S.BTMinerM65SVK20
@@ -915,7 +915,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M6X.M65S.BTMinerM65SVL60 ::: pyasic.miners.whatsminer.btminer.M6X.M65S.BTMinerM65SVL60
@@ -928,7 +928,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M6X.M66S_Plus_Plus.BTMinerM66SPlusPlusVL20 ::: pyasic.miners.whatsminer.btminer.M6X.M66S_Plus_Plus.BTMinerM66SPlusPlusVL20
@@ -941,7 +941,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M6X.M66S_Plus.BTMinerM66SPlusVK30 ::: pyasic.miners.whatsminer.btminer.M6X.M66S_Plus.BTMinerM66SPlusVK30
@@ -954,7 +954,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M6X.M66S_Plus.BTMinerM66SPlusVL10 ::: pyasic.miners.whatsminer.btminer.M6X.M66S_Plus.BTMinerM66SPlusVL10
@@ -967,7 +967,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M6X.M66S_Plus.BTMinerM66SPlusVL20 ::: pyasic.miners.whatsminer.btminer.M6X.M66S_Plus.BTMinerM66SPlusVL20
@@ -980,7 +980,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M6X.M66S_Plus.BTMinerM66SPlusVL30 ::: pyasic.miners.whatsminer.btminer.M6X.M66S_Plus.BTMinerM66SPlusVL30
@@ -993,7 +993,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M6X.M66S_Plus.BTMinerM66SPlusVL40 ::: pyasic.miners.whatsminer.btminer.M6X.M66S_Plus.BTMinerM66SPlusVL40
@@ -1006,7 +1006,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M6X.M66S_Plus.BTMinerM66SPlusVL60 ::: pyasic.miners.whatsminer.btminer.M6X.M66S_Plus.BTMinerM66SPlusVL60
@@ -1019,7 +1019,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M6X.M66S.BTMinerM66SVK20 ::: pyasic.miners.whatsminer.btminer.M6X.M66S.BTMinerM66SVK20
@@ -1032,7 +1032,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M6X.M66S.BTMinerM66SVK30 ::: pyasic.miners.whatsminer.btminer.M6X.M66S.BTMinerM66SVK30
@@ -1045,7 +1045,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M6X.M66S.BTMinerM66SVK40 ::: pyasic.miners.whatsminer.btminer.M6X.M66S.BTMinerM66SVK40
@@ -1058,7 +1058,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M6X.M66S.BTMinerM66SVK50 ::: pyasic.miners.whatsminer.btminer.M6X.M66S.BTMinerM66SVK50
@@ -1071,7 +1071,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M6X.M66S.BTMinerM66SVK60 ::: pyasic.miners.whatsminer.btminer.M6X.M66S.BTMinerM66SVK60
@@ -1084,7 +1084,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M6X.M66S.BTMinerM66SVL10 ::: pyasic.miners.whatsminer.btminer.M6X.M66S.BTMinerM66SVL10
@@ -1097,7 +1097,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M6X.M66S.BTMinerM66SVL20 ::: pyasic.miners.whatsminer.btminer.M6X.M66S.BTMinerM66SVL20
@@ -1110,7 +1110,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M6X.M66S.BTMinerM66SVL30 ::: pyasic.miners.whatsminer.btminer.M6X.M66S.BTMinerM66SVL30
@@ -1123,7 +1123,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M6X.M66S.BTMinerM66SVL40 ::: pyasic.miners.whatsminer.btminer.M6X.M66S.BTMinerM66SVL40
@@ -1136,7 +1136,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M6X.M66S.BTMinerM66SVL50 ::: pyasic.miners.whatsminer.btminer.M6X.M66S.BTMinerM66SVL50
@@ -1149,7 +1149,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M6X.M66.BTMinerM66VK20 ::: pyasic.miners.whatsminer.btminer.M6X.M66.BTMinerM66VK20
@@ -1162,7 +1162,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M6X.M66.BTMinerM66VK30 ::: pyasic.miners.whatsminer.btminer.M6X.M66.BTMinerM66VK30
@@ -1175,7 +1175,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M6X.M66.BTMinerM66VL20 ::: pyasic.miners.whatsminer.btminer.M6X.M66.BTMinerM66VL20
@@ -1188,7 +1188,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M6X.M66.BTMinerM66VL30 ::: pyasic.miners.whatsminer.btminer.M6X.M66.BTMinerM66VL30
@@ -1201,7 +1201,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M6X.M67S.BTMinerM67SVK30 ::: pyasic.miners.whatsminer.btminer.M6X.M67S.BTMinerM67SVK30

View File

@@ -5,7 +5,7 @@
- [x] Shutdowns - [x] Shutdowns
- [x] Power Modes - [x] Power Modes
- [x] Setpoints - [ ] Setpoints
- [ ] Presets - [ ] Presets
::: pyasic.miners.whatsminer.btminer.M7X.M70.BTMinerM70VM30 ::: pyasic.miners.whatsminer.btminer.M7X.M70.BTMinerM70VM30

View File

@@ -98,6 +98,7 @@ nav:
- Innosilicon A10X: "miners/innosilicon/A10X.md" - Innosilicon A10X: "miners/innosilicon/A10X.md"
- Innosilicon A11X: "miners/innosilicon/A11X.md" - Innosilicon A11X: "miners/innosilicon/A11X.md"
- Goldshell Byte: "miners/goldshell/Byte.md" - Goldshell Byte: "miners/goldshell/Byte.md"
- Goldshell Mini Doge: "miners/goldshell/MiniDoge.md"
- Goldshell X5: "miners/goldshell/X5.md" - Goldshell X5: "miners/goldshell/X5.md"
- Goldshell XMax: "miners/goldshell/XMax.md" - Goldshell XMax: "miners/goldshell/XMax.md"
- Goldshell XBox: "miners/goldshell/XBox.md" - Goldshell XBox: "miners/goldshell/XBox.md"

14
poetry.lock generated
View File

@@ -1489,6 +1489,18 @@ urllib3 = ">=1.21.1,<3"
socks = ["PySocks (>=1.5.6,!=1.5.7)"] socks = ["PySocks (>=1.5.6,!=1.5.7)"]
use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"]
[[package]]
name = "semver"
version = "3.0.4"
description = "Python helper for Semantic Versioning (https://semver.org)"
optional = false
python-versions = ">=3.7"
groups = ["main"]
files = [
{file = "semver-3.0.4-py3-none-any.whl", hash = "sha256:9c824d87ba7f7ab4a1890799cec8596f15c1241cb473404ea1cb0c55e4b04746"},
{file = "semver-3.0.4.tar.gz", hash = "sha256:afc7d8c584a5ed0a11033af086e8af226a9c0b206f313e0301f8dd7b6b589602"},
]
[[package]] [[package]]
name = "six" name = "six"
version = "1.17.0" version = "1.17.0"
@@ -1702,4 +1714,4 @@ type = ["pytest-mypy"]
[metadata] [metadata]
lock-version = "2.1" lock-version = "2.1"
python-versions = ">3.9, <4.0" python-versions = ">3.9, <4.0"
content-hash = "4152b0f7a2143d20368ddfad0aa44dfebdced4ab03586158a54eb27341a547e1" content-hash = "81ec4faceddb41badda1649e77ddcfba03b0275021ba37ba69290b7e6a326829"

View File

@@ -85,6 +85,13 @@ class MinerConfig(BaseModel):
**self.temperature.as_wm(), **self.temperature.as_wm(),
} }
def as_btminer_v3(self, user_suffix: str | None = None) -> dict:
"""Generates the configuration in the format suitable for Whatsminers running BTMiner V3."""
return {
"set.miner.pools": self.pools.as_btminer_v3()
** self.mining_mode.as_btminer_v3()
}
def as_am_old(self, user_suffix: str | None = None) -> dict: def as_am_old(self, user_suffix: str | None = None) -> dict:
"""Generates the configuration in the format suitable for old versions of Antminers.""" """Generates the configuration in the format suitable for old versions of Antminers."""
return { return {
@@ -247,6 +254,11 @@ class MinerConfig(BaseModel):
"""Constructs a MinerConfig object from web configuration for Goldshell miners.""" """Constructs a MinerConfig object from web configuration for Goldshell miners."""
return cls(pools=PoolConfig.from_am_modern(web_conf)) return cls(pools=PoolConfig.from_am_modern(web_conf))
@classmethod
def from_goldshell_list(cls, web_conf: list) -> "MinerConfig":
"""Constructs a MinerConfig object from web configuration for Goldshell miners."""
return cls(pools=PoolConfig.from_goldshell(web_conf))
@classmethod @classmethod
def from_goldshell_byte(cls, web_conf: dict) -> "MinerConfig": def from_goldshell_byte(cls, web_conf: dict) -> "MinerConfig":
"""Constructs a MinerConfig object from web configuration for Goldshell Byte miners.""" """Constructs a MinerConfig object from web configuration for Goldshell Byte miners."""
@@ -355,3 +367,14 @@ class MinerConfig(BaseModel):
@classmethod @classmethod
def from_hammer(cls, *args, **kwargs) -> "MinerConfig": def from_hammer(cls, *args, **kwargs) -> "MinerConfig":
return cls.from_am_modern(*args, **kwargs) return cls.from_am_modern(*args, **kwargs)
@classmethod
def from_btminer_v3(
cls, rpc_pools: dict, rpc_settings: dict, rpc_device_info: dict
) -> "MinerConfig":
return cls(
pools=PoolConfig.from_btminer_v3(rpc_pools=rpc_pools["msg"]),
mining_mode=MiningModeConfig.from_btminer_v3(
rpc_device_info=rpc_device_info, rpc_settings=rpc_settings
),
)

View File

@@ -107,6 +107,9 @@ class MinerConfigValue(BaseModel):
def as_wm(self) -> dict: def as_wm(self) -> dict:
return {} return {}
def as_btminer_v3(self) -> dict:
return {}
def as_inno(self) -> dict: def as_inno(self) -> dict:
return {} return {}

View File

@@ -63,6 +63,9 @@ class MiningModeNormal(MinerConfigValue):
def as_wm(self) -> dict: def as_wm(self) -> dict:
return {"mode": self.mode} return {"mode": self.mode}
def as_btminer_v3(self) -> dict:
return {"set.miner.service": "start", "set.miner.power_mode": self.mode}
def as_auradine(self) -> dict: def as_auradine(self) -> dict:
return {"mode": {"mode": self.mode}} return {"mode": {"mode": self.mode}}
@@ -109,6 +112,9 @@ class MiningModeSleep(MinerConfigValue):
def as_wm(self) -> dict: def as_wm(self) -> dict:
return {"mode": self.mode} return {"mode": self.mode}
def as_btminer_v3(self) -> dict:
return {"set.miner.service": "stop"}
def as_auradine(self) -> dict: def as_auradine(self) -> dict:
return {"mode": {"sleep": "on"}} return {"mode": {"sleep": "on"}}
@@ -149,6 +155,9 @@ class MiningModeLPM(MinerConfigValue):
def as_wm(self) -> dict: def as_wm(self) -> dict:
return {"mode": self.mode} return {"mode": self.mode}
def as_btminer_v3(self) -> dict:
return {"set.miner.service": "start", "set.miner.power_mode": self.mode}
def as_auradine(self) -> dict: def as_auradine(self) -> dict:
return {"mode": {"mode": "eco"}} return {"mode": {"mode": "eco"}}
@@ -179,6 +188,9 @@ class MiningModeHPM(MinerConfigValue):
def as_wm(self) -> dict: def as_wm(self) -> dict:
return {"mode": self.mode} return {"mode": self.mode}
def as_btminer_v3(self) -> dict:
return {"set.miner.service": "start", "set.miner.power_mode": self.mode}
def as_auradine(self) -> dict: def as_auradine(self) -> dict:
return {"mode": {"mode": "turbo"}} return {"mode": {"mode": "turbo"}}
@@ -222,6 +234,9 @@ class MiningModePowerTune(MinerConfigValue):
return {"mode": self.mode, self.mode: {"wattage": self.power}} return {"mode": self.mode, self.mode: {"wattage": self.power}}
return {} return {}
def as_btminer_v3(self) -> dict:
return {"set.miner.service": "start", "set.miner.power_limit": self.power}
def as_bosminer(self) -> dict: def as_bosminer(self) -> dict:
tuning_cfg = {"enabled": True, "mode": "power_target"} tuning_cfg = {"enabled": True, "mode": "power_target"}
if self.power is not None: if self.power is not None:
@@ -789,6 +804,26 @@ class MiningModeConfig(MinerConfigOption):
except LookupError: except LookupError:
return cls.default() return cls.default()
@classmethod
def from_btminer_v3(cls, rpc_device_info: dict, rpc_settings: dict):
try:
is_mining = rpc_device_info["msg"]["miner"]["working"] == "true"
if not is_mining:
return cls.sleep()
power_limit = rpc_settings["msg"]["power-limit"]
if not power_limit == 0:
return cls.power_tuning(power=power_limit)
power_mode = rpc_settings["msg"]["power-mode"]
if power_mode == "normal":
return cls.normal()
if power_mode == "high":
return cls.high()
if power_mode == "low":
return cls.low()
except LookupError:
return cls.default()
@classmethod @classmethod
def from_mara(cls, web_config: dict): def from_mara(cls, web_config: dict):
try: try:

View File

@@ -64,6 +64,13 @@ class Pool(MinerConfigValue):
f"passwd_{idx}": self.password, f"passwd_{idx}": self.password,
} }
def as_btminer_v3(self, user_suffix: str | None = None) -> dict:
return {
f"pool": self.url,
f"worker": f"{self.user}{user_suffix or ''}",
f"passwd": self.password,
}
def as_am_old(self, idx: int = 1, user_suffix: str | None = None) -> dict: def as_am_old(self, idx: int = 1, user_suffix: str | None = None) -> dict:
return { return {
f"_ant_pool{idx}url": self.url, f"_ant_pool{idx}url": self.url,
@@ -148,6 +155,10 @@ class Pool(MinerConfigValue):
def from_api(cls, api_pool: dict) -> "Pool": def from_api(cls, api_pool: dict) -> "Pool":
return cls(url=api_pool["URL"], user=api_pool["User"], password="x") return cls(url=api_pool["URL"], user=api_pool["User"], password="x")
@classmethod
def from_btminer_v3(cls, api_pool: dict) -> "Pool":
return cls(url=api_pool["url"], user=api_pool["account"], password="x")
@classmethod @classmethod
def from_epic(cls, api_pool: dict) -> "Pool": def from_epic(cls, api_pool: dict) -> "Pool":
return cls( return cls(
@@ -296,6 +307,9 @@ class PoolGroup(MinerConfigValue):
idx += 1 idx += 1
return pools return pools
def as_btminer_v3(self, user_suffix: str | None = None) -> list:
return [pool.as_btminer_v3(user_suffix) for pool in self.pools[:3]]
def as_am_old(self, user_suffix: str | None = None) -> dict: def as_am_old(self, user_suffix: str | None = None) -> dict:
pools = {} pools = {}
idx = 0 idx = 0
@@ -385,6 +399,13 @@ class PoolGroup(MinerConfigValue):
pools.append(Pool.from_api(pool)) pools.append(Pool.from_api(pool))
return cls(pools=pools) return cls(pools=pools)
@classmethod
def from_btminer_v3(cls, api_pool_list: list) -> "PoolGroup":
pools = []
for pool in api_pool_list:
pools.append(Pool.from_btminer_v3(pool))
return cls(pools=pools)
@classmethod @classmethod
def from_epic(cls, api_pool_list: list) -> "PoolGroup": def from_epic(cls, api_pool_list: list) -> "PoolGroup":
pools = [] pools = []
@@ -513,6 +534,11 @@ class PoolConfig(MinerConfigValue):
return {"pools": self.groups[0].as_wm(user_suffix=user_suffix)} return {"pools": self.groups[0].as_wm(user_suffix=user_suffix)}
return {"pools": PoolGroup().as_wm()} return {"pools": PoolGroup().as_wm()}
def as_btminer_v3(self, user_suffix: str | None = None) -> dict:
if len(self.groups) > 0:
return {"pools": self.groups[0].as_btminer_v3(user_suffix=user_suffix)}
return {"pools": PoolGroup().as_btminer_v3()}
def as_am_old(self, user_suffix: str | None = None) -> dict: def as_am_old(self, user_suffix: str | None = None) -> dict:
if len(self.groups) > 0: if len(self.groups) > 0:
return self.groups[0].as_am_old(user_suffix=user_suffix) return self.groups[0].as_am_old(user_suffix=user_suffix)
@@ -598,6 +624,16 @@ class PoolConfig(MinerConfigValue):
return cls(groups=[PoolGroup.from_api(pool_data)]) return cls(groups=[PoolGroup.from_api(pool_data)])
@classmethod
def from_btminer_v3(cls, rpc_pools: dict) -> "PoolConfig":
try:
pool_data = rpc_pools["pools"]
except KeyError:
return PoolConfig.default()
pool_data = sorted(pool_data, key=lambda x: int(x["id"]))
return cls(groups=[PoolGroup.from_btminer_v3(pool_data)])
@classmethod @classmethod
def from_epic(cls, web_conf: dict) -> "PoolConfig": def from_epic(cls, web_conf: dict) -> "PoolConfig":
pool_data = web_conf["StratumConfigs"] pool_data = web_conf["StratumConfigs"]

View File

@@ -77,7 +77,6 @@ class HashBoard(BaseModel):
raise KeyError(f"{item}") raise KeyError(f"{item}")
def as_influxdb(self, key_root: str, level_delimiter: str = ".") -> str: def as_influxdb(self, key_root: str, level_delimiter: str = ".") -> str:
def serialize_int(key: str, value: int) -> str: def serialize_int(key: str, value: int) -> str:
return f"{key}={value}" return f"{key}={value}"

View File

@@ -94,7 +94,6 @@ class PoolMetrics(BaseModel):
return (value / total) * 100 return (value / total) * 100
def as_influxdb(self, key_root: str, level_delimiter: str = ".") -> str: def as_influxdb(self, key_root: str, level_delimiter: str = ".") -> str:
def serialize_int(key: str, value: int) -> str: def serialize_int(key: str, value: int) -> str:
return f"{key}={value}" return f"{key}={value}"

View File

@@ -480,6 +480,7 @@ class GoldshellModels(MinerModelType):
KDBoxII = "KD Box II" KDBoxII = "KD Box II"
KDBoxPro = "KD Box Pro" KDBoxPro = "KD Box Pro"
Byte = "Byte" Byte = "Byte"
MiniDoge = "Mini Doge"
def __str__(self): def __str__(self):
return self.value return self.value

View File

@@ -167,7 +167,6 @@ class CGMinerAvalonNano3(AvalonMiner, AvalonNano3):
class CGMinerAvalonNano3s(AvalonMiner, AvalonNano3s): class CGMinerAvalonNano3s(AvalonMiner, AvalonNano3s):
data_locations = AVALON_NANO3S_DATA_LOC data_locations = AVALON_NANO3S_DATA_LOC
async def _get_wattage(self, rpc_estats: dict = None) -> Optional[int]: async def _get_wattage(self, rpc_estats: dict = None) -> Optional[int]:
@@ -179,8 +178,7 @@ class CGMinerAvalonNano3s(AvalonMiner, AvalonNano3s):
if rpc_estats is not None: if rpc_estats is not None:
try: try:
unparsed_estats = rpc_estats["STATS"][0]["MM ID0"] parsed_estats = self.parse_estats(rpc_estats)["STATS"][0]["MM ID0"]
parsed_estats = self.parse_estats(unparsed_estats)
return int(parsed_estats["PS"][6]) return int(parsed_estats["PS"][6])
except (IndexError, KeyError, ValueError, TypeError): except (IndexError, KeyError, ValueError, TypeError):
pass pass
@@ -194,8 +192,7 @@ class CGMinerAvalonNano3s(AvalonMiner, AvalonNano3s):
if rpc_estats is not None: if rpc_estats is not None:
try: try:
unparsed_estats = rpc_estats["STATS"][0]["MM ID0"] parsed_estats = self.parse_estats(rpc_estats)["STATS"][0]["MM ID0"]
parsed_estats = self.parse_estats(unparsed_estats)
return self.algo.hashrate( return self.algo.hashrate(
rate=float(parsed_estats["GHSspd"]), unit=self.algo.unit.GH rate=float(parsed_estats["GHSspd"]), unit=self.algo.unit.GH
).into(self.algo.unit.default) ).into(self.algo.unit.default)
@@ -212,16 +209,14 @@ class CGMinerAvalonNano3s(AvalonMiner, AvalonNano3s):
pass pass
if rpc_estats is not None: if rpc_estats is not None:
try: try:
unparsed_estats = rpc_estats["STATS"][0]["MM ID0"] parsed_estats = self.parse_estats(rpc_estats)["STATS"][0]["MM ID0"]
parsed_estats = self.parse_estats(unparsed_estats)
except (IndexError, KeyError, ValueError, TypeError): except (IndexError, KeyError, ValueError, TypeError):
return hashboards return hashboards
for board in range(len(hashboards)): for board in range(len(hashboards)):
try: try:
board_hr = parsed_estats["GHSspd"][board] board_hr = parsed_estats["GHSspd"]
hashboards[board].hashrate = self.algo.hashrate( hashboards[board].hashrate = self.algo.hashrate(
rate=float(board_hr), unit=self.algo.unit.GH rate=float(board_hr), unit=self.algo.unit.GH
).into(self.algo.unit.default) ).into(self.algo.unit.default)

View File

@@ -20,7 +20,7 @@ from .bfgminer import BFGMiner
from .bitaxe import BitAxe from .bitaxe import BitAxe
from .bmminer import BMMiner from .bmminer import BMMiner
from .braiins_os import BOSer, BOSMiner from .braiins_os import BOSer, BOSMiner
from .btminer import BTMiner from .btminer import BTMiner, BTMinerV2, BTMinerV3
from .cgminer import CGMiner from .cgminer import CGMiner
from .elphapex import ElphapexMiner from .elphapex import ElphapexMiner
from .epic import ePIC from .epic import ePIC

View File

@@ -287,7 +287,6 @@ class AvalonMiner(CGMiner):
return hashboards return hashboards
for board in range(self.expected_hashboards): for board in range(self.expected_hashboards):
try: try:
board_hr = parsed_estats["STATS"][0]["MM ID0"]["MGHS"] board_hr = parsed_estats["STATS"][0]["MM ID0"]["MGHS"]
if isinstance(board_hr, list): if isinstance(board_hr, list):
@@ -306,10 +305,12 @@ class AvalonMiner(CGMiner):
hashboards[board].chip_temp = int( hashboards[board].chip_temp = int(
parsed_estats["STATS"][0]["MM ID0"]["MTmax"][board] parsed_estats["STATS"][0]["MM ID0"]["MTmax"][board]
) )
except LookupError: except (LookupError, TypeError):
try: try:
hashboards[board].chip_temp = int( hashboards[board].chip_temp = int(
parsed_estats["STATS"][0]["MM ID0"]["Tmax"] parsed_estats["STATS"][0]["MM ID0"].get(
"Tmax", parsed_estats["STATS"][0]["MM ID0"]["TMax"]
)
) )
except LookupError: except LookupError:
pass pass
@@ -318,10 +319,12 @@ class AvalonMiner(CGMiner):
hashboards[board].temp = int( hashboards[board].temp = int(
parsed_estats["STATS"][0]["MM ID0"]["MTmax"][board] parsed_estats["STATS"][0]["MM ID0"]["MTmax"][board]
) )
except LookupError: except (LookupError, TypeError):
try: try:
hashboards[board].temp = int( hashboards[board].temp = int(
parsed_estats["STATS"][0]["MM ID0"]["Tavg"] parsed_estats["STATS"][0]["MM ID0"].get(
"Tavg", parsed_estats["STATS"][0]["MM ID0"]["TAvg"]
)
) )
except LookupError: except LookupError:
pass pass
@@ -330,7 +333,7 @@ class AvalonMiner(CGMiner):
hashboards[board].inlet_temp = int( hashboards[board].inlet_temp = int(
parsed_estats["STATS"][0]["MM ID0"]["MTavg"][board] parsed_estats["STATS"][0]["MM ID0"]["MTavg"][board]
) )
except LookupError: except (LookupError, TypeError):
try: try:
hashboards[board].inlet_temp = int( hashboards[board].inlet_temp = int(
parsed_estats["STATS"][0]["MM ID0"]["HBITemp"] parsed_estats["STATS"][0]["MM ID0"]["HBITemp"]
@@ -342,7 +345,7 @@ class AvalonMiner(CGMiner):
hashboards[board].outlet_temp = int( hashboards[board].outlet_temp = int(
parsed_estats["STATS"][0]["MM ID0"]["MTmax"][board] parsed_estats["STATS"][0]["MM ID0"]["MTmax"][board]
) )
except LookupError: except (LookupError, TypeError):
try: try:
hashboards[board].outlet_temp = int( hashboards[board].outlet_temp = int(
parsed_estats["STATS"][0]["MM ID0"]["HBOTemp"] parsed_estats["STATS"][0]["MM ID0"]["HBOTemp"]
@@ -357,7 +360,7 @@ class AvalonMiner(CGMiner):
hashboards[board].chips = len( hashboards[board].chips = len(
[item for item in chip_data if not item == "0"] [item for item in chip_data if not item == "0"]
) )
except LookupError: except (LookupError, TypeError):
try: try:
chip_data = parsed_estats["STATS"][0]["HBinfo"][f"HB{board}"][ chip_data = parsed_estats["STATS"][0]["HBinfo"][f"HB{board}"][
f"PVT_T{board}" f"PVT_T{board}"

View File

@@ -216,7 +216,7 @@ class BFGMiner(StockFirmware):
) )
except LookupError: except LookupError:
pass pass
fans = [Fan(speed=d) if d else Fan() for d in fans_data] fans = [Fan(speed=d) for d in fans_data if d is not None]
return fans return fans

View File

@@ -13,13 +13,14 @@
# 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. -
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
import asyncio
import logging import logging
from pathlib import Path from pathlib import Path
import aiofiles import aiofiles
import semver
from pyasic.config import MinerConfig, MiningModeConfig from pyasic.config import MinerConfig, MiningModeConfig, PoolConfig
from pyasic.data import Fan, HashBoard from pyasic.data import Fan, HashBoard
from pyasic.data.error_codes import MinerErrorData, WhatsminerError from pyasic.data.error_codes import MinerErrorData, WhatsminerError
from pyasic.data.pools import PoolMetrics, PoolUrl from pyasic.data.pools import PoolMetrics, PoolUrl
@@ -29,6 +30,35 @@ from pyasic.miners.data import DataFunction, DataLocations, DataOptions, RPCAPIC
from pyasic.miners.device.firmware import StockFirmware from pyasic.miners.device.firmware import StockFirmware
from pyasic.rpc.btminer import BTMinerRPCAPI, BTMinerV3RPCAPI from pyasic.rpc.btminer import BTMinerRPCAPI, BTMinerV3RPCAPI
class BTMiner(StockFirmware):
def __new__(cls, ip: str, version: str | None = None):
bases = cls.__bases__
bases = bases[1:]
def get_new(v: str | None):
if v is None:
return BTMinerV2
try:
semantic = semver.Version(
major=int(v[0:4]),
minor=int(v[4:6]),
patch=int(v[6:8]),
)
except ValueError:
return BTMinerV2
if semantic > semver.Version(major=2024, minor=11, patch=0):
return BTMinerV3
return BTMinerV2
inject = get_new(version)
bases = (inject,) + bases
cls = type(cls.__name__, bases, {})(ip=ip, version=version)
return cls
BTMINER_DATA_LOC = DataLocations( BTMINER_DATA_LOC = DataLocations(
**{ **{
str(DataOptions.MAC): DataFunction( str(DataOptions.MAC): DataFunction(
@@ -118,7 +148,7 @@ BTMINER_DATA_LOC = DataLocations(
) )
class BTMiner(StockFirmware): class BTMinerV2(StockFirmware):
"""Base handler for BTMiner based miners.""" """Base handler for BTMiner based miners."""
_rpc_cls = BTMinerRPCAPI _rpc_cls = BTMinerRPCAPI
@@ -753,67 +783,67 @@ class BTMiner(StockFirmware):
BTMINERV3_DATA_LOC = DataLocations( BTMINERV3_DATA_LOC = DataLocations(
**{ **{
str(DataOptions.MAC): DataFunction( str(DataOptions.MAC): DataFunction(
"_get_mac", [RPCAPICommand("rpc_get_device_info", "get_device_info")] "_get_mac", [RPCAPICommand("rpc_get_device_info", "get.device.info")]
), ),
str(DataOptions.API_VERSION): DataFunction( str(DataOptions.API_VERSION): DataFunction(
"_get_api_version", "_get_api_version",
[RPCAPICommand("rpc_get_device_info", "get_device_info")], [RPCAPICommand("rpc_get_device_info", "get.device.info")],
), ),
str(DataOptions.FW_VERSION): DataFunction( str(DataOptions.FW_VERSION): DataFunction(
"_get_firmware_version", "_get_firmware_version",
[RPCAPICommand("rpc_get_device_info", "get_device_info")], [RPCAPICommand("rpc_get_device_info", "get.device.info")],
), ),
str(DataOptions.HOSTNAME): DataFunction( str(DataOptions.HOSTNAME): DataFunction(
"_get_hostname", [RPCAPICommand("rpc_get_device_info", "get_device_info")] "_get_hostname", [RPCAPICommand("rpc_get_device_info", "get.device.info")]
), ),
str(DataOptions.FAULT_LIGHT): DataFunction( str(DataOptions.FAULT_LIGHT): DataFunction(
"_get_light_flashing", "_get_light_flashing",
[RPCAPICommand("rpc_get_device_info", "get_device_info")], [RPCAPICommand("rpc_get_device_info", "get.device.info")],
), ),
str(DataOptions.WATTAGE_LIMIT): DataFunction( str(DataOptions.WATTAGE_LIMIT): DataFunction(
"_get_wattage_limit", "_get_wattage_limit",
[RPCAPICommand("rpc_get_device_info", "get_device_info")], [RPCAPICommand("rpc_get_device_info", "get.device.info")],
), ),
str(DataOptions.FANS): DataFunction( str(DataOptions.FANS): DataFunction(
"_get_fans", "_get_fans",
[RPCAPICommand("rpc_get_miner_status_summary", "get_miner_status_summary")], [RPCAPICommand("rpc_get_miner_status_summary", "get.miner.status:summary")],
), ),
str(DataOptions.FAN_PSU): DataFunction( str(DataOptions.FAN_PSU): DataFunction(
"_get_psu_fans", [RPCAPICommand("rpc_get_device_info", "get_device_info")] "_get_psu_fans", [RPCAPICommand("rpc_get_device_info", "get.device.info")]
), ),
str(DataOptions.HASHBOARDS): DataFunction( str(DataOptions.HASHBOARDS): DataFunction(
"_get_hashboards", "_get_hashboards",
[ [
RPCAPICommand("rpc_get_device_info", "get_device_info"), RPCAPICommand("rpc_get_device_info", "get.device.info"),
RPCAPICommand( RPCAPICommand(
"rpc_get_miner_status_edevs", "rpc_get_miner_status_edevs",
"get_miner_status_edevs", "get.miner.status:edevs",
), ),
], ],
), ),
str(DataOptions.POOLS): DataFunction( str(DataOptions.POOLS): DataFunction(
"_get_pools", "_get_pools",
[RPCAPICommand("rpc_get_miner_status_summary", "get_miner_status_summary")], [RPCAPICommand("rpc_get_miner_status_summary", "get.miner.status:summary")],
), ),
str(DataOptions.UPTIME): DataFunction( str(DataOptions.UPTIME): DataFunction(
"_get_uptime", "_get_uptime",
[RPCAPICommand("rpc_get_miner_status_summary", "get_miner_status_summary")], [RPCAPICommand("rpc_get_miner_status_summary", "get.miner.status:summary")],
), ),
str(DataOptions.WATTAGE): DataFunction( str(DataOptions.WATTAGE): DataFunction(
"_get_wattage", "_get_wattage",
[RPCAPICommand("rpc_get_miner_status_summary", "get_miner_status_summary")], [RPCAPICommand("rpc_get_miner_status_summary", "get.miner.status:summary")],
), ),
str(DataOptions.HASHRATE): DataFunction( str(DataOptions.HASHRATE): DataFunction(
"_get_hashrate", "_get_hashrate",
[RPCAPICommand("rpc_get_miner_status_summary", "get_miner_status_summary")], [RPCAPICommand("rpc_get_miner_status_summary", "get.miner.status:summary")],
), ),
str(DataOptions.EXPECTED_HASHRATE): DataFunction( str(DataOptions.EXPECTED_HASHRATE): DataFunction(
"_get_expected_hashrate", "_get_expected_hashrate",
[RPCAPICommand("rpc_get_miner_status_summary", "get_miner_status_summary")], [RPCAPICommand("rpc_get_miner_status_summary", "get.miner.status:summary")],
), ),
str(DataOptions.ENVIRONMENT_TEMP): DataFunction( str(DataOptions.ENVIRONMENT_TEMP): DataFunction(
"_get_env_temp", "_get_env_temp",
[RPCAPICommand("rpc_get_miner_status_summary", "get_miner_status_summary")], [RPCAPICommand("rpc_get_miner_status_summary", "get.miner.status:summary")],
), ),
} }
) )
@@ -829,6 +859,34 @@ class BTMinerV3(StockFirmware):
supports_autotuning = True supports_autotuning = True
supports_power_modes = True supports_power_modes = True
async def get_config(self) -> MinerConfig:
pools = None
settings = None
device_info = None
try:
pools = await self.rpc.get_miner_status_pools()
settings = await self.rpc.get_miner_setting()
device_info = await self.rpc.get_device_info()
except APIError as e:
logging.warning(e)
except LookupError:
pass
self.config = MinerConfig.from_btminer_v3(
rpc_pools=pools, rpc_settings=settings, rpc_device_info=device_info
)
return self.config
async def send_config(self, config: MinerConfig, user_suffix: str = None) -> None:
self.config = config
conf = config.as_btminer_v3(user_suffix=user_suffix)
await asyncio.gather(
*[self.rpc.send_command(k, parameters=v) for k, v in conf.values()]
)
async def fault_light_off(self) -> bool: async def fault_light_off(self) -> bool:
try: try:
data = await self.rpc.set_system_led() data = await self.rpc.set_system_led()
@@ -1024,7 +1082,9 @@ class BTMinerV3(StockFirmware):
temp=board_data.get("chip-temp-min"), temp=board_data.get("chip-temp-min"),
inlet_temp=board_data.get("chip-temp-min"), inlet_temp=board_data.get("chip-temp-min"),
outlet_temp=board_data.get("chip-temp-max"), outlet_temp=board_data.get("chip-temp-max"),
serial_number=board_data.get(f"pcbsn{idx}"), serial_number=rpc_get_device_info.get("msg", {})
.get("miner", {})
.get(f"pcbsn{idx}"),
chips=board_data.get("effective-chips"), chips=board_data.get("effective-chips"),
expected_chips=self.expected_chips, expected_chips=self.expected_chips,
active=(board_data.get("hash-average") or 0) > 0, active=(board_data.get("hash-average") or 0) > 0,
@@ -1106,12 +1166,16 @@ class BTMinerV3(StockFirmware):
rpc_get_miner_status_summary = await self.rpc.get_miner_status_summary() rpc_get_miner_status_summary = await self.rpc.get_miner_status_summary()
except APIError: except APIError:
return None return None
return ( res = (
rpc_get_miner_status_summary.get("msg", {}) rpc_get_miner_status_summary.get("msg", {})
.get("summary", {}) .get("summary", {})
.get("factory-hash") .get("factory-hash")
) )
if res == (-0.001 * self.expected_hashboards):
return None
return res
async def _get_env_temp( async def _get_env_temp(
self, rpc_get_miner_status_summary: dict = None self, rpc_get_miner_status_summary: dict = None
) -> float | None: ) -> float | None:

View File

@@ -233,9 +233,10 @@ class ElphapexMiner(StockFirmware):
board_temp_data = list( board_temp_data = list(
filter(lambda x: not x == 0, board["temp_pcb"]) filter(lambda x: not x == 0, board["temp_pcb"])
) )
hashboards[board["index"]].temp = sum(board_temp_data) / len( if not len(board_temp_data) == 0:
board_temp_data hashboards[board["index"]].temp = sum(board_temp_data) / len(
) board_temp_data
)
chip_temp_data = list( chip_temp_data = list(
filter(lambda x: not x == "", board["temp_chip"]) filter(lambda x: not x == "", board["temp_chip"])
) )

View File

@@ -13,24 +13,28 @@
# 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 pyasic.miners.backends.btminer import BTMiner, BTMinerV3 from pyasic.miners.backends.btminer import BTMiner, BTMinerV2
class M7X(BTMinerV3): class M7X(BTMiner):
pass supports_autotuning = True
supports_presets = True
class M6X(BTMinerV3):
pass class M6X(BTMiner):
supports_autotuning = True
supports_presets = True
class M5X(BTMinerV3):
pass
class M5X(BTMiner):
supports_autotuning = True
class M3X(BTMinerV3): supports_presets = True
pass
class M3X(BTMiner):
class M2X(BTMiner): supports_autotuning = True
supports_presets = True
class M2X(BTMinerV2):
pass pass

View File

@@ -576,7 +576,7 @@ class MinerProtocol(Protocol):
class BaseMiner(MinerProtocol): class BaseMiner(MinerProtocol):
def __init__(self, ip: str) -> None: def __init__(self, ip: str, version: str | None = None) -> None:
self.ip = ip self.ip = ip
if self.expected_chips is None and self.raw_model is not None: if self.expected_chips is None and self.raw_model is not None:

View File

@@ -13,7 +13,8 @@
# 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 .Byte import * from .byte import *
from .mini_doge import *
from .X5 import * from .X5 import *
from .XBox import * from .XBox import *
from .XMax import * from .XMax import *

View File

@@ -1,5 +1,5 @@
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
# Copyright 2022 Upstream Data Inc - # Copyright 2025 Upstream Data Inc -
# - # -
# Licensed under the Apache License, Version 2.0 (the "License"); - # Licensed under the Apache License, Version 2.0 (the "License"); -
# you may not use this file except in compliance with the License. - # you may not use this file except in compliance with the License. -
@@ -13,4 +13,4 @@
# 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 .Byte import Byte from .byte import Byte

View File

@@ -1,5 +1,5 @@
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
# Copyright 2022 Upstream Data Inc - # Copyright 2025 Upstream Data Inc -
# - # -
# Licensed under the Apache License, Version 2.0 (the "License"); - # Licensed under the Apache License, Version 2.0 (the "License"); -
# you may not use this file except in compliance with the License. - # you may not use this file except in compliance with the License. -

View File

@@ -1,5 +1,5 @@
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
# Copyright 2022 Upstream Data Inc - # Copyright 2025 Upstream Data Inc -
# - # -
# Licensed under the Apache License, Version 2.0 (the "License"); - # Licensed under the Apache License, Version 2.0 (the "License"); -
# you may not use this file except in compliance with the License. - # you may not use this file except in compliance with the License. -
@@ -13,4 +13,4 @@
# 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 .Byte import GoldshellByte from .mini_doge import MiniDoge

View File

@@ -0,0 +1,27 @@
# ------------------------------------------------------------------------------
# Copyright 2025 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.device.algorithm import MinerAlgo
from pyasic.device.models import MinerModel
from pyasic.miners.device.makes import GoldshellMake
class MiniDoge(GoldshellMake):
raw_model = MinerModel.GOLDSHELL.MiniDoge
expected_chips = 40
expected_fans = 2
expected_hashboards = 1
algo = MinerAlgo.SCRYPT

View File

@@ -40,5 +40,6 @@ class KS5M(IceRiverMake):
raw_model = MinerModel.ICERIVER.KS5M raw_model = MinerModel.ICERIVER.KS5M
expected_fans = 4 expected_fans = 4
expected_chips = 18
expected_hashboards = 3 expected_hashboards = 3
algo = MinerAlgo.KHEAVYHASH algo = MinerAlgo.KHEAVYHASH

View File

@@ -82,6 +82,7 @@ MINER_CLASSES = {
"ANTMINER KS5": BMMinerKS5, "ANTMINER KS5": BMMinerKS5,
"ANTMINER KS5 PRO": BMMinerKS5Pro, "ANTMINER KS5 PRO": BMMinerKS5Pro,
"ANTMINER L7": BMMinerL7, "ANTMINER L7": BMMinerL7,
"ANTMINER L7_I": BMMinerL7,
"ANTMINER K7": BMMinerK7, "ANTMINER K7": BMMinerK7,
"ANTMINER D7": BMMinerD7, "ANTMINER D7": BMMinerD7,
"ANTMINER E9 PRO": BMMinerE9Pro, "ANTMINER E9 PRO": BMMinerE9Pro,
@@ -91,6 +92,7 @@ MINER_CLASSES = {
"ANTMINER S9J": BMMinerS9j, "ANTMINER S9J": BMMinerS9j,
"ANTMINER T9": BMMinerT9, "ANTMINER T9": BMMinerT9,
"ANTMINER L9": BMMinerL9, "ANTMINER L9": BMMinerL9,
"ANTMINER L9_I": BMMinerL9,
"ANTMINER Z15": CGMinerZ15, "ANTMINER Z15": CGMinerZ15,
"ANTMINER Z15 PRO": BMMinerZ15Pro, "ANTMINER Z15 PRO": BMMinerZ15Pro,
"ANTMINER S17": BMMinerS17, "ANTMINER S17": BMMinerS17,
@@ -531,6 +533,7 @@ MINER_CLASSES = {
"GOLDSHELL KDBOXII": GoldshellKDBoxII, "GOLDSHELL KDBOXII": GoldshellKDBoxII,
"GOLDSHELL KDBOXPRO": GoldshellKDBoxPro, "GOLDSHELL KDBOXPRO": GoldshellKDBoxPro,
"GOLDSHELL BYTE": GoldshellByte, "GOLDSHELL BYTE": GoldshellByte,
"GOLDSHELL MINIDOGE": GoldshellMiniDoge,
}, },
MinerTypes.BRAIINS_OS: { MinerTypes.BRAIINS_OS: {
None: BOSMiner, None: BOSMiner,
@@ -592,6 +595,7 @@ MINER_CLASSES = {
"ANTMINER S19A PRO": VNishS19aPro, "ANTMINER S19A PRO": VNishS19aPro,
"ANTMINER S19 PRO A": VNishS19ProA, "ANTMINER S19 PRO A": VNishS19ProA,
"ANTMINER S19 PRO HYD.": VNishS19ProHydro, "ANTMINER S19 PRO HYD.": VNishS19ProHydro,
"ANTMINER S19 PRO HYDRO": VNishS19ProHydro,
"ANTMINER S19K PRO": VNishS19kPro, "ANTMINER S19K PRO": VNishS19kPro,
"ANTMINER T19": VNishT19, "ANTMINER T19": VNishT19,
"ANTMINER T21": VNishT21, "ANTMINER T21": VNishT21,
@@ -788,21 +792,32 @@ class MinerFactory:
MinerTypes.VOLCMINER: self.get_miner_model_volcminer, MinerTypes.VOLCMINER: self.get_miner_model_volcminer,
MinerTypes.ELPHAPEX: self.get_miner_model_elphapex, MinerTypes.ELPHAPEX: self.get_miner_model_elphapex,
} }
fn = miner_model_fns.get(miner_type) version = None
miner_version_fns = {
MinerTypes.WHATSMINER: self.get_miner_version_whatsminer,
}
model_fn = miner_model_fns.get(miner_type)
version_fn = miner_version_fns.get(miner_type)
if fn is not None: if model_fn is not None:
# noinspection PyArgumentList # noinspection PyArgumentList
task = asyncio.create_task(fn(ip)) task = asyncio.create_task(model_fn(ip))
try: try:
miner_model = await asyncio.wait_for( miner_model = await asyncio.wait_for(
task, timeout=settings.get("factory_get_timeout", 3) task, timeout=settings.get("factory_get_timeout", 3)
) )
except asyncio.TimeoutError: except asyncio.TimeoutError:
pass pass
if version_fn is not None:
task = asyncio.create_task(version_fn(ip))
try:
version = await asyncio.wait_for(
task, timeout=settings.get("factory_get_timeout", 3)
)
except asyncio.TimeoutError:
pass
miner = self._select_miner_from_classes( miner = self._select_miner_from_classes(
ip, ip, miner_type=miner_type, miner_model=miner_model, version=version
miner_type=miner_type,
miner_model=miner_model,
) )
return miner return miner
@@ -1144,13 +1159,14 @@ class MinerFactory:
ip: ipaddress.ip_address, ip: ipaddress.ip_address,
miner_model: str | None, miner_model: str | None,
miner_type: MinerTypes | None, miner_type: MinerTypes | None,
version: str | None = None,
) -> AnyMiner | None: ) -> AnyMiner | None:
# special case since hiveon miners return web results copying the antminer stock FW # special case since hiveon miners return web results copying the antminer stock FW
if "HIVEON" in str(miner_model).upper(): if "HIVEON" in str(miner_model).upper():
miner_model = str(miner_model).upper().replace(" HIVEON", "") miner_model = str(miner_model).upper().replace(" HIVEON", "")
miner_type = MinerTypes.HIVEON miner_type = MinerTypes.HIVEON
try: try:
return MINER_CLASSES[miner_type][str(miner_model).upper()](ip) return MINER_CLASSES[miner_type][str(miner_model).upper()](ip, version)
except LookupError: except LookupError:
if miner_type in MINER_CLASSES: if miner_type in MINER_CLASSES:
if miner_model is not None: if miner_model is not None:
@@ -1158,8 +1174,8 @@ class MinerFactory:
f"Partially supported miner found: {miner_model}, type: {miner_type}, please open an issue with miner data " f"Partially supported miner found: {miner_model}, type: {miner_type}, please open an issue with miner data "
f"and this model on GitHub (https://github.com/UpstreamData/pyasic/issues)." f"and this model on GitHub (https://github.com/UpstreamData/pyasic/issues)."
) )
return MINER_CLASSES[miner_type][None](ip) return MINER_CLASSES[miner_type][None](ip, version)
return UnknownMiner(str(ip)) return UnknownMiner(str(ip), version)
async def get_miner_model_antminer(self, ip: str) -> str | None: async def get_miner_model_antminer(self, ip: str) -> str | None:
tasks = [ tasks = [
@@ -1238,6 +1254,14 @@ class MinerFactory:
except (TypeError, LookupError): except (TypeError, LookupError):
pass pass
async def get_miner_version_whatsminer(self, ip: str) -> str | None:
sock_json_data = await self.send_api_command(ip, "get_version")
try:
version = sock_json_data["Msg"]["fw_ver"]
return version
except LookupError:
pass
async def get_miner_model_avalonminer(self, ip: str) -> str | None: async def get_miner_model_avalonminer(self, ip: str) -> str | None:
sock_json_data = await self.send_api_command(ip, "version") sock_json_data = await self.send_api_command(ip, "version")
try: try:

View File

@@ -13,7 +13,8 @@
# 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 .Byte import * from .byte import *
from .mini_doge import *
from .X5 import * from .X5 import *
from .XBox import * from .XBox import *
from .XMax import * from .XMax import *

View File

@@ -0,0 +1,16 @@
# ------------------------------------------------------------------------------
# Copyright 2025 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 .byte import GoldshellByte

View File

@@ -1,5 +1,5 @@
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
# Copyright 2022 Upstream Data Inc - # Copyright 2025 Upstream Data Inc -
# - # -
# Licensed under the Apache License, Version 2.0 (the "License"); - # Licensed under the Apache License, Version 2.0 (the "License"); -
# you may not use this file except in compliance with the License. - # you may not use this file except in compliance with the License. -
@@ -73,15 +73,23 @@ GOLDSHELL_BYTE_DATA_LOC = DataLocations(
"_get_pools", "_get_pools",
[RPCAPICommand("rpc_pools", "pools")], [RPCAPICommand("rpc_pools", "pools")],
), ),
str(DataOptions.UPTIME): DataFunction(
"_get_uptime",
[WebAPICommand("web_devs", "devs")],
),
str(DataOptions.WATTAGE): DataFunction(
"_get_wattage",
[WebAPICommand("web_devs", "devs")],
),
} }
) )
class GoldshellByte(GoldshellMiner, Byte): class GoldshellByte(GoldshellMiner, Byte):
data_locations = GOLDSHELL_BYTE_DATA_LOC data_locations = GOLDSHELL_BYTE_DATA_LOC
supports_shutdown = False
cgdev: dict | None = None supports_power_modes = False
web_devs: dict | None = None
async def get_data( async def get_data(
self, self,
@@ -89,29 +97,22 @@ class GoldshellByte(GoldshellMiner, Byte):
include: List[Union[str, DataOptions]] = None, include: List[Union[str, DataOptions]] = None,
exclude: List[Union[str, DataOptions]] = None, exclude: List[Union[str, DataOptions]] = None,
) -> MinerData: ) -> MinerData:
if self.cgdev is None: if self.web_devs is None:
try: try:
self.cgdev = await self.web.send_command("cgminer?cgminercmd=devs") self.web_devs = await self.web.devs()
except APIError: except APIError:
pass pass
scrypt_board_count = 0 scrypt_board_count = 0
zksnark_board_count = 0 zksnark_board_count = 0
total_wattage = 0
total_uptime_mins = 0
for minfo in self.cgdev.get("minfos", []):
for minfo in self.web_devs.get("minfos", []):
algo_name = minfo.get("name") algo_name = minfo.get("name")
for info in minfo.get("infos", []): for _ in minfo.get("infos", []):
self.expected_hashboards += 1 self.expected_hashboards += 1
self.expected_fans += 1 self.expected_fans += 1
total_wattage = int(float(info.get("power", 0)))
total_uptime_mins = int(info.get("time", 0))
if algo_name == ALGORITHM_SCRYPT_NAME: if algo_name == ALGORITHM_SCRYPT_NAME:
scrypt_board_count += 1 scrypt_board_count += 1
elif algo_name == ALGORITHM_ZKSNARK_NAME: elif algo_name == ALGORITHM_ZKSNARK_NAME:
@@ -128,12 +129,6 @@ class GoldshellByte(GoldshellMiner, Byte):
data = await super().get_data(allow_warning, include, exclude) data = await super().get_data(allow_warning, include, exclude)
data.expected_chips = self.expected_chips data.expected_chips = self.expected_chips
data.wattage = total_wattage
data.uptime = total_uptime_mins
data.voltage = 0
for board in data.hashboards:
data.voltage += board.voltage
return data return data
@@ -177,7 +172,6 @@ class GoldshellByte(GoldshellMiner, Byte):
if rpc_devs is not None: if rpc_devs is not None:
for board in rpc_devs.get("DEVS", []): for board in rpc_devs.get("DEVS", []):
algo_name = board.get("pool") algo_name = board.get("pool")
if algo_name == ALGORITHM_SCRYPT_NAME: if algo_name == ALGORITHM_SCRYPT_NAME:
@@ -317,3 +311,39 @@ class GoldshellByte(GoldshellMiner, Byte):
fans = [Fan(speed=d) if d else Fan() for d in fans_data] fans = [Fan(speed=d) if d else Fan() for d in fans_data]
return fans return fans
async def _get_uptime(self, web_devs: dict = None) -> Optional[int]:
if web_devs is None:
try:
web_devs = await self.web.devs()
except APIError:
pass
if web_devs is not None:
try:
for minfo in self.web_devs.get("minfos", []):
for info in minfo.get("infos", []):
uptime = int(float(info["time"]))
return uptime
except KeyError:
pass
return None
async def _get_wattage(self, web_devs: dict = None) -> Optional[int]:
if web_devs is None:
try:
web_devs = await self.web.devs()
except APIError:
pass
if web_devs is not None:
try:
for minfo in self.web_devs.get("minfos", []):
for info in minfo.get("infos", []):
wattage = int(float(info["power"]))
return wattage
except KeyError:
pass
return None

View File

@@ -0,0 +1,16 @@
# ------------------------------------------------------------------------------
# Copyright 2025 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 .mini_doge import GoldshellMiniDoge

View File

@@ -0,0 +1,179 @@
# ------------------------------------------------------------------------------
# Copyright 2025 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 typing import List, Optional
from pyasic.config import MinerConfig
from pyasic.data.boards import HashBoard
from pyasic.device.algorithm import AlgoHashRate
from pyasic.errors import APIError
from pyasic.logger import logger
from pyasic.miners.backends import GoldshellMiner
from pyasic.miners.data import (
DataFunction,
DataLocations,
DataOptions,
RPCAPICommand,
WebAPICommand,
)
from pyasic.miners.device.models import MiniDoge
GOLDSHELL_MINI_DOGE_DATA_LOC = DataLocations(
**{
str(DataOptions.MAC): DataFunction(
"_get_mac",
[WebAPICommand("web_setting", "setting")],
),
str(DataOptions.API_VERSION): DataFunction(
"_get_api_ver",
[RPCAPICommand("rpc_version", "version")],
),
str(DataOptions.FW_VERSION): DataFunction(
"_get_fw_ver",
[WebAPICommand("web_status", "status")],
),
str(DataOptions.HASHRATE): DataFunction(
"_get_hashrate",
[RPCAPICommand("rpc_summary", "summary")],
),
str(DataOptions.EXPECTED_HASHRATE): DataFunction(
"_get_expected_hashrate",
[RPCAPICommand("rpc_devs", "devs")],
),
str(DataOptions.HASHBOARDS): DataFunction(
"_get_hashboards",
[
RPCAPICommand("rpc_devs", "devs"),
RPCAPICommand("rpc_devdetails", "devdetails"),
],
),
str(DataOptions.FANS): DataFunction(
"_get_fans",
[RPCAPICommand("rpc_stats", "stats")],
),
str(DataOptions.POOLS): DataFunction(
"_get_pools",
[RPCAPICommand("rpc_pools", "pools")],
),
str(DataOptions.UPTIME): DataFunction(
"_get_uptime",
[WebAPICommand("web_devs", "devs")],
),
}
)
class GoldshellMiniDoge(GoldshellMiner, MiniDoge):
data_locations = GOLDSHELL_MINI_DOGE_DATA_LOC
supports_shutdown = False
supports_power_modes = False
async def get_config(self) -> MinerConfig:
try:
pools = await self.web.pools()
except APIError:
return self.config
self.config = MinerConfig.from_goldshell_list(pools)
return self.config
async def _get_expected_hashrate(
self, rpc_devs: dict = None
) -> Optional[AlgoHashRate]:
if rpc_devs is None:
try:
rpc_devs = await self.rpc.devs()
except APIError:
pass
if rpc_devs is not None:
try:
hash_rate = rpc_devs["DEVS"][0]["estimate_hash_rate"]
return self.algo.hashrate(
rate=float(hash_rate), unit=self.algo.unit.H
).into(self.algo.unit.default)
except KeyError:
pass
return None
async def _get_hashboards(
self, rpc_devs: dict = None, rpc_devdetails: dict = None
) -> List[HashBoard]:
if rpc_devs is None:
try:
rpc_devs = await self.rpc.devs()
except APIError:
pass
hashboards = [
HashBoard(slot=i, expected_chips=self.expected_chips)
for i in range(self.expected_hashboards)
]
if rpc_devs is not None:
if rpc_devs.get("DEVS"):
for board in rpc_devs["DEVS"]:
if board.get("ID") is not None:
try:
b_id = board["ID"]
hashboards[b_id].hashrate = self.algo.hashrate(
rate=float(board["MHS 20s"]), unit=self.algo.unit.MH
).into(self.algo.unit.default)
hashboards[b_id].chip_temp = board["tstemp-0"]
hashboards[b_id].temp = board["tstemp-1"]
hashboards[b_id].voltage = board["voltage"]
hashboards[b_id].active = board["Status"] == "Alive"
hashboards[b_id].missing = False
except KeyError:
pass
else:
logger.error(self, rpc_devs)
if rpc_devdetails is None:
try:
rpc_devdetails = await self.rpc.devdetails()
except APIError:
pass
if rpc_devdetails is not None:
if rpc_devdetails.get("DEVS"):
for board in rpc_devdetails["DEVS"]:
if board.get("ID") is not None:
try:
b_id = board["ID"]
hashboards[b_id].chips = board["chips-nr"]
except KeyError:
pass
else:
logger.error(self, rpc_devdetails)
return hashboards
async def _get_uptime(self, web_devs: dict = None) -> Optional[int]:
if web_devs is None:
try:
web_devs = await self.web.devs()
except APIError:
pass
if web_devs is not None:
try:
uptime = int(web_devs["data"][0]["time"])
return uptime
except KeyError:
pass
return None

View File

@@ -253,10 +253,10 @@ If you are sure you want to use this command please use API.send_command("{comma
# some json from the API returns with a null byte (\x00) on the end # some json from the API returns with a null byte (\x00) on the end
if data.endswith(b"\x00"): if data.endswith(b"\x00"):
# handle the null byte # handle the null byte
str_data = data.decode("utf-8")[:-1] str_data = data.decode("utf-8", errors="replace")[:-1]
else: else:
# no null byte # no null byte
str_data = data.decode("utf-8") str_data = data.decode("utf-8", errors="replace")
# fix an error with a btminer return having an extra comma that breaks json.loads() # fix an error with a btminer return having an extra comma that breaks json.loads()
str_data = str_data.replace(",}", "}") str_data = str_data.replace(",}", "}")
# fix an error with a btminer return having a newline that breaks json.loads() # fix an error with a btminer return having a newline that breaks json.loads()

View File

@@ -23,6 +23,7 @@ import json
import logging import logging
import re import re
import struct import struct
import warnings
from asyncio import Future, StreamReader, StreamWriter from asyncio import Future, StreamReader, StreamWriter
from typing import Any, AsyncGenerator, Callable, Literal, Union from typing import Any, AsyncGenerator, Callable, Literal, Union
@@ -31,7 +32,7 @@ from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from passlib.handlers.md5_crypt import md5_crypt from passlib.handlers.md5_crypt import md5_crypt
from pyasic import settings from pyasic import settings
from pyasic.errors import APIError from pyasic.errors import APIError, APIWarning
from pyasic.misc import api_min_version, validate_command_output from pyasic.misc import api_min_version, validate_command_output
from pyasic.rpc.base import BaseMinerRPCAPI from pyasic.rpc.base import BaseMinerRPCAPI
@@ -251,13 +252,13 @@ class BTMinerRPCAPI(BaseMinerRPCAPI):
except APIError as e: except APIError as e:
if not e.message == "can't access write cmd": if not e.message == "can't access write cmd":
raise raise
try: # try:
await self.open_api() # await self.open_api()
except Exception as e: # except Exception as e:
raise APIError("Failed to open whatsminer API.") from e # raise APIError("Failed to open whatsminer API.") from e
return await self._send_privileged_command( # return await self._send_privileged_command(
command=command, ignore_errors=ignore_errors, timeout=timeout, **kwargs # command=command, ignore_errors=ignore_errors, timeout=timeout, **kwargs
) # )
async def _send_privileged_command( async def _send_privileged_command(
self, self,
@@ -292,6 +293,7 @@ class BTMinerRPCAPI(BaseMinerRPCAPI):
try: try:
data = parse_btminer_priviledge_data(self.token, data) data = parse_btminer_priviledge_data(self.token, data)
print(data)
except Exception as e: except Exception as e:
logging.info(f"{str(self.ip)}: {e}") logging.info(f"{str(self.ip)}: {e}")
@@ -1107,39 +1109,28 @@ class BTMinerV3RPCAPI(BaseMinerRPCAPI):
def __init__(self, ip: str, port: int = 4433, api_ver: str = "0.0.0"): def __init__(self, ip: str, port: int = 4433, api_ver: str = "0.0.0"):
super().__init__(ip, port, api_ver=api_ver) super().__init__(ip, port, api_ver=api_ver)
self.reader: StreamReader | None = None
self.writer: StreamWriter | None = None
self.reader_loop = None
self.salt = None self.salt = None
self.pwd = "super"
self.cmd_results = {} async def multicommand(self, *commands: str, allow_warning: bool = True) -> dict:
self.cmd_callbacks = {"get.miner.report": set()} """Creates and sends multiple commands as one command to the miner.
async def connect(self): Parameters:
self.reader, self.writer = await asyncio.open_connection( *commands: The commands to send as a multicommand to the miner.
str(self.ip), self.port allow_warning: A boolean to supress APIWarnings.
)
self.reader_loop = asyncio.create_task(self._read_loop())
async def disconnect(self): """
self.writer.close() commands = self._check_commands(*commands)
await self.writer.wait_closed() data = await self._send_split_multicommand(*commands)
self.reader_loop.cancel() data["multicommand"] = True
return data
async def send_command( async def send_command(
self, command: str, parameters: Any = None, **kwargs self, command: str, parameters: Any = None, **kwargs
) -> dict: ) -> dict:
if self.writer is None: if ":" in command:
await self.connect() parameters = command.split(":")[1]
command = command.split(":")[0]
while command in self.cmd_results:
wait_fut = self.cmd_results[command]
await wait_fut
result_fut = Future()
self.cmd_results[command] = result_fut
cmd = {"cmd": command} cmd = {"cmd": command}
if parameters is not None: if parameters is not None:
cmd["param"] = parameters cmd["param"] = parameters
@@ -1152,40 +1143,89 @@ class BTMinerV3RPCAPI(BaseMinerRPCAPI):
token_hashed = bytearray( token_hashed = bytearray(
base64.b64encode(hashlib.sha256(token_str.encode("utf-8")).digest()) base64.b64encode(hashlib.sha256(token_str.encode("utf-8")).digest())
) )
token_hashed[8] = 0 b_arr = bytearray(token_hashed)
b_arr[8] = 0
str_token = b_arr.split(b"\x00")[0].decode("utf-8")
cmd["account"] = "super" cmd["account"] = "super"
cmd["token"] = token_hashed.decode("ascii") cmd["token"] = str_token
# send the command # send the command
ser = json.dumps(cmd).encode("utf-8") ser = json.dumps(cmd).encode("utf-8")
header = struct.pack("<I", len(ser)) header = struct.pack("<I", len(ser))
await self._send_bytes(header + json.dumps(cmd).encode("utf-8")) return json.loads(
await self._send_bytes(header + json.dumps(cmd).encode("utf-8"))
)
await result_fut async def _send_bytes(
return result_fut.result() self,
data: bytes,
*,
port: int = None,
timeout: int = 100,
) -> bytes:
if port is None:
port = self.port
logging.debug(f"{self} - ([Hidden] Send Bytes) - Sending")
try:
# get reader and writer streams
reader, writer = await asyncio.open_connection(str(self.ip), port)
# handle OSError 121
except OSError as e:
if e.errno == 121:
logging.warning(
f"{self} - ([Hidden] Send Bytes) - Semaphore timeout expired."
)
return b"{}"
async def _read_loop(self): # send the command
while True: try:
result = await self._read_bytes() data_task = asyncio.create_task(self._read_bytes(reader, timeout=timeout))
data = self._load_api_data(result) logging.debug(f"{self} - ([Hidden] Send Bytes) - Writing")
command = data["desc"] writer.write(data)
if command in self.cmd_callbacks: logging.debug(f"{self} - ([Hidden] Send Bytes) - Draining")
callbacks: list[Callable] = self.cmd_callbacks[command] await writer.drain()
await asyncio.gather(*[callback(data) for callback in callbacks])
elif command in self.cmd_results: await data_task
future: Future = self.cmd_results.pop(command) ret_data = data_task.result()
future.set_result(data) except TimeoutError:
logging.warning(f"{self} - ([Hidden] Send Bytes) - Read timeout expired.")
return b"{}"
# close the connection
logging.debug(f"{self} - ([Hidden] Send Bytes) - Closing")
writer.close()
await writer.wait_closed()
return ret_data
def _check_commands(self, *commands) -> list:
return_commands = []
for command in commands:
if command.startswith("get.") or command.startswith("set."):
return_commands.append(command)
else: else:
logging.error(f"Received unexpected data for {self}: {data}") warnings.warn(
f"""Removing incorrect command: {command}
If you are sure you want to use this command please use API.send_command("{command}", ignore_errors=True) instead.""",
APIWarning,
)
return return_commands
async def _read_bytes(self, **kwargs) -> bytes: async def _read_bytes(self, reader: asyncio.StreamReader, timeout: int) -> bytes:
header = await self.reader.readexactly(4) ret_data = b""
length = struct.unpack("<I", header)[0]
return await self.reader.readexactly(length)
async def _send_bytes(self, data: bytes, **kwargs): # loop to receive all the data
self.writer.write(data) logging.debug(f"{self} - ([Hidden] Send Bytes) - Receiving")
await self.writer.drain() try:
header = await reader.readexactly(4)
length = struct.unpack("<I", header)[0]
ret_data = await reader.readexactly(length)
except (asyncio.CancelledError, asyncio.TimeoutError) as e:
raise e
except Exception as e:
logging.warning(f"{self} - ([Hidden] Send Bytes) - API Command Error {e}")
return ret_data
async def get_salt(self) -> str: async def get_salt(self) -> str:
if self.salt is not None: if self.salt is not None:
@@ -1223,6 +1263,9 @@ class BTMinerV3RPCAPI(BaseMinerRPCAPI):
async def get_miner_status_edevs(self) -> dict | None: async def get_miner_status_edevs(self) -> dict | None:
return await self.send_command("get.miner.status", parameters="edevs") return await self.send_command("get.miner.status", parameters="edevs")
async def get_miner_status_pools(self) -> dict | None:
return await self.send_command("get.miner.status", parameters="pools")
async def get_miner_history(self) -> dict | None: async def get_miner_history(self) -> dict | None:
data = await self.send_command( data = await self.send_command(
"get.miner.history", "get.miner.history",

View File

@@ -62,7 +62,6 @@ class AntminerModernWebAPI(BaseWebAPI):
auth = httpx.DigestAuth(self.username, self.pwd) auth = httpx.DigestAuth(self.username, self.pwd)
try: try:
async with httpx.AsyncClient(transport=settings.transport()) as client: async with httpx.AsyncClient(transport=settings.transport()) as client:
if parameters: if parameters:
data = await client.post( data = await client.post(
url, url,

View File

@@ -84,13 +84,13 @@ class BOSerWebAPI(BaseWebAPI):
except AttributeError: except AttributeError:
pass pass
await asyncio.gather(*[t for t in tasks.values()], return_exceptions=True) results = await asyncio.gather(
*[t for t in tasks.values()], return_exceptions=True
)
for cmd in tasks: for cmd, task_result in zip(tasks.keys(), results):
try: if not isinstance(task_result, (GRPCError, APIError, ConnectionError)):
result[cmd] = await tasks[cmd] result[cmd] = task_result
except (GRPCError, APIError, ConnectionError):
pass
return result return result

View File

@@ -52,7 +52,6 @@ class ApiVersionServiceStub(betterproto.ServiceStub):
class ApiVersionServiceBase(ServiceBase): class ApiVersionServiceBase(ServiceBase):
async def get_api_version( async def get_api_version(
self, api_version_request: "ApiVersionRequest" self, api_version_request: "ApiVersionRequest"
) -> "ApiVersion": ) -> "ApiVersion":

View File

@@ -2485,7 +2485,6 @@ class NetworkServiceStub(betterproto.ServiceStub):
class ActionsServiceBase(ServiceBase): class ActionsServiceBase(ServiceBase):
async def start(self, start_request: "StartRequest") -> "StartResponse": async def start(self, start_request: "StartRequest") -> "StartResponse":
raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED) raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)
@@ -2630,7 +2629,6 @@ class ActionsServiceBase(ServiceBase):
class AuthenticationServiceBase(ServiceBase): class AuthenticationServiceBase(ServiceBase):
async def login(self, login_request: "LoginRequest") -> "LoginResponse": async def login(self, login_request: "LoginRequest") -> "LoginResponse":
raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED) raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)
@@ -2671,7 +2669,6 @@ class AuthenticationServiceBase(ServiceBase):
class CoolingServiceBase(ServiceBase): class CoolingServiceBase(ServiceBase):
async def get_cooling_state( async def get_cooling_state(
self, get_cooling_state_request: "GetCoolingStateRequest" self, get_cooling_state_request: "GetCoolingStateRequest"
) -> "GetCoolingStateResponse": ) -> "GetCoolingStateResponse":
@@ -2716,7 +2713,6 @@ class CoolingServiceBase(ServiceBase):
class PerformanceServiceBase(ServiceBase): class PerformanceServiceBase(ServiceBase):
async def get_tuner_state( async def get_tuner_state(
self, get_tuner_state_request: "GetTunerStateRequest" self, get_tuner_state_request: "GetTunerStateRequest"
) -> "GetTunerStateResponse": ) -> "GetTunerStateResponse":
@@ -2986,7 +2982,6 @@ class PerformanceServiceBase(ServiceBase):
class PoolServiceBase(ServiceBase): class PoolServiceBase(ServiceBase):
async def get_pool_groups( async def get_pool_groups(
self, get_pool_groups_request: "GetPoolGroupsRequest" self, get_pool_groups_request: "GetPoolGroupsRequest"
) -> "GetPoolGroupsResponse": ) -> "GetPoolGroupsResponse":
@@ -3088,7 +3083,6 @@ class PoolServiceBase(ServiceBase):
class ConfigurationServiceBase(ServiceBase): class ConfigurationServiceBase(ServiceBase):
async def get_miner_configuration( async def get_miner_configuration(
self, get_miner_configuration_request: "GetMinerConfigurationRequest" self, get_miner_configuration_request: "GetMinerConfigurationRequest"
) -> "GetMinerConfigurationResponse": ) -> "GetMinerConfigurationResponse":
@@ -3133,7 +3127,6 @@ class ConfigurationServiceBase(ServiceBase):
class LicenseServiceBase(ServiceBase): class LicenseServiceBase(ServiceBase):
async def get_license_state( async def get_license_state(
self, get_license_state_request: "GetLicenseStateRequest" self, get_license_state_request: "GetLicenseStateRequest"
) -> "GetLicenseStateResponse": ) -> "GetLicenseStateResponse":
@@ -3159,7 +3152,6 @@ class LicenseServiceBase(ServiceBase):
class MinerServiceBase(ServiceBase): class MinerServiceBase(ServiceBase):
async def get_miner_status( async def get_miner_status(
self, get_miner_status_request: "GetMinerStatusRequest" self, get_miner_status_request: "GetMinerStatusRequest"
) -> AsyncIterator[GetMinerStatusResponse]: ) -> AsyncIterator[GetMinerStatusResponse]:
@@ -3325,7 +3317,6 @@ class MinerServiceBase(ServiceBase):
class NetworkServiceBase(ServiceBase): class NetworkServiceBase(ServiceBase):
async def get_network_configuration( async def get_network_configuration(
self, get_network_configuration_request: "GetNetworkConfigurationRequest" self, get_network_configuration_request: "GetNetworkConfigurationRequest"
) -> "GetNetworkConfigurationResponse": ) -> "GetNetworkConfigurationResponse":

View File

@@ -60,7 +60,6 @@ class ElphapexWebAPI(BaseWebAPI):
auth = httpx.DigestAuth(self.username, self.pwd) auth = httpx.DigestAuth(self.username, self.pwd)
try: try:
async with httpx.AsyncClient(transport=settings.transport()) as client: async with httpx.AsyncClient(transport=settings.transport()) as client:
if parameters: if parameters:
data = await client.post( data = await client.post(
url, url,
@@ -121,18 +120,28 @@ class ElphapexWebAPI(BaseWebAPI):
""" """
auth = httpx.DigestAuth(self.username, self.pwd) auth = httpx.DigestAuth(self.username, self.pwd)
try: async def _send():
url = f"http://{self.ip}/cgi-bin/{command}.cgi" try:
ret = await client.get(url, auth=auth) url = f"http://{self.ip}/cgi-bin/{command}.cgi"
except httpx.HTTPError: ret = await client.get(url, auth=auth)
pass except httpx.HTTPError:
else: pass
if ret.status_code == 200: else:
try: if ret.status_code == 200:
json_data = ret.json() try:
return {command: json_data} json_data = ret.json()
except json.decoder.JSONDecodeError: if json_data.get("STATUS", {}).get("STATUS") not in ["S", "I"]:
pass return None
return {command: json_data}
except json.decoder.JSONDecodeError:
pass
return None
# retry 3 times
for i in range(3):
res = await _send()
if res is not None:
return res
return {command: {}} return {command: {}}
async def get_miner_conf(self) -> dict: async def get_miner_conf(self) -> dict:

View File

@@ -103,8 +103,12 @@ class GoldshellWebAPI(BaseWebAPI):
async with httpx.AsyncClient(transport=settings.transport()) as client: async with httpx.AsyncClient(transport=settings.transport()) as client:
for command in commands: for command in commands:
try: try:
uri_commnand = command
if command == "devs":
uri_commnand = "cgminer?cgminercmd=devs"
response = await client.get( response = await client.get(
f"http://{self.ip}:{self.port}/mcb/{command}", f"http://{self.ip}:{self.port}/mcb/{uri_commnand}",
headers={"Authorization": "Bearer " + self.token}, headers={"Authorization": "Bearer " + self.token},
timeout=settings.get("api_function_timeout", 5), timeout=settings.get("api_function_timeout", 5),
) )
@@ -143,3 +147,6 @@ class GoldshellWebAPI(BaseWebAPI):
async def status(self) -> dict: async def status(self) -> dict:
return await self.send_command("status") return await self.send_command("status")
async def devs(self) -> dict:
return await self.send_command("cgminer?cgminercmd=devs")

View File

@@ -60,7 +60,6 @@ class HammerWebAPI(BaseWebAPI):
auth = httpx.DigestAuth(self.username, self.pwd) auth = httpx.DigestAuth(self.username, self.pwd)
try: try:
async with httpx.AsyncClient(transport=settings.transport()) as client: async with httpx.AsyncClient(transport=settings.transport()) as client:
if parameters: if parameters:
data = await client.post( data = await client.post(
url, url,

View File

@@ -1,6 +1,6 @@
[project] [project]
name = "pyasic" name = "pyasic"
version = "0.75.2" version = "0.76.8"
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"}]
@@ -52,6 +52,7 @@ dependencies = [
"aiofiles>=23.2.1", "aiofiles>=23.2.1",
"betterproto==2.0.0b7", "betterproto==2.0.0b7",
"pydantic>=2.11.0", "pydantic>=2.11.0",
"semver (>=3.0.4,<4.0.0)",
] ]
[tool.poetry.group.dev] [tool.poetry.group.dev]

View File

@@ -33,10 +33,7 @@ class MinersTest(unittest.TestCase):
miner_type=miner_type, miner_type=miner_type,
miner_model=miner_model, miner_model=miner_model,
): ):
miner = MINER_CLASSES[miner_type][miner_model]("127.0.0.1") MINER_CLASSES[miner_type][miner_model]("127.0.0.1")
self.assertTrue(
isinstance(miner, MINER_CLASSES[miner_type][miner_model])
)
def test_miner_has_hashboards(self): def test_miner_has_hashboards(self):
warnings.filterwarnings("ignore") warnings.filterwarnings("ignore")