Compare commits

...

42 Commits

Author SHA1 Message Date
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
Brett Rowan
076958ec0e version: bump version number 2025-08-15 12:39:04 -06:00
Brett Rowan
5319089ebe feature: fix S21+ hydro for cases where there is no . at the end 2025-08-15 12:38:17 -06:00
Brett Rowan
76a77b51e8 version: bump version number 2025-08-14 13:25:26 -06:00
Brett Rowan
b099ff45d2 bug: remove print statements 2025-08-14 13:25:05 -06:00
Brett Rowan
9bc3cc221a version: bump version number 2025-08-14 11:41:50 -06:00
Brett Rowan
6418c2e102 feature: add BTMinerV3 control support 2025-08-14 11:41:08 -06:00
Brett Rowan
aa9f3b2c45 feature: add BTMinerV3 data support 2025-08-14 11:41:08 -06:00
Ryan Heideman
bb1c98f061 Goldshell Byte Support (#366) 2025-08-12 21:53:28 -06:00
Brett Rowan
d984431fe5 version: bump version number 2025-08-08 11:46:46 -06:00
Tony Scelfo
f1e4feb91e add expected chips for BraiinsModels BM100 and BM101 2025-08-08 11:45:43 -06:00
Brett Rowan
90c8986900 version: bump version number 2025-07-23 11:56:21 -06:00
Brett Rowan
5457ae6cd5 feature: add support for avalon Q 2025-07-23 11:55:57 -06:00
Brett Rowan
aa3d105fcb version: bump version number 2025-07-21 15:41:35 -06:00
Brett Rowan
77f59f6db6 feature: add support for Elphapex DG1 Home
Fixes: #311
2025-07-21 10:08:11 -06:00
Brett Rowan
3fa0d96fbb feature: add support for Iceriver AL3
Fixes: #317
2025-07-21 10:02:06 -06:00
Brett Rowan
e55477a8b8 feature: add support for S19j+
Fixes: #330
2025-07-21 09:51:51 -06:00
Brett Rowan
7d5744ae28 feature: add support for vnish XP Hydro
Fixes: #342
2025-07-21 09:48:11 -06:00
Brett Rowan
d4500be10c feature: add support for a couple alternate models
- Antminer S19j Pro+, ANTMINER
 - Antminer S19 Pro A, VNISH
 - Antminer S19 XP, VNISH
 - Antminer L9, VNISH
 - DG1, ELPHAPEX

 Fixes: #354
2025-07-21 09:35:00 -06:00
Brett Rowan
7ef2540133 feature: add support for Vnish S19 Hydro
Fixes: #355
2025-07-21 09:18:20 -06:00
Brett Rowan
1ea4f4e124 version: bump version number 2025-07-15 08:11:34 -06:00
bbemoll
a8a0e4a5fe Added support for Antminer S19XH Hydro running on Braiins OS (#353)
* Add pyasic files

* Add pyasic files

* Update pyproject.toml

* Update pyproject.toml

* Added support for Antminer S19XP Hydro running on Braiins OS

* [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-07-15 08:10:59 -06:00
Brett Rowan
5f2f6e01da version: bump version number 2025-07-10 10:56:42 -06:00
Brody
41b4c23d45 Fix API Issue with Bitaxe Miners (#352)
* added checks to identify which field is None.

* better logging

* if asicCount is None, try to find it in /system/asic

* ran pre-commit
2025-07-10 10:56:22 -06:00
Brett Rowan
b4687f18fd version: bump version number 2025-05-01 15:15:42 -06:00
Brett Rowan
2437421005 feature: add support for a bunch of BOS and VNish S21 models. 2025-05-01 15:15:18 -06:00
Ryan Heideman
40ebc2773f Retry and Timeout Changes for espminer (#340)
* Retry and Timeout Fixes for espminer

* Build check fix
2025-05-01 15:07:58 -06:00
Art
b8ae238d23 Fix incorrect computation of active_preset for Antminer VNish. See #338. (#339)
* Fix incorrect computation of active_preset for Antminer VNish. See #338.

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

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

* #338 renamed perf_summary to web_perf_summary for clarity and consistency. New API call is done in backward compatibility manner. Data is also retrieved safely

* [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-05-01 15:07:11 -06:00
Brett Rowan
2920639b70 version: bump version number 2025-04-27 11:01:10 -06:00
Brett Rowan
bd9144b3de requirements: bump dependency versions 2025-04-27 11:01:10 -06:00
SKART1
8f7a67d4dc Fix efficiency_fract property to correctly return computed value. See #334. 2025-04-19 08:28:44 -06:00
Brett Rowan
a62bea33a7 docs: update docs 2025-04-18 16:15:31 -06:00
pre-commit-ci[bot]
406bcd179c [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
2025-04-18 16:12:55 -06:00
Ryan Heideman
aa87ef7d71 nano3s fixes 2025-04-18 16:12:55 -06:00
SKART1
ec88fbf6aa Fix #334 efficiency calculation and add computed fields 2025-04-18 16:12:44 -06:00
pre-commit-ci[bot]
e23c86a944 [pre-commit.ci] pre-commit autoupdate
updates:
- [github.com/python-poetry/poetry: 2.1.1 → 2.1.2](https://github.com/python-poetry/poetry/compare/2.1.1...2.1.2)
2025-04-16 08:41:30 -06:00
Brett Rowan
b81276cb19 version: bump version number 2025-04-16 08:40:36 -06:00
Adrian
8dcc72b1bb T21 working on LuxOS (#331) 2025-04-14 12:55:54 -06:00
Timur Taipov
540572356f feature: add support for S21+ hydro (#326) 2025-04-14 09:15:06 -06:00
Ryan Heideman
83035a869b feature: Add Support for Avalon Nano 3s (#329) 2025-04-12 15:34:45 -06:00
107 changed files with 3427 additions and 883 deletions

1
.gitignore vendored
View File

@@ -7,3 +7,4 @@ pyvenv.cfg
bin/ bin/
lib/ lib/
.idea/ .idea/
.vs/

View File

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

View File

@@ -23,7 +23,7 @@ Welcome to `pyasic`! `pyasic` uses an asynchronous method of communicating with
## Installation ## Installation
It is recommended to install `pyasic` in a [virtual environment](https://realpython.com/python-virtual-environments-a-primer/#what-other-popular-options-exist-aside-from-venv) to isolate it from the rest of your system. Options include: It is recommended to install `pyasic` in a [virtual environment](https://realpython.com/python-virtual-environments-a-primer/#what-other-popular-options-exist-aside-from-venv) to isolate it from the rest of your system. Options include:
- [pypoetry](https://python-poetry.org/): the reccommended way, since pyasic already uses it by default - [pypoetry](https://python-poetry.org/): the reccommended way, since pyasic already uses it by default. Use version 2.0+
``` ```
poetry install poetry install

View File

@@ -157,6 +157,19 @@
show_root_heading: false show_root_heading: false
heading_level: 0 heading_level: 0
## S19j Pro+ (Stock)
- [x] Shutdowns
- [x] Power Modes
- [ ] Setpoints
- [ ] Presets
::: pyasic.miners.antminer.bmminer.X19.S19.BMMinerS19jProPlus
handler: python
options:
show_root_heading: false
heading_level: 0
## S19j XP (Stock) ## S19j XP (Stock)
- [x] Shutdowns - [x] Shutdowns
@@ -170,6 +183,19 @@
show_root_heading: false show_root_heading: false
heading_level: 0 heading_level: 0
## S19j+ (Stock)
- [x] Shutdowns
- [x] Power Modes
- [ ] Setpoints
- [ ] Presets
::: pyasic.miners.antminer.bmminer.X19.S19.BMMinerS19jPlus
handler: python
options:
show_root_heading: false
heading_level: 0
## S19j No PIC (Stock) ## S19j No PIC (Stock)
- [x] Shutdowns - [x] Shutdowns
@@ -287,6 +313,19 @@
show_root_heading: false show_root_heading: false
heading_level: 0 heading_level: 0
## S19 XP Hydro (BOS+)
- [x] Shutdowns
- [ ] Power Modes
- [x] Setpoints
- [ ] Presets
::: pyasic.miners.antminer.bosminer.X19.S19.BOSMinerS19XPHydro
handler: python
options:
show_root_heading: false
heading_level: 0
## S19+ (BOS+) ## S19+ (BOS+)
- [x] Shutdowns - [x] Shutdowns
@@ -443,6 +482,19 @@
show_root_heading: false show_root_heading: false
heading_level: 0 heading_level: 0
## S19 Hydro (VNish)
- [x] Shutdowns
- [ ] Power Modes
- [x] Setpoints
- [x] Presets
::: pyasic.miners.antminer.vnish.X19.S19.VNishS19Hydro
handler: python
options:
show_root_heading: false
heading_level: 0
## S19 Pro (VNish) ## S19 Pro (VNish)
- [x] Shutdowns - [x] Shutdowns
@@ -456,6 +508,19 @@
show_root_heading: false show_root_heading: false
heading_level: 0 heading_level: 0
## S19 Pro A (VNish)
- [x] Shutdowns
- [ ] Power Modes
- [x] Setpoints
- [x] Presets
::: pyasic.miners.antminer.vnish.X19.S19.VNishS19ProA
handler: python
options:
show_root_heading: false
heading_level: 0
## S19 Pro Hydro (VNish) ## S19 Pro Hydro (VNish)
- [x] Shutdowns - [x] Shutdowns
@@ -469,6 +534,32 @@
show_root_heading: false show_root_heading: false
heading_level: 0 heading_level: 0
## S19 XP (VNish)
- [x] Shutdowns
- [ ] Power Modes
- [x] Setpoints
- [x] Presets
::: pyasic.miners.antminer.vnish.X19.S19.VNishS19XP
handler: python
options:
show_root_heading: false
heading_level: 0
## S19 XP Hydro (VNish)
- [x] Shutdowns
- [ ] Power Modes
- [x] Setpoints
- [x] Presets
::: pyasic.miners.antminer.vnish.X19.S19.VNishS19XPHydro
handler: python
options:
show_root_heading: false
heading_level: 0
## S19a (VNish) ## S19a (VNish)
- [x] Shutdowns - [x] Shutdowns
@@ -759,7 +850,7 @@
- [x] Shutdowns - [x] Shutdowns
- [ ] Power Modes - [ ] Power Modes
- [ ] Setpoints - [x] Setpoints
- [x] Presets - [x] Presets
::: pyasic.miners.antminer.luxos.X19.S19.LUXMinerS19 ::: pyasic.miners.antminer.luxos.X19.S19.LUXMinerS19
@@ -772,7 +863,7 @@
- [x] Shutdowns - [x] Shutdowns
- [ ] Power Modes - [ ] Power Modes
- [ ] Setpoints - [x] Setpoints
- [x] Presets - [x] Presets
::: pyasic.miners.antminer.luxos.X19.S19.LUXMinerS19Pro ::: pyasic.miners.antminer.luxos.X19.S19.LUXMinerS19Pro
@@ -785,7 +876,7 @@
- [x] Shutdowns - [x] Shutdowns
- [ ] Power Modes - [ ] Power Modes
- [ ] Setpoints - [x] Setpoints
- [x] Presets - [x] Presets
::: pyasic.miners.antminer.luxos.X19.S19.LUXMinerS19XP ::: pyasic.miners.antminer.luxos.X19.S19.LUXMinerS19XP
@@ -798,7 +889,7 @@
- [x] Shutdowns - [x] Shutdowns
- [ ] Power Modes - [ ] Power Modes
- [ ] Setpoints - [x] Setpoints
- [x] Presets - [x] Presets
::: pyasic.miners.antminer.luxos.X19.S19.LUXMinerS19jPro ::: pyasic.miners.antminer.luxos.X19.S19.LUXMinerS19jPro
@@ -811,7 +902,7 @@
- [x] Shutdowns - [x] Shutdowns
- [ ] Power Modes - [ ] Power Modes
- [ ] Setpoints - [x] Setpoints
- [x] Presets - [x] Presets
::: pyasic.miners.antminer.luxos.X19.S19.LUXMinerS19jProPlus ::: pyasic.miners.antminer.luxos.X19.S19.LUXMinerS19jProPlus
@@ -824,7 +915,7 @@
- [x] Shutdowns - [x] Shutdowns
- [ ] Power Modes - [ ] Power Modes
- [ ] Setpoints - [x] Setpoints
- [x] Presets - [x] Presets
::: pyasic.miners.antminer.luxos.X19.S19.LUXMinerS19kPro ::: pyasic.miners.antminer.luxos.X19.S19.LUXMinerS19kPro
@@ -837,7 +928,7 @@
- [x] Shutdowns - [x] Shutdowns
- [ ] Power Modes - [ ] Power Modes
- [ ] Setpoints - [x] Setpoints
- [x] Presets - [x] Presets
::: pyasic.miners.antminer.luxos.X19.T19.LUXMinerT19 ::: pyasic.miners.antminer.luxos.X19.T19.LUXMinerT19

View File

@@ -53,6 +53,19 @@
show_root_heading: false show_root_heading: false
heading_level: 0 heading_level: 0
## S21+ Hydro (Stock)
- [x] Shutdowns
- [x] Power Modes
- [ ] Setpoints
- [ ] Presets
::: pyasic.miners.antminer.bmminer.X21.S21.BMMinerS21PlusHydro
handler: python
options:
show_root_heading: false
heading_level: 0
## T21 (Stock) ## T21 (Stock)
- [x] Shutdowns - [x] Shutdowns
@@ -79,6 +92,19 @@
show_root_heading: false show_root_heading: false
heading_level: 0 heading_level: 0
## S21 Hydro (BOS+)
- [x] Shutdowns
- [ ] Power Modes
- [x] Setpoints
- [ ] Presets
::: pyasic.miners.antminer.bosminer.X21.S21.BOSMinerS21Hydro
handler: python
options:
show_root_heading: false
heading_level: 0
## S21 Pro (BOS+) ## S21 Pro (BOS+)
- [x] Shutdowns - [x] Shutdowns
@@ -92,6 +118,32 @@
show_root_heading: false show_root_heading: false
heading_level: 0 heading_level: 0
## S21+ (BOS+)
- [x] Shutdowns
- [ ] Power Modes
- [x] Setpoints
- [ ] Presets
::: pyasic.miners.antminer.bosminer.X21.S21.BOSMinerS21Plus
handler: python
options:
show_root_heading: false
heading_level: 0
## S21+ Hydro (BOS+)
- [x] Shutdowns
- [ ] Power Modes
- [x] Setpoints
- [ ] Presets
::: pyasic.miners.antminer.bosminer.X21.S21.BOSMinerS21PlusHydro
handler: python
options:
show_root_heading: false
heading_level: 0
## T21 (BOS+) ## T21 (BOS+)
- [x] Shutdowns - [x] Shutdowns
@@ -118,6 +170,58 @@
show_root_heading: false show_root_heading: false
heading_level: 0 heading_level: 0
## S21 Hydro (VNish)
- [x] Shutdowns
- [ ] Power Modes
- [x] Setpoints
- [x] Presets
::: pyasic.miners.antminer.vnish.X21.S21.VNishS21Hydro
handler: python
options:
show_root_heading: false
heading_level: 0
## S21 Pro (VNish)
- [x] Shutdowns
- [ ] Power Modes
- [x] Setpoints
- [x] Presets
::: pyasic.miners.antminer.vnish.X21.S21.VNishS21Pro
handler: python
options:
show_root_heading: false
heading_level: 0
## S21+ (VNish)
- [x] Shutdowns
- [ ] Power Modes
- [x] Setpoints
- [x] Presets
::: pyasic.miners.antminer.vnish.X21.S21.VNishS21Plus
handler: python
options:
show_root_heading: false
heading_level: 0
## S21+ Hydro (VNish)
- [x] Shutdowns
- [ ] Power Modes
- [x] Setpoints
- [x] Presets
::: pyasic.miners.antminer.vnish.X21.S21.VNishS21PlusHydro
handler: python
options:
show_root_heading: false
heading_level: 0
## T21 (VNish) ## T21 (VNish)
- [x] Shutdowns - [x] Shutdowns
@@ -174,7 +278,7 @@
- [x] Shutdowns - [x] Shutdowns
- [ ] Power Modes - [ ] Power Modes
- [ ] Setpoints - [x] Setpoints
- [x] Presets - [x] Presets
::: pyasic.miners.antminer.luxos.X21.S21.LUXMinerS21 ::: pyasic.miners.antminer.luxos.X21.S21.LUXMinerS21
@@ -183,6 +287,19 @@
show_root_heading: false show_root_heading: false
heading_level: 0 heading_level: 0
## T21 (LuxOS)
- [x] Shutdowns
- [ ] Power Modes
- [x] Setpoints
- [x] Presets
::: pyasic.miners.antminer.luxos.X21.T21.LUXMinerT21
handler: python
options:
show_root_heading: false
heading_level: 0
## S21 (MaraFW) ## S21 (MaraFW)
- [ ] Shutdowns - [ ] Shutdowns

View File

@@ -73,7 +73,7 @@
- [x] Setpoints - [x] Setpoints
- [x] Presets - [x] Presets
::: pyasic.miners.antminer.vnish.X3.L3.VnishL3Plus ::: pyasic.miners.antminer.vnish.X3.L3.VNishL3Plus
handler: python handler: python
options: options:
show_root_heading: false show_root_heading: false

View File

@@ -47,7 +47,7 @@
- [x] Setpoints - [x] Setpoints
- [x] Presets - [x] Presets
::: pyasic.miners.antminer.vnish.X7.L7.VnishL7 ::: pyasic.miners.antminer.vnish.X7.L7.VNishL7
handler: python handler: python
options: options:
show_root_heading: false show_root_heading: false

View File

@@ -105,6 +105,19 @@
show_root_heading: false show_root_heading: false
heading_level: 0 heading_level: 0
## L9 (VNish)
- [x] Shutdowns
- [ ] Power Modes
- [x] Setpoints
- [x] Presets
::: pyasic.miners.antminer.vnish.X9.L9.VNishL9
handler: python
options:
show_root_heading: false
heading_level: 0
## T9 (Hive) ## T9 (Hive)
- [ ] Shutdowns - [ ] Shutdowns
@@ -122,7 +135,7 @@
- [x] Shutdowns - [x] Shutdowns
- [ ] Power Modes - [ ] Power Modes
- [ ] Setpoints - [x] Setpoints
- [x] Presets - [x] Presets
::: pyasic.miners.antminer.luxos.X9.S9.LUXMinerS9 ::: pyasic.miners.antminer.luxos.X9.S9.LUXMinerS9

View File

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

View File

@@ -1,6 +1,19 @@
# pyasic # pyasic
## DGX Models ## DGX Models
## DG1 (Stock)
- [ ] Shutdowns
- [ ] Power Modes
- [ ] Setpoints
- [ ] Presets
::: pyasic.miners.elphapex.daoge.DGX.DG1.ElphapexDG1
handler: python
options:
show_root_heading: false
heading_level: 0
## DG1+ (Stock) ## DG1+ (Stock)
- [ ] Shutdowns - [ ] Shutdowns
@@ -14,3 +27,16 @@
show_root_heading: false show_root_heading: false
heading_level: 0 heading_level: 0
## DG1Home (Stock)
- [ ] Shutdowns
- [ ] Power Modes
- [ ] Setpoints
- [ ] Presets
::: pyasic.miners.elphapex.daoge.DGX.DG1.ElphapexDG1Home
handler: python
options:
show_root_heading: false
heading_level: 0

View File

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

View File

@@ -86,6 +86,8 @@ details {
<li><a href="../antminer/X19#s19j-no-pic-stock">S19j No PIC (Stock)</a></li> <li><a href="../antminer/X19#s19j-no-pic-stock">S19j No PIC (Stock)</a></li>
<li><a href="../antminer/X19#s19-pro_1-stock">S19 Pro+ (Stock)</a></li> <li><a href="../antminer/X19#s19-pro_1-stock">S19 Pro+ (Stock)</a></li>
<li><a href="../antminer/X19#s19j-pro-stock">S19j Pro (Stock)</a></li> <li><a href="../antminer/X19#s19j-pro-stock">S19j Pro (Stock)</a></li>
<li><a href="../antminer/X19#s19j_1-stock">S19j+ (Stock)</a></li>
<li><a href="../antminer/X19#s19j-pro_1-stock">S19j Pro+ (Stock)</a></li>
<li><a href="../antminer/X19#s19-xp-stock">S19 XP (Stock)</a></li> <li><a href="../antminer/X19#s19-xp-stock">S19 XP (Stock)</a></li>
<li><a href="../antminer/X19#s19a-stock">S19a (Stock)</a></li> <li><a href="../antminer/X19#s19a-stock">S19a (Stock)</a></li>
<li><a href="../antminer/X19#s19a-pro-stock">S19a Pro (Stock)</a></li> <li><a href="../antminer/X19#s19a-pro-stock">S19a Pro (Stock)</a></li>
@@ -104,6 +106,8 @@ details {
<li><a href="../antminer/X21#s21-stock">S21 (Stock)</a></li> <li><a href="../antminer/X21#s21-stock">S21 (Stock)</a></li>
<li><a href="../antminer/X21#s21-stock">S21 (Stock)</a></li> <li><a href="../antminer/X21#s21-stock">S21 (Stock)</a></li>
<li><a href="../antminer/X21#s21_1-stock">S21+ (Stock)</a></li> <li><a href="../antminer/X21#s21_1-stock">S21+ (Stock)</a></li>
<li><a href="../antminer/X21#s21_1-hydro-stock">S21+ Hydro (Stock)</a></li>
<li><a href="../antminer/X21#s21_1-hydro-stock">S21+ Hydro (Stock)</a></li>
<li><a href="../antminer/X21#s21-pro-stock">S21 Pro (Stock)</a></li> <li><a href="../antminer/X21#s21-pro-stock">S21 Pro (Stock)</a></li>
<li><a href="../antminer/X21#t21-stock">T21 (Stock)</a></li> <li><a href="../antminer/X21#t21-stock">T21 (Stock)</a></li>
<li><a href="../antminer/X21#s21-hydro-stock">S21 Hydro (Stock)</a></li> <li><a href="../antminer/X21#s21-hydro-stock">S21 Hydro (Stock)</a></li>
@@ -553,6 +557,7 @@ details {
<summary>nano Series:</summary> <summary>nano Series:</summary>
<ul> <ul>
<li><a href="../avalonminer/nano#avalon-nano-3-stock">Avalon Nano 3 (Stock)</a></li> <li><a href="../avalonminer/nano#avalon-nano-3-stock">Avalon Nano 3 (Stock)</a></li>
<li><a href="../avalonminer/nano#avalon-nano-3s-stock">Avalon Nano 3s (Stock)</a></li>
</ul> </ul>
</details> </details>
<details> <details>
@@ -561,6 +566,12 @@ details {
<li><a href="../avalonminer/A15X#avalon-1566-stock">Avalon 1566 (Stock)</a></li> <li><a href="../avalonminer/A15X#avalon-1566-stock">Avalon 1566 (Stock)</a></li>
</ul> </ul>
</details> </details>
<details>
<summary>Q Series:</summary>
<ul>
<li><a href="../avalonminer/Q#avalon-q-home-stock">Avalon Q Home (Stock)</a></li>
</ul>
</details>
</ul> </ul>
</details> </details>
<details> <details>
@@ -611,6 +622,12 @@ details {
<li><a href="../goldshell/XBox#kd-box-pro-stock">KD Box Pro (Stock)</a></li> <li><a href="../goldshell/XBox#kd-box-pro-stock">KD Box Pro (Stock)</a></li>
</ul> </ul>
</details> </details>
<details>
<summary>Byte Series:</summary>
<ul>
<li><a href="../goldshell/Byte#byte-stock">Byte (Stock)</a></li>
</ul>
</details>
</ul> </ul>
</details> </details>
<details> <details>
@@ -654,6 +671,7 @@ details {
<li><a href="../antminer/X19#s19-xp-bos_1">S19 XP (BOS+)</a></li> <li><a href="../antminer/X19#s19-xp-bos_1">S19 XP (BOS+)</a></li>
<li><a href="../antminer/X19#s19-pro_1-hydro-bos_1">S19 Pro+ Hydro (BOS+)</a></li> <li><a href="../antminer/X19#s19-pro_1-hydro-bos_1">S19 Pro+ Hydro (BOS+)</a></li>
<li><a href="../antminer/X19#t19-bos_1">T19 (BOS+)</a></li> <li><a href="../antminer/X19#t19-bos_1">T19 (BOS+)</a></li>
<li><a href="../antminer/X19#s19-xp-hydro-bos_1">S19 XP Hydro (BOS+)</a></li>
</ul> </ul>
</details> </details>
<details> <details>
@@ -661,6 +679,9 @@ details {
<ul> <ul>
<li><a href="../antminer/X21#s21-bos_1">S21 (BOS+)</a></li> <li><a href="../antminer/X21#s21-bos_1">S21 (BOS+)</a></li>
<li><a href="../antminer/X21#s21-pro-bos_1">S21 Pro (BOS+)</a></li> <li><a href="../antminer/X21#s21-pro-bos_1">S21 Pro (BOS+)</a></li>
<li><a href="../antminer/X21#s21_1-bos_1">S21+ (BOS+)</a></li>
<li><a href="../antminer/X21#s21_1-hydro-bos_1">S21+ Hydro (BOS+)</a></li>
<li><a href="../antminer/X21#s21-hydro-bos_1">S21 Hydro (BOS+)</a></li>
<li><a href="../antminer/X21#t21-bos_1">T21 (BOS+)</a></li> <li><a href="../antminer/X21#t21-bos_1">T21 (BOS+)</a></li>
</ul> </ul>
</details> </details>
@@ -689,6 +710,12 @@ details {
<li><a href="../antminer/X7#l7-vnish">L7 (VNish)</a></li> <li><a href="../antminer/X7#l7-vnish">L7 (VNish)</a></li>
</ul> </ul>
</details> </details>
<details>
<summary>X9 Series:</summary>
<ul>
<li><a href="../antminer/X9#l9-vnish">L9 (VNish)</a></li>
</ul>
</details>
<details> <details>
<summary>X17 Series:</summary> <summary>X17 Series:</summary>
<ul> <ul>
@@ -704,11 +731,16 @@ details {
<li><a href="../antminer/X19#s19-pro-vnish">S19 Pro (VNish)</a></li> <li><a href="../antminer/X19#s19-pro-vnish">S19 Pro (VNish)</a></li>
<li><a href="../antminer/X19#s19j-vnish">S19j (VNish)</a></li> <li><a href="../antminer/X19#s19j-vnish">S19j (VNish)</a></li>
<li><a href="../antminer/X19#s19i-vnish">S19i (VNish)</a></li> <li><a href="../antminer/X19#s19i-vnish">S19i (VNish)</a></li>
<li><a href="../antminer/X19#s19-xp-vnish">S19 XP (VNish)</a></li>
<li><a href="../antminer/X19#s19-xp-hydro-vnish">S19 XP Hydro (VNish)</a></li>
<li><a href="../antminer/X19#s19j-pro-vnish">S19j Pro (VNish)</a></li> <li><a href="../antminer/X19#s19j-pro-vnish">S19j Pro (VNish)</a></li>
<li><a href="../antminer/X19#s19j-pro-vnish">S19j Pro (VNish)</a></li> <li><a href="../antminer/X19#s19j-pro-vnish">S19j Pro (VNish)</a></li>
<li><a href="../antminer/X19#s19j-pro-vnish">S19j Pro (VNish)</a></li> <li><a href="../antminer/X19#s19j-pro-vnish">S19j Pro (VNish)</a></li>
<li><a href="../antminer/X19#s19a-vnish">S19a (VNish)</a></li> <li><a href="../antminer/X19#s19a-vnish">S19a (VNish)</a></li>
<li><a href="../antminer/X19#s19-hydro-vnish">S19 Hydro (VNish)</a></li>
<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-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>
@@ -719,6 +751,10 @@ details {
<ul> <ul>
<li><a href="../antminer/X21#t21-vnish">T21 (VNish)</a></li> <li><a href="../antminer/X21#t21-vnish">T21 (VNish)</a></li>
<li><a href="../antminer/X21#s21-vnish">S21 (VNish)</a></li> <li><a href="../antminer/X21#s21-vnish">S21 (VNish)</a></li>
<li><a href="../antminer/X21#s21_1-vnish">S21+ (VNish)</a></li>
<li><a href="../antminer/X21#s21_1-hydro-vnish">S21+ Hydro (VNish)</a></li>
<li><a href="../antminer/X21#s21-pro-vnish">S21 Pro (VNish)</a></li>
<li><a href="../antminer/X21#s21-hydro-vnish">S21 Hydro (VNish)</a></li>
</ul> </ul>
</details> </details>
</ul> </ul>
@@ -814,6 +850,7 @@ details {
<summary>X21 Series:</summary> <summary>X21 Series:</summary>
<ul> <ul>
<li><a href="../antminer/X21#s21-luxos">S21 (LuxOS)</a></li> <li><a href="../antminer/X21#s21-luxos">S21 (LuxOS)</a></li>
<li><a href="../antminer/X21#t21-luxos">T21 (LuxOS)</a></li>
</ul> </ul>
</details> </details>
</ul> </ul>
@@ -912,6 +949,12 @@ details {
<li><a href="../iceriver/KSX#ks5m-stock">KS5M (Stock)</a></li> <li><a href="../iceriver/KSX#ks5m-stock">KS5M (Stock)</a></li>
</ul> </ul>
</details> </details>
<details>
<summary>ALX Series:</summary>
<ul>
<li><a href="../iceriver/ALX#al3-stock">AL3 (Stock)</a></li>
</ul>
</details>
</ul> </ul>
</details> </details>
<details> <details>
@@ -943,6 +986,8 @@ details {
<summary>DGX Series:</summary> <summary>DGX Series:</summary>
<ul> <ul>
<li><a href="../elphapex/DGX#dg1_1-stock">DG1+ (Stock)</a></li> <li><a href="../elphapex/DGX#dg1_1-stock">DG1+ (Stock)</a></li>
<li><a href="../elphapex/DGX#dg1-stock">DG1 (Stock)</a></li>
<li><a href="../elphapex/DGX#dg1home-stock">DG1Home (Stock)</a></li>
</ul> </ul>
</details> </details>
</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

@@ -97,6 +97,7 @@ nav:
- Innosilicon T3X: "miners/innosilicon/T3X.md" - Innosilicon T3X: "miners/innosilicon/T3X.md"
- 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 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"

577
poetry.lock generated
View File

@@ -1,4 +1,4 @@
# This file is automatically @generated by Poetry 2.1.1 and should not be changed by hand. # This file is automatically @generated by Poetry 2.1.0 and should not be changed by hand.
[[package]] [[package]]
name = "aiofiles" name = "aiofiles"
@@ -26,14 +26,14 @@ files = [
[[package]] [[package]]
name = "anyio" name = "anyio"
version = "4.8.0" version = "4.9.0"
description = "High level compatibility layer for multiple asynchronous event loop implementations" description = "High level compatibility layer for multiple asynchronous event loop implementations"
optional = false optional = false
python-versions = ">=3.9" python-versions = ">=3.9"
groups = ["main"] groups = ["main"]
files = [ files = [
{file = "anyio-4.8.0-py3-none-any.whl", hash = "sha256:b5011f270ab5eb0abf13385f851315585cc37ef330dd88e27ec3d34d651fd47a"}, {file = "anyio-4.9.0-py3-none-any.whl", hash = "sha256:9f76d541cad6e36af7beb62e978876f3b41e3e04f2c1fbf0884604c0a9c4d93c"},
{file = "anyio-4.8.0.tar.gz", hash = "sha256:1d9fe889df5212298c0c0723fa20479d1b94883a2df44bd3897aa91083316f7a"}, {file = "anyio-4.9.0.tar.gz", hash = "sha256:673c0c244e15788651a4ff38710fea9675823028a6f08a5eda409e0c9840a028"},
] ]
[package.dependencies] [package.dependencies]
@@ -43,8 +43,8 @@ sniffio = ">=1.1"
typing_extensions = {version = ">=4.5", markers = "python_version < \"3.13\""} typing_extensions = {version = ">=4.5", markers = "python_version < \"3.13\""}
[package.extras] [package.extras]
doc = ["Sphinx (>=7.4,<8.0)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx_rtd_theme"] doc = ["Sphinx (>=8.2,<9.0)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx_rtd_theme"]
test = ["anyio[trio]", "coverage[toml] (>=7)", "exceptiongroup (>=1.2.0)", "hypothesis (>=4.0)", "psutil (>=5.9)", "pytest (>=7.0)", "trustme", "truststore (>=0.9.1) ; python_version >= \"3.10\"", "uvloop (>=0.21) ; platform_python_implementation == \"CPython\" and platform_system != \"Windows\" and python_version < \"3.14\""] test = ["anyio[trio]", "blockbuster (>=1.5.23)", "coverage[toml] (>=7)", "exceptiongroup (>=1.2.0)", "hypothesis (>=4.0)", "psutil (>=5.9)", "pytest (>=7.0)", "trustme", "truststore (>=0.9.1) ; python_version >= \"3.10\"", "uvloop (>=0.21) ; platform_python_implementation == \"CPython\" and platform_system != \"Windows\" and python_version < \"3.14\""]
trio = ["trio (>=0.26.1)"] trio = ["trio (>=0.26.1)"]
[[package]] [[package]]
@@ -129,14 +129,14 @@ rust-codec = ["betterproto-rust-codec (==0.1.1)"]
[[package]] [[package]]
name = "certifi" name = "certifi"
version = "2025.1.31" version = "2025.4.26"
description = "Python package for providing Mozilla's CA Bundle." description = "Python package for providing Mozilla's CA Bundle."
optional = false optional = false
python-versions = ">=3.6" python-versions = ">=3.6"
groups = ["main", "docs"] groups = ["main", "docs"]
files = [ files = [
{file = "certifi-2025.1.31-py3-none-any.whl", hash = "sha256:ca78db4565a652026a4db2bcdf68f2fb589ea80d0be70e03929ed730746b84fe"}, {file = "certifi-2025.4.26-py3-none-any.whl", hash = "sha256:30350364dfe371162649852c63336a15c70c6510c2ad5015b21c2345311805f3"},
{file = "certifi-2025.1.31.tar.gz", hash = "sha256:3d5da6925056f6f18f119200434a4780a94263f10d1c21d032a6f6b2baa20651"}, {file = "certifi-2025.4.26.tar.gz", hash = "sha256:0a816057ea3cdefcef70270d2c515e4506bbc954f417fa5ade2021213bb8f0c6"},
] ]
[[package]] [[package]]
@@ -441,14 +441,14 @@ test = ["pytest (>=6)"]
[[package]] [[package]]
name = "filelock" name = "filelock"
version = "3.17.0" version = "3.18.0"
description = "A platform independent file lock." description = "A platform independent file lock."
optional = false optional = false
python-versions = ">=3.9" python-versions = ">=3.9"
groups = ["dev"] groups = ["dev"]
files = [ files = [
{file = "filelock-3.17.0-py3-none-any.whl", hash = "sha256:533dc2f7ba78dc2f0f531fc6c4940addf7b70a481e269a5a3b93be94ffbe8338"}, {file = "filelock-3.18.0-py3-none-any.whl", hash = "sha256:c401f4f8377c4464e6db25fff06205fd89bdd83b65eb0488ed1b160f780e21de"},
{file = "filelock-3.17.0.tar.gz", hash = "sha256:ee4e77401ef576ebb38cd7f13b9b28893194acc20a8e68e18730ba9c0e54660e"}, {file = "filelock-3.18.0.tar.gz", hash = "sha256:adbc88eabb99d2fec8c9c1b229b171f18afa655400173ddc653d5d01501fb9f2"},
] ]
[package.extras] [package.extras]
@@ -476,14 +476,14 @@ dev = ["flake8", "markdown", "twine", "wheel"]
[[package]] [[package]]
name = "griffe" name = "griffe"
version = "1.6.0" version = "1.7.3"
description = "Signatures for entire Python programs. Extract the structure, the frame, the skeleton of your project, to generate API documentation or find breaking changes in your API." description = "Signatures for entire Python programs. Extract the structure, the frame, the skeleton of your project, to generate API documentation or find breaking changes in your API."
optional = false optional = false
python-versions = ">=3.9" python-versions = ">=3.9"
groups = ["docs"] groups = ["docs"]
files = [ files = [
{file = "griffe-1.6.0-py3-none-any.whl", hash = "sha256:9f1dfe035d4715a244ed2050dfbceb05b1f470809ed4f6bb10ece5a7302f8dd1"}, {file = "griffe-1.7.3-py3-none-any.whl", hash = "sha256:c6b3ee30c2f0f17f30bcdef5068d6ab7a2a4f1b8bf1a3e74b56fffd21e1c5f75"},
{file = "griffe-1.6.0.tar.gz", hash = "sha256:eb5758088b9c73ad61c7ac014f3cdfb4c57b5c2fcbfca69996584b702aefa354"}, {file = "griffe-1.7.3.tar.gz", hash = "sha256:52ee893c6a3a968b639ace8015bec9d36594961e156e23315c8e8e51401fa50b"},
] ]
[package.dependencies] [package.dependencies]
@@ -509,14 +509,14 @@ protobuf = ["protobuf (>=3.20.0)"]
[[package]] [[package]]
name = "h11" name = "h11"
version = "0.14.0" version = "0.16.0"
description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1"
optional = false optional = false
python-versions = ">=3.7" python-versions = ">=3.8"
groups = ["main"] groups = ["main"]
files = [ files = [
{file = "h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761"}, {file = "h11-0.16.0-py3-none-any.whl", hash = "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86"},
{file = "h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d"}, {file = "h11-0.16.0.tar.gz", hash = "sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1"},
] ]
[[package]] [[package]]
@@ -549,19 +549,19 @@ files = [
[[package]] [[package]]
name = "httpcore" name = "httpcore"
version = "1.0.7" version = "1.0.9"
description = "A minimal low-level HTTP client." description = "A minimal low-level HTTP client."
optional = false optional = false
python-versions = ">=3.8" python-versions = ">=3.8"
groups = ["main"] groups = ["main"]
files = [ files = [
{file = "httpcore-1.0.7-py3-none-any.whl", hash = "sha256:a3fff8f43dc260d5bd363d9f9cf1830fa3a458b332856f34282de498ed420edd"}, {file = "httpcore-1.0.9-py3-none-any.whl", hash = "sha256:2d400746a40668fc9dec9810239072b40b4484b640a8c38fd654a024c7a1bf55"},
{file = "httpcore-1.0.7.tar.gz", hash = "sha256:8551cb62a169ec7162ac7be8d4817d561f60e08eaa485234898414bb5a8a0b4c"}, {file = "httpcore-1.0.9.tar.gz", hash = "sha256:6e34463af53fd2ab5d807f399a9b45ea31c3dfa2276f15a2c3f00afff6e176e8"},
] ]
[package.dependencies] [package.dependencies]
certifi = "*" certifi = "*"
h11 = ">=0.13,<0.15" h11 = ">=0.16"
[package.extras] [package.extras]
asyncio = ["anyio (>=4.0,<5.0)"] asyncio = ["anyio (>=4.0,<5.0)"]
@@ -608,14 +608,14 @@ files = [
[[package]] [[package]]
name = "identify" name = "identify"
version = "2.6.8" version = "2.6.10"
description = "File identification library for Python" description = "File identification library for Python"
optional = false optional = false
python-versions = ">=3.9" python-versions = ">=3.9"
groups = ["dev"] groups = ["dev"]
files = [ files = [
{file = "identify-2.6.8-py2.py3-none-any.whl", hash = "sha256:83657f0f766a3c8d0eaea16d4ef42494b39b34629a4b3192a9d020d349b3e255"}, {file = "identify-2.6.10-py2.py3-none-any.whl", hash = "sha256:5f34248f54136beed1a7ba6a6b5c4b6cf21ff495aac7c359e1ef831ae3b8ab25"},
{file = "identify-2.6.8.tar.gz", hash = "sha256:61491417ea2c0c5c670484fd8abbb34de34cdae1e5f39a73ee65e48e4bb663fc"}, {file = "identify-2.6.10.tar.gz", hash = "sha256:45e92fd704f3da71cc3880036633f48b4b7265fd4de2b57627cb157216eb7eb8"},
] ]
[package.extras] [package.extras]
@@ -638,15 +638,15 @@ all = ["flake8 (>=7.1.1)", "mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2
[[package]] [[package]]
name = "importlib-metadata" name = "importlib-metadata"
version = "8.6.1" version = "8.7.0"
description = "Read metadata from Python packages" description = "Read metadata from Python packages"
optional = false optional = false
python-versions = ">=3.9" python-versions = ">=3.9"
groups = ["docs"] groups = ["docs"]
markers = "python_version < \"3.10\"" markers = "python_version < \"3.10\""
files = [ files = [
{file = "importlib_metadata-8.6.1-py3-none-any.whl", hash = "sha256:02a89390c1e15fdfdc0d7c6b25cb3e62650d0494005c97d6f148bf5b9787525e"}, {file = "importlib_metadata-8.7.0-py3-none-any.whl", hash = "sha256:e5dd1551894c77868a30651cef00984d50e1002d06942a7101d34870c5f02afd"},
{file = "importlib_metadata-8.6.1.tar.gz", hash = "sha256:310b41d755445d74569f993ccfc22838295d9fe005425094fad953d7f15c8580"}, {file = "importlib_metadata-8.7.0.tar.gz", hash = "sha256:d13b81ad223b890aa16c5471f2ac3056cf76c5f10f82d6f9292f0b415f389000"},
] ]
[package.dependencies] [package.dependencies]
@@ -678,14 +678,14 @@ colors = ["colorama (>=0.4.6)"]
[[package]] [[package]]
name = "jinja2" name = "jinja2"
version = "3.1.5" version = "3.1.6"
description = "A very fast and expressive template engine." description = "A very fast and expressive template engine."
optional = false optional = false
python-versions = ">=3.7" python-versions = ">=3.7"
groups = ["docs"] groups = ["docs"]
files = [ files = [
{file = "jinja2-3.1.5-py3-none-any.whl", hash = "sha256:aba0f4dc9ed8013c424088f68a5c226f7d6097ed89b246d7749c2ec4175c6adb"}, {file = "jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67"},
{file = "jinja2-3.1.5.tar.gz", hash = "sha256:8fefff8dc3034e27bb80d67c671eb8a9bc424c0ef4c0826edbff304cceff43bb"}, {file = "jinja2-3.1.6.tar.gz", hash = "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d"},
] ]
[package.dependencies] [package.dependencies]
@@ -696,21 +696,21 @@ i18n = ["Babel (>=2.7)"]
[[package]] [[package]]
name = "markdown" name = "markdown"
version = "3.7" version = "3.8"
description = "Python implementation of John Gruber's Markdown." description = "Python implementation of John Gruber's Markdown."
optional = false optional = false
python-versions = ">=3.8" python-versions = ">=3.9"
groups = ["docs"] groups = ["docs"]
files = [ files = [
{file = "Markdown-3.7-py3-none-any.whl", hash = "sha256:7eb6df5690b81a1d7942992c97fad2938e956e79df20cbc6186e9c3a77b1c803"}, {file = "markdown-3.8-py3-none-any.whl", hash = "sha256:794a929b79c5af141ef5ab0f2f642d0f7b1872981250230e72682346f7cc90dc"},
{file = "markdown-3.7.tar.gz", hash = "sha256:2ae2471477cfd02dbbf038d5d9bc226d40def84b4fe2986e49b59b6b472bbed2"}, {file = "markdown-3.8.tar.gz", hash = "sha256:7df81e63f0df5c4b24b7d156eb81e4690595239b7d70937d0409f1b0de319c6f"},
] ]
[package.dependencies] [package.dependencies]
importlib-metadata = {version = ">=4.4", markers = "python_version < \"3.10\""} importlib-metadata = {version = ">=4.4", markers = "python_version < \"3.10\""}
[package.extras] [package.extras]
docs = ["mdx-gh-links (>=0.2)", "mkdocs (>=1.5)", "mkdocs-gen-files", "mkdocs-literate-nav", "mkdocs-nature (>=0.6)", "mkdocs-section-index", "mkdocstrings[python]"] docs = ["mdx_gh_links (>=0.2)", "mkdocs (>=1.6)", "mkdocs-gen-files", "mkdocs-literate-nav", "mkdocs-nature (>=0.6)", "mkdocs-section-index", "mkdocstrings[python]"]
testing = ["coverage", "pyyaml"] testing = ["coverage", "pyyaml"]
[[package]] [[package]]
@@ -830,14 +830,14 @@ min-versions = ["babel (==2.9.0)", "click (==7.0)", "colorama (==0.4) ; platform
[[package]] [[package]]
name = "mkdocs-autorefs" name = "mkdocs-autorefs"
version = "1.4.0" version = "1.4.1"
description = "Automatically link across pages in MkDocs." description = "Automatically link across pages in MkDocs."
optional = false optional = false
python-versions = ">=3.9" python-versions = ">=3.9"
groups = ["docs"] groups = ["docs"]
files = [ files = [
{file = "mkdocs_autorefs-1.4.0-py3-none-any.whl", hash = "sha256:bad19f69655878d20194acd0162e29a89c3f7e6365ffe54e72aa3fd1072f240d"}, {file = "mkdocs_autorefs-1.4.1-py3-none-any.whl", hash = "sha256:9793c5ac06a6ebbe52ec0f8439256e66187badf4b5334b5fde0b128ec134df4f"},
{file = "mkdocs_autorefs-1.4.0.tar.gz", hash = "sha256:a9c0aa9c90edbce302c09d050a3c4cb7c76f8b7b2c98f84a7a05f53d00392156"}, {file = "mkdocs_autorefs-1.4.1.tar.gz", hash = "sha256:4b5b6235a4becb2b10425c2fa191737e415b37aa3418919db33e5d774c9db079"},
] ]
[package.dependencies] [package.dependencies]
@@ -865,21 +865,21 @@ pyyaml = ">=5.1"
[[package]] [[package]]
name = "mkdocs-material" name = "mkdocs-material"
version = "9.6.7" version = "9.6.12"
description = "Documentation that simply works" description = "Documentation that simply works"
optional = false optional = false
python-versions = ">=3.8" python-versions = ">=3.8"
groups = ["docs"] groups = ["docs"]
files = [ files = [
{file = "mkdocs_material-9.6.7-py3-none-any.whl", hash = "sha256:8a159e45e80fcaadd9fbeef62cbf928569b93df954d4dc5ba76d46820caf7b47"}, {file = "mkdocs_material-9.6.12-py3-none-any.whl", hash = "sha256:92b4fbdc329e4febc267ca6e2c51e8501fa97b2225c5f4deb4d4e43550f8e61e"},
{file = "mkdocs_material-9.6.7.tar.gz", hash = "sha256:3e2c1fceb9410056c2d91f334a00cdea3215c28750e00c691c1e46b2a33309b4"}, {file = "mkdocs_material-9.6.12.tar.gz", hash = "sha256:add6a6337b29f9ea7912cb1efc661de2c369060b040eb5119855d794ea85b473"},
] ]
[package.dependencies] [package.dependencies]
babel = ">=2.10,<3.0" babel = ">=2.10,<3.0"
backrefs = ">=5.7.post1,<6.0" backrefs = ">=5.7.post1,<6.0"
colorama = ">=0.4,<1.0" colorama = ">=0.4,<1.0"
jinja2 = ">=3.0,<4.0" jinja2 = ">=3.1,<4.0"
markdown = ">=3.2,<4.0" markdown = ">=3.2,<4.0"
mkdocs = ">=1.6,<2.0" mkdocs = ">=1.6,<2.0"
mkdocs-material-extensions = ">=1.3,<2.0" mkdocs-material-extensions = ">=1.3,<2.0"
@@ -954,104 +954,116 @@ mkdocstrings = ">=0.26"
[[package]] [[package]]
name = "multidict" name = "multidict"
version = "6.1.0" version = "6.4.3"
description = "multidict implementation" description = "multidict implementation"
optional = false optional = false
python-versions = ">=3.8" python-versions = ">=3.9"
groups = ["main"] groups = ["main"]
files = [ files = [
{file = "multidict-6.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:3380252550e372e8511d49481bd836264c009adb826b23fefcc5dd3c69692f60"}, {file = "multidict-6.4.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:32a998bd8a64ca48616eac5a8c1cc4fa38fb244a3facf2eeb14abe186e0f6cc5"},
{file = "multidict-6.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:99f826cbf970077383d7de805c0681799491cb939c25450b9b5b3ced03ca99f1"}, {file = "multidict-6.4.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a54ec568f1fc7f3c313c2f3b16e5db346bf3660e1309746e7fccbbfded856188"},
{file = "multidict-6.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a114d03b938376557927ab23f1e950827c3b893ccb94b62fd95d430fd0e5cf53"}, {file = "multidict-6.4.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a7be07e5df178430621c716a63151165684d3e9958f2bbfcb644246162007ab7"},
{file = "multidict-6.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b1c416351ee6271b2f49b56ad7f308072f6f44b37118d69c2cad94f3fa8a40d5"}, {file = "multidict-6.4.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b128dbf1c939674a50dd0b28f12c244d90e5015e751a4f339a96c54f7275e291"},
{file = "multidict-6.1.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6b5d83030255983181005e6cfbac1617ce9746b219bc2aad52201ad121226581"}, {file = "multidict-6.4.3-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:b9cb19dfd83d35b6ff24a4022376ea6e45a2beba8ef3f0836b8a4b288b6ad685"},
{file = "multidict-6.1.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3e97b5e938051226dc025ec80980c285b053ffb1e25a3db2a3aa3bc046bf7f56"}, {file = "multidict-6.4.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3cf62f8e447ea2c1395afa289b332e49e13d07435369b6f4e41f887db65b40bf"},
{file = "multidict-6.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d618649d4e70ac6efcbba75be98b26ef5078faad23592f9b51ca492953012429"}, {file = "multidict-6.4.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:909f7d43ff8f13d1adccb6a397094adc369d4da794407f8dd592c51cf0eae4b1"},
{file = "multidict-6.1.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:10524ebd769727ac77ef2278390fb0068d83f3acb7773792a5080f2b0abf7748"}, {file = "multidict-6.4.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0bb8f8302fbc7122033df959e25777b0b7659b1fd6bcb9cb6bed76b5de67afef"},
{file = "multidict-6.1.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:ff3827aef427c89a25cc96ded1759271a93603aba9fb977a6d264648ebf989db"}, {file = "multidict-6.4.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:224b79471b4f21169ea25ebc37ed6f058040c578e50ade532e2066562597b8a9"},
{file = "multidict-6.1.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:06809f4f0f7ab7ea2cabf9caca7d79c22c0758b58a71f9d32943ae13c7ace056"}, {file = "multidict-6.4.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:a7bd27f7ab3204f16967a6f899b3e8e9eb3362c0ab91f2ee659e0345445e0078"},
{file = "multidict-6.1.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:f179dee3b863ab1c59580ff60f9d99f632f34ccb38bf67a33ec6b3ecadd0fd76"}, {file = "multidict-6.4.3-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:99592bd3162e9c664671fd14e578a33bfdba487ea64bcb41d281286d3c870ad7"},
{file = "multidict-6.1.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:aaed8b0562be4a0876ee3b6946f6869b7bcdb571a5d1496683505944e268b160"}, {file = "multidict-6.4.3-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:a62d78a1c9072949018cdb05d3c533924ef8ac9bcb06cbf96f6d14772c5cd451"},
{file = "multidict-6.1.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:3c8b88a2ccf5493b6c8da9076fb151ba106960a2df90c2633f342f120751a9e7"}, {file = "multidict-6.4.3-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:3ccdde001578347e877ca4f629450973c510e88e8865d5aefbcb89b852ccc666"},
{file = "multidict-6.1.0-cp310-cp310-win32.whl", hash = "sha256:4a9cb68166a34117d6646c0023c7b759bf197bee5ad4272f420a0141d7eb03a0"}, {file = "multidict-6.4.3-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:eccb67b0e78aa2e38a04c5ecc13bab325a43e5159a181a9d1a6723db913cbb3c"},
{file = "multidict-6.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:20b9b5fbe0b88d0bdef2012ef7dee867f874b72528cf1d08f1d59b0e3850129d"}, {file = "multidict-6.4.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:8b6fcf6054fc4114a27aa865f8840ef3d675f9316e81868e0ad5866184a6cba5"},
{file = "multidict-6.1.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:3efe2c2cb5763f2f1b275ad2bf7a287d3f7ebbef35648a9726e3b69284a4f3d6"}, {file = "multidict-6.4.3-cp310-cp310-win32.whl", hash = "sha256:f92c7f62d59373cd93bc9969d2da9b4b21f78283b1379ba012f7ee8127b3152e"},
{file = "multidict-6.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c7053d3b0353a8b9de430a4f4b4268ac9a4fb3481af37dfe49825bf45ca24156"}, {file = "multidict-6.4.3-cp310-cp310-win_amd64.whl", hash = "sha256:b57e28dbc031d13916b946719f213c494a517b442d7b48b29443e79610acd887"},
{file = "multidict-6.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:27e5fc84ccef8dfaabb09d82b7d179c7cf1a3fbc8a966f8274fcb4ab2eb4cadb"}, {file = "multidict-6.4.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:f6f19170197cc29baccd33ccc5b5d6a331058796485857cf34f7635aa25fb0cd"},
{file = "multidict-6.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0e2b90b43e696f25c62656389d32236e049568b39320e2735d51f08fd362761b"}, {file = "multidict-6.4.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f2882bf27037eb687e49591690e5d491e677272964f9ec7bc2abbe09108bdfb8"},
{file = "multidict-6.1.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d83a047959d38a7ff552ff94be767b7fd79b831ad1cd9920662db05fec24fe72"}, {file = "multidict-6.4.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:fbf226ac85f7d6b6b9ba77db4ec0704fde88463dc17717aec78ec3c8546c70ad"},
{file = "multidict-6.1.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d1a9dd711d0877a1ece3d2e4fea11a8e75741ca21954c919406b44e7cf971304"}, {file = "multidict-6.4.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2e329114f82ad4b9dd291bef614ea8971ec119ecd0f54795109976de75c9a852"},
{file = "multidict-6.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ec2abea24d98246b94913b76a125e855eb5c434f7c46546046372fe60f666351"}, {file = "multidict-6.4.3-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:1f4e0334d7a555c63f5c8952c57ab6f1c7b4f8c7f3442df689fc9f03df315c08"},
{file = "multidict-6.1.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4867cafcbc6585e4b678876c489b9273b13e9fff9f6d6d66add5e15d11d926cb"}, {file = "multidict-6.4.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:740915eb776617b57142ce0bb13b7596933496e2f798d3d15a20614adf30d229"},
{file = "multidict-6.1.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:5b48204e8d955c47c55b72779802b219a39acc3ee3d0116d5080c388970b76e3"}, {file = "multidict-6.4.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:255dac25134d2b141c944b59a0d2f7211ca12a6d4779f7586a98b4b03ea80508"},
{file = "multidict-6.1.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:d8fff389528cad1618fb4b26b95550327495462cd745d879a8c7c2115248e399"}, {file = "multidict-6.4.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d4e8535bd4d741039b5aad4285ecd9b902ef9e224711f0b6afda6e38d7ac02c7"},
{file = "multidict-6.1.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:a7a9541cd308eed5e30318430a9c74d2132e9a8cb46b901326272d780bf2d423"}, {file = "multidict-6.4.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:30c433a33be000dd968f5750722eaa0991037be0be4a9d453eba121774985bc8"},
{file = "multidict-6.1.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:da1758c76f50c39a2efd5e9859ce7d776317eb1dd34317c8152ac9251fc574a3"}, {file = "multidict-6.4.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:4eb33b0bdc50acd538f45041f5f19945a1f32b909b76d7b117c0c25d8063df56"},
{file = "multidict-6.1.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:c943a53e9186688b45b323602298ab727d8865d8c9ee0b17f8d62d14b56f0753"}, {file = "multidict-6.4.3-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:75482f43465edefd8a5d72724887ccdcd0c83778ded8f0cb1e0594bf71736cc0"},
{file = "multidict-6.1.0-cp311-cp311-win32.whl", hash = "sha256:90f8717cb649eea3504091e640a1b8568faad18bd4b9fcd692853a04475a4b80"}, {file = "multidict-6.4.3-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:ce5b3082e86aee80b3925ab4928198450d8e5b6466e11501fe03ad2191c6d777"},
{file = "multidict-6.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:82176036e65644a6cc5bd619f65f6f19781e8ec2e5330f51aa9ada7504cc1926"}, {file = "multidict-6.4.3-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:e413152e3212c4d39f82cf83c6f91be44bec9ddea950ce17af87fbf4e32ca6b2"},
{file = "multidict-6.1.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:b04772ed465fa3cc947db808fa306d79b43e896beb677a56fb2347ca1a49c1fa"}, {file = "multidict-6.4.3-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:8aac2eeff69b71f229a405c0a4b61b54bade8e10163bc7b44fcd257949620618"},
{file = "multidict-6.1.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:6180c0ae073bddeb5a97a38c03f30c233e0a4d39cd86166251617d1bbd0af436"}, {file = "multidict-6.4.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ab583ac203af1d09034be41458feeab7863c0635c650a16f15771e1386abf2d7"},
{file = "multidict-6.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:071120490b47aa997cca00666923a83f02c7fbb44f71cf7f136df753f7fa8761"}, {file = "multidict-6.4.3-cp311-cp311-win32.whl", hash = "sha256:1b2019317726f41e81154df636a897de1bfe9228c3724a433894e44cd2512378"},
{file = "multidict-6.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50b3a2710631848991d0bf7de077502e8994c804bb805aeb2925a981de58ec2e"}, {file = "multidict-6.4.3-cp311-cp311-win_amd64.whl", hash = "sha256:43173924fa93c7486402217fab99b60baf78d33806af299c56133a3755f69589"},
{file = "multidict-6.1.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b58c621844d55e71c1b7f7c498ce5aa6985d743a1a59034c57a905b3f153c1ef"}, {file = "multidict-6.4.3-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:1f1c2f58f08b36f8475f3ec6f5aeb95270921d418bf18f90dffd6be5c7b0e676"},
{file = "multidict-6.1.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:55b6d90641869892caa9ca42ff913f7ff1c5ece06474fbd32fb2cf6834726c95"}, {file = "multidict-6.4.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:26ae9ad364fc61b936fb7bf4c9d8bd53f3a5b4417142cd0be5c509d6f767e2f1"},
{file = "multidict-6.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4b820514bfc0b98a30e3d85462084779900347e4d49267f747ff54060cc33925"}, {file = "multidict-6.4.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:659318c6c8a85f6ecfc06b4e57529e5a78dfdd697260cc81f683492ad7e9435a"},
{file = "multidict-6.1.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:10a9b09aba0c5b48c53761b7c720aaaf7cf236d5fe394cd399c7ba662d5f9966"}, {file = "multidict-6.4.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e1eb72c741fd24d5a28242ce72bb61bc91f8451877131fa3fe930edb195f7054"},
{file = "multidict-6.1.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1e16bf3e5fc9f44632affb159d30a437bfe286ce9e02754759be5536b169b305"}, {file = "multidict-6.4.3-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:3cd06d88cb7398252284ee75c8db8e680aa0d321451132d0dba12bc995f0adcc"},
{file = "multidict-6.1.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:76f364861c3bfc98cbbcbd402d83454ed9e01a5224bb3a28bf70002a230f73e2"}, {file = "multidict-6.4.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4543d8dc6470a82fde92b035a92529317191ce993533c3c0c68f56811164ed07"},
{file = "multidict-6.1.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:820c661588bd01a0aa62a1283f20d2be4281b086f80dad9e955e690c75fb54a2"}, {file = "multidict-6.4.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:30a3ebdc068c27e9d6081fca0e2c33fdf132ecea703a72ea216b81a66860adde"},
{file = "multidict-6.1.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:0e5f362e895bc5b9e67fe6e4ded2492d8124bdf817827f33c5b46c2fe3ffaca6"}, {file = "multidict-6.4.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b038f10e23f277153f86f95c777ba1958bcd5993194fda26a1d06fae98b2f00c"},
{file = "multidict-6.1.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3ec660d19bbc671e3a6443325f07263be452c453ac9e512f5eb935e7d4ac28b3"}, {file = "multidict-6.4.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c605a2b2dc14282b580454b9b5d14ebe0668381a3a26d0ac39daa0ca115eb2ae"},
{file = "multidict-6.1.0-cp312-cp312-win32.whl", hash = "sha256:58130ecf8f7b8112cdb841486404f1282b9c86ccb30d3519faf301b2e5659133"}, {file = "multidict-6.4.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8bd2b875f4ca2bb527fe23e318ddd509b7df163407b0fb717df229041c6df5d3"},
{file = "multidict-6.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:188215fc0aafb8e03341995e7c4797860181562380f81ed0a87ff455b70bf1f1"}, {file = "multidict-6.4.3-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:c2e98c840c9c8e65c0e04b40c6c5066c8632678cd50c8721fdbcd2e09f21a507"},
{file = "multidict-6.1.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:d569388c381b24671589335a3be6e1d45546c2988c2ebe30fdcada8457a31008"}, {file = "multidict-6.4.3-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:66eb80dd0ab36dbd559635e62fba3083a48a252633164857a1d1684f14326427"},
{file = "multidict-6.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:052e10d2d37810b99cc170b785945421141bf7bb7d2f8799d431e7db229c385f"}, {file = "multidict-6.4.3-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:c23831bdee0a2a3cf21be057b5e5326292f60472fb6c6f86392bbf0de70ba731"},
{file = "multidict-6.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f90c822a402cb865e396a504f9fc8173ef34212a342d92e362ca498cad308e28"}, {file = "multidict-6.4.3-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:1535cec6443bfd80d028052e9d17ba6ff8a5a3534c51d285ba56c18af97e9713"},
{file = "multidict-6.1.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b225d95519a5bf73860323e633a664b0d85ad3d5bede6d30d95b35d4dfe8805b"}, {file = "multidict-6.4.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3b73e7227681f85d19dec46e5b881827cd354aabe46049e1a61d2f9aaa4e285a"},
{file = "multidict-6.1.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:23bfd518810af7de1116313ebd9092cb9aa629beb12f6ed631ad53356ed6b86c"}, {file = "multidict-6.4.3-cp312-cp312-win32.whl", hash = "sha256:8eac0c49df91b88bf91f818e0a24c1c46f3622978e2c27035bfdca98e0e18124"},
{file = "multidict-6.1.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5c09fcfdccdd0b57867577b719c69e347a436b86cd83747f179dbf0cc0d4c1f3"}, {file = "multidict-6.4.3-cp312-cp312-win_amd64.whl", hash = "sha256:11990b5c757d956cd1db7cb140be50a63216af32cd6506329c2c59d732d802db"},
{file = "multidict-6.1.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf6bea52ec97e95560af5ae576bdac3aa3aae0b6758c6efa115236d9e07dae44"}, {file = "multidict-6.4.3-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:7a76534263d03ae0cfa721fea40fd2b5b9d17a6f85e98025931d41dc49504474"},
{file = "multidict-6.1.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:57feec87371dbb3520da6192213c7d6fc892d5589a93db548331954de8248fd2"}, {file = "multidict-6.4.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:805031c2f599eee62ac579843555ed1ce389ae00c7e9f74c2a1b45e0564a88dd"},
{file = "multidict-6.1.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:0c3f390dc53279cbc8ba976e5f8035eab997829066756d811616b652b00a23a3"}, {file = "multidict-6.4.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:c56c179839d5dcf51d565132185409d1d5dd8e614ba501eb79023a6cab25576b"},
{file = "multidict-6.1.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:59bfeae4b25ec05b34f1956eaa1cb38032282cd4dfabc5056d0a1ec4d696d3aa"}, {file = "multidict-6.4.3-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9c64f4ddb3886dd8ab71b68a7431ad4aa01a8fa5be5b11543b29674f29ca0ba3"},
{file = "multidict-6.1.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:b2f59caeaf7632cc633b5cf6fc449372b83bbdf0da4ae04d5be36118e46cc0aa"}, {file = "multidict-6.4.3-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:3002a856367c0b41cad6784f5b8d3ab008eda194ed7864aaa58f65312e2abcac"},
{file = "multidict-6.1.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:37bb93b2178e02b7b618893990941900fd25b6b9ac0fa49931a40aecdf083fe4"}, {file = "multidict-6.4.3-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3d75e621e7d887d539d6e1d789f0c64271c250276c333480a9e1de089611f790"},
{file = "multidict-6.1.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4e9f48f58c2c523d5a06faea47866cd35b32655c46b443f163d08c6d0ddb17d6"}, {file = "multidict-6.4.3-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:995015cf4a3c0d72cbf453b10a999b92c5629eaf3a0c3e1efb4b5c1f602253bb"},
{file = "multidict-6.1.0-cp313-cp313-win32.whl", hash = "sha256:3a37ffb35399029b45c6cc33640a92bef403c9fd388acce75cdc88f58bd19a81"}, {file = "multidict-6.4.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a2b0fabae7939d09d7d16a711468c385272fa1b9b7fb0d37e51143585d8e72e0"},
{file = "multidict-6.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:e9aa71e15d9d9beaad2c6b9319edcdc0a49a43ef5c0a4c8265ca9ee7d6c67774"}, {file = "multidict-6.4.3-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:61ed4d82f8a1e67eb9eb04f8587970d78fe7cddb4e4d6230b77eda23d27938f9"},
{file = "multidict-6.1.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:db7457bac39421addd0c8449933ac32d8042aae84a14911a757ae6ca3eef1392"}, {file = "multidict-6.4.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:062428944a8dc69df9fdc5d5fc6279421e5f9c75a9ee3f586f274ba7b05ab3c8"},
{file = "multidict-6.1.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d094ddec350a2fb899fec68d8353c78233debde9b7d8b4beeafa70825f1c281a"}, {file = "multidict-6.4.3-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:b90e27b4674e6c405ad6c64e515a505c6d113b832df52fdacb6b1ffd1fa9a1d1"},
{file = "multidict-6.1.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:5845c1fd4866bb5dd3125d89b90e57ed3138241540897de748cdf19de8a2fca2"}, {file = "multidict-6.4.3-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:7d50d4abf6729921e9613d98344b74241572b751c6b37feed75fb0c37bd5a817"},
{file = "multidict-6.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9079dfc6a70abe341f521f78405b8949f96db48da98aeb43f9907f342f627cdc"}, {file = "multidict-6.4.3-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:43fe10524fb0a0514be3954be53258e61d87341008ce4914f8e8b92bee6f875d"},
{file = "multidict-6.1.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3914f5aaa0f36d5d60e8ece6a308ee1c9784cd75ec8151062614657a114c4478"}, {file = "multidict-6.4.3-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:236966ca6c472ea4e2d3f02f6673ebfd36ba3f23159c323f5a496869bc8e47c9"},
{file = "multidict-6.1.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c08be4f460903e5a9d0f76818db3250f12e9c344e79314d1d570fc69d7f4eae4"}, {file = "multidict-6.4.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:422a5ec315018e606473ba1f5431e064cf8b2a7468019233dcf8082fabad64c8"},
{file = "multidict-6.1.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d093be959277cb7dee84b801eb1af388b6ad3ca6a6b6bf1ed7585895789d027d"}, {file = "multidict-6.4.3-cp313-cp313-win32.whl", hash = "sha256:f901a5aace8e8c25d78960dcc24c870c8d356660d3b49b93a78bf38eb682aac3"},
{file = "multidict-6.1.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3702ea6872c5a2a4eeefa6ffd36b042e9773f05b1f37ae3ef7264b1163c2dcf6"}, {file = "multidict-6.4.3-cp313-cp313-win_amd64.whl", hash = "sha256:1c152c49e42277bc9a2f7b78bd5fa10b13e88d1b0328221e7aef89d5c60a99a5"},
{file = "multidict-6.1.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:2090f6a85cafc5b2db085124d752757c9d251548cedabe9bd31afe6363e0aff2"}, {file = "multidict-6.4.3-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:be8751869e28b9c0d368d94f5afcb4234db66fe8496144547b4b6d6a0645cfc6"},
{file = "multidict-6.1.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:f67f217af4b1ff66c68a87318012de788dd95fcfeb24cc889011f4e1c7454dfd"}, {file = "multidict-6.4.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:0d4b31f8a68dccbcd2c0ea04f0e014f1defc6b78f0eb8b35f2265e8716a6df0c"},
{file = "multidict-6.1.0-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:189f652a87e876098bbc67b4da1049afb5f5dfbaa310dd67c594b01c10388db6"}, {file = "multidict-6.4.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:032efeab3049e37eef2ff91271884303becc9e54d740b492a93b7e7266e23756"},
{file = "multidict-6.1.0-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:6bb5992037f7a9eff7991ebe4273ea7f51f1c1c511e6a2ce511d0e7bdb754492"}, {file = "multidict-6.4.3-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9e78006af1a7c8a8007e4f56629d7252668344442f66982368ac06522445e375"},
{file = "multidict-6.1.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:ac10f4c2b9e770c4e393876e35a7046879d195cd123b4f116d299d442b335bcd"}, {file = "multidict-6.4.3-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:daeac9dd30cda8703c417e4fddccd7c4dc0c73421a0b54a7da2713be125846be"},
{file = "multidict-6.1.0-cp38-cp38-win32.whl", hash = "sha256:e27bbb6d14416713a8bd7aaa1313c0fc8d44ee48d74497a0ff4c3a1b6ccb5167"}, {file = "multidict-6.4.3-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1f6f90700881438953eae443a9c6f8a509808bc3b185246992c4233ccee37fea"},
{file = "multidict-6.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:22f3105d4fb15c8f57ff3959a58fcab6ce36814486500cd7485651230ad4d4ef"}, {file = "multidict-6.4.3-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f84627997008390dd15762128dcf73c3365f4ec0106739cde6c20a07ed198ec8"},
{file = "multidict-6.1.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:4e18b656c5e844539d506a0a06432274d7bd52a7487e6828c63a63d69185626c"}, {file = "multidict-6.4.3-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3307b48cd156153b117c0ea54890a3bdbf858a5b296ddd40dc3852e5f16e9b02"},
{file = "multidict-6.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a185f876e69897a6f3325c3f19f26a297fa058c5e456bfcff8015e9a27e83ae1"}, {file = "multidict-6.4.3-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ead46b0fa1dcf5af503a46e9f1c2e80b5d95c6011526352fa5f42ea201526124"},
{file = "multidict-6.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ab7c4ceb38d91570a650dba194e1ca87c2b543488fe9309b4212694174fd539c"}, {file = "multidict-6.4.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:1748cb2743bedc339d63eb1bca314061568793acd603a6e37b09a326334c9f44"},
{file = "multidict-6.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e617fb6b0b6953fffd762669610c1c4ffd05632c138d61ac7e14ad187870669c"}, {file = "multidict-6.4.3-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:acc9fa606f76fc111b4569348cc23a771cb52c61516dcc6bcef46d612edb483b"},
{file = "multidict-6.1.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:16e5f4bf4e603eb1fdd5d8180f1a25f30056f22e55ce51fb3d6ad4ab29f7d96f"}, {file = "multidict-6.4.3-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:31469d5832b5885adeb70982e531ce86f8c992334edd2f2254a10fa3182ac504"},
{file = "multidict-6.1.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f4c035da3f544b1882bac24115f3e2e8760f10a0107614fc9839fd232200b875"}, {file = "multidict-6.4.3-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:ba46b51b6e51b4ef7bfb84b82f5db0dc5e300fb222a8a13b8cd4111898a869cf"},
{file = "multidict-6.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:957cf8e4b6e123a9eea554fa7ebc85674674b713551de587eb318a2df3e00255"}, {file = "multidict-6.4.3-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:389cfefb599edf3fcfd5f64c0410da686f90f5f5e2c4d84e14f6797a5a337af4"},
{file = "multidict-6.1.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:483a6aea59cb89904e1ceabd2b47368b5600fb7de78a6e4a2c2987b2d256cf30"}, {file = "multidict-6.4.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:64bc2bbc5fba7b9db5c2c8d750824f41c6994e3882e6d73c903c2afa78d091e4"},
{file = "multidict-6.1.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:87701f25a2352e5bf7454caa64757642734da9f6b11384c1f9d1a8e699758057"}, {file = "multidict-6.4.3-cp313-cp313t-win32.whl", hash = "sha256:0ecdc12ea44bab2807d6b4a7e5eef25109ab1c82a8240d86d3c1fc9f3b72efd5"},
{file = "multidict-6.1.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:682b987361e5fd7a139ed565e30d81fd81e9629acc7d925a205366877d8c8657"}, {file = "multidict-6.4.3-cp313-cp313t-win_amd64.whl", hash = "sha256:7146a8742ea71b5d7d955bffcef58a9e6e04efba704b52a460134fefd10a8208"},
{file = "multidict-6.1.0-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:ce2186a7df133a9c895dea3331ddc5ddad42cdd0d1ea2f0a51e5d161e4762f28"}, {file = "multidict-6.4.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:5427a2679e95a642b7f8b0f761e660c845c8e6fe3141cddd6b62005bd133fc21"},
{file = "multidict-6.1.0-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:9f636b730f7e8cb19feb87094949ba54ee5357440b9658b2a32a5ce4bce53972"}, {file = "multidict-6.4.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:24a8caa26521b9ad09732972927d7b45b66453e6ebd91a3c6a46d811eeb7349b"},
{file = "multidict-6.1.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:73eae06aa53af2ea5270cc066dcaf02cc60d2994bbb2c4ef5764949257d10f43"}, {file = "multidict-6.4.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:6b5a272bc7c36a2cd1b56ddc6bff02e9ce499f9f14ee4a45c45434ef083f2459"},
{file = "multidict-6.1.0-cp39-cp39-win32.whl", hash = "sha256:1ca0083e80e791cffc6efce7660ad24af66c8d4079d2a750b29001b53ff59ada"}, {file = "multidict-6.4.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:edf74dc5e212b8c75165b435c43eb0d5e81b6b300a938a4eb82827119115e840"},
{file = "multidict-6.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:aa466da5b15ccea564bdab9c89175c762bc12825f4659c11227f515cee76fa4a"}, {file = "multidict-6.4.3-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:9f35de41aec4b323c71f54b0ca461ebf694fb48bec62f65221f52e0017955b39"},
{file = "multidict-6.1.0-py3-none-any.whl", hash = "sha256:48e171e52d1c4d33888e529b999e5900356b9ae588c2f09a52dcefb158b27506"}, {file = "multidict-6.4.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ae93e0ff43b6f6892999af64097b18561691ffd835e21a8348a441e256592e1f"},
{file = "multidict-6.1.0.tar.gz", hash = "sha256:22ae2ebf9b0c69d206c003e2f6a914ea33f0a932d4aa16f236afc049d9958f4a"}, {file = "multidict-6.4.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5e3929269e9d7eff905d6971d8b8c85e7dbc72c18fb99c8eae6fe0a152f2e343"},
{file = "multidict-6.4.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fb6214fe1750adc2a1b801a199d64b5a67671bf76ebf24c730b157846d0e90d2"},
{file = "multidict-6.4.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6d79cf5c0c6284e90f72123f4a3e4add52d6c6ebb4a9054e88df15b8d08444c6"},
{file = "multidict-6.4.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:2427370f4a255262928cd14533a70d9738dfacadb7563bc3b7f704cc2360fc4e"},
{file = "multidict-6.4.3-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:fbd8d737867912b6c5f99f56782b8cb81f978a97b4437a1c476de90a3e41c9a1"},
{file = "multidict-6.4.3-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:0ee1bf613c448997f73fc4efb4ecebebb1c02268028dd4f11f011f02300cf1e8"},
{file = "multidict-6.4.3-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:578568c4ba5f2b8abd956baf8b23790dbfdc953e87d5b110bce343b4a54fc9e7"},
{file = "multidict-6.4.3-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:a059ad6b80de5b84b9fa02a39400319e62edd39d210b4e4f8c4f1243bdac4752"},
{file = "multidict-6.4.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:dd53893675b729a965088aaadd6a1f326a72b83742b056c1065bdd2e2a42b4df"},
{file = "multidict-6.4.3-cp39-cp39-win32.whl", hash = "sha256:abcfed2c4c139f25c2355e180bcc077a7cae91eefbb8b3927bb3f836c9586f1f"},
{file = "multidict-6.4.3-cp39-cp39-win_amd64.whl", hash = "sha256:b1b389ae17296dd739015d5ddb222ee99fd66adeae910de21ac950e00979d897"},
{file = "multidict-6.4.3-py3-none-any.whl", hash = "sha256:59fe01ee8e2a1e8ceb3f6dbb216b09c8d9f4ef1c22c4fc825d045a147fa2ebc9"},
{file = "multidict-6.4.3.tar.gz", hash = "sha256:3ada0b058c9f213c5f95ba301f922d402ac234f1111a7d8fd70f1b99f3c281ec"},
] ]
[package.dependencies] [package.dependencies]
@@ -1071,14 +1083,14 @@ files = [
[[package]] [[package]]
name = "packaging" name = "packaging"
version = "24.2" version = "25.0"
description = "Core utilities for Python packages" description = "Core utilities for Python packages"
optional = false optional = false
python-versions = ">=3.8" python-versions = ">=3.8"
groups = ["docs"] groups = ["docs"]
files = [ files = [
{file = "packaging-24.2-py3-none-any.whl", hash = "sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759"}, {file = "packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484"},
{file = "packaging-24.2.tar.gz", hash = "sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f"}, {file = "packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f"},
] ]
[[package]] [[package]]
@@ -1129,31 +1141,31 @@ files = [
[[package]] [[package]]
name = "platformdirs" name = "platformdirs"
version = "4.3.6" version = "4.3.7"
description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`."
optional = false optional = false
python-versions = ">=3.8" python-versions = ">=3.9"
groups = ["dev", "docs"] groups = ["dev", "docs"]
files = [ files = [
{file = "platformdirs-4.3.6-py3-none-any.whl", hash = "sha256:73e575e1408ab8103900836b97580d5307456908a03e92031bab39e4554cc3fb"}, {file = "platformdirs-4.3.7-py3-none-any.whl", hash = "sha256:a03875334331946f13c549dbd8f4bac7a13a50a895a0eb1e8c6a8ace80d40a94"},
{file = "platformdirs-4.3.6.tar.gz", hash = "sha256:357fb2acbc885b0419afd3ce3ed34564c13c9b95c89360cd9563f73aa5e2b907"}, {file = "platformdirs-4.3.7.tar.gz", hash = "sha256:eb437d586b6a0986388f0d6f74aa0cde27b48d0e3d66843640bfb6bdcdb6e351"},
] ]
[package.extras] [package.extras]
docs = ["furo (>=2024.8.6)", "proselint (>=0.14)", "sphinx (>=8.0.2)", "sphinx-autodoc-typehints (>=2.4)"] docs = ["furo (>=2024.8.6)", "proselint (>=0.14)", "sphinx (>=8.1.3)", "sphinx-autodoc-typehints (>=3)"]
test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=8.3.2)", "pytest-cov (>=5)", "pytest-mock (>=3.14)"] test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=8.3.4)", "pytest-cov (>=6)", "pytest-mock (>=3.14)"]
type = ["mypy (>=1.11.2)"] type = ["mypy (>=1.14.1)"]
[[package]] [[package]]
name = "pre-commit" name = "pre-commit"
version = "4.1.0" version = "4.2.0"
description = "A framework for managing and maintaining multi-language pre-commit hooks." description = "A framework for managing and maintaining multi-language pre-commit hooks."
optional = false optional = false
python-versions = ">=3.9" python-versions = ">=3.9"
groups = ["dev"] groups = ["dev"]
files = [ files = [
{file = "pre_commit-4.1.0-py2.py3-none-any.whl", hash = "sha256:d29e7cb346295bcc1cc75fc3e92e343495e3ea0196c9ec6ba53f49f10ab6ae7b"}, {file = "pre_commit-4.2.0-py2.py3-none-any.whl", hash = "sha256:a009ca7205f1eb497d10b845e52c838a98b6cdd2102a6c8e4540e94ee75c58bd"},
{file = "pre_commit-4.1.0.tar.gz", hash = "sha256:ae3f018575a588e30dfddfab9a05448bfbd6b73d78709617b5a2b853549716d4"}, {file = "pre_commit-4.2.0.tar.gz", hash = "sha256:601283b9757afd87d40c4c4a9b2b5de9637a8ea02eaff7adc2d0fb4e04841146"},
] ]
[package.dependencies] [package.dependencies]
@@ -1196,20 +1208,21 @@ files = [
[[package]] [[package]]
name = "pydantic" name = "pydantic"
version = "2.10.6" version = "2.11.3"
description = "Data validation using Python type hints" description = "Data validation using Python type hints"
optional = false optional = false
python-versions = ">=3.8" python-versions = ">=3.9"
groups = ["main"] groups = ["main"]
files = [ files = [
{file = "pydantic-2.10.6-py3-none-any.whl", hash = "sha256:427d664bf0b8a2b34ff5dd0f5a18df00591adcee7198fbd71981054cef37b584"}, {file = "pydantic-2.11.3-py3-none-any.whl", hash = "sha256:a082753436a07f9ba1289c6ffa01cd93db3548776088aa917cc43b63f68fa60f"},
{file = "pydantic-2.10.6.tar.gz", hash = "sha256:ca5daa827cce33de7a42be142548b0096bf05a7e7b365aebfa5f8eeec7128236"}, {file = "pydantic-2.11.3.tar.gz", hash = "sha256:7471657138c16adad9322fe3070c0116dd6c3ad8d649300e3cbdfe91f4db4ec3"},
] ]
[package.dependencies] [package.dependencies]
annotated-types = ">=0.6.0" annotated-types = ">=0.6.0"
pydantic-core = "2.27.2" pydantic-core = "2.33.1"
typing-extensions = ">=4.12.2" typing-extensions = ">=4.12.2"
typing-inspection = ">=0.4.0"
[package.extras] [package.extras]
email = ["email-validator (>=2.0.0)"] email = ["email-validator (>=2.0.0)"]
@@ -1217,112 +1230,111 @@ timezone = ["tzdata ; python_version >= \"3.9\" and platform_system == \"Windows
[[package]] [[package]]
name = "pydantic-core" name = "pydantic-core"
version = "2.27.2" version = "2.33.1"
description = "Core functionality for Pydantic validation and serialization" description = "Core functionality for Pydantic validation and serialization"
optional = false optional = false
python-versions = ">=3.8" python-versions = ">=3.9"
groups = ["main"] groups = ["main"]
files = [ files = [
{file = "pydantic_core-2.27.2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:2d367ca20b2f14095a8f4fa1210f5a7b78b8a20009ecced6b12818f455b1e9fa"}, {file = "pydantic_core-2.33.1-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:3077cfdb6125cc8dab61b155fdd714663e401f0e6883f9632118ec12cf42df26"},
{file = "pydantic_core-2.27.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:491a2b73db93fab69731eaee494f320faa4e093dbed776be1a829c2eb222c34c"}, {file = "pydantic_core-2.33.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8ffab8b2908d152e74862d276cf5017c81a2f3719f14e8e3e8d6b83fda863927"},
{file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7969e133a6f183be60e9f6f56bfae753585680f3b7307a8e555a948d443cc05a"}, {file = "pydantic_core-2.33.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5183e4f6a2d468787243ebcd70cf4098c247e60d73fb7d68d5bc1e1beaa0c4db"},
{file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3de9961f2a346257caf0aa508a4da705467f53778e9ef6fe744c038119737ef5"}, {file = "pydantic_core-2.33.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:398a38d323f37714023be1e0285765f0a27243a8b1506b7b7de87b647b517e48"},
{file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e2bb4d3e5873c37bb3dd58714d4cd0b0e6238cebc4177ac8fe878f8b3aa8e74c"}, {file = "pydantic_core-2.33.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:87d3776f0001b43acebfa86f8c64019c043b55cc5a6a2e313d728b5c95b46969"},
{file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:280d219beebb0752699480fe8f1dc61ab6615c2046d76b7ab7ee38858de0a4e7"}, {file = "pydantic_core-2.33.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c566dd9c5f63d22226409553531f89de0cac55397f2ab8d97d6f06cfce6d947e"},
{file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47956ae78b6422cbd46f772f1746799cbb862de838fd8d1fbd34a82e05b0983a"}, {file = "pydantic_core-2.33.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a0d5f3acc81452c56895e90643a625302bd6be351e7010664151cc55b7b97f89"},
{file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:14d4a5c49d2f009d62a2a7140d3064f686d17a5d1a268bc641954ba181880236"}, {file = "pydantic_core-2.33.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d3a07fadec2a13274a8d861d3d37c61e97a816beae717efccaa4b36dfcaadcde"},
{file = "pydantic_core-2.27.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:337b443af21d488716f8d0b6164de833e788aa6bd7e3a39c005febc1284f4962"}, {file = "pydantic_core-2.33.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:f99aeda58dce827f76963ee87a0ebe75e648c72ff9ba1174a253f6744f518f65"},
{file = "pydantic_core-2.27.2-cp310-cp310-musllinux_1_1_armv7l.whl", hash = "sha256:03d0f86ea3184a12f41a2d23f7ccb79cdb5a18e06993f8a45baa8dfec746f0e9"}, {file = "pydantic_core-2.33.1-cp310-cp310-musllinux_1_1_armv7l.whl", hash = "sha256:902dbc832141aa0ec374f4310f1e4e7febeebc3256f00dc359a9ac3f264a45dc"},
{file = "pydantic_core-2.27.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:7041c36f5680c6e0f08d922aed302e98b3745d97fe1589db0a3eebf6624523af"}, {file = "pydantic_core-2.33.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fe44d56aa0b00d66640aa84a3cbe80b7a3ccdc6f0b1ca71090696a6d4777c091"},
{file = "pydantic_core-2.27.2-cp310-cp310-win32.whl", hash = "sha256:50a68f3e3819077be2c98110c1f9dcb3817e93f267ba80a2c05bb4f8799e2ff4"}, {file = "pydantic_core-2.33.1-cp310-cp310-win32.whl", hash = "sha256:ed3eb16d51257c763539bde21e011092f127a2202692afaeaccb50db55a31383"},
{file = "pydantic_core-2.27.2-cp310-cp310-win_amd64.whl", hash = "sha256:e0fd26b16394ead34a424eecf8a31a1f5137094cabe84a1bcb10fa6ba39d3d31"}, {file = "pydantic_core-2.33.1-cp310-cp310-win_amd64.whl", hash = "sha256:694ad99a7f6718c1a498dc170ca430687a39894a60327f548e02a9c7ee4b6504"},
{file = "pydantic_core-2.27.2-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:8e10c99ef58cfdf2a66fc15d66b16c4a04f62bca39db589ae8cba08bc55331bc"}, {file = "pydantic_core-2.33.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:6e966fc3caaf9f1d96b349b0341c70c8d6573bf1bac7261f7b0ba88f96c56c24"},
{file = "pydantic_core-2.27.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:26f32e0adf166a84d0cb63be85c562ca8a6fa8de28e5f0d92250c6b7e9e2aff7"}, {file = "pydantic_core-2.33.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:bfd0adeee563d59c598ceabddf2c92eec77abcb3f4a391b19aa7366170bd9e30"},
{file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c19d1ea0673cd13cc2f872f6c9ab42acc4e4f492a7ca9d3795ce2b112dd7e15"}, {file = "pydantic_core-2.33.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:91815221101ad3c6b507804178a7bb5cb7b2ead9ecd600041669c8d805ebd595"},
{file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5e68c4446fe0810e959cdff46ab0a41ce2f2c86d227d96dc3847af0ba7def306"}, {file = "pydantic_core-2.33.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9fea9c1869bb4742d174a57b4700c6dadea951df8b06de40c2fedb4f02931c2e"},
{file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d9640b0059ff4f14d1f37321b94061c6db164fbe49b334b31643e0528d100d99"}, {file = "pydantic_core-2.33.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1d20eb4861329bb2484c021b9d9a977566ab16d84000a57e28061151c62b349a"},
{file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:40d02e7d45c9f8af700f3452f329ead92da4c5f4317ca9b896de7ce7199ea459"}, {file = "pydantic_core-2.33.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0fb935c5591573ae3201640579f30128ccc10739b45663f93c06796854405505"},
{file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1c1fd185014191700554795c99b347d64f2bb637966c4cfc16998a0ca700d048"}, {file = "pydantic_core-2.33.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c964fd24e6166420d18fb53996d8c9fd6eac9bf5ae3ec3d03015be4414ce497f"},
{file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d81d2068e1c1228a565af076598f9e7451712700b673de8f502f0334f281387d"}, {file = "pydantic_core-2.33.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:681d65e9011f7392db5aa002b7423cc442d6a673c635668c227c6c8d0e5a4f77"},
{file = "pydantic_core-2.27.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:1a4207639fb02ec2dbb76227d7c751a20b1a6b4bc52850568e52260cae64ca3b"}, {file = "pydantic_core-2.33.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e100c52f7355a48413e2999bfb4e139d2977a904495441b374f3d4fb4a170961"},
{file = "pydantic_core-2.27.2-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:3de3ce3c9ddc8bbd88f6e0e304dea0e66d843ec9de1b0042b0911c1663ffd474"}, {file = "pydantic_core-2.33.1-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:048831bd363490be79acdd3232f74a0e9951b11b2b4cc058aeb72b22fdc3abe1"},
{file = "pydantic_core-2.27.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:30c5f68ded0c36466acede341551106821043e9afaad516adfb6e8fa80a4e6a6"}, {file = "pydantic_core-2.33.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:bdc84017d28459c00db6f918a7272a5190bec3090058334e43a76afb279eac7c"},
{file = "pydantic_core-2.27.2-cp311-cp311-win32.whl", hash = "sha256:c70c26d2c99f78b125a3459f8afe1aed4d9687c24fd677c6a4436bc042e50d6c"}, {file = "pydantic_core-2.33.1-cp311-cp311-win32.whl", hash = "sha256:32cd11c5914d1179df70406427097c7dcde19fddf1418c787540f4b730289896"},
{file = "pydantic_core-2.27.2-cp311-cp311-win_amd64.whl", hash = "sha256:08e125dbdc505fa69ca7d9c499639ab6407cfa909214d500897d02afb816e7cc"}, {file = "pydantic_core-2.33.1-cp311-cp311-win_amd64.whl", hash = "sha256:2ea62419ba8c397e7da28a9170a16219d310d2cf4970dbc65c32faf20d828c83"},
{file = "pydantic_core-2.27.2-cp311-cp311-win_arm64.whl", hash = "sha256:26f0d68d4b235a2bae0c3fc585c585b4ecc51382db0e3ba402a22cbc440915e4"}, {file = "pydantic_core-2.33.1-cp311-cp311-win_arm64.whl", hash = "sha256:fc903512177361e868bc1f5b80ac8c8a6e05fcdd574a5fb5ffeac5a9982b9e89"},
{file = "pydantic_core-2.27.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:9e0c8cfefa0ef83b4da9588448b6d8d2a2bf1a53c3f1ae5fca39eb3061e2f0b0"}, {file = "pydantic_core-2.33.1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:1293d7febb995e9d3ec3ea09caf1a26214eec45b0f29f6074abb004723fc1de8"},
{file = "pydantic_core-2.27.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:83097677b8e3bd7eaa6775720ec8e0405f1575015a463285a92bfdfe254529ef"}, {file = "pydantic_core-2.33.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:99b56acd433386c8f20be5c4000786d1e7ca0523c8eefc995d14d79c7a081498"},
{file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:172fce187655fece0c90d90a678424b013f8fbb0ca8b036ac266749c09438cb7"}, {file = "pydantic_core-2.33.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:35a5ec3fa8c2fe6c53e1b2ccc2454398f95d5393ab398478f53e1afbbeb4d939"},
{file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:519f29f5213271eeeeb3093f662ba2fd512b91c5f188f3bb7b27bc5973816934"}, {file = "pydantic_core-2.33.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b172f7b9d2f3abc0efd12e3386f7e48b576ef309544ac3a63e5e9cdd2e24585d"},
{file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:05e3a55d124407fffba0dd6b0c0cd056d10e983ceb4e5dbd10dda135c31071d6"}, {file = "pydantic_core-2.33.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9097b9f17f91eea659b9ec58148c0747ec354a42f7389b9d50701610d86f812e"},
{file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9c3ed807c7b91de05e63930188f19e921d1fe90de6b4f5cd43ee7fcc3525cb8c"}, {file = "pydantic_core-2.33.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cc77ec5b7e2118b152b0d886c7514a4653bcb58c6b1d760134a9fab915f777b3"},
{file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6fb4aadc0b9a0c063206846d603b92030eb6f03069151a625667f982887153e2"}, {file = "pydantic_core-2.33.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d5e3d15245b08fa4a84cefc6c9222e6f37c98111c8679fbd94aa145f9a0ae23d"},
{file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:28ccb213807e037460326424ceb8b5245acb88f32f3d2777427476e1b32c48c4"}, {file = "pydantic_core-2.33.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ef99779001d7ac2e2461d8ab55d3373fe7315caefdbecd8ced75304ae5a6fc6b"},
{file = "pydantic_core-2.27.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:de3cd1899e2c279b140adde9357c4495ed9d47131b4a4eaff9052f23398076b3"}, {file = "pydantic_core-2.33.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:fc6bf8869e193855e8d91d91f6bf59699a5cdfaa47a404e278e776dd7f168b39"},
{file = "pydantic_core-2.27.2-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:220f892729375e2d736b97d0e51466252ad84c51857d4d15f5e9692f9ef12be4"}, {file = "pydantic_core-2.33.1-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:b1caa0bc2741b043db7823843e1bde8aaa58a55a58fda06083b0569f8b45693a"},
{file = "pydantic_core-2.27.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:a0fcd29cd6b4e74fe8ddd2c90330fd8edf2e30cb52acda47f06dd615ae72da57"}, {file = "pydantic_core-2.33.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:ec259f62538e8bf364903a7d0d0239447059f9434b284f5536e8402b7dd198db"},
{file = "pydantic_core-2.27.2-cp312-cp312-win32.whl", hash = "sha256:1e2cb691ed9834cd6a8be61228471d0a503731abfb42f82458ff27be7b2186fc"}, {file = "pydantic_core-2.33.1-cp312-cp312-win32.whl", hash = "sha256:e14f369c98a7c15772b9da98987f58e2b509a93235582838bd0d1d8c08b68fda"},
{file = "pydantic_core-2.27.2-cp312-cp312-win_amd64.whl", hash = "sha256:cc3f1a99a4f4f9dd1de4fe0312c114e740b5ddead65bb4102884b384c15d8bc9"}, {file = "pydantic_core-2.33.1-cp312-cp312-win_amd64.whl", hash = "sha256:1c607801d85e2e123357b3893f82c97a42856192997b95b4d8325deb1cd0c5f4"},
{file = "pydantic_core-2.27.2-cp312-cp312-win_arm64.whl", hash = "sha256:3911ac9284cd8a1792d3cb26a2da18f3ca26c6908cc434a18f730dc0db7bfa3b"}, {file = "pydantic_core-2.33.1-cp312-cp312-win_arm64.whl", hash = "sha256:8d13f0276806ee722e70a1c93da19748594f19ac4299c7e41237fc791d1861ea"},
{file = "pydantic_core-2.27.2-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:7d14bd329640e63852364c306f4d23eb744e0f8193148d4044dd3dacdaacbd8b"}, {file = "pydantic_core-2.33.1-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:70af6a21237b53d1fe7b9325b20e65cbf2f0a848cf77bed492b029139701e66a"},
{file = "pydantic_core-2.27.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:82f91663004eb8ed30ff478d77c4d1179b3563df6cdb15c0817cd1cdaf34d154"}, {file = "pydantic_core-2.33.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:282b3fe1bbbe5ae35224a0dbd05aed9ccabccd241e8e6b60370484234b456266"},
{file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:71b24c7d61131bb83df10cc7e687433609963a944ccf45190cfc21e0887b08c9"}, {file = "pydantic_core-2.33.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4b315e596282bbb5822d0c7ee9d255595bd7506d1cb20c2911a4da0b970187d3"},
{file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fa8e459d4954f608fa26116118bb67f56b93b209c39b008277ace29937453dc9"}, {file = "pydantic_core-2.33.1-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:1dfae24cf9921875ca0ca6a8ecb4bb2f13c855794ed0d468d6abbec6e6dcd44a"},
{file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ce8918cbebc8da707ba805b7fd0b382816858728ae7fe19a942080c24e5b7cd1"}, {file = "pydantic_core-2.33.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6dd8ecfde08d8bfadaea669e83c63939af76f4cf5538a72597016edfa3fad516"},
{file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:eda3f5c2a021bbc5d976107bb302e0131351c2ba54343f8a496dc8783d3d3a6a"}, {file = "pydantic_core-2.33.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2f593494876eae852dc98c43c6f260f45abdbfeec9e4324e31a481d948214764"},
{file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bd8086fa684c4775c27f03f062cbb9eaa6e17f064307e86b21b9e0abc9c0f02e"}, {file = "pydantic_core-2.33.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:948b73114f47fd7016088e5186d13faf5e1b2fe83f5e320e371f035557fd264d"},
{file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8d9b3388db186ba0c099a6d20f0604a44eabdeef1777ddd94786cdae158729e4"}, {file = "pydantic_core-2.33.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e11f3864eb516af21b01e25fac915a82e9ddad3bb0fb9e95a246067398b435a4"},
{file = "pydantic_core-2.27.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:7a66efda2387de898c8f38c0cf7f14fca0b51a8ef0b24bfea5849f1b3c95af27"}, {file = "pydantic_core-2.33.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:549150be302428b56fdad0c23c2741dcdb5572413776826c965619a25d9c6bde"},
{file = "pydantic_core-2.27.2-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:18a101c168e4e092ab40dbc2503bdc0f62010e95d292b27827871dc85450d7ee"}, {file = "pydantic_core-2.33.1-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:495bc156026efafd9ef2d82372bd38afce78ddd82bf28ef5276c469e57c0c83e"},
{file = "pydantic_core-2.27.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:ba5dd002f88b78a4215ed2f8ddbdf85e8513382820ba15ad5ad8955ce0ca19a1"}, {file = "pydantic_core-2.33.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:ec79de2a8680b1a67a07490bddf9636d5c2fab609ba8c57597e855fa5fa4dacd"},
{file = "pydantic_core-2.27.2-cp313-cp313-win32.whl", hash = "sha256:1ebaf1d0481914d004a573394f4be3a7616334be70261007e47c2a6fe7e50130"}, {file = "pydantic_core-2.33.1-cp313-cp313-win32.whl", hash = "sha256:ee12a7be1742f81b8a65b36c6921022301d466b82d80315d215c4c691724986f"},
{file = "pydantic_core-2.27.2-cp313-cp313-win_amd64.whl", hash = "sha256:953101387ecf2f5652883208769a79e48db18c6df442568a0b5ccd8c2723abee"}, {file = "pydantic_core-2.33.1-cp313-cp313-win_amd64.whl", hash = "sha256:ede9b407e39949d2afc46385ce6bd6e11588660c26f80576c11c958e6647bc40"},
{file = "pydantic_core-2.27.2-cp313-cp313-win_arm64.whl", hash = "sha256:ac4dbfd1691affb8f48c2c13241a2e3b60ff23247cbcf981759c768b6633cf8b"}, {file = "pydantic_core-2.33.1-cp313-cp313-win_arm64.whl", hash = "sha256:aa687a23d4b7871a00e03ca96a09cad0f28f443690d300500603bd0adba4b523"},
{file = "pydantic_core-2.27.2-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:d3e8d504bdd3f10835468f29008d72fc8359d95c9c415ce6e767203db6127506"}, {file = "pydantic_core-2.33.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:401d7b76e1000d0dd5538e6381d28febdcacb097c8d340dde7d7fc6e13e9f95d"},
{file = "pydantic_core-2.27.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:521eb9b7f036c9b6187f0b47318ab0d7ca14bd87f776240b90b21c1f4f149320"}, {file = "pydantic_core-2.33.1-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7aeb055a42d734c0255c9e489ac67e75397d59c6fbe60d155851e9782f276a9c"},
{file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:85210c4d99a0114f5a9481b44560d7d1e35e32cc5634c656bc48e590b669b145"}, {file = "pydantic_core-2.33.1-cp313-cp313t-win_amd64.whl", hash = "sha256:338ea9b73e6e109f15ab439e62cb3b78aa752c7fd9536794112e14bee02c8d18"},
{file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d716e2e30c6f140d7560ef1538953a5cd1a87264c737643d481f2779fc247fe1"}, {file = "pydantic_core-2.33.1-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:5ab77f45d33d264de66e1884fca158bc920cb5e27fd0764a72f72f5756ae8bdb"},
{file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f66d89ba397d92f840f8654756196d93804278457b5fbede59598a1f9f90b228"}, {file = "pydantic_core-2.33.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e7aaba1b4b03aaea7bb59e1b5856d734be011d3e6d98f5bcaa98cb30f375f2ad"},
{file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:669e193c1c576a58f132e3158f9dfa9662969edb1a250c54d8fa52590045f046"}, {file = "pydantic_core-2.33.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7fb66263e9ba8fea2aa85e1e5578980d127fb37d7f2e292773e7bc3a38fb0c7b"},
{file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9fdbe7629b996647b99c01b37f11170a57ae675375b14b8c13b8518b8320ced5"}, {file = "pydantic_core-2.33.1-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3f2648b9262607a7fb41d782cc263b48032ff7a03a835581abbf7a3bec62bcf5"},
{file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d262606bf386a5ba0b0af3b97f37c83d7011439e3dc1a9298f21efb292e42f1a"}, {file = "pydantic_core-2.33.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:723c5630c4259400818b4ad096735a829074601805d07f8cafc366d95786d331"},
{file = "pydantic_core-2.27.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:cabb9bcb7e0d97f74df8646f34fc76fbf793b7f6dc2438517d7a9e50eee4f14d"}, {file = "pydantic_core-2.33.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d100e3ae783d2167782391e0c1c7a20a31f55f8015f3293647544df3f9c67824"},
{file = "pydantic_core-2.27.2-cp38-cp38-musllinux_1_1_armv7l.whl", hash = "sha256:d2d63f1215638d28221f664596b1ccb3944f6e25dd18cd3b86b0a4c408d5ebb9"}, {file = "pydantic_core-2.33.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:177d50460bc976a0369920b6c744d927b0ecb8606fb56858ff542560251b19e5"},
{file = "pydantic_core-2.27.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:bca101c00bff0adb45a833f8451b9105d9df18accb8743b08107d7ada14bd7da"}, {file = "pydantic_core-2.33.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a3edde68d1a1f9af1273b2fe798997b33f90308fb6d44d8550c89fc6a3647cf6"},
{file = "pydantic_core-2.27.2-cp38-cp38-win32.whl", hash = "sha256:f6f8e111843bbb0dee4cb6594cdc73e79b3329b526037ec242a3e49012495b3b"}, {file = "pydantic_core-2.33.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:a62c3c3ef6a7e2c45f7853b10b5bc4ddefd6ee3cd31024754a1a5842da7d598d"},
{file = "pydantic_core-2.27.2-cp38-cp38-win_amd64.whl", hash = "sha256:fd1aea04935a508f62e0d0ef1f5ae968774a32afc306fb8545e06f5ff5cdf3ad"}, {file = "pydantic_core-2.33.1-cp39-cp39-musllinux_1_1_armv7l.whl", hash = "sha256:c91dbb0ab683fa0cd64a6e81907c8ff41d6497c346890e26b23de7ee55353f96"},
{file = "pydantic_core-2.27.2-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:c10eb4f1659290b523af58fa7cffb452a61ad6ae5613404519aee4bfbf1df993"}, {file = "pydantic_core-2.33.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:9f466e8bf0a62dc43e068c12166281c2eca72121dd2adc1040f3aa1e21ef8599"},
{file = "pydantic_core-2.27.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ef592d4bad47296fb11f96cd7dc898b92e795032b4894dfb4076cfccd43a9308"}, {file = "pydantic_core-2.33.1-cp39-cp39-win32.whl", hash = "sha256:ab0277cedb698749caada82e5d099dc9fed3f906a30d4c382d1a21725777a1e5"},
{file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c61709a844acc6bf0b7dce7daae75195a10aac96a596ea1b776996414791ede4"}, {file = "pydantic_core-2.33.1-cp39-cp39-win_amd64.whl", hash = "sha256:5773da0ee2d17136b1f1c6fbde543398d452a6ad2a7b54ea1033e2daa739b8d2"},
{file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:42c5f762659e47fdb7b16956c71598292f60a03aa92f8b6351504359dbdba6cf"}, {file = "pydantic_core-2.33.1-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:5c834f54f8f4640fd7e4b193f80eb25a0602bba9e19b3cd2fc7ffe8199f5ae02"},
{file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4c9775e339e42e79ec99c441d9730fccf07414af63eac2f0e48e08fd38a64d76"}, {file = "pydantic_core-2.33.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:049e0de24cf23766f12cc5cc71d8abc07d4a9deb9061b334b62093dedc7cb068"},
{file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:57762139821c31847cfb2df63c12f725788bd9f04bc2fb392790959b8f70f118"}, {file = "pydantic_core-2.33.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1a28239037b3d6f16916a4c831a5a0eadf856bdd6d2e92c10a0da3a59eadcf3e"},
{file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0d1e85068e818c73e048fe28cfc769040bb1f475524f4745a5dc621f75ac7630"}, {file = "pydantic_core-2.33.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9d3da303ab5f378a268fa7d45f37d7d85c3ec19769f28d2cc0c61826a8de21fe"},
{file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:097830ed52fd9e427942ff3b9bc17fab52913b2f50f2880dc4a5611446606a54"}, {file = "pydantic_core-2.33.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:25626fb37b3c543818c14821afe0fd3830bc327a43953bc88db924b68c5723f1"},
{file = "pydantic_core-2.27.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:044a50963a614ecfae59bb1eaf7ea7efc4bc62f49ed594e18fa1e5d953c40e9f"}, {file = "pydantic_core-2.33.1-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:3ab2d36e20fbfcce8f02d73c33a8a7362980cff717926bbae030b93ae46b56c7"},
{file = "pydantic_core-2.27.2-cp39-cp39-musllinux_1_1_armv7l.whl", hash = "sha256:4e0b4220ba5b40d727c7f879eac379b822eee5d8fff418e9d3381ee45b3b0362"}, {file = "pydantic_core-2.33.1-pp310-pypy310_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:2f9284e11c751b003fd4215ad92d325d92c9cb19ee6729ebd87e3250072cdcde"},
{file = "pydantic_core-2.27.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5e4f4bb20d75e9325cc9696c6802657b58bc1dbbe3022f32cc2b2b632c3fbb96"}, {file = "pydantic_core-2.33.1-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:048c01eee07d37cbd066fc512b9d8b5ea88ceeb4e629ab94b3e56965ad655add"},
{file = "pydantic_core-2.27.2-cp39-cp39-win32.whl", hash = "sha256:cca63613e90d001b9f2f9a9ceb276c308bfa2a43fafb75c8031c4f66039e8c6e"}, {file = "pydantic_core-2.33.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:5ccd429694cf26af7997595d627dd2637e7932214486f55b8a357edaac9dae8c"},
{file = "pydantic_core-2.27.2-cp39-cp39-win_amd64.whl", hash = "sha256:77d1bca19b0f7021b3a982e6f903dcd5b2b06076def36a652e3907f596e29f67"}, {file = "pydantic_core-2.33.1-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:3a371dc00282c4b84246509a5ddc808e61b9864aa1eae9ecc92bb1268b82db4a"},
{file = "pydantic_core-2.27.2-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:2bf14caea37e91198329b828eae1618c068dfb8ef17bb33287a7ad4b61ac314e"}, {file = "pydantic_core-2.33.1-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:f59295ecc75a1788af8ba92f2e8c6eeaa5a94c22fc4d151e8d9638814f85c8fc"},
{file = "pydantic_core-2.27.2-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:b0cb791f5b45307caae8810c2023a184c74605ec3bcbb67d13846c28ff731ff8"}, {file = "pydantic_core-2.33.1-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:08530b8ac922003033f399128505f513e30ca770527cc8bbacf75a84fcc2c74b"},
{file = "pydantic_core-2.27.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:688d3fd9fcb71f41c4c015c023d12a79d1c4c0732ec9eb35d96e3388a120dcf3"}, {file = "pydantic_core-2.33.1-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bae370459da6a5466978c0eacf90690cb57ec9d533f8e63e564ef3822bfa04fe"},
{file = "pydantic_core-2.27.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3d591580c34f4d731592f0e9fe40f9cc1b430d297eecc70b962e93c5c668f15f"}, {file = "pydantic_core-2.33.1-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e3de2777e3b9f4d603112f78006f4ae0acb936e95f06da6cb1a45fbad6bdb4b5"},
{file = "pydantic_core-2.27.2-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:82f986faf4e644ffc189a7f1aafc86e46ef70372bb153e7001e8afccc6e54133"}, {file = "pydantic_core-2.33.1-pp311-pypy311_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:3a64e81e8cba118e108d7126362ea30e021291b7805d47e4896e52c791be2761"},
{file = "pydantic_core-2.27.2-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:bec317a27290e2537f922639cafd54990551725fc844249e64c523301d0822fc"}, {file = "pydantic_core-2.33.1-pp311-pypy311_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:52928d8c1b6bda03cc6d811e8923dffc87a2d3c8b3bfd2ce16471c7147a24850"},
{file = "pydantic_core-2.27.2-pp310-pypy310_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:0296abcb83a797db256b773f45773da397da75a08f5fcaef41f2044adec05f50"}, {file = "pydantic_core-2.33.1-pp311-pypy311_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:1b30d92c9412beb5ac6b10a3eb7ef92ccb14e3f2a8d7732e2d739f58b3aa7544"},
{file = "pydantic_core-2.27.2-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:0d75070718e369e452075a6017fbf187f788e17ed67a3abd47fa934d001863d9"}, {file = "pydantic_core-2.33.1-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:f995719707e0e29f0f41a8aa3bcea6e761a36c9136104d3189eafb83f5cec5e5"},
{file = "pydantic_core-2.27.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:7e17b560be3c98a8e3aa66ce828bdebb9e9ac6ad5466fba92eb74c4c95cb1151"}, {file = "pydantic_core-2.33.1-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:7edbc454a29fc6aeae1e1eecba4f07b63b8d76e76a748532233c4c167b4cb9ea"},
{file = "pydantic_core-2.27.2-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:c33939a82924da9ed65dab5a65d427205a73181d8098e79b6b426bdf8ad4e656"}, {file = "pydantic_core-2.33.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:ad05b683963f69a1d5d2c2bdab1274a31221ca737dbbceaa32bcb67359453cdd"},
{file = "pydantic_core-2.27.2-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:00bad2484fa6bda1e216e7345a798bd37c68fb2d97558edd584942aa41b7d278"}, {file = "pydantic_core-2.33.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:df6a94bf9452c6da9b5d76ed229a5683d0306ccb91cca8e1eea883189780d568"},
{file = "pydantic_core-2.27.2-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c817e2b40aba42bac6f457498dacabc568c3b7a986fc9ba7c8d9d260b71485fb"}, {file = "pydantic_core-2.33.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7965c13b3967909a09ecc91f21d09cfc4576bf78140b988904e94f130f188396"},
{file = "pydantic_core-2.27.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:251136cdad0cb722e93732cb45ca5299fb56e1344a833640bf93b2803f8d1bfd"}, {file = "pydantic_core-2.33.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:3f1fdb790440a34f6ecf7679e1863b825cb5ffde858a9197f851168ed08371e5"},
{file = "pydantic_core-2.27.2-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d2088237af596f0a524d3afc39ab3b036e8adb054ee57cbb1dcf8e09da5b29cc"}, {file = "pydantic_core-2.33.1-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:5277aec8d879f8d05168fdd17ae811dd313b8ff894aeeaf7cd34ad28b4d77e33"},
{file = "pydantic_core-2.27.2-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:d4041c0b966a84b4ae7a09832eb691a35aec90910cd2dbe7a208de59be77965b"}, {file = "pydantic_core-2.33.1-pp39-pypy39_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:8ab581d3530611897d863d1a649fb0644b860286b4718db919bfd51ece41f10b"},
{file = "pydantic_core-2.27.2-pp39-pypy39_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:8083d4e875ebe0b864ffef72a4304827015cff328a1be6e22cc850753bfb122b"}, {file = "pydantic_core-2.33.1-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:0483847fa9ad5e3412265c1bd72aad35235512d9ce9d27d81a56d935ef489672"},
{file = "pydantic_core-2.27.2-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:f141ee28a0ad2123b6611b6ceff018039df17f32ada8b534e6aa039545a3efb2"}, {file = "pydantic_core-2.33.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:de9e06abe3cc5ec6a2d5f75bc99b0bdca4f5c719a5b34026f8c57efbdecd2ee3"},
{file = "pydantic_core-2.27.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:7d0c8399fcc1848491f00e0314bd59fb34a9c008761bcb422a057670c3f65e35"}, {file = "pydantic_core-2.33.1.tar.gz", hash = "sha256:bcc9c6fdb0ced789245b02b7d6603e17d1563064ddcfc36f046b61c0c05dd9df"},
{file = "pydantic_core-2.27.2.tar.gz", hash = "sha256:eb026e5a4c1fee05726072337ff51d1efb6f59090b7da90d30ea58625b1ffb39"},
] ]
[package.dependencies] [package.dependencies]
@@ -1477,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"
@@ -1558,27 +1582,42 @@ files = [
[[package]] [[package]]
name = "typing-extensions" name = "typing-extensions"
version = "4.12.2" version = "4.13.2"
description = "Backported and Experimental Type Hints for Python 3.8+" description = "Backported and Experimental Type Hints for Python 3.8+"
optional = false optional = false
python-versions = ">=3.8" python-versions = ">=3.8"
groups = ["main", "docs"] groups = ["main", "docs"]
files = [ files = [
{file = "typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d"}, {file = "typing_extensions-4.13.2-py3-none-any.whl", hash = "sha256:a439e7c04b49fec3e5d3e2beaa21755cadbbdc391694e28ccdd36ca4a1408f8c"},
{file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"}, {file = "typing_extensions-4.13.2.tar.gz", hash = "sha256:e6c81219bd689f51865d9e372991c540bda33a0379d5573cddb9a3a23f7caaef"},
] ]
markers = {docs = "python_version < \"3.10\""} markers = {docs = "python_version < \"3.10\""}
[[package]]
name = "typing-inspection"
version = "0.4.0"
description = "Runtime typing introspection tools"
optional = false
python-versions = ">=3.9"
groups = ["main"]
files = [
{file = "typing_inspection-0.4.0-py3-none-any.whl", hash = "sha256:50e72559fcd2a6367a19f7a7e610e6afcb9fac940c650290eed893d61386832f"},
{file = "typing_inspection-0.4.0.tar.gz", hash = "sha256:9765c87de36671694a67904bf2c96e395be9c6439bb6c87b5142569dcdd65122"},
]
[package.dependencies]
typing-extensions = ">=4.12.0"
[[package]] [[package]]
name = "urllib3" name = "urllib3"
version = "2.3.0" version = "2.4.0"
description = "HTTP library with thread-safe connection pooling, file post, and more." description = "HTTP library with thread-safe connection pooling, file post, and more."
optional = false optional = false
python-versions = ">=3.9" python-versions = ">=3.9"
groups = ["docs"] groups = ["docs"]
files = [ files = [
{file = "urllib3-2.3.0-py3-none-any.whl", hash = "sha256:1cee9ad369867bfdbbb48b7dd50374c0967a0bb7710050facf0dd6911440e3df"}, {file = "urllib3-2.4.0-py3-none-any.whl", hash = "sha256:4e16665048960a0900c702d4a66415956a584919c03361cac9f1df5c5dd7e813"},
{file = "urllib3-2.3.0.tar.gz", hash = "sha256:f8c5449b3cf0861679ce7e0503c7b44b5ec981bec0d1d3795a07f1ba96f0204d"}, {file = "urllib3-2.4.0.tar.gz", hash = "sha256:414bc6535b787febd7567804cc015fee39daab8ad86268f1310a9250697de466"},
] ]
[package.extras] [package.extras]
@@ -1589,14 +1628,14 @@ zstd = ["zstandard (>=0.18.0)"]
[[package]] [[package]]
name = "virtualenv" name = "virtualenv"
version = "20.29.2" version = "20.30.0"
description = "Virtual Python Environment builder" description = "Virtual Python Environment builder"
optional = false optional = false
python-versions = ">=3.8" python-versions = ">=3.8"
groups = ["dev"] groups = ["dev"]
files = [ files = [
{file = "virtualenv-20.29.2-py3-none-any.whl", hash = "sha256:febddfc3d1ea571bdb1dc0f98d7b45d24def7428214d4fb73cc486c9568cce6a"}, {file = "virtualenv-20.30.0-py3-none-any.whl", hash = "sha256:e34302959180fca3af42d1800df014b35019490b119eba981af27f2fa486e5d6"},
{file = "virtualenv-20.29.2.tar.gz", hash = "sha256:fdaabebf6d03b5ba83ae0a02cfe96f48a716f4fae556461d180825866f75b728"}, {file = "virtualenv-20.30.0.tar.gz", hash = "sha256:800863162bcaa5450a6e4d721049730e7f2dae07720e0902b0e4040bd6f9ada8"},
] ]
[package.dependencies] [package.dependencies]
@@ -1606,7 +1645,7 @@ platformdirs = ">=3.9.1,<5"
[package.extras] [package.extras]
docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.2,!=7.3)", "sphinx-argparse (>=0.4)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=23.6)"] docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.2,!=7.3)", "sphinx-argparse (>=0.4)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=23.6)"]
test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=23.1)", "pytest (>=7.4)", "pytest-env (>=0.8.2)", "pytest-freezer (>=0.4.8) ; platform_python_implementation == \"PyPy\" or platform_python_implementation == \"CPython\" and sys_platform == \"win32\" and python_version >= \"3.13\"", "pytest-mock (>=3.11.1)", "pytest-randomly (>=3.12)", "pytest-timeout (>=2.1)", "setuptools (>=68)", "time-machine (>=2.10) ; platform_python_implementation == \"CPython\""] test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=23.1)", "pytest (>=7.4)", "pytest-env (>=0.8.2)", "pytest-freezer (>=0.4.8) ; platform_python_implementation == \"PyPy\" or platform_python_implementation == \"GraalVM\" or platform_python_implementation == \"CPython\" and sys_platform == \"win32\" and python_version >= \"3.13\"", "pytest-mock (>=3.11.1)", "pytest-randomly (>=3.12)", "pytest-timeout (>=2.1)", "setuptools (>=68)", "time-machine (>=2.10) ; platform_python_implementation == \"CPython\""]
[[package]] [[package]]
name = "watchdog" name = "watchdog"
@@ -1675,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 = "67a8e0d34c0d1af0f8e4d617d80fd5afc8d197e5d5444f78fd82e4f716a52965" 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_byte(cls, web_conf: dict) -> "MinerConfig":
"""Constructs a MinerConfig object from web configuration for Goldshell Byte miners."""
return cls(pools=PoolConfig.from_goldshell_byte(web_conf))
@classmethod @classmethod
def from_inno(cls, web_pools: list) -> "MinerConfig": def from_inno(cls, web_pools: list) -> "MinerConfig":
"""Constructs a MinerConfig object from web configuration for Innosilicon miners.""" """Constructs a MinerConfig object from web configuration for Innosilicon miners."""
@@ -283,13 +295,17 @@ class MinerConfig(BaseModel):
) )
@classmethod @classmethod
def from_vnish(cls, web_settings: dict, web_presets: list[dict]) -> "MinerConfig": def from_vnish(
cls, web_settings: dict, web_presets: list[dict], web_perf_summary: dict
) -> "MinerConfig":
"""Constructs a MinerConfig object from web settings for VNish miners.""" """Constructs a MinerConfig object from web settings for VNish miners."""
return cls( return cls(
pools=PoolConfig.from_vnish(web_settings), pools=PoolConfig.from_vnish(web_settings),
fan_mode=FanModeConfig.from_vnish(web_settings), fan_mode=FanModeConfig.from_vnish(web_settings),
temperature=TemperatureConfig.from_vnish(web_settings), temperature=TemperatureConfig.from_vnish(web_settings),
mining_mode=MiningModeConfig.from_vnish(web_settings, web_presets), mining_mode=MiningModeConfig.from_vnish(
web_settings, web_presets, web_perf_summary
),
) )
@classmethod @classmethod
@@ -346,3 +362,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:
@@ -412,12 +427,18 @@ class MiningModePreset(MinerConfigValue):
@classmethod @classmethod
def from_vnish( def from_vnish(
cls, web_overclock_settings: dict, web_presets: list[dict] cls,
web_overclock_settings: dict,
web_presets: list[dict],
web_perf_summary: dict,
) -> "MiningModePreset": ) -> "MiningModePreset":
active_preset = None active_preset = web_perf_summary.get("current_preset")
for preset in web_presets:
if preset["name"] == web_overclock_settings["preset"]: if active_preset is None:
active_preset = preset for preset in web_presets:
if preset["name"] == web_overclock_settings["preset"]:
active_preset = preset
return cls( return cls(
active_preset=MiningPreset.from_vnish(active_preset), active_preset=MiningPreset.from_vnish(active_preset),
available_presets=[MiningPreset.from_vnish(p) for p in web_presets], available_presets=[MiningPreset.from_vnish(p) for p in web_presets],
@@ -703,7 +724,9 @@ class MiningModeConfig(MinerConfigOption):
return cls.default() return cls.default()
@classmethod @classmethod
def from_vnish(cls, web_settings: dict, web_presets: list[dict]): def from_vnish(
cls, web_settings: dict, web_presets: list[dict], web_perf_summary: dict
):
try: try:
mode_settings = web_settings["miner"]["overclock"] mode_settings = web_settings["miner"]["overclock"]
except KeyError: except KeyError:
@@ -712,7 +735,9 @@ class MiningModeConfig(MinerConfigOption):
if mode_settings["preset"] == "disabled": if mode_settings["preset"] == "disabled":
return MiningModeManual.from_vnish(mode_settings) return MiningModeManual.from_vnish(mode_settings)
else: else:
return MiningModePreset.from_vnish(mode_settings, web_presets) return MiningModePreset.from_vnish(
mode_settings, web_presets, web_perf_summary
)
@classmethod @classmethod
def from_boser(cls, grpc_miner_conf: dict): def from_boser(cls, grpc_miner_conf: dict):
@@ -779,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"]
@@ -631,6 +667,16 @@ class PoolConfig(MinerConfigValue):
def from_goldshell(cls, web_pools: list) -> "PoolConfig": def from_goldshell(cls, web_pools: list) -> "PoolConfig":
return cls(groups=[PoolGroup.from_goldshell(web_pools)]) return cls(groups=[PoolGroup.from_goldshell(web_pools)])
@classmethod
def from_goldshell_byte(cls, web_pools: list) -> "PoolConfig":
return cls(
groups=[
PoolGroup.from_goldshell(g["pools"])
for g in web_pools
if len(g["pools"]) > 0
]
)
@classmethod @classmethod
def from_inno(cls, web_pools: list) -> "PoolConfig": def from_inno(cls, web_pools: list) -> "PoolConfig":
return cls(groups=[PoolGroup.from_inno(web_pools)]) return cls(groups=[PoolGroup.from_inno(web_pools)])

View File

@@ -70,6 +70,7 @@ class MinerData(BaseModel):
errors: A list of errors on the miner. errors: A list of errors on the miner.
fault_light: Whether the fault light is on as a boolean. fault_light: Whether the fault light is on as a boolean.
efficiency: Efficiency of the miner in J/TH (Watts per TH/s). Calculated automatically. efficiency: Efficiency of the miner in J/TH (Watts per TH/s). Calculated automatically.
efficiency_fract: Same as efficiency, but is not rounded to integer. Calculated automatically.
is_mining: Whether the miner is mining. is_mining: Whether the miner is mining.
pools: A list of PoolMetrics instances, each representing metrics for a pool. pools: A list of PoolMetrics instances, each representing metrics for a pool.
""" """
@@ -284,12 +285,24 @@ class MinerData(BaseModel):
@computed_field # type: ignore[misc] @computed_field # type: ignore[misc]
@property @property
def efficiency(self) -> int | None: def efficiency(self) -> int | None:
efficiency = self._efficiency(0)
if efficiency is None:
return None
else:
return int(efficiency)
@computed_field # type: ignore[misc]
@property
def efficiency_fract(self) -> float | None:
return self._efficiency(2)
def _efficiency(self, ndigits: int) -> float | None:
if self.hashrate is None or self.wattage is None: if self.hashrate is None or self.wattage is None:
return None return None
try: try:
return round(self.wattage / float(self.hashrate)) return round(self.wattage / float(self.hashrate), ndigits)
except ZeroDivisionError: except ZeroDivisionError:
return 0 return 0.0
@computed_field # type: ignore[misc] @computed_field # type: ignore[misc]
@property @property

View File

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

@@ -1,5 +1,6 @@
from .base import MinerAlgoType from .base import MinerAlgoType
from .blake256 import Blake256Algo from .blake256 import Blake256Algo
from .blockflow import BlockFlowAlgo
from .eaglesong import EaglesongAlgo from .eaglesong import EaglesongAlgo
from .equihash import EquihashAlgo from .equihash import EquihashAlgo
from .ethash import EtHashAlgo from .ethash import EtHashAlgo
@@ -11,6 +12,7 @@ from .kheavyhash import KHeavyHashAlgo
from .scrypt import ScryptAlgo from .scrypt import ScryptAlgo
from .sha256 import SHA256Algo from .sha256 import SHA256Algo
from .x11 import X11Algo from .x11 import X11Algo
from .zksnark import ZkSnarkAlgo
class MinerAlgo: class MinerAlgo:
@@ -24,3 +26,5 @@ class MinerAlgo:
EAGLESONG = EaglesongAlgo EAGLESONG = EaglesongAlgo
ETHASH = EtHashAlgo ETHASH = EtHashAlgo
EQUIHASH = EquihashAlgo EQUIHASH = EquihashAlgo
BLOCKFLOW = BlockFlowAlgo
ZKSNARK = ZkSnarkAlgo

View File

@@ -0,0 +1,12 @@
from __future__ import annotations
from .base import MinerAlgoType
from .hashrate import BlockFlowHashRate
from .hashrate.unit import BlockFlowUnit
class BlockFlowAlgo(MinerAlgoType):
hashrate: type[BlockFlowHashRate] = BlockFlowHashRate
unit: type[BlockFlowUnit] = BlockFlowUnit
name = "BlockFlow"

View File

@@ -1,5 +1,6 @@
from .base import AlgoHashRateType from .base import AlgoHashRateType
from .blake256 import Blake256HashRate from .blake256 import Blake256HashRate
from .blockflow import BlockFlowHashRate
from .eaglesong import EaglesongHashRate from .eaglesong import EaglesongHashRate
from .equihash import EquihashHashRate from .equihash import EquihashHashRate
from .ethash import EtHashHashRate from .ethash import EtHashHashRate
@@ -9,6 +10,7 @@ from .kheavyhash import KHeavyHashHashRate
from .scrypt import ScryptHashRate from .scrypt import ScryptHashRate
from .sha256 import SHA256HashRate from .sha256 import SHA256HashRate
from .x11 import X11HashRate from .x11 import X11HashRate
from .zksnark import ZkSnarkHashRate
class AlgoHashRate: class AlgoHashRate:
@@ -22,3 +24,5 @@ class AlgoHashRate:
EAGLESONG = EaglesongHashRate EAGLESONG = EaglesongHashRate
ETHASH = EtHashHashRate ETHASH = EtHashHashRate
EQUIHASH = EquihashHashRate EQUIHASH = EquihashHashRate
BLOCKFLOW = BlockFlowHashRate
ZKSNARK = ZkSnarkHashRate

View File

@@ -0,0 +1,18 @@
from __future__ import annotations
from typing_extensions import Self
from pyasic.device.algorithm.hashrate.base import AlgoHashRateType
from pyasic.device.algorithm.hashrate.unit.blockflow import BlockFlowUnit
from .unit import HashUnit
class BlockFlowHashRate(AlgoHashRateType):
rate: float
unit: BlockFlowUnit = HashUnit.BLOCKFLOW.default
def into(self, other: BlockFlowUnit) -> Self:
return self.__class__(
rate=self.rate / (other.value / self.unit.value), unit=other
)

View File

@@ -1,4 +1,5 @@
from .blake256 import Blake256Unit from .blake256 import Blake256Unit
from .blockflow import BlockFlowUnit
from .eaglesong import EaglesongUnit from .eaglesong import EaglesongUnit
from .equihash import EquihashUnit from .equihash import EquihashUnit
from .ethash import EtHashUnit from .ethash import EtHashUnit
@@ -8,6 +9,7 @@ from .kheavyhash import KHeavyHashUnit
from .scrypt import ScryptUnit from .scrypt import ScryptUnit
from .sha256 import SHA256Unit from .sha256 import SHA256Unit
from .x11 import X11Unit from .x11 import X11Unit
from .zksnark import ZkSnarkUnit
class HashUnit: class HashUnit:
@@ -21,3 +23,5 @@ class HashUnit:
EAGLESONG = EaglesongUnit EAGLESONG = EaglesongUnit
ETHASH = EtHashUnit ETHASH = EtHashUnit
EQUIHASH = EquihashUnit EQUIHASH = EquihashUnit
BLOCKFLOW = BlockFlowUnit
ZKSNARK = ZkSnarkUnit

View File

@@ -0,0 +1,16 @@
from __future__ import annotations
from .base import AlgoHashRateUnitType
class BlockFlowUnit(AlgoHashRateUnitType):
H = 1
KH = int(H) * 1000
MH = int(KH) * 1000
GH = int(MH) * 1000
TH = int(GH) * 1000
PH = int(TH) * 1000
EH = int(PH) * 1000
ZH = int(EH) * 1000
default = MH

View File

@@ -0,0 +1,16 @@
from __future__ import annotations
from .base import AlgoHashRateUnitType
class ZkSnarkUnit(AlgoHashRateUnitType):
H = 1
KH = int(H) * 1000
MH = int(KH) * 1000
GH = int(MH) * 1000
TH = int(GH) * 1000
PH = int(TH) * 1000
EH = int(PH) * 1000
ZH = int(EH) * 1000
default = GH

View File

@@ -0,0 +1,18 @@
from __future__ import annotations
from typing_extensions import Self
from pyasic.device.algorithm.hashrate.base import AlgoHashRateType
from pyasic.device.algorithm.hashrate.unit.zksnark import ZkSnarkUnit
from .unit import HashUnit
class ZkSnarkHashRate(AlgoHashRateType):
rate: float
unit: ZkSnarkUnit = HashUnit.ZKSNARK.default
def into(self, other: ZkSnarkUnit) -> Self:
return self.__class__(
rate=self.rate / (other.value / self.unit.value), unit=other
)

View File

@@ -0,0 +1,12 @@
from __future__ import annotations
from .base import MinerAlgoType
from .hashrate import ZkSnarkHashRate
from .hashrate.unit import ZkSnarkUnit
class ZkSnarkAlgo(MinerAlgoType):
hashrate: type[ZkSnarkHashRate] = ZkSnarkHashRate
unit: type[ZkSnarkUnit] = ZkSnarkUnit
name = "zkSNARK"

View File

@@ -43,6 +43,7 @@ class AntminerModels(MinerModelType):
S19jNoPIC = "S19j No PIC" S19jNoPIC = "S19j No PIC"
S19ProPlus = "S19 Pro+" S19ProPlus = "S19 Pro+"
S19jPro = "S19j Pro" S19jPro = "S19j Pro"
S19jPlus = "S19j+"
S19jProNoPIC = "S19j Pro No PIC" S19jProNoPIC = "S19j Pro No PIC"
S19jProPlus = "S19j Pro+" S19jProPlus = "S19j Pro+"
S19jProPlusNoPIC = "S19j Pro+ No PIC" S19jProPlusNoPIC = "S19j Pro+ No PIC"
@@ -54,14 +55,17 @@ class AntminerModels(MinerModelType):
S19ProPlusHydro = "S19 Pro+ Hydro" S19ProPlusHydro = "S19 Pro+ Hydro"
S19KPro = "S19K Pro" S19KPro = "S19K Pro"
S19kPro = "S19k Pro" S19kPro = "S19k Pro"
S19ProA = "S19 Pro A"
S19kProNoPIC = "S19k Pro No PIC" S19kProNoPIC = "S19k Pro No PIC"
S19jXP = "S19j XP" S19jXP = "S19j XP"
T19 = "T19" T19 = "T19"
S21 = "S21" S21 = "S21"
S21Plus = "S21+" S21Plus = "S21+"
S21PlusHydro = "S21+ Hydro"
S21Pro = "S21 Pro" S21Pro = "S21 Pro"
S21Hydro = "S21 Hydro" S21Hydro = "S21 Hydro"
T21 = "T21" T21 = "T21"
S19XPHydro = "S19 XP Hydro"
def __str__(self): def __str__(self):
return self.value return self.value
@@ -451,6 +455,8 @@ class AvalonminerModels(MinerModelType):
Avalon1246 = "Avalon 1246" Avalon1246 = "Avalon 1246"
Avalon1566 = "Avalon 1566" Avalon1566 = "Avalon 1566"
AvalonNano3 = "Avalon Nano 3" AvalonNano3 = "Avalon Nano 3"
AvalonNano3s = "Avalon Nano 3s"
AvalonQHome = "Avalon Q Home"
def __str__(self): def __str__(self):
return self.value return self.value
@@ -473,6 +479,7 @@ class GoldshellModels(MinerModelType):
KDMax = "KD Max" KDMax = "KD Max"
KDBoxII = "KD Box II" KDBoxII = "KD Box II"
KDBoxPro = "KD Box Pro" KDBoxPro = "KD Box Pro"
Byte = "Byte"
def __str__(self): def __str__(self):
return self.value return self.value
@@ -530,6 +537,7 @@ class IceRiverModels(MinerModelType):
KS5 = "KS5" KS5 = "KS5"
KS5L = "KS5L" KS5L = "KS5L"
KS5M = "KS5M" KS5M = "KS5M"
AL3 = "AL3"
def __str__(self): def __str__(self):
return self.value return self.value
@@ -555,7 +563,9 @@ class BraiinsModels(MinerModelType):
class ElphapexModels(MinerModelType): class ElphapexModels(MinerModelType):
DG1 = "DG1"
DG1Plus = "DG1+" DG1Plus = "DG1+"
DG1Home = "DG1Home"
class MinerModel: class MinerModel:

View File

@@ -25,7 +25,9 @@ from pyasic.miners.device.models import (
S19i, S19i,
S19j, S19j,
S19jNoPIC, S19jNoPIC,
S19jPlus,
S19jPro, S19jPro,
S19jProPlus,
S19jXP, S19jXP,
S19KPro, S19KPro,
S19Plus, S19Plus,
@@ -80,6 +82,10 @@ class BMMinerS19jPro(AntminerModern, S19jPro):
pass pass
class BMMinerS19jPlus(AntminerModern, S19jPlus):
pass
class BMMinerS19L(AntminerModern, S19L): class BMMinerS19L(AntminerModern, S19L):
pass pass
@@ -102,3 +108,7 @@ class BMMinerS19KPro(AntminerModern, S19KPro):
class BMMinerS19jXP(AntminerModern, S19jXP): class BMMinerS19jXP(AntminerModern, S19jXP):
pass pass
class BMMinerS19jProPlus(AntminerModern, S19jProPlus):
pass

View File

@@ -22,7 +22,9 @@ from .S19 import (
BMMinerS19i, BMMinerS19i,
BMMinerS19j, BMMinerS19j,
BMMinerS19jNoPIC, BMMinerS19jNoPIC,
BMMinerS19jPlus,
BMMinerS19jPro, BMMinerS19jPro,
BMMinerS19jProPlus,
BMMinerS19jXP, BMMinerS19jXP,
BMMinerS19KPro, BMMinerS19KPro,
BMMinerS19L, BMMinerS19L,

View File

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

View File

@@ -13,5 +13,11 @@
# See the License for the specific language governing permissions and - # See the License for the specific language governing permissions and -
# limitations under the License. - # limitations under the License. -
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
from .S21 import BMMinerS21, BMMinerS21Hydro, BMMinerS21Plus, BMMinerS21Pro from .S21 import (
BMMinerS21,
BMMinerS21Hydro,
BMMinerS21Plus,
BMMinerS21PlusHydro,
BMMinerS21Pro,
)
from .T21 import BMMinerT21 from .T21 import BMMinerT21

View File

@@ -30,6 +30,7 @@ from pyasic.miners.device.models import (
S19Plus, S19Plus,
S19Pro, S19Pro,
S19ProPlusHydro, S19ProPlusHydro,
S19XPHydro,
) )
@@ -87,3 +88,7 @@ class BOSMinerS19XP(BOSer, S19XP):
class BOSMinerS19ProPlusHydro(BOSer, S19ProPlusHydro): class BOSMinerS19ProPlusHydro(BOSer, S19ProPlusHydro):
pass pass
class BOSMinerS19XPHydro(BOSer, S19XPHydro):
pass

View File

@@ -29,5 +29,6 @@ from .S19 import (
BOSMinerS19Pro, BOSMinerS19Pro,
BOSMinerS19ProPlusHydro, BOSMinerS19ProPlusHydro,
BOSMinerS19XP, BOSMinerS19XP,
BOSMinerS19XPHydro,
) )
from .T19 import BOSMinerT19 from .T19 import BOSMinerT19

View File

@@ -15,12 +15,40 @@
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
from pyasic.miners.backends import BOSer from pyasic.miners.backends import BOSer
from pyasic.miners.device.models import S21, S21Pro from pyasic.miners.device.models import S21, S21Hydro, S21Plus, S21PlusHydro, S21Pro
# ------------------------------------------------------------------------------
# Copyright 2022 Upstream Data Inc -
# -
# Licensed under the Apache License, Version 2.0 (the "License"); -
# you may not use this file except in compliance with the License. -
# You may obtain a copy of the License at -
# -
# http://www.apache.org/licenses/LICENSE-2.0 -
# -
# Unless required by applicable law or agreed to in writing, software -
# distributed under the License is distributed on an "AS IS" BASIS, -
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -
# See the License for the specific language governing permissions and -
# limitations under the License. -
# ------------------------------------------------------------------------------
class BOSMinerS21(BOSer, S21): class BOSMinerS21(BOSer, S21):
pass pass
class BOSMinerS21Plus(BOSer, S21Plus):
pass
class BOSMinerS21PlusHydro(BOSer, S21PlusHydro):
pass
class BOSMinerS21Pro(BOSer, S21Pro): class BOSMinerS21Pro(BOSer, S21Pro):
pass pass
class BOSMinerS21Hydro(BOSer, S21Hydro):
pass

View File

@@ -14,5 +14,11 @@
# limitations under the License. - # limitations under the License. -
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
from .S21 import BOSMinerS21, BOSMinerS21Pro from .S21 import (
BOSMinerS21,
BOSMinerS21Hydro,
BOSMinerS21Plus,
BOSMinerS21PlusHydro,
BOSMinerS21Pro,
)
from .T21 import BOSMinerT21 from .T21 import BOSMinerT21

View File

@@ -0,0 +1,22 @@
# ------------------------------------------------------------------------------
# Copyright 2022 Upstream Data Inc -
# -
# Licensed under the Apache License, Version 2.0 (the "License"); -
# you may not use this file except in compliance with the License. -
# You may obtain a copy of the License at -
# -
# http://www.apache.org/licenses/LICENSE-2.0 -
# -
# Unless required by applicable law or agreed to in writing, software -
# distributed under the License is distributed on an "AS IS" BASIS, -
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -
# See the License for the specific language governing permissions and -
# limitations under the License. -
# ------------------------------------------------------------------------------
from pyasic.miners.backends import LUXMiner
from pyasic.miners.device.models import S21, T21
class LUXMinerT21(LUXMiner, T21):
pass

View File

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

View File

@@ -20,13 +20,16 @@ from pyasic.miners.device.models import (
S19XP, S19XP,
S19a, S19a,
S19aPro, S19aPro,
S19Hydro,
S19i, S19i,
S19j, S19j,
S19jPro, S19jPro,
S19kPro, S19kPro,
S19NoPIC, S19NoPIC,
S19Pro, S19Pro,
S19ProA,
S19ProHydro, S19ProHydro,
S19XPHydro,
) )
@@ -42,10 +45,18 @@ class VNishS19Pro(VNish, S19Pro):
pass pass
class VNishS19Hydro(VNish, S19Hydro):
pass
class VNishS19XP(VNish, S19XP): class VNishS19XP(VNish, S19XP):
pass pass
class VNishS19XPHydro(VNish, S19XPHydro):
pass
class VNishS19a(VNish, S19a): class VNishS19a(VNish, S19a):
pass pass
@@ -54,6 +65,10 @@ class VNishS19aPro(VNish, S19aPro):
pass pass
class VNishS19ProA(VNish, S19ProA):
pass
class VNishS19i(VNish, S19i): class VNishS19i(VNish, S19i):
pass pass
@@ -72,3 +87,7 @@ class VNishS19ProHydro(VNish, S19ProHydro):
class VNishS19kPro(VNish, S19kPro): class VNishS19kPro(VNish, S19kPro):
pass pass
class VNishS19ProA(VNish, S19ProA):
pass

View File

@@ -18,13 +18,16 @@ from .S19 import (
VNishS19, VNishS19,
VNishS19a, VNishS19a,
VNishS19aPro, VNishS19aPro,
VNishS19Hydro,
VNishS19i, VNishS19i,
VNishS19j, VNishS19j,
VNishS19jPro, VNishS19jPro,
VNishS19kPro, VNishS19kPro,
VNishS19NoPIC, VNishS19NoPIC,
VNishS19Pro, VNishS19Pro,
VNishS19ProA,
VNishS19ProHydro, VNishS19ProHydro,
VNishS19XP, VNishS19XP,
VNishS19XPHydro,
) )
from .T19 import VNishT19 from .T19 import VNishT19

View File

@@ -15,8 +15,24 @@
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
from pyasic.miners.backends import VNish from pyasic.miners.backends import VNish
from pyasic.miners.device.models import S21 from pyasic.miners.device.models import S21, S21Hydro, S21Plus, S21PlusHydro, S21Pro
class VNishS21(VNish, S21): class VNishS21(VNish, S21):
pass pass
class VNishS21Plus(VNish, S21Plus):
pass
class VNishS21PlusHydro(VNish, S21PlusHydro):
pass
class VNishS21Pro(VNish, S21Pro):
pass
class VNishS21Hydro(VNish, S21Hydro):
pass

View File

@@ -14,5 +14,11 @@
# limitations under the License. - # limitations under the License. -
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
from .S21 import VNishS21 from .S21 import (
VNishS21,
VNishS21Hydro,
VNishS21Plus,
VNishS21PlusHydro,
VNishS21Pro,
)
from .T21 import VNishT21 from .T21 import VNishT21

View File

@@ -18,5 +18,5 @@ from pyasic.miners.backends import VNish
from pyasic.miners.device.models import L3Plus from pyasic.miners.device.models import L3Plus
class VnishL3Plus(VNish, L3Plus): class VNishL3Plus(VNish, L3Plus):
pass pass

View File

@@ -14,4 +14,4 @@
# limitations under the License. - # limitations under the License. -
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
from .L3 import VnishL3Plus from .L3 import VNishL3Plus

View File

@@ -18,5 +18,5 @@ from pyasic.miners.backends import VNish
from pyasic.miners.device.models import L7 from pyasic.miners.device.models import L7
class VnishL7(VNish, L7): class VNishL7(VNish, L7):
pass pass

View File

@@ -14,4 +14,4 @@
# limitations under the License. - # limitations under the License. -
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
from .L7 import VnishL7 from .L7 import VNishL7

View File

@@ -0,0 +1,22 @@
# ------------------------------------------------------------------------------
# Copyright 2022 Upstream Data Inc -
# -
# Licensed under the Apache License, Version 2.0 (the "License"); -
# you may not use this file except in compliance with the License. -
# You may obtain a copy of the License at -
# -
# http://www.apache.org/licenses/LICENSE-2.0 -
# -
# Unless required by applicable law or agreed to in writing, software -
# distributed under the License is distributed on an "AS IS" BASIS, -
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -
# See the License for the specific language governing permissions and -
# limitations under the License. -
# ------------------------------------------------------------------------------
from pyasic.miners.backends import VNish
from pyasic.miners.device.models import L9
class VNishL9(VNish, L9):
pass

View File

@@ -0,0 +1,17 @@
# ------------------------------------------------------------------------------
# Copyright 2022 Upstream Data Inc -
# -
# Licensed under the Apache License, Version 2.0 (the "License"); -
# you may not use this file except in compliance with the License. -
# You may obtain a copy of the License at -
# -
# http://www.apache.org/licenses/LICENSE-2.0 -
# -
# Unless required by applicable law or agreed to in writing, software -
# distributed under the License is distributed on an "AS IS" BASIS, -
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -
# See the License for the specific language governing permissions and -
# limitations under the License. -
# ------------------------------------------------------------------------------
from .L9 import VNishL9

View File

@@ -16,6 +16,7 @@
from .X3 import * from .X3 import *
from .X7 import * from .X7 import *
from .X9 import *
from .X17 import * from .X17 import *
from .X19 import * from .X19 import *
from .X21 import * from .X21 import *

View File

@@ -0,0 +1,22 @@
# ------------------------------------------------------------------------------
# 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.miners.backends import AvalonMiner
from pyasic.miners.device.models import AvalonQHome
class CGMinerAvalonQHome(AvalonMiner, AvalonQHome):
pass

View File

@@ -0,0 +1 @@
from .Q import CGMinerAvalonQHome

View File

@@ -22,3 +22,4 @@ from .A11X import *
from .A12X import * from .A12X import *
from .A15X import * from .A15X import *
from .nano import * from .nano import *
from .Q import *

View File

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

View File

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

View File

@@ -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

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

View File

@@ -13,8 +13,9 @@
# 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 copy
import re import re
import time
from typing import List, Optional from typing import List, Optional
from pyasic.data import Fan, HashBoard from pyasic.data import Fan, HashBoard
@@ -22,6 +23,7 @@ from pyasic.device.algorithm import AlgoHashRate
from pyasic.errors import APIError from pyasic.errors import APIError
from pyasic.miners.backends.cgminer import CGMiner from pyasic.miners.backends.cgminer import CGMiner
from pyasic.miners.data import DataFunction, DataLocations, DataOptions, RPCAPICommand from pyasic.miners.data import DataFunction, DataLocations, DataOptions, RPCAPICommand
from pyasic.rpc.avalonminer import AvalonMinerRPCAPI
AVALON_DATA_LOC = DataLocations( AVALON_DATA_LOC = DataLocations(
**{ **{
@@ -43,31 +45,31 @@ AVALON_DATA_LOC = DataLocations(
), ),
str(DataOptions.EXPECTED_HASHRATE): DataFunction( str(DataOptions.EXPECTED_HASHRATE): DataFunction(
"_get_expected_hashrate", "_get_expected_hashrate",
[RPCAPICommand("rpc_stats", "stats")], [RPCAPICommand("rpc_estats", "estats")],
), ),
str(DataOptions.HASHBOARDS): DataFunction( str(DataOptions.HASHBOARDS): DataFunction(
"_get_hashboards", "_get_hashboards",
[RPCAPICommand("rpc_stats", "stats")], [RPCAPICommand("rpc_estats", "estats")],
), ),
str(DataOptions.ENVIRONMENT_TEMP): DataFunction( str(DataOptions.ENVIRONMENT_TEMP): DataFunction(
"_get_env_temp", "_get_env_temp",
[RPCAPICommand("rpc_stats", "stats")], [RPCAPICommand("rpc_estats", "estats")],
), ),
str(DataOptions.WATTAGE_LIMIT): DataFunction( str(DataOptions.WATTAGE_LIMIT): DataFunction(
"_get_wattage_limit", "_get_wattage_limit",
[RPCAPICommand("rpc_stats", "stats")], [RPCAPICommand("rpc_estats", "estats")],
), ),
str(DataOptions.WATTAGE): DataFunction( str(DataOptions.WATTAGE): DataFunction(
"_get_wattage", "_get_wattage",
[RPCAPICommand("rpc_stats", "stats")], [RPCAPICommand("rpc_estats", "estats")],
), ),
str(DataOptions.FANS): DataFunction( str(DataOptions.FANS): DataFunction(
"_get_fans", "_get_fans",
[RPCAPICommand("rpc_stats", "stats")], [RPCAPICommand("rpc_estats", "estats")],
), ),
str(DataOptions.FAULT_LIGHT): DataFunction( str(DataOptions.FAULT_LIGHT): DataFunction(
"_get_fault_light", "_get_fault_light",
[RPCAPICommand("rpc_stats", "stats")], [RPCAPICommand("rpc_estats", "estats")],
), ),
str(DataOptions.UPTIME): DataFunction( str(DataOptions.UPTIME): DataFunction(
"_get_uptime", "_get_uptime",
@@ -84,6 +86,9 @@ AVALON_DATA_LOC = DataLocations(
class AvalonMiner(CGMiner): class AvalonMiner(CGMiner):
"""Handler for Avalon Miners""" """Handler for Avalon Miners"""
_rpc_cls = AvalonMinerRPCAPI
rpc: AvalonMinerRPCAPI
data_locations = AVALON_DATA_LOC data_locations = AVALON_DATA_LOC
async def fault_light_on(self) -> bool: async def fault_light_on(self) -> bool:
@@ -134,45 +139,94 @@ class AvalonMiner(CGMiner):
return False return False
return False return False
async def stop_mining(self) -> bool:
try:
# Shut off 5 seconds from now
timestamp = int(time.time()) + 5
data = await self.rpc.ascset(0, f"softoff", f"1:{timestamp}")
except APIError:
return False
if "success" in data["STATUS"][0]["Msg"]:
return True
return False
async def resume_mining(self) -> bool:
try:
# Shut off 5 seconds from now
timestamp = int(time.time()) + 5
data = await self.rpc.ascset(0, f"softon", f"1:{timestamp}")
except APIError:
return False
if "success" in data["STATUS"][0]["Msg"]:
return True
return False
@staticmethod @staticmethod
def parse_stats(stats): def parse_estats(data):
_stats_items = re.findall(".+?\\[*?]", stats) # Deep copy to preserve original structure
stats_items = [] new_data = copy.deepcopy(data)
stats_dict = {}
for item in _stats_items:
if ": " in item:
data = item.replace("]", "").split("[")
data_list = [i.split(": ") for i in data[1].strip().split(", ")]
data_dict = {}
try:
for key, val in [tuple(item) for item in data_list]:
data_dict[key] = val
except ValueError:
# --avalon args
for arg_item in data_list:
item_data = arg_item[0].split(" ")
for idx, val in enumerate(item_data):
if idx % 2 == 0 or idx == 0:
data_dict[val] = item_data[idx + 1]
raw_data = [data[0].strip(), data_dict] def convert_value(val, key):
val = val.strip()
if key == "SYSTEMSTATU":
return val
if " " in val:
parts = val.split()
result = []
for part in parts:
if part.isdigit():
result.append(int(part))
else:
try:
result.append(float(part))
except ValueError:
result.append(part)
return result
else: else:
raw_data = [ if val.isdigit():
value return int(val)
for value in item.replace("[", " ") try:
.replace("]", " ") return float(val)
.split(" ")[:-1] except ValueError:
if value != "" return val
]
if len(raw_data) == 1:
raw_data.append("")
if raw_data[0] == "":
raw_data = raw_data[1:]
stats_dict[raw_data[0]] = raw_data[1:] def parse_info_block(info_str):
stats_items.append(raw_data) pattern = re.compile(r"(\w+)\[([^\]]*)\]")
return {
key: convert_value(val, key) for key, val in pattern.findall(info_str)
}
return stats_dict for stat in new_data.get("STATS", []):
keys_to_replace = {}
for key, value in stat.items():
if "MM" in key:
# Normalize key by removing suffix after colon
norm_key = key.split(":")[0]
mm_data = value
if not isinstance(mm_data, str):
continue
if mm_data.startswith("'STATS':"):
mm_data = mm_data[len("'STATS':") :]
keys_to_replace[norm_key] = parse_info_block(mm_data)
elif key == "HBinfo":
match = re.search(r"'(\w+)':\{(.+)\}", value)
if match:
hb_key = match.group(1)
hb_data = match.group(2)
keys_to_replace[key] = {hb_key: parse_info_block(hb_data)}
# Remove old keys and insert parsed versions
for k in list(stat.keys()):
if "MM" in k or k == "HBinfo":
del stat[k]
stat.update(keys_to_replace)
return new_data
################################################## ##################################################
### DATA GATHERING FUNCTIONS (get_{some_data}) ### ### DATA GATHERING FUNCTIONS (get_{some_data}) ###
@@ -211,7 +265,7 @@ class AvalonMiner(CGMiner):
except (KeyError, IndexError, ValueError, TypeError): except (KeyError, IndexError, ValueError, TypeError):
pass pass
async def _get_hashboards(self, rpc_stats: dict = None) -> List[HashBoard]: async def _get_hashboards(self, rpc_estats: dict = None) -> List[HashBoard]:
if self.expected_hashboards is None: if self.expected_hashboards is None:
return [] return []
@@ -220,164 +274,201 @@ class AvalonMiner(CGMiner):
for i in range(self.expected_hashboards) for i in range(self.expected_hashboards)
] ]
if rpc_stats is None: if rpc_estats is None:
try: try:
rpc_stats = await self.rpc.stats() rpc_estats = await self.rpc.estats()
except APIError: except APIError:
pass pass
if rpc_stats is not None: if rpc_estats is not None:
try: try:
unparsed_stats = rpc_stats["STATS"][0]["MM ID0"] parsed_estats = self.parse_estats(rpc_estats)
parsed_stats = self.parse_stats(unparsed_stats)
except (IndexError, KeyError, ValueError, TypeError): except (IndexError, KeyError, ValueError, TypeError):
return hashboards return hashboards
for board in range(self.expected_hashboards): for board in range(self.expected_hashboards):
try: try:
hashboards[board].chip_temp = int(parsed_stats["MTmax"][board]) board_hr = parsed_estats["STATS"][0]["MM ID0"]["MGHS"]
if isinstance(board_hr, list):
hashboards[board].hashrate = self.algo.hashrate(
rate=float(board_hr[board]), unit=self.algo.unit.GH
).into(self.algo.unit.default)
else:
hashboards[board].hashrate = self.algo.hashrate(
rate=float(board_hr), unit=self.algo.unit.GH
).into(self.algo.unit.default)
except LookupError: except LookupError:
pass pass
try: try:
board_hr = parsed_stats["MGHS"][board] hashboards[board].chip_temp = int(
hashboards[board].hashrate = self.algo.hashrate( parsed_estats["STATS"][0]["MM ID0"]["MTmax"][board]
rate=float(board_hr), unit=self.algo.unit.GH )
).into(self.algo.unit.default)
except LookupError: except LookupError:
pass try:
hashboards[board].chip_temp = int(
parsed_estats["STATS"][0]["MM ID0"]["Tmax"]
)
except LookupError:
pass
try: try:
hashboards[board].temp = int(parsed_stats["MTavg"][board]) hashboards[board].temp = int(
parsed_estats["STATS"][0]["MM ID0"]["MTmax"][board]
)
except LookupError: except LookupError:
pass try:
hashboards[board].temp = int(
parsed_estats["STATS"][0]["MM ID0"]["Tavg"]
)
except LookupError:
pass
try: try:
chip_data = parsed_stats[f"PVT_T{board}"] hashboards[board].inlet_temp = int(
parsed_estats["STATS"][0]["MM ID0"]["MTavg"][board]
)
except LookupError:
try:
hashboards[board].inlet_temp = int(
parsed_estats["STATS"][0]["MM ID0"]["HBITemp"]
)
except LookupError:
pass
try:
hashboards[board].outlet_temp = int(
parsed_estats["STATS"][0]["MM ID0"]["MTmax"][board]
)
except LookupError:
try:
hashboards[board].outlet_temp = int(
parsed_estats["STATS"][0]["MM ID0"]["HBOTemp"]
)
except LookupError:
pass
try:
chip_data = parsed_estats["STATS"][0]["MM ID0"][f"PVT_T{board}"]
hashboards[board].missing = False hashboards[board].missing = False
if chip_data: if chip_data:
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:
pass try:
chip_data = parsed_estats["STATS"][0]["HBinfo"][f"HB{board}"][
f"PVT_T{board}"
]
hashboards[board].missing = False
if chip_data:
hashboards[board].chips = len(
[item for item in chip_data if not item == "0"]
)
except LookupError:
pass
return hashboards return hashboards
async def _get_expected_hashrate( async def _get_expected_hashrate(
self, rpc_stats: dict = None self, rpc_estats: dict = None
) -> Optional[AlgoHashRate]: ) -> Optional[AlgoHashRate]:
if rpc_stats is None: if rpc_estats is None:
try: try:
rpc_stats = await self.rpc.stats() rpc_estats = await self.rpc.estats()
except APIError: except APIError:
pass pass
if rpc_stats is not None: if rpc_estats is not None:
try: try:
unparsed_stats = rpc_stats["STATS"][0]["MM ID0"] parsed_estats = self.parse_estats(rpc_estats)["STATS"][0]["MM ID0"]
parsed_stats = self.parse_stats(unparsed_stats)
return self.algo.hashrate( return self.algo.hashrate(
rate=float(parsed_stats["GHSmm"][0]), unit=self.algo.unit.GH rate=float(parsed_estats["GHSmm"]), unit=self.algo.unit.GH
).into(self.algo.unit.default) ).into(self.algo.unit.default)
except (IndexError, KeyError, ValueError, TypeError): except (IndexError, KeyError, ValueError, TypeError):
pass pass
async def _get_env_temp(self, rpc_stats: dict = None) -> Optional[float]: async def _get_env_temp(self, rpc_estats: dict = None) -> Optional[float]:
if rpc_stats is None: if rpc_estats is None:
try: try:
rpc_stats = await self.rpc.stats() rpc_estats = await self.rpc.estats()
except APIError: except APIError:
pass pass
if rpc_stats is not None: if rpc_estats is not None:
try: try:
unparsed_stats = rpc_stats["STATS"][0]["MM ID0"] parsed_estats = self.parse_estats(rpc_estats)["STATS"][0]["MM ID0"]
parsed_stats = self.parse_stats(unparsed_stats) return float(parsed_estats["Temp"])
return float(parsed_stats["Temp"][0])
except (IndexError, KeyError, ValueError, TypeError): except (IndexError, KeyError, ValueError, TypeError):
pass pass
async def _get_wattage_limit(self, rpc_stats: dict = None) -> Optional[int]: async def _get_wattage_limit(self, rpc_estats: dict = None) -> Optional[int]:
if rpc_stats is None: if rpc_estats is None:
try: try:
rpc_stats = await self.rpc.stats() rpc_estats = await self.rpc.estats()
except APIError: except APIError:
pass pass
if rpc_stats is not None: if rpc_estats is not None:
try: try:
unparsed_stats = rpc_stats["STATS"][0]["MM ID0"] parsed_estats = self.parse_estats(rpc_estats)["STATS"][0]["MM ID0"]
parsed_stats = self.parse_stats(unparsed_stats) return int(parsed_estats["MPO"])
return int(parsed_stats["MPO"][0])
except (IndexError, KeyError, ValueError, TypeError): except (IndexError, KeyError, ValueError, TypeError):
pass pass
async def _get_wattage(self, rpc_stats: dict = None) -> Optional[int]: async def _get_wattage(self, rpc_estats: dict = None) -> Optional[int]:
if rpc_stats is None: if rpc_estats is None:
try: try:
rpc_stats = await self.rpc.stats() rpc_estats = await self.rpc.estats()
except APIError: except APIError:
pass pass
if rpc_stats is not None: if rpc_estats is not None:
try: try:
unparsed_stats = rpc_stats["STATS"][0]["MM ID0"] parsed_estats = self.parse_estats(rpc_estats)["STATS"][0]["MM ID0"]
parsed_stats = self.parse_stats(unparsed_stats) return int(parsed_estats["WALLPOWER"])
return int(parsed_stats["WALLPOWER"][0])
except (IndexError, KeyError, ValueError, TypeError): except (IndexError, KeyError, ValueError, TypeError):
pass pass
async def _get_fans(self, rpc_stats: dict = None) -> List[Fan]: async def _get_fans(self, rpc_estats: dict = None) -> List[Fan]:
if self.expected_fans is None: if self.expected_fans is None:
return [] return []
if rpc_stats is None: if rpc_estats is None:
try: try:
rpc_stats = await self.rpc.stats() rpc_estats = await self.rpc.estats()
except APIError: except APIError:
pass pass
fans_data = [Fan() for _ in range(self.expected_fans)] fans_data = [Fan() for _ in range(self.expected_fans)]
if rpc_stats is not None: if rpc_estats is not None:
try: try:
unparsed_stats = rpc_stats["STATS"][0]["MM ID0"] parsed_estats = self.parse_estats(rpc_estats)["STATS"][0]["MM ID0"]
parsed_stats = self.parse_stats(unparsed_stats)
except LookupError: except LookupError:
return fans_data return fans_data
for fan in range(self.expected_fans): for fan in range(self.expected_fans):
try: try:
fans_data[fan].speed = int(parsed_stats[f"Fan{fan + 1}"][0]) fans_data[fan].speed = int(parsed_estats[f"Fan{fan + 1}"])
except (IndexError, KeyError, ValueError, TypeError): except (IndexError, KeyError, ValueError, TypeError):
pass pass
return fans_data return fans_data
async def _get_fault_light(self, rpc_stats: dict = None) -> Optional[bool]: async def _get_fault_light(self, rpc_estats: dict = None) -> Optional[bool]:
if self.light: if self.light:
return self.light return self.light
if rpc_stats is None: if rpc_estats is None:
try: try:
rpc_stats = await self.rpc.stats() rpc_estats = await self.rpc.estats()
except APIError: except APIError:
pass pass
if rpc_stats is not None: if rpc_estats is not None:
try: try:
unparsed_stats = rpc_stats["STATS"][0]["MM ID0"] parsed_estats = self.parse_estats(rpc_estats)["STATS"][0]["MM ID0"]
parsed_stats = self.parse_stats(unparsed_stats) led = int(parsed_estats["Led"])
led = int(parsed_stats["Led"][0])
return True if led == 1 else False return True if led == 1 else False
except (IndexError, KeyError, ValueError, TypeError): except (IndexError, KeyError, ValueError, TypeError):
pass pass
try:
data = await self.rpc.ascset(0, "led", "1-255")
except APIError:
return False
try:
if data["STATUS"][0]["Msg"] == "ASC 0 set info: LED[1]":
return True
except LookupError:
pass
return False return False

View File

@@ -13,14 +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
from typing import List, Optional
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
@@ -28,7 +28,36 @@ from pyasic.device.algorithm import AlgoHashRate
from pyasic.errors import APIError from pyasic.errors import APIError
from pyasic.miners.data import DataFunction, DataLocations, DataOptions, RPCAPICommand from pyasic.miners.data import DataFunction, DataLocations, DataOptions, RPCAPICommand
from pyasic.miners.device.firmware import StockFirmware from pyasic.miners.device.firmware import StockFirmware
from pyasic.rpc.btminer import BTMinerRPCAPI 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(
**{ **{
@@ -119,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
@@ -294,7 +323,7 @@ class BTMiner(StockFirmware):
async def _get_mac( async def _get_mac(
self, rpc_summary: dict = None, rpc_get_miner_info: dict = None self, rpc_summary: dict = None, rpc_get_miner_info: dict = None
) -> Optional[str]: ) -> str | None:
if rpc_get_miner_info is None: if rpc_get_miner_info is None:
try: try:
rpc_get_miner_info = await self.rpc.get_miner_info() rpc_get_miner_info = await self.rpc.get_miner_info()
@@ -321,7 +350,7 @@ class BTMiner(StockFirmware):
except LookupError: except LookupError:
pass pass
async def _get_api_ver(self, rpc_get_version: dict = None) -> Optional[str]: async def _get_api_ver(self, rpc_get_version: dict = None) -> str | None:
if rpc_get_version is None: if rpc_get_version is None:
try: try:
rpc_get_version = await self.rpc.get_version() rpc_get_version = await self.rpc.get_version()
@@ -346,7 +375,7 @@ class BTMiner(StockFirmware):
async def _get_fw_ver( async def _get_fw_ver(
self, rpc_get_version: dict = None, rpc_summary: dict = None self, rpc_get_version: dict = None, rpc_summary: dict = None
) -> Optional[str]: ) -> str | None:
if rpc_get_version is None: if rpc_get_version is None:
try: try:
rpc_get_version = await self.rpc.get_version() rpc_get_version = await self.rpc.get_version()
@@ -379,7 +408,7 @@ class BTMiner(StockFirmware):
return self.fw_ver return self.fw_ver
async def _get_hostname(self, rpc_get_miner_info: dict = None) -> Optional[str]: async def _get_hostname(self, rpc_get_miner_info: dict = None) -> str | None:
hostname = None hostname = None
if rpc_get_miner_info is None: if rpc_get_miner_info is None:
try: try:
@@ -395,7 +424,7 @@ class BTMiner(StockFirmware):
return hostname return hostname
async def _get_hashrate(self, rpc_summary: dict = None) -> Optional[AlgoHashRate]: async def _get_hashrate(self, rpc_summary: dict = None) -> AlgoHashRate | None:
if rpc_summary is None: if rpc_summary is None:
try: try:
rpc_summary = await self.rpc.summary() rpc_summary = await self.rpc.summary()
@@ -410,8 +439,9 @@ class BTMiner(StockFirmware):
).into(self.algo.unit.default) ).into(self.algo.unit.default)
except LookupError: except LookupError:
pass pass
return None
async def _get_hashboards(self, rpc_devs: dict = None) -> List[HashBoard]: async def _get_hashboards(self, rpc_devs: dict = None) -> list[HashBoard]:
if self.expected_hashboards is None: if self.expected_hashboards is None:
return [] return []
@@ -450,7 +480,7 @@ class BTMiner(StockFirmware):
return hashboards return hashboards
async def _get_env_temp(self, rpc_summary: dict = None) -> Optional[float]: async def _get_env_temp(self, rpc_summary: dict = None) -> float | None:
if rpc_summary is None: if rpc_summary is None:
try: try:
rpc_summary = await self.rpc.summary() rpc_summary = await self.rpc.summary()
@@ -462,8 +492,9 @@ class BTMiner(StockFirmware):
return rpc_summary["SUMMARY"][0]["Env Temp"] return rpc_summary["SUMMARY"][0]["Env Temp"]
except LookupError: except LookupError:
pass pass
return None
async def _get_wattage(self, rpc_summary: dict = None) -> Optional[int]: async def _get_wattage(self, rpc_summary: dict = None) -> int | None:
if rpc_summary is None: if rpc_summary is None:
try: try:
rpc_summary = await self.rpc.summary() rpc_summary = await self.rpc.summary()
@@ -476,8 +507,9 @@ class BTMiner(StockFirmware):
return wattage if not wattage == -1 else None return wattage if not wattage == -1 else None
except LookupError: except LookupError:
pass pass
return None
async def _get_wattage_limit(self, rpc_summary: dict = None) -> Optional[int]: async def _get_wattage_limit(self, rpc_summary: dict = None) -> int | None:
if rpc_summary is None: if rpc_summary is None:
try: try:
rpc_summary = await self.rpc.summary() rpc_summary = await self.rpc.summary()
@@ -489,10 +521,11 @@ class BTMiner(StockFirmware):
return rpc_summary["SUMMARY"][0]["Power Limit"] return rpc_summary["SUMMARY"][0]["Power Limit"]
except LookupError: except LookupError:
pass pass
return None
async def _get_fans( async def _get_fans(
self, rpc_summary: dict = None, rpc_get_psu: dict = None self, rpc_summary: dict = None, rpc_get_psu: dict = None
) -> List[Fan]: ) -> list[Fan]:
if self.expected_fans is None: if self.expected_fans is None:
return [] return []
@@ -517,7 +550,7 @@ class BTMiner(StockFirmware):
async def _get_fan_psu( async def _get_fan_psu(
self, rpc_summary: dict = None, rpc_get_psu: dict = None self, rpc_summary: dict = None, rpc_get_psu: dict = None
) -> Optional[int]: ) -> int | None:
if rpc_summary is None: if rpc_summary is None:
try: try:
rpc_summary = await self.rpc.summary() rpc_summary = await self.rpc.summary()
@@ -541,10 +574,11 @@ class BTMiner(StockFirmware):
return int(rpc_get_psu["Msg"]["fan_speed"]) return int(rpc_get_psu["Msg"]["fan_speed"])
except (KeyError, TypeError): except (KeyError, TypeError):
pass pass
return None
async def _get_errors( async def _get_errors(
self, rpc_summary: dict = None, rpc_get_error_code: dict = None self, rpc_summary: dict = None, rpc_get_error_code: dict = None
) -> List[MinerErrorData]: ) -> list[MinerErrorData]:
errors = [] errors = []
if rpc_get_error_code is None and rpc_summary is None: if rpc_get_error_code is None and rpc_summary is None:
try: try:
@@ -581,7 +615,7 @@ class BTMiner(StockFirmware):
async def _get_expected_hashrate( async def _get_expected_hashrate(
self, rpc_summary: dict = None self, rpc_summary: dict = None
) -> Optional[AlgoHashRate]: ) -> AlgoHashRate | None:
if rpc_summary is None: if rpc_summary is None:
try: try:
rpc_summary = await self.rpc.summary() rpc_summary = await self.rpc.summary()
@@ -598,8 +632,9 @@ class BTMiner(StockFirmware):
except LookupError: except LookupError:
pass pass
return None
async def _get_fault_light(self, rpc_get_miner_info: dict = None) -> Optional[bool]: async def _get_fault_light(self, rpc_get_miner_info: dict = None) -> bool | None:
if rpc_get_miner_info is None: if rpc_get_miner_info is None:
try: try:
rpc_get_miner_info = await self.rpc.get_miner_info() rpc_get_miner_info = await self.rpc.get_miner_info()
@@ -637,7 +672,7 @@ class BTMiner(StockFirmware):
async def set_hostname(self, hostname: str): async def set_hostname(self, hostname: str):
await self.rpc.set_hostname(hostname) await self.rpc.set_hostname(hostname)
async def _is_mining(self, rpc_status: dict = None) -> Optional[bool]: async def _is_mining(self, rpc_status: dict = None) -> bool | None:
if rpc_status is None: if rpc_status is None:
try: try:
rpc_status = await self.rpc.status() rpc_status = await self.rpc.status()
@@ -655,8 +690,9 @@ class BTMiner(StockFirmware):
return True if rpc_status["Msg"]["mineroff"] == "false" else False return True if rpc_status["Msg"]["mineroff"] == "false" else False
except LookupError: except LookupError:
pass pass
return False
async def _get_uptime(self, rpc_summary: dict = None) -> Optional[int]: async def _get_uptime(self, rpc_summary: dict = None) -> int | None:
if rpc_summary is None: if rpc_summary is None:
try: try:
rpc_summary = await self.rpc.summary() rpc_summary = await self.rpc.summary()
@@ -669,7 +705,7 @@ class BTMiner(StockFirmware):
except LookupError: except LookupError:
pass pass
async def _get_pools(self, rpc_pools: dict = None) -> List[PoolMetrics]: async def _get_pools(self, rpc_pools: dict = None) -> list[PoolMetrics]:
if rpc_pools is None: if rpc_pools is None:
try: try:
rpc_pools = await self.rpc.pools() rpc_pools = await self.rpc.pools()
@@ -742,3 +778,408 @@ class BTMiner(StockFirmware):
exc_info=True, exc_info=True,
) )
raise raise
BTMINERV3_DATA_LOC = DataLocations(
**{
str(DataOptions.MAC): DataFunction(
"_get_mac", [RPCAPICommand("rpc_get_device_info", "get_device_info")]
),
str(DataOptions.API_VERSION): DataFunction(
"_get_api_version",
[RPCAPICommand("rpc_get_device_info", "get_device_info")],
),
str(DataOptions.FW_VERSION): DataFunction(
"_get_firmware_version",
[RPCAPICommand("rpc_get_device_info", "get_device_info")],
),
str(DataOptions.HOSTNAME): DataFunction(
"_get_hostname", [RPCAPICommand("rpc_get_device_info", "get_device_info")]
),
str(DataOptions.FAULT_LIGHT): DataFunction(
"_get_light_flashing",
[RPCAPICommand("rpc_get_device_info", "get_device_info")],
),
str(DataOptions.WATTAGE_LIMIT): DataFunction(
"_get_wattage_limit",
[RPCAPICommand("rpc_get_device_info", "get_device_info")],
),
str(DataOptions.FANS): DataFunction(
"_get_fans",
[RPCAPICommand("rpc_get_miner_status_summary", "get_miner_status_summary")],
),
str(DataOptions.FAN_PSU): DataFunction(
"_get_psu_fans", [RPCAPICommand("rpc_get_device_info", "get_device_info")]
),
str(DataOptions.HASHBOARDS): DataFunction(
"_get_hashboards",
[
RPCAPICommand("rpc_get_device_info", "get_device_info"),
RPCAPICommand(
"rpc_get_miner_status_edevs",
"get_miner_status_edevs",
),
],
),
str(DataOptions.POOLS): DataFunction(
"_get_pools",
[RPCAPICommand("rpc_get_miner_status_summary", "get_miner_status_summary")],
),
str(DataOptions.UPTIME): DataFunction(
"_get_uptime",
[RPCAPICommand("rpc_get_miner_status_summary", "get_miner_status_summary")],
),
str(DataOptions.WATTAGE): DataFunction(
"_get_wattage",
[RPCAPICommand("rpc_get_miner_status_summary", "get_miner_status_summary")],
),
str(DataOptions.HASHRATE): DataFunction(
"_get_hashrate",
[RPCAPICommand("rpc_get_miner_status_summary", "get_miner_status_summary")],
),
str(DataOptions.EXPECTED_HASHRATE): DataFunction(
"_get_expected_hashrate",
[RPCAPICommand("rpc_get_miner_status_summary", "get_miner_status_summary")],
),
str(DataOptions.ENVIRONMENT_TEMP): DataFunction(
"_get_env_temp",
[RPCAPICommand("rpc_get_miner_status_summary", "get_miner_status_summary")],
),
}
)
class BTMinerV3(StockFirmware):
_rpc_cls = BTMinerV3RPCAPI
rpc: BTMinerV3RPCAPI
data_locations = BTMINERV3_DATA_LOC
supports_shutdown = True
supports_autotuning = 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:
try:
data = await self.rpc.set_system_led()
except APIError:
return False
if data:
if "code" in data.keys():
if data["code"] == 0:
self.light = False
return True
return False
async def fault_light_on(self) -> bool:
try:
data = await self.rpc.set_system_led(
leds=[
{
{"color": "red", "period": 60, "duration": 20, "start": 0},
}
],
)
except APIError:
return False
if data:
if "code" in data.keys():
if data["code"] == 0:
self.light = True
return True
return False
async def reboot(self) -> bool:
try:
data = await self.rpc.set_system_reboot()
except APIError:
return False
if data.get("msg"):
if data["msg"] == "ok":
return True
return False
async def restart_backend(self) -> bool:
try:
data = await self.rpc.set_miner_service("restart")
except APIError:
return False
if data.get("msg"):
if data["msg"] == "ok":
return True
return False
async def stop_mining(self) -> bool:
try:
data = await self.rpc.set_miner_service("stop")
except APIError:
return False
if data.get("msg"):
if data["msg"] == "ok":
return True
return False
async def resume_mining(self) -> bool:
try:
data = await self.rpc.set_miner_service("start")
except APIError:
return False
if data.get("msg"):
if data["msg"] == "ok":
return True
return False
async def set_power_limit(self, wattage: int) -> bool:
try:
await self.rpc.set_miner_power_limit(wattage)
except Exception as e:
logging.warning(f"{self} set_power_limit: {e}")
return False
else:
return True
async def _get_mac(self, rpc_get_device_info: dict = None) -> str | None:
if rpc_get_device_info is None:
try:
rpc_get_device_info = await self.rpc.get_device_info()
except APIError:
return None
return rpc_get_device_info.get("msg", {}).get("network", {}).get("mac")
async def _get_api_version(self, rpc_get_device_info: dict = None) -> str | None:
if rpc_get_device_info is None:
try:
rpc_get_device_info = await self.rpc.get_device_info()
except APIError:
return None
return rpc_get_device_info.get("msg", {}).get("system", {}).get("api")
async def _get_firmware_version(
self, rpc_get_device_info: dict = None
) -> str | None:
if rpc_get_device_info is None:
try:
rpc_get_device_info = await self.rpc.get_device_info()
except APIError:
return None
return rpc_get_device_info.get("msg", {}).get("system", {}).get("fwversion")
async def _get_hostname(self, rpc_get_device_info: dict = None) -> str | None:
if rpc_get_device_info is None:
try:
rpc_get_device_info = await self.rpc.get_device_info()
except APIError:
return None
return rpc_get_device_info.get("msg", {}).get("network", {}).get("hostname")
async def _get_light_flashing(
self, rpc_get_device_info: dict = None
) -> bool | None:
if rpc_get_device_info is None:
try:
rpc_get_device_info = await self.rpc.get_device_info()
except APIError:
return None
val = rpc_get_device_info.get("msg", {}).get("system", {}).get("ledstatus")
if isinstance(val, str):
return val != "auto"
return None
async def _get_wattage_limit(
self, rpc_get_device_info: dict = None
) -> float | None:
if rpc_get_device_info is None:
try:
rpc_get_device_info = await self.rpc.get_device_info()
except APIError:
return None
val = rpc_get_device_info.get("msg", {}).get("miner", {}).get("power-limit-set")
try:
return float(val)
except (ValueError, TypeError):
return None
async def _get_fans(self, rpc_get_miner_status_summary: dict = None) -> list[Fan]:
if rpc_get_miner_status_summary is None:
try:
rpc_get_miner_status_summary = await self.rpc.get_miner_status_summary()
except APIError:
return []
fans = []
summary = rpc_get_miner_status_summary.get("msg", {}).get("summary", {})
for idx, direction in enumerate(["in", "out"]):
rpm = summary.get(f"fan-speed-{direction}")
if rpm is not None:
fans.append(Fan(speed=rpm))
return fans
async def _get_psu_fans(self, rpc_get_device_info: dict = None) -> list[Fan]:
if rpc_get_device_info is None:
try:
rpc_get_device_info = await self.rpc.get_device_info()
except APIError:
return []
rpm = rpc_get_device_info.get("msg", {}).get("power", {}).get("fanspeed")
return [Fan(speed=rpm)] if rpm is not None else []
async def _get_hashboards(
self,
rpc_get_device_info: dict = None,
rpc_get_miner_status_edevs: dict = None,
) -> list[HashBoard]:
if rpc_get_device_info is None:
try:
rpc_get_device_info = await self.rpc.get_device_info()
except APIError:
return []
if rpc_get_miner_status_edevs is None:
try:
rpc_get_miner_status_edevs = await self.rpc.get_miner_status_edevs()
except APIError:
return []
boards = []
board_count = (
rpc_get_device_info.get("msg", {}).get("hardware", {}).get("boards", 3)
)
edevs = rpc_get_miner_status_edevs.get("msg", {}).get("edevs", [])
for idx in range(board_count):
board_data = edevs[idx] if idx < len(edevs) else {}
boards.append(
HashBoard(
slot=idx,
hashrate=self.algo.hashrate(
rate=board_data.get("hash-average", 0), unit=self.algo.unit.TH
).into(self.algo.unit.default),
temp=board_data.get("chip-temp-min"),
inlet_temp=board_data.get("chip-temp-min"),
outlet_temp=board_data.get("chip-temp-max"),
serial_number=board_data.get(f"pcbsn{idx}"),
chips=board_data.get("effective-chips"),
expected_chips=self.expected_chips,
active=(board_data.get("hash-average") or 0) > 0,
missing=False,
tuned=True,
)
)
return boards
async def _get_pools(
self, rpc_get_miner_status_summary: dict = None
) -> list[PoolMetrics]:
if rpc_get_miner_status_summary is None:
try:
rpc_get_miner_status_summary = await self.rpc.get_miner_status_summary()
except APIError:
return []
pools = []
msg_pools = rpc_get_miner_status_summary.get("msg", {}).get("pools", [])
for idx, pool in enumerate(msg_pools):
pools.append(
PoolMetrics(
index=idx,
user=pool.get("account"),
alive=pool.get("status") == "alive",
active=pool.get("stratum-active"),
url=pool.get("url"),
)
)
return pools
async def _get_uptime(
self, rpc_get_miner_status_summary: dict = None
) -> int | None:
if rpc_get_miner_status_summary is None:
try:
rpc_get_miner_status_summary = await self.rpc.get_miner_status_summary()
except APIError:
return None
return (
rpc_get_miner_status_summary.get("msg", {})
.get("summary", {})
.get("elapsed")
)
async def _get_wattage(
self, rpc_get_miner_status_summary: dict = None
) -> float | None:
if rpc_get_miner_status_summary is None:
try:
rpc_get_miner_status_summary = await self.rpc.get_miner_status_summary()
except APIError:
return None
return (
rpc_get_miner_status_summary.get("msg", {})
.get("summary", {})
.get("power-realtime")
)
async def _get_hashrate(
self, rpc_get_miner_status_summary: dict = None
) -> float | None:
if rpc_get_miner_status_summary is None:
try:
rpc_get_miner_status_summary = await self.rpc.get_miner_status_summary()
except APIError:
return None
return (
rpc_get_miner_status_summary.get("msg", {})
.get("summary", {})
.get("hash-realtime")
)
async def _get_expected_hashrate(
self, rpc_get_miner_status_summary: dict = None
) -> float | None:
if rpc_get_miner_status_summary is None:
try:
rpc_get_miner_status_summary = await self.rpc.get_miner_status_summary()
except APIError:
return None
return (
rpc_get_miner_status_summary.get("msg", {})
.get("summary", {})
.get("factory-hash")
)
async def _get_env_temp(
self, rpc_get_miner_status_summary: dict = None
) -> float | None:
if rpc_get_miner_status_summary is None:
try:
rpc_get_miner_status_summary = await self.rpc.get_miner_status_summary()
except APIError:
return None
return (
rpc_get_miner_status_summary.get("msg", {})
.get("summary", {})
.get("environment-temperature")
)

View File

@@ -115,11 +115,18 @@ class ESPMiner(BaseMiner):
if web_system_info is not None: if web_system_info is not None:
try: try:
expected_hashrate = ( small_core_count = web_system_info.get("smallCoreCount")
web_system_info.get("smallCoreCount") asic_count = web_system_info.get("asicCount")
* web_system_info.get("asicCount") frequency = web_system_info.get("frequency")
* web_system_info.get("frequency")
) if asic_count is None:
try:
asic_info = await self.web.asic_info()
asic_count = asic_info.get("asicCount")
except APIError:
pass
expected_hashrate = small_core_count * asic_count * frequency
return self.algo.hashrate( return self.algo.hashrate(
rate=float(expected_hashrate), unit=self.algo.unit.MH rate=float(expected_hashrate), unit=self.algo.unit.MH

View File

@@ -293,9 +293,12 @@ class VNish(VNishFirmware, BMMiner):
try: try:
web_settings = await self.web.settings() web_settings = await self.web.settings()
web_presets = await self.web.autotune_presets() web_presets = await self.web.autotune_presets()
web_perf_summary = (await self.web.perf_summary()) or {}
except APIError: except APIError:
return self.config return self.config
self.config = MinerConfig.from_vnish(web_settings, web_presets) self.config = MinerConfig.from_vnish(
web_settings, web_presets, web_perf_summary
)
return self.config return self.config
async def set_power_limit(self, wattage: int) -> bool: async def set_power_limit(self, wattage: int) -> bool:

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 from pyasic.miners.backends.btminer import BTMiner, BTMinerV2
class M7X(BTMiner): class M7X(BTMiner):
supports_autotuning = True supports_autotuning = True
supports_presets = True
class M6X(BTMiner): class M6X(BTMiner):
supports_autotuning = True supports_autotuning = True
supports_presets = True
class M5X(BTMiner): class M5X(BTMiner):
supports_autotuning = True supports_autotuning = True
supports_presets = True
class M3X(BTMiner): class M3X(BTMiner):
supports_autotuning = True supports_autotuning = True
supports_presets = True
class M2X(BTMiner): 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

@@ -126,6 +126,15 @@ class S19jPro(AntMinerMake):
algo = MinerAlgo.SHA256 algo = MinerAlgo.SHA256
class S19jPlus(AntMinerMake):
raw_model = MinerModel.ANTMINER.S19jPlus
expected_chips = 108
expected_fans = 4
expected_hashboards = 3
algo = MinerAlgo.SHA256
class S19jProNoPIC(AntMinerMake): class S19jProNoPIC(AntMinerMake):
raw_model = MinerModel.ANTMINER.S19jProNoPIC raw_model = MinerModel.ANTMINER.S19jProNoPIC
@@ -216,6 +225,15 @@ class S19KPro(AntMinerMake):
algo = MinerAlgo.SHA256 algo = MinerAlgo.SHA256
class S19ProA(AntMinerMake):
raw_model = MinerModel.ANTMINER.S19ProA
expected_chips = 114
expected_fans = 4
expected_hashboards = 3
algo = MinerAlgo.SHA256
class S19jXP(AntMinerMake): class S19jXP(AntMinerMake):
raw_model = MinerModel.ANTMINER.S19jXP raw_model = MinerModel.ANTMINER.S19jXP
@@ -223,3 +241,12 @@ class S19jXP(AntMinerMake):
expected_fans = 4 expected_fans = 4
expected_hashboards = 3 expected_hashboards = 3
algo = MinerAlgo.SHA256 algo = MinerAlgo.SHA256
class S19XPHydro(AntMinerMake):
raw_model = MinerModel.ANTMINER.S19XPHydro
expected_chips = 204
expected_fans = 0
expected_hashboards = 3
algo = MinerAlgo.SHA256

View File

@@ -24,6 +24,7 @@ from .S19 import (
S19i, S19i,
S19j, S19j,
S19jNoPIC, S19jNoPIC,
S19jPlus,
S19jPro, S19jPro,
S19jProNoPIC, S19jProNoPIC,
S19jProPlus, S19jProPlus,
@@ -35,8 +36,10 @@ from .S19 import (
S19NoPIC, S19NoPIC,
S19Plus, S19Plus,
S19Pro, S19Pro,
S19ProA,
S19ProHydro, S19ProHydro,
S19ProPlus, S19ProPlus,
S19ProPlusHydro, S19ProPlusHydro,
S19XPHydro,
) )
from .T19 import T19 from .T19 import T19

View File

@@ -36,6 +36,15 @@ class S21Plus(AntMinerMake):
algo = MinerAlgo.SHA256 algo = MinerAlgo.SHA256
class S21PlusHydro(AntMinerMake):
raw_model = MinerModel.ANTMINER.S21PlusHydro
expected_chips = 95
expected_fans = 0
expected_hashboards = 3
algo = MinerAlgo.SHA256
class S21Pro(AntMinerMake): class S21Pro(AntMinerMake):
raw_model = MinerModel.ANTMINER.S21Pro raw_model = MinerModel.ANTMINER.S21Pro

View File

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

View File

@@ -0,0 +1,27 @@
# ------------------------------------------------------------------------------
# Copyright 2022 Upstream Data Inc -
# -
# Licensed under the Apache License, Version 2.0 (the "License"); -
# you may not use this file except in compliance with the License. -
# You may obtain a copy of the License at -
# -
# http://www.apache.org/licenses/LICENSE-2.0 -
# -
# Unless required by applicable law or agreed to in writing, software -
# distributed under the License is distributed on an "AS IS" BASIS, -
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -
# See the License for the specific language governing permissions and -
# limitations under the License. -
# ------------------------------------------------------------------------------
from pyasic.device.algorithm import MinerAlgo
from pyasic.device.models import MinerModel
from pyasic.miners.device.makes import AvalonMinerMake
class AvalonQHome(AvalonMinerMake):
raw_model = MinerModel.AVALONMINER.AvalonQHome
expected_chips = 160
expected_fans = 2
expected_hashboards = 1
algo = MinerAlgo.SHA256

View File

@@ -0,0 +1,17 @@
# ------------------------------------------------------------------------------
# Copyright 2022 Upstream Data Inc -
# -
# Licensed under the Apache License, Version 2.0 (the "License"); -
# you may not use this file except in compliance with the License. -
# You may obtain a copy of the License at -
# -
# http://www.apache.org/licenses/LICENSE-2.0 -
# -
# Unless required by applicable law or agreed to in writing, software -
# distributed under the License is distributed on an "AS IS" BASIS, -
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -
# See the License for the specific language governing permissions and -
# limitations under the License. -
# ------------------------------------------------------------------------------
from .Q import AvalonQHome

View File

@@ -22,3 +22,4 @@ from .A11X import *
from .A12X import * from .A12X import *
from .A15X import * from .A15X import *
from .nano import * from .nano import *
from .Q import *

View File

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

View File

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

View File

@@ -6,6 +6,7 @@ from pyasic.miners.device.makes import BraiinsMake
class BMM100(BraiinsMake): class BMM100(BraiinsMake):
raw_model = MinerModel.BRAIINS.BMM100 raw_model = MinerModel.BRAIINS.BMM100
expected_chips = 1
expected_hashboards = 1 expected_hashboards = 1
expected_fans = 1 expected_fans = 1
algo = MinerAlgo.SHA256 algo = MinerAlgo.SHA256
@@ -14,6 +15,7 @@ class BMM100(BraiinsMake):
class BMM101(BraiinsMake): class BMM101(BraiinsMake):
raw_model = MinerModel.BRAIINS.BMM101 raw_model = MinerModel.BRAIINS.BMM101
expected_chips = 1
expected_hashboards = 1 expected_hashboards = 1
expected_fans = 1 expected_fans = 1
algo = MinerAlgo.SHA256 algo = MinerAlgo.SHA256

View File

@@ -18,6 +18,15 @@ from pyasic.device.models import MinerModel
from pyasic.miners.device.makes import ElphapexMake from pyasic.miners.device.makes import ElphapexMake
class DG1(ElphapexMake):
raw_model = MinerModel.ELPHAPEX.DG1
expected_chips = 144
expected_hashboards = 4
expected_fans = 4
algo = MinerAlgo.SCRYPT
class DG1Plus(ElphapexMake): class DG1Plus(ElphapexMake):
raw_model = MinerModel.ELPHAPEX.DG1Plus raw_model = MinerModel.ELPHAPEX.DG1Plus
@@ -25,3 +34,12 @@ class DG1Plus(ElphapexMake):
expected_hashboards = 4 expected_hashboards = 4
expected_fans = 4 expected_fans = 4
algo = MinerAlgo.SCRYPT algo = MinerAlgo.SCRYPT
class DG1Home(ElphapexMake):
raw_model = MinerModel.ELPHAPEX.DG1Home
expected_chips = 120
expected_hashboards = 4
expected_fans = 4
algo = MinerAlgo.SCRYPT

View File

@@ -1 +1 @@
from .DG1 import DG1Plus from .DG1 import DG1, DG1Home, DG1Plus

View File

@@ -0,0 +1,27 @@
# ------------------------------------------------------------------------------
# Copyright 2022 Upstream Data Inc -
# -
# Licensed under the Apache License, Version 2.0 (the "License"); -
# you may not use this file except in compliance with the License. -
# You may obtain a copy of the License at -
# -
# http://www.apache.org/licenses/LICENSE-2.0 -
# -
# Unless required by applicable law or agreed to in writing, software -
# distributed under the License is distributed on an "AS IS" BASIS, -
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -
# See the License for the specific language governing permissions and -
# limitations under the License. -
# ------------------------------------------------------------------------------
from pyasic.device.algorithm.base import GenericAlgo
from pyasic.device.models import MinerModel
from pyasic.miners.device.makes import GoldshellMake
class Byte(GoldshellMake):
raw_model = MinerModel.GOLDSHELL.Byte
expected_chips = 0
expected_fans = 0
expected_hashboards = 0
algo = GenericAlgo

View File

@@ -0,0 +1,16 @@
# ------------------------------------------------------------------------------
# Copyright 2022 Upstream Data Inc -
# -
# Licensed under the Apache License, Version 2.0 (the "License"); -
# you may not use this file except in compliance with the License. -
# You may obtain a copy of the License at -
# -
# http://www.apache.org/licenses/LICENSE-2.0 -
# -
# Unless required by applicable law or agreed to in writing, software -
# distributed under the License is distributed on an "AS IS" BASIS, -
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -
# See the License for the specific language governing permissions and -
# limitations under the License. -
# ------------------------------------------------------------------------------
from .Byte import Byte

View File

@@ -13,6 +13,7 @@
# See the License for the specific language governing permissions and - # See the License for the specific language governing permissions and -
# limitations under the License. - # limitations under the License. -
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
from .Byte import *
from .X5 import * from .X5 import *
from .XBox import * from .XBox import *
from .XMax import * from .XMax import *

View File

@@ -0,0 +1,27 @@
# ------------------------------------------------------------------------------
# Copyright 2024 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 IceRiverMake
class AL3(IceRiverMake):
raw_model = MinerModel.ICERIVER.AL3
expected_chips = 156
expected_fans = 4
expected_hashboards = 3
algo = MinerAlgo.BLOCKFLOW

View File

@@ -0,0 +1 @@
from .AL3 import AL3

View File

@@ -1 +1,2 @@
from .ALX import *
from .KSX import * from .KSX import *

View File

@@ -1,6 +1,14 @@
from pyasic.miners.backends.elphapex import ElphapexMiner from pyasic.miners.backends.elphapex import ElphapexMiner
from pyasic.miners.device.models import DG1Plus from pyasic.miners.device.models import DG1, DG1Home, DG1Plus
class ElphapexDG1Plus(ElphapexMiner, DG1Plus): class ElphapexDG1Plus(ElphapexMiner, DG1Plus):
pass pass
class ElphapexDG1(ElphapexMiner, DG1):
pass
class ElphapexDG1Home(ElphapexMiner, DG1Home):
pass

View File

@@ -1 +1 @@
from .DG1 import ElphapexDG1Plus from .DG1 import ElphapexDG1, ElphapexDG1Home, ElphapexDG1Plus

View File

@@ -41,6 +41,7 @@ from pyasic.miners.elphapex import *
from pyasic.miners.goldshell import * from pyasic.miners.goldshell import *
from pyasic.miners.hammer import * from pyasic.miners.hammer import *
from pyasic.miners.iceriver import * from pyasic.miners.iceriver import *
from pyasic.miners.iceriver.iceminer.ALX import IceRiverAL3
from pyasic.miners.innosilicon import * from pyasic.miners.innosilicon import *
from pyasic.miners.luckyminer import * from pyasic.miners.luckyminer import *
from pyasic.miners.volcminer import * from pyasic.miners.volcminer import *
@@ -108,6 +109,8 @@ MINER_CLASSES = {
"ANTMINER S19J88NOPIC": BMMinerS19jNoPIC, "ANTMINER S19J88NOPIC": BMMinerS19jNoPIC,
"ANTMINER S19PRO+": BMMinerS19ProPlus, "ANTMINER S19PRO+": BMMinerS19ProPlus,
"ANTMINER S19J PRO": BMMinerS19jPro, "ANTMINER S19J PRO": BMMinerS19jPro,
"ANTMINER S19J+": BMMinerS19jPlus,
"ANTMINER S19J PRO+": BMMinerS19jProPlus,
"ANTMINER S19 XP": BMMinerS19XP, "ANTMINER S19 XP": BMMinerS19XP,
"ANTMINER S19A": BMMinerS19a, "ANTMINER S19A": BMMinerS19a,
"ANTMINER S19A PRO": BMMinerS19aPro, "ANTMINER S19A PRO": BMMinerS19aPro,
@@ -121,6 +124,8 @@ MINER_CLASSES = {
"ANTMINER BHB68601": BMMinerS21, # ??? "ANTMINER BHB68601": BMMinerS21, # ???
"ANTMINER BHB68606": BMMinerS21, # ??? "ANTMINER BHB68606": BMMinerS21, # ???
"ANTMINER S21+": BMMinerS21Plus, "ANTMINER S21+": BMMinerS21Plus,
"ANTMINER S21+ HYD.": BMMinerS21PlusHydro,
"ANTMINER S21+ HYD": BMMinerS21PlusHydro,
"ANTMINER S21 PRO": BMMinerS21Pro, "ANTMINER S21 PRO": BMMinerS21Pro,
"ANTMINER T21": BMMinerT21, "ANTMINER T21": BMMinerT21,
"ANTMINER S21 HYD.": BMMinerS21Hydro, "ANTMINER S21 HYD.": BMMinerS21Hydro,
@@ -506,7 +511,9 @@ MINER_CLASSES = {
"AVALONMINER 1166PRO": CGMinerAvalon1166Pro, "AVALONMINER 1166PRO": CGMinerAvalon1166Pro,
"AVALONMINER 1246": CGMinerAvalon1246, "AVALONMINER 1246": CGMinerAvalon1246,
"AVALONMINER NANO3": CGMinerAvalonNano3, "AVALONMINER NANO3": CGMinerAvalonNano3,
"AVALON NANO3S": CGMinerAvalonNano3s,
"AVALONMINER 15-194": CGMinerAvalon1566, "AVALONMINER 15-194": CGMinerAvalon1566,
"AVALON Q": CGMinerAvalonQHome,
}, },
MinerTypes.INNOSILICON: { MinerTypes.INNOSILICON: {
None: type("InnosiliconUnknown", (Innosilicon, InnosiliconMake), {}), None: type("InnosiliconUnknown", (Innosilicon, InnosiliconMake), {}),
@@ -523,6 +530,7 @@ MINER_CLASSES = {
"GOLDSHELL KDMAX": GoldshellKDMax, "GOLDSHELL KDMAX": GoldshellKDMax,
"GOLDSHELL KDBOXII": GoldshellKDBoxII, "GOLDSHELL KDBOXII": GoldshellKDBoxII,
"GOLDSHELL KDBOXPRO": GoldshellKDBoxPro, "GOLDSHELL KDBOXPRO": GoldshellKDBoxPro,
"GOLDSHELL BYTE": GoldshellByte,
}, },
MinerTypes.BRAIINS_OS: { MinerTypes.BRAIINS_OS: {
None: BOSMiner, None: BOSMiner,
@@ -553,15 +561,20 @@ MINER_CLASSES = {
"ANTMINER T19": BOSMinerT19, "ANTMINER T19": BOSMinerT19,
"ANTMINER S21": BOSMinerS21, "ANTMINER S21": BOSMinerS21,
"ANTMINER S21 PRO": BOSMinerS21Pro, "ANTMINER S21 PRO": BOSMinerS21Pro,
"ANTMINER S21+": BOSMinerS21Plus,
"ANTMINER S21+ HYD.": BOSMinerS21PlusHydro,
"ANTMINER S21 HYD.": BOSMinerS21Hydro,
"ANTMINER T21": BOSMinerT21, "ANTMINER T21": BOSMinerT21,
"BRAIINS MINI MINER BMM 100": BraiinsBMM100, "BRAIINS MINI MINER BMM 100": BraiinsBMM100,
"BRAIINS MINI MINER BMM 101": BraiinsBMM101, "BRAIINS MINI MINER BMM 101": BraiinsBMM101,
"ANTMINER S19 XP HYD.": BOSMinerS19XPHydro,
}, },
MinerTypes.VNISH: { MinerTypes.VNISH: {
None: VNish, None: VNish,
"L3+": VnishL3Plus, "L3+": VNishL3Plus,
"ANTMINER L3+": VnishL3Plus, "ANTMINER L3+": VNishL3Plus,
"ANTMINER L7": VnishL7, "ANTMINER L7": VNishL7,
"ANTMINER L9": VNishL9,
"ANTMINER S17+": VNishS17Plus, "ANTMINER S17+": VNishS17Plus,
"ANTMINER S17 PRO": VNishS17Pro, "ANTMINER S17 PRO": VNishS17Pro,
"ANTMINER S19": VNishS19, "ANTMINER S19": VNishS19,
@@ -569,16 +582,25 @@ MINER_CLASSES = {
"ANTMINER S19 PRO": VNishS19Pro, "ANTMINER S19 PRO": VNishS19Pro,
"ANTMINER S19J": VNishS19j, "ANTMINER S19J": VNishS19j,
"ANTMINER S19I": VNishS19i, "ANTMINER S19I": VNishS19i,
"ANTMINER S19 XP": VNishS19XP,
"ANTMINER S19 XP HYD.": VNishS19XPHydro,
"ANTMINER S19J PRO": VNishS19jPro, "ANTMINER S19J PRO": VNishS19jPro,
"ANTMINER S19J PRO A": VNishS19jPro, "ANTMINER S19J PRO A": VNishS19jPro,
"ANTMINER S19J PRO BB": VNishS19jPro, "ANTMINER S19J PRO BB": VNishS19jPro,
"ANTMINER S19A": VNishS19a, "ANTMINER S19A": VNishS19a,
"ANTMINER S19 HYD.": VNishS19Hydro,
"ANTMINER S19A PRO": VNishS19aPro, "ANTMINER S19A PRO": VNishS19aPro,
"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,
"ANTMINER S21": VNishS21, "ANTMINER S21": VNishS21,
"ANTMINER S21+": VNishS21Plus,
"ANTMINER S21+ HYD.": VNishS21PlusHydro,
"ANTMINER S21 PRO": VNishS21Pro,
"ANTMINER S21 HYD.": VNishS21Hydro,
}, },
MinerTypes.EPIC: { MinerTypes.EPIC: {
None: ePIC, None: ePIC,
@@ -621,6 +643,7 @@ MINER_CLASSES = {
"ANTMINER S19 XP": LUXMinerS19XP, "ANTMINER S19 XP": LUXMinerS19XP,
"ANTMINER T19": LUXMinerT19, "ANTMINER T19": LUXMinerT19,
"ANTMINER S21": LUXMinerS21, "ANTMINER S21": LUXMinerS21,
"ANTMINER T21": LUXMinerT21,
}, },
MinerTypes.AURADINE: { MinerTypes.AURADINE: {
None: type("AuradineUnknown", (Auradine, AuradineMake), {}), None: type("AuradineUnknown", (Auradine, AuradineMake), {}),
@@ -667,6 +690,7 @@ MINER_CLASSES = {
"KS5": IceRiverKS5, "KS5": IceRiverKS5,
"KS5L": IceRiverKS5L, "KS5L": IceRiverKS5L,
"KS5M": IceRiverKS5M, "KS5M": IceRiverKS5M,
"10306": IceRiverAL3,
}, },
MinerTypes.HAMMER: { MinerTypes.HAMMER: {
None: type("HammerUnknown", (BlackMiner, HammerMake), {}), None: type("HammerUnknown", (BlackMiner, HammerMake), {}),
@@ -679,6 +703,8 @@ MINER_CLASSES = {
MinerTypes.ELPHAPEX: { MinerTypes.ELPHAPEX: {
None: type("ElphapexUnknown", (ElphapexMiner, ElphapexMake), {}), None: type("ElphapexUnknown", (ElphapexMiner, ElphapexMake), {}),
"DG1+": ElphapexDG1Plus, "DG1+": ElphapexDG1Plus,
"DG1": ElphapexDG1,
"DG1-Home": ElphapexDG1Home,
}, },
} }
@@ -763,21 +789,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
@@ -1042,6 +1079,45 @@ class MinerFactory:
return data return data
async def send_btminer_v3_api_command(self, ip, command):
try:
reader, writer = await asyncio.open_connection(ip, 4433)
except (ConnectionError, OSError):
return
cmd = {"cmd": command}
try:
# send the command
json_cmd = json.dumps(cmd).encode("utf-8")
length = len(json_cmd)
writer.write(length.to_bytes(4, byteorder="little"))
writer.write(json_cmd)
await writer.drain()
# receive all the data
resp_len = await reader.readexactly(4)
data = await reader.readexactly(
int.from_bytes(resp_len, byteorder="little")
)
writer.close()
await writer.wait_closed()
except asyncio.CancelledError:
writer.close()
await writer.wait_closed()
return
except (ConnectionError, OSError):
return
if data == b"Socket connect failed: Connection refused\n":
return
try:
data = json.loads(data)
except json.JSONDecodeError:
return {}
return data
@staticmethod @staticmethod
async def _fix_api_data(data: bytes) -> str: async def _fix_api_data(data: bytes) -> str:
if data.endswith(b"\x00"): if data.endswith(b"\x00"):
@@ -1080,13 +1156,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:
@@ -1094,8 +1171,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 = [
@@ -1161,9 +1238,25 @@ class MinerFactory:
try: try:
miner_model = sock_json_data["DEVDETAILS"][0]["Model"].replace("_", "") miner_model = sock_json_data["DEVDETAILS"][0]["Model"].replace("_", "")
miner_model = miner_model[:-1] + "0" miner_model = miner_model[:-1] + "0"
return miner_model return miner_model
except (TypeError, LookupError): except (TypeError, LookupError):
sock_json_data_v3 = await self.send_btminer_v3_api_command(
ip, "get.device.info"
)
try:
miner_model = sock_json_data_v3["msg"]["miner"]["type"].replace("_", "")
miner_model = miner_model[:-1] + "0"
return miner_model
except (TypeError, LookupError):
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 pass
async def get_miner_model_avalonminer(self, ip: str) -> str | None: async def get_miner_model_avalonminer(self, ip: str) -> str | None:

View File

@@ -0,0 +1,315 @@
# ------------------------------------------------------------------------------
# Copyright 2022 Upstream Data Inc -
# -
# Licensed under the Apache License, Version 2.0 (the "License"); -
# you may not use this file except in compliance with the License. -
# You may obtain a copy of the License at -
# -
# http://www.apache.org/licenses/LICENSE-2.0 -
# -
# Unless required by applicable law or agreed to in writing, software -
# distributed under the License is distributed on an "AS IS" BASIS, -
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -
# See the License for the specific language governing permissions and -
# limitations under the License. -
# ------------------------------------------------------------------------------
from typing import List, Optional, Union
from pyasic.config import MinerConfig
from pyasic.data import Fan, MinerData
from pyasic.data.boards import HashBoard
from pyasic.data.pools import PoolMetrics, PoolUrl
from pyasic.device.algorithm import AlgoHashRate, MinerAlgo
from pyasic.errors import APIError
from pyasic.miners.backends import GoldshellMiner
from pyasic.miners.data import (
DataFunction,
DataLocations,
DataOptions,
RPCAPICommand,
WebAPICommand,
)
from pyasic.miners.device.models import Byte
ALGORITHM_SCRYPT_NAME = "scrypt(LTC)"
ALGORITHM_ZKSNARK_NAME = "zkSNARK(ALEO)"
EXPECTED_CHIPS_PER_SCRYPT_BOARD = 5
EXPECTED_CHIPS_PER_ZKSNARK_BOARD = 3
GOLDSHELL_BYTE_DATA_LOC = DataLocations(
**{
str(DataOptions.MAC): DataFunction(
"_get_mac",
[WebAPICommand("web_setting", "setting")],
),
str(DataOptions.API_VERSION): DataFunction(
"_get_api_ver",
[WebAPICommand("web_setting", "version")],
),
str(DataOptions.FW_VERSION): DataFunction(
"_get_fw_ver",
[WebAPICommand("web_status", "status")],
),
str(DataOptions.HASHRATE): DataFunction(
"_get_hashrate",
[RPCAPICommand("rpc_devs", "devs")],
),
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_devs", "devs")],
),
str(DataOptions.POOLS): DataFunction(
"_get_pools",
[RPCAPICommand("rpc_pools", "pools")],
),
}
)
class GoldshellByte(GoldshellMiner, Byte):
data_locations = GOLDSHELL_BYTE_DATA_LOC
cgdev: dict | None = None
async def get_data(
self,
allow_warning: bool = False,
include: List[Union[str, DataOptions]] = None,
exclude: List[Union[str, DataOptions]] = None,
) -> MinerData:
if self.cgdev is None:
try:
self.cgdev = await self.web.send_command("cgminer?cgminercmd=devs")
except APIError:
pass
scrypt_board_count = 0
zksnark_board_count = 0
total_wattage = 0
total_uptime_mins = 0
for minfo in self.cgdev.get("minfos", []):
algo_name = minfo.get("name")
for info in minfo.get("infos", []):
self.expected_hashboards += 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:
scrypt_board_count += 1
elif algo_name == ALGORITHM_ZKSNARK_NAME:
zksnark_board_count += 1
self.expected_chips = (EXPECTED_CHIPS_PER_SCRYPT_BOARD * scrypt_board_count) + (
EXPECTED_CHIPS_PER_ZKSNARK_BOARD * zksnark_board_count
)
if scrypt_board_count > 0 and zksnark_board_count == 0:
self.algo = MinerAlgo.SCRYPT
elif zksnark_board_count > 0 and scrypt_board_count == 0:
self.algo = MinerAlgo.ZKSNARK
data = await super().get_data(allow_warning, include, exclude)
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
async def get_config(self) -> MinerConfig:
try:
pools = await self.web.pools()
except APIError:
return self.config
self.config = MinerConfig.from_goldshell_byte(pools)
return self.config
async def _get_api_ver(self, web_setting: dict = None) -> Optional[str]:
if web_setting is None:
try:
web_setting = await self.web.setting()
except APIError:
pass
if web_setting is not None:
try:
version = web_setting.get("version")
if version is not None:
self.api_ver = version.strip("v")
return self.api_ver
except KeyError:
pass
return self.api_ver
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
total_hash_rate_mh = 0
if rpc_devs is not None:
for board in rpc_devs.get("DEVS", []):
algo_name = board.get("pool")
if algo_name == ALGORITHM_SCRYPT_NAME:
total_hash_rate_mh += (
self.algo.hashrate(
rate=float(board.get("estimate_hash_rate", 0)),
unit=self.algo.unit.H,
)
.into(self.algo.unit.MH)
.rate
)
elif algo_name == ALGORITHM_ZKSNARK_NAME:
total_hash_rate_mh += float(board.get("theory_hash", 0))
hash_rate = self.algo.hashrate(
rate=total_hash_rate_mh, unit=self.algo.unit.MH
).into(self.algo.unit.default)
return hash_rate
async def _get_hashrate(self, rpc_devs: dict = None) -> Optional[AlgoHashRate]:
if rpc_devs is None:
try:
rpc_devs = await self.rpc.devs()
except APIError:
pass
total_hash_rate_mh = 0
if rpc_devs is not None:
for board in rpc_devs.get("DEVS", []):
total_hash_rate_mh += float(board.get("MHS 20s", 0))
hash_rate = self.algo.hashrate(
rate=total_hash_rate_mh, unit=self.algo.unit.MH
).into(self.algo.unit.default)
return hash_rate
async def _get_pools(self, rpc_pools: dict = None) -> List[PoolMetrics]:
if rpc_pools is None:
try:
rpc_pools = await self.rpc.pools()
except APIError:
pass
pools_data = []
if rpc_pools is not None:
try:
pools = rpc_pools.get("POOLS", [])
for index, pool_info in enumerate(pools):
url = pool_info.get("URL")
pool_url = PoolUrl.from_str(url) if url else None
pool_data = PoolMetrics(
accepted=pool_info.get("Accepted"),
rejected=pool_info.get("Rejected"),
active=pool_info.get("Stratum Active"),
alive=pool_info.get("Status") == "Alive",
url=pool_url,
user=pool_info.get("User"),
index=index,
)
pools_data.append(pool_data)
except LookupError:
pass
return pools_data
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:
for board in rpc_devs.get("DEVS", []):
b_id = board["PGA"]
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-1"]
hashboards[b_id].temp = board["tstemp-2"]
hashboards[b_id].voltage = board["voltage"]
hashboards[b_id].active = board["Status"] == "Alive"
hashboards[b_id].missing = False
algo_name = board.get("pool")
if algo_name == ALGORITHM_SCRYPT_NAME:
hashboards[b_id].expected_chips = EXPECTED_CHIPS_PER_SCRYPT_BOARD
elif algo_name == ALGORITHM_ZKSNARK_NAME:
hashboards[b_id].expected_chips = EXPECTED_CHIPS_PER_ZKSNARK_BOARD
if rpc_devdetails is None:
try:
rpc_devdetails = await self.rpc.devdetails()
except APIError:
pass
if rpc_devdetails is not None:
for board in rpc_devdetails.get("DEVS", []):
b_id = board["DEVDETAILS"]
hashboards[b_id].chips = board["chips-nr"]
return hashboards
async def _get_fans(self, rpc_devs: dict = None) -> List[Fan]:
if self.expected_fans is None:
return []
if rpc_devs is None:
try:
rpc_devs = await self.rpc.devs()
except APIError:
pass
fans_data = []
if rpc_devs is not None:
for board in rpc_devs.get("DEVS", []):
if board.get("PGA") is not None:
try:
b_id = board["PGA"]
fan_speed = board[f"fan{b_id}"]
fans_data.append(fan_speed)
except KeyError:
pass
fans = [Fan(speed=d) if d else Fan() for d in fans_data]
return fans

View File

@@ -0,0 +1,16 @@
# ------------------------------------------------------------------------------
# Copyright 2022 Upstream Data Inc -
# -
# Licensed under the Apache License, Version 2.0 (the "License"); -
# you may not use this file except in compliance with the License. -
# You may obtain a copy of the License at -
# -
# http://www.apache.org/licenses/LICENSE-2.0 -
# -
# Unless required by applicable law or agreed to in writing, software -
# distributed under the License is distributed on an "AS IS" BASIS, -
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -
# See the License for the specific language governing permissions and -
# limitations under the License. -
# ------------------------------------------------------------------------------
from .Byte import GoldshellByte

View File

@@ -13,6 +13,7 @@
# See the License for the specific language governing permissions and - # See the License for the specific language governing permissions and -
# limitations under the License. - # limitations under the License. -
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
from .Byte import *
from .X5 import * from .X5 import *
from .XBox import * from .XBox import *
from .XMax import * from .XMax import *

View File

@@ -0,0 +1,6 @@
from pyasic.miners.backends.iceriver import IceRiver
from pyasic.miners.device.models.iceriver import AL3
class IceRiverAL3(IceRiver, AL3):
pass

View File

@@ -0,0 +1 @@
from .AL3 import IceRiverAL3

27
pyasic/rpc/avalonminer.py Normal file
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.rpc.cgminer import CGMinerRPCAPI
class AvalonMinerRPCAPI(CGMinerRPCAPI):
"""An abstraction of the AvalonMiner API.
Each method corresponds to an API command in AvalonMiner.
"""
async def litestats(self):
return await self.send_command("litestats")

View File

@@ -23,7 +23,8 @@ import json
import logging import logging
import re import re
import struct import struct
from typing import Literal, Union from asyncio import Future, StreamReader, StreamWriter
from typing import Any, AsyncGenerator, Callable, Literal, Union
import httpx import httpx
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
@@ -1100,3 +1101,280 @@ class BTMinerRPCAPI(BaseMinerRPCAPI):
</details> </details>
""" """
return await self.send_command("get_error_code", allow_warning=False) return await self.send_command("get_error_code", allow_warning=False)
class BTMinerV3RPCAPI(BaseMinerRPCAPI):
def __init__(self, ip: str, port: int = 4433, api_ver: str = "0.0.0"):
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.cmd_results = {}
self.cmd_callbacks = {"get.miner.report": set()}
async def connect(self):
self.reader, self.writer = await asyncio.open_connection(
str(self.ip), self.port
)
self.reader_loop = asyncio.create_task(self._read_loop())
async def disconnect(self):
self.writer.close()
await self.writer.wait_closed()
self.reader_loop.cancel()
async def send_command(
self, command: str, parameters: Any = None, **kwargs
) -> dict:
if self.writer is None:
await self.connect()
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}
if parameters is not None:
cmd["param"] = parameters
if command.startswith("set."):
salt = await self.get_salt()
ts = int(datetime.datetime.now().timestamp())
cmd["ts"] = ts
token_str = cmd["cmd"] + self.pwd + salt + str(ts)
token_hashed = bytearray(
base64.b64encode(hashlib.sha256(token_str.encode("utf-8")).digest())
)
token_hashed[8] = 0
cmd["account"] = "super"
cmd["token"] = token_hashed.decode("ascii")
# send the command
ser = json.dumps(cmd).encode("utf-8")
header = struct.pack("<I", len(ser))
await self._send_bytes(header + json.dumps(cmd).encode("utf-8"))
await result_fut
return result_fut.result()
async def _read_loop(self):
while True:
result = await self._read_bytes()
data = self._load_api_data(result)
command = data["desc"]
if command in self.cmd_callbacks:
callbacks: list[Callable] = self.cmd_callbacks[command]
await asyncio.gather(*[callback(data) for callback in callbacks])
elif command in self.cmd_results:
future: Future = self.cmd_results.pop(command)
future.set_result(data)
else:
logging.error(f"Received unexpected data for {self}: {data}")
async def _read_bytes(self, **kwargs) -> bytes:
header = await self.reader.readexactly(4)
length = struct.unpack("<I", header)[0]
return await self.reader.readexactly(length)
async def _send_bytes(self, data: bytes, **kwargs):
self.writer.write(data)
await self.writer.drain()
async def get_salt(self) -> str:
if self.salt is not None:
return self.salt
data = await self.send_command("get.device.info", "salt")
self.salt = data["msg"]["salt"]
return self.salt
async def get_miner_report(self) -> AsyncGenerator[dict, None]:
if self.writer is None:
await self.connect()
result = asyncio.Queue()
async def callback(data: dict):
await result.put(data)
cb_fn = callback
try:
self.cmd_callbacks["get.miner.report"].add(cb_fn)
while True:
yield await result.get()
if self.writer.is_closing():
break
finally:
self.cmd_callbacks["get.miner.report"].remove(cb_fn)
async def get_system_setting(self) -> dict | None:
return await self.send_command("get.system.setting")
async def get_miner_status_summary(self) -> dict | None:
return await self.send_command("get.miner.status", parameters="summary")
async def get_miner_status_edevs(self) -> dict | None:
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:
data = await self.send_command(
"get.miner.history",
parameters={
"start": "1",
"stop": str(datetime.datetime.now().timestamp()),
},
)
ret = {}
result = data.get("msg")
if result is not None:
unparsed = result["Data"].strip()
for item in unparsed.split(" "):
list_item = item.split(",")
timestamp = int(list_item.pop(0))
ret[timestamp] = list_item
return ret
async def get_psu_command(self):
return await self.send_command("get.psu.command")
async def get_miner_setting(self) -> dict | None:
return await self.send_command("get.miner.setting")
async def get_device_info(self) -> dict | None:
return await self.send_command("get.device.info")
async def get_log_download(self) -> dict | None:
return await self.send_command("get.log.download")
async def get_fan_setting(self) -> dict | None:
return await self.send_command("get.fan.setting")
async def set_system_reboot(self) -> dict | None:
return await self.send_command("set.system.reboot")
async def set_system_factory_reset(self, *args, **kwargs) -> dict | None:
raise NotImplementedError
return await self.send_command("set.system.factory_reset")
async def set_system_update_firmware(self, *args, **kwargs) -> dict | None:
raise NotImplementedError
return await self.send_command("set.system.update_firmware")
async def set_system_net_config(self, *args, **kwargs) -> dict | None:
raise NotImplementedError
return await self.send_command("set.system.net_config")
async def set_system_led(self, leds: list | None = None) -> dict | None:
if leds is None:
return await self.send_command("set.system.led", parameters="auto")
else:
return await self.send_command("set.system.led", parameters=leds)
async def set_system_time_randomized(self, *args, **kwargs) -> dict | None:
raise NotImplementedError
return await self.send_command("set.system.time_randomized")
async def set_system_timezone(self, *args, **kwargs) -> dict | None:
raise NotImplementedError
return await self.send_command("set.system.timezone")
async def set_system_hostname(self, *args, **kwargs) -> dict | None:
raise NotImplementedError
return await self.send_command("set.system.hostname")
async def set_system_webpools(self, *args, **kwargs) -> dict | None:
raise NotImplementedError
return await self.send_command("set.system.webpools")
async def set_miner_target_freq(self, *args, **kwargs) -> dict | None:
raise NotImplementedError
return await self.send_command("set.miner.target_freq")
async def set_miner_heat_mode(self, *args, **kwargs) -> dict | None:
raise NotImplementedError
return await self.send_command("set.miner.heat_mode")
async def set_system_ntp_server(self, *args, **kwargs) -> dict | None:
raise NotImplementedError
return await self.send_command("set.system.ntp_server")
async def set_miner_service(self, value: str) -> dict | None:
return await self.send_command("set.miner.service", parameters=value)
async def set_miner_power_mode(self, *args, **kwargs) -> dict | None:
raise NotImplementedError
return await self.send_command("set.miner.power_mode")
async def set_miner_cointype(self, *args, **kwargs) -> dict | None:
raise NotImplementedError
return await self.send_command("set.miner.cointype")
async def set_miner_pools(self, *args, **kwargs) -> dict | None:
raise NotImplementedError
return await self.send_command("set.miner.pools")
async def set_miner_fastboot(self, *args, **kwargs) -> dict | None:
raise NotImplementedError
return await self.send_command("set.miner.fastboot")
async def set_miner_power_percent(self, *args, **kwargs) -> dict | None:
raise NotImplementedError
return await self.send_command("set.miner.power_percent")
async def set_miner_pre_power_on(self, *args, **kwargs) -> dict | None:
raise NotImplementedError
return await self.send_command("set.miner.pre_power_on")
async def set_miner_restore_setting(self, *args, **kwargs) -> dict | None:
raise NotImplementedError
return await self.send_command("set.miner.restore_setting")
async def set_miner_report(self, frequency: int = 1) -> dict | None:
return await self.send_command(
"set.miner.report", parameters={"gap": frequency}
)
async def set_miner_power_limit(self, power: int) -> dict | None:
return await self.send_command("set.miner.power_limit", parameters=power)
async def set_miner_upfreq_speed(self, *args, **kwargs) -> dict | None:
raise NotImplementedError
return await self.send_command("set.miner.upfreq_speed")
async def set_log_upload(self, *args, **kwargs) -> dict | None:
raise NotImplementedError
return await self.send_command("set.log.upload")
async def set_user_change_passwd(self, *args, **kwargs) -> dict | None:
raise NotImplementedError
return await self.send_command("set.user.change_passwd")
async def set_user_permission(self, *args, **kwargs) -> dict | None:
raise NotImplementedError
return await self.send_command("set.user.permission")
async def set_fan_temp_offset(self, *args, **kwargs) -> dict | None:
raise NotImplementedError
return await self.send_command("set.fan.temp_offset")
async def set_fan_poweroff_cool(self, *args, **kwargs) -> dict | None:
raise NotImplementedError
return await self.send_command("set.fan.poweroff_cool")
async def set_fan_zero_speed(self, *args, **kwargs) -> dict | None:
raise NotImplementedError
return await self.send_command("set.fan.zero_speed")
async def set_shell_debug(self, *args, **kwargs) -> dict | None:
raise NotImplementedError
return await self.send_command("set.shell.debug")

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

@@ -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":

Some files were not shown because too many files have changed in this diff Show More