Compare commits
35 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
90d8a795e6 | ||
|
|
07cf1b134c | ||
|
|
53e1f33fa6 | ||
|
|
16ab2bd4e3 | ||
|
|
de728f12d2 | ||
|
|
8092e12dfb | ||
|
|
e70c3e9f79 | ||
|
|
39a97f2914 | ||
|
|
35af74ad1a | ||
|
|
15fa91fb98 | ||
|
|
084987a3e1 | ||
|
|
e93cc77a58 | ||
|
|
788d43c51c | ||
|
|
74c22b82ce | ||
|
|
1f46ce1b9a | ||
|
|
7964336a0c | ||
|
|
a24fc07c2a | ||
|
|
4c64481d3b | ||
|
|
66fb5834f0 | ||
|
|
db05cc1d97 | ||
|
|
418e3ce26e | ||
|
|
5a0bb11a44 | ||
|
|
39f9d087db | ||
|
|
067a376f94 | ||
|
|
a5d6e122f9 | ||
|
|
b160fd75ba | ||
|
|
d1007d3ae8 | ||
|
|
33803e89e2 | ||
|
|
10a44b9877 | ||
|
|
bbd883f639 | ||
|
|
8e2ad478e9 | ||
|
|
957981a9c6 | ||
|
|
13a67dfdd1 | ||
|
|
e86f2b62c5 | ||
|
|
88b4d2cac3 |
@@ -1,7 +1,15 @@
|
||||
ci:
|
||||
skip:
|
||||
- poetry-lock
|
||||
- unittest
|
||||
- generate-docs
|
||||
repos:
|
||||
- repo: https://github.com/python-poetry/poetry
|
||||
rev: 2.0.1
|
||||
hooks:
|
||||
- id: poetry-check
|
||||
- id: poetry-lock
|
||||
- id: poetry-install
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||
rev: v5.0.0
|
||||
hooks:
|
||||
@@ -15,11 +23,11 @@ repos:
|
||||
exclude: ^mkdocs\.yml$
|
||||
- id: check-added-large-files
|
||||
- repo: https://github.com/psf/black
|
||||
rev: 24.10.0
|
||||
rev: 25.1.0
|
||||
hooks:
|
||||
- id: black
|
||||
- repo: https://github.com/pycqa/isort
|
||||
rev: 5.13.2
|
||||
rev: 6.0.0
|
||||
hooks:
|
||||
- id: isort
|
||||
name: isort (python)
|
||||
@@ -30,6 +38,12 @@ repos:
|
||||
name: unittest
|
||||
entry: python -m unittest discover
|
||||
language: system
|
||||
'types': [python]
|
||||
types: [ python ]
|
||||
args: ["-p '*test.py'"] # Probably this option is absolutely not needed.
|
||||
pass_filenames: false
|
||||
- id: generate-docs
|
||||
name: generate-docs
|
||||
entry: python docs/generate_miners.py
|
||||
language: system
|
||||
types: [ python ]
|
||||
pass_filenames: false
|
||||
|
||||
@@ -50,6 +50,13 @@ poetry install --with dev
|
||||
pre-commit install
|
||||
```
|
||||
|
||||
##### Building Documentation Locally
|
||||
```
|
||||
poetry install --with docs
|
||||
python docs/generate_miners.py
|
||||
poetry run mkdocs serve
|
||||
```
|
||||
|
||||
---
|
||||
## Getting started
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ import asyncio
|
||||
import importlib
|
||||
import os
|
||||
import warnings
|
||||
from pathlib import Path
|
||||
|
||||
from pyasic.miners.factory import MINER_CLASSES, MinerTypes
|
||||
|
||||
@@ -51,12 +52,15 @@ def backend_str(backend: MinerTypes) -> str:
|
||||
return "Mara Firmware Miners"
|
||||
case MinerTypes.BITAXE:
|
||||
return "Stock Firmware BitAxe Miners"
|
||||
case MinerTypes.LUCKYMINER:
|
||||
return "Stock Firmware Lucky Miners"
|
||||
case MinerTypes.ICERIVER:
|
||||
return "Stock Firmware IceRiver Miners"
|
||||
case MinerTypes.HAMMER:
|
||||
return "Stock Firmware Hammer Miners"
|
||||
case MinerTypes.VOLCMINER:
|
||||
return "Stock Firmware Volcminers"
|
||||
raise TypeError("Unknown miner backend, cannot generate docs")
|
||||
|
||||
|
||||
def create_url_str(mtype: str):
|
||||
@@ -135,14 +139,14 @@ for m in MINER_CLASSES:
|
||||
done.append(miner)
|
||||
|
||||
|
||||
async def create_directory_structure(directory, data):
|
||||
def create_directory_structure(directory, data):
|
||||
if not os.path.exists(directory):
|
||||
os.makedirs(directory)
|
||||
|
||||
for key, value in data.items():
|
||||
subdirectory = os.path.join(directory, key)
|
||||
if isinstance(value, dict):
|
||||
await create_directory_structure(subdirectory, value)
|
||||
create_directory_structure(subdirectory, value)
|
||||
elif isinstance(value, list):
|
||||
file_path = os.path.join(subdirectory + ".md")
|
||||
|
||||
@@ -163,7 +167,7 @@ async def create_directory_structure(directory, data):
|
||||
)
|
||||
|
||||
|
||||
async def create_supported_types(directory):
|
||||
def create_supported_types(directory):
|
||||
with open(os.path.join(directory, "supported_types.md"), "w") as file:
|
||||
file.write(SUPPORTED_TYPES_HEADER)
|
||||
for mback in MINER_CLASSES:
|
||||
@@ -180,7 +184,7 @@ async def create_supported_types(directory):
|
||||
for mtype in backend_types:
|
||||
file.write(MINER_TYPE_HEADER.format(mtype))
|
||||
for minstance in backend_types[mtype]:
|
||||
model = await minstance("1.1.1.1").get_model()
|
||||
model = minstance("1.1.1.1").model
|
||||
file.write(
|
||||
MINER_DETAILS.format(
|
||||
make(minstance), mtype, create_url_str(model), model
|
||||
@@ -190,6 +194,7 @@ async def create_supported_types(directory):
|
||||
file.write(BACKEND_TYPE_CLOSER)
|
||||
|
||||
|
||||
root_directory = os.path.join(os.getcwd(), "miners")
|
||||
asyncio.run(create_directory_structure(root_directory, m_data))
|
||||
asyncio.run(create_supported_types(root_directory))
|
||||
if __name__ == "__main__":
|
||||
root_directory = Path(__file__).parent.joinpath("miners")
|
||||
create_directory_structure(root_directory, m_data)
|
||||
create_supported_types(root_directory)
|
||||
|
||||
@@ -495,6 +495,19 @@
|
||||
show_root_heading: false
|
||||
heading_level: 0
|
||||
|
||||
## S19i (VNish)
|
||||
|
||||
- [x] Shutdowns
|
||||
- [ ] Power Modes
|
||||
- [x] Setpoints
|
||||
- [x] Presets
|
||||
|
||||
::: pyasic.miners.antminer.vnish.X19.S19.VNishS19i
|
||||
handler: python
|
||||
options:
|
||||
show_root_heading: false
|
||||
heading_level: 0
|
||||
|
||||
## S19j (VNish)
|
||||
|
||||
- [x] Shutdowns
|
||||
@@ -690,6 +703,19 @@
|
||||
show_root_heading: false
|
||||
heading_level: 0
|
||||
|
||||
## S19 No PIC (Hive)
|
||||
|
||||
- [ ] Shutdowns
|
||||
- [ ] Power Modes
|
||||
- [ ] Setpoints
|
||||
- [ ] Presets
|
||||
|
||||
::: pyasic.miners.antminer.hiveon.X19.S19.HiveonS19NoPIC
|
||||
handler: python
|
||||
options:
|
||||
show_root_heading: false
|
||||
heading_level: 0
|
||||
|
||||
## S19 (LuxOS)
|
||||
|
||||
- [x] Shutdowns
|
||||
|
||||
@@ -14,6 +14,19 @@
|
||||
show_root_heading: false
|
||||
heading_level: 0
|
||||
|
||||
## S21 Hydro (Stock)
|
||||
|
||||
- [x] Shutdowns
|
||||
- [x] Power Modes
|
||||
- [ ] Setpoints
|
||||
- [ ] Presets
|
||||
|
||||
::: pyasic.miners.antminer.bmminer.X21.S21.BMMinerS21Hydro
|
||||
handler: python
|
||||
options:
|
||||
show_root_heading: false
|
||||
heading_level: 0
|
||||
|
||||
## S21 Pro (Stock)
|
||||
|
||||
- [x] Shutdowns
|
||||
@@ -53,6 +66,19 @@
|
||||
show_root_heading: false
|
||||
heading_level: 0
|
||||
|
||||
## S21 Pro (BOS+)
|
||||
|
||||
- [x] Shutdowns
|
||||
- [ ] Power Modes
|
||||
- [x] Setpoints
|
||||
- [ ] Presets
|
||||
|
||||
::: pyasic.miners.antminer.bosminer.X21.S21.BOSMinerS21Pro
|
||||
handler: python
|
||||
options:
|
||||
show_root_heading: false
|
||||
heading_level: 0
|
||||
|
||||
## T21 (BOS+)
|
||||
|
||||
- [x] Shutdowns
|
||||
|
||||
29
docs/miners/luckyminer/LV.md
Normal file
29
docs/miners/luckyminer/LV.md
Normal file
@@ -0,0 +1,29 @@
|
||||
# pyasic
|
||||
## LV Models
|
||||
|
||||
## LV07 (Stock)
|
||||
|
||||
- [ ] Shutdowns
|
||||
- [ ] Power Modes
|
||||
- [ ] Setpoints
|
||||
- [ ] Presets
|
||||
|
||||
::: pyasic.miners.luckyminer.espminer.LV.LV07.LuckyMinerLV07
|
||||
handler: python
|
||||
options:
|
||||
show_root_heading: false
|
||||
heading_level: 0
|
||||
|
||||
## LV08 (Stock)
|
||||
|
||||
- [ ] Shutdowns
|
||||
- [ ] Power Modes
|
||||
- [ ] Setpoints
|
||||
- [ ] Presets
|
||||
|
||||
::: pyasic.miners.luckyminer.espminer.LV.LV08.LuckyMinerLV08
|
||||
handler: python
|
||||
options:
|
||||
show_root_heading: false
|
||||
heading_level: 0
|
||||
|
||||
@@ -105,6 +105,7 @@ details {
|
||||
<li><a href="../antminer/X21#s21-stock">S21 (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#s21-hydro-stock">S21 Hydro (Stock)</a></li>
|
||||
</ul>
|
||||
</details>
|
||||
</ul>
|
||||
@@ -652,6 +653,7 @@ details {
|
||||
<summary>X21 Series:</summary>
|
||||
<ul>
|
||||
<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#t21-bos_1">T21 (BOS+)</a></li>
|
||||
</ul>
|
||||
</details>
|
||||
@@ -694,6 +696,7 @@ details {
|
||||
<li><a href="../antminer/X19#s19-no-pic-vnish">S19 No PIC (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#s19i-vnish">S19i (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>
|
||||
@@ -760,6 +763,7 @@ details {
|
||||
<ul>
|
||||
<li><a href="../antminer/X19#s19j-pro-hive">S19j Pro (Hive)</a></li>
|
||||
<li><a href="../antminer/X19#s19-hive">S19 (Hive)</a></li>
|
||||
<li><a href="../antminer/X19#s19-no-pic-hive">S19 No PIC (Hive)</a></li>
|
||||
</ul>
|
||||
</details>
|
||||
</ul>
|
||||
@@ -859,6 +863,18 @@ details {
|
||||
</ul>
|
||||
</details>
|
||||
<details>
|
||||
<summary>Stock Firmware Lucky Miners:</summary>
|
||||
<ul>
|
||||
<details>
|
||||
<summary>LV Series:</summary>
|
||||
<ul>
|
||||
<li><a href="../luckyminer/LV#lv08-stock">LV08 (Stock)</a></li>
|
||||
<li><a href="../luckyminer/LV#lv07-stock">LV07 (Stock)</a></li>
|
||||
</ul>
|
||||
</details>
|
||||
</ul>
|
||||
</details>
|
||||
<details>
|
||||
<summary>Stock Firmware IceRiver Miners:</summary>
|
||||
<ul>
|
||||
<details>
|
||||
|
||||
120
poetry.lock
generated
120
poetry.lock
generated
@@ -1,4 +1,4 @@
|
||||
# This file is automatically @generated by Poetry 2.0.0 and should not be changed by hand.
|
||||
# This file is automatically @generated by Poetry 2.0.1 and should not be changed by hand.
|
||||
|
||||
[[package]]
|
||||
name = "aiofiles"
|
||||
@@ -74,18 +74,18 @@ pywin32 = ["pywin32 (>=227)"]
|
||||
|
||||
[[package]]
|
||||
name = "babel"
|
||||
version = "2.16.0"
|
||||
version = "2.17.0"
|
||||
description = "Internationalization utilities"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
groups = ["docs"]
|
||||
files = [
|
||||
{file = "babel-2.16.0-py3-none-any.whl", hash = "sha256:368b5b98b37c06b7daf6696391c3240c938b37767d4584413e8438c5c435fa8b"},
|
||||
{file = "babel-2.16.0.tar.gz", hash = "sha256:d1f3554ca26605fe173f3de0c65f750f5a42f924499bf134de6423582298e316"},
|
||||
{file = "babel-2.17.0-py3-none-any.whl", hash = "sha256:4d0b53093fdfb4b21c92b5213dba5a1b23885afa8383709427046b21c366e5f2"},
|
||||
{file = "babel-2.17.0.tar.gz", hash = "sha256:0c54cffb19f690cdcc52a3b50bcbf71e07a808d1c80d549f2459b9d2cf0afb9d"},
|
||||
]
|
||||
|
||||
[package.extras]
|
||||
dev = ["freezegun (>=1.0,<2.0)", "pytest (>=6.0)", "pytest-cov"]
|
||||
dev = ["backports.zoneinfo", "freezegun (>=1.0,<2.0)", "jinja2 (>=3.0)", "pytest (>=6.0)", "pytest-cov", "pytz", "setuptools", "tzdata"]
|
||||
|
||||
[[package]]
|
||||
name = "betterproto"
|
||||
@@ -110,14 +110,14 @@ rust-codec = ["betterproto-rust-codec (==0.1.1)"]
|
||||
|
||||
[[package]]
|
||||
name = "certifi"
|
||||
version = "2024.12.14"
|
||||
version = "2025.1.31"
|
||||
description = "Python package for providing Mozilla's CA Bundle."
|
||||
optional = false
|
||||
python-versions = ">=3.6"
|
||||
groups = ["main", "docs"]
|
||||
files = [
|
||||
{file = "certifi-2024.12.14-py3-none-any.whl", hash = "sha256:1275f7a45be9464efc1173084eaa30f866fe2e47d389406136d332ed4967ec56"},
|
||||
{file = "certifi-2024.12.14.tar.gz", hash = "sha256:b650d30f370c2b724812bee08008be0c4163b163ddaec3f2546c1caf65f191db"},
|
||||
{file = "certifi-2025.1.31-py3-none-any.whl", hash = "sha256:ca78db4565a652026a4db2bcdf68f2fb589ea80d0be70e03929ed730746b84fe"},
|
||||
{file = "certifi-2025.1.31.tar.gz", hash = "sha256:3d5da6925056f6f18f119200434a4780a94263f10d1c21d032a6f6b2baa20651"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -422,19 +422,19 @@ test = ["pytest (>=6)"]
|
||||
|
||||
[[package]]
|
||||
name = "filelock"
|
||||
version = "3.16.1"
|
||||
version = "3.17.0"
|
||||
description = "A platform independent file lock."
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
python-versions = ">=3.9"
|
||||
groups = ["dev"]
|
||||
files = [
|
||||
{file = "filelock-3.16.1-py3-none-any.whl", hash = "sha256:2082e5703d51fbf98ea75855d9d5527e33d8ff23099bec374a134febee6946b0"},
|
||||
{file = "filelock-3.16.1.tar.gz", hash = "sha256:c249fbfcd5db47e5e2d6d62198e565475ee65e4831e2561c8e313fa7eb961435"},
|
||||
{file = "filelock-3.17.0-py3-none-any.whl", hash = "sha256:533dc2f7ba78dc2f0f531fc6c4940addf7b70a481e269a5a3b93be94ffbe8338"},
|
||||
{file = "filelock-3.17.0.tar.gz", hash = "sha256:ee4e77401ef576ebb38cd7f13b9b28893194acc20a8e68e18730ba9c0e54660e"},
|
||||
]
|
||||
|
||||
[package.extras]
|
||||
docs = ["furo (>=2024.8.6)", "sphinx (>=8.0.2)", "sphinx-autodoc-typehints (>=2.4.1)"]
|
||||
testing = ["covdefaults (>=2.3)", "coverage (>=7.6.1)", "diff-cover (>=9.2)", "pytest (>=8.3.3)", "pytest-asyncio (>=0.24)", "pytest-cov (>=5)", "pytest-mock (>=3.14)", "pytest-timeout (>=2.3.1)", "virtualenv (>=20.26.4)"]
|
||||
docs = ["furo (>=2024.8.6)", "sphinx (>=8.1.3)", "sphinx-autodoc-typehints (>=3)"]
|
||||
testing = ["covdefaults (>=2.3)", "coverage (>=7.6.10)", "diff-cover (>=9.2.1)", "pytest (>=8.3.4)", "pytest-asyncio (>=0.25.2)", "pytest-cov (>=6)", "pytest-mock (>=3.14)", "pytest-timeout (>=2.3.1)", "virtualenv (>=20.28.1)"]
|
||||
typing = ["typing-extensions (>=4.12.2)"]
|
||||
|
||||
[[package]]
|
||||
@@ -457,14 +457,14 @@ dev = ["flake8", "markdown", "twine", "wheel"]
|
||||
|
||||
[[package]]
|
||||
name = "griffe"
|
||||
version = "1.5.4"
|
||||
version = "1.5.6"
|
||||
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
|
||||
python-versions = ">=3.9"
|
||||
groups = ["docs"]
|
||||
files = [
|
||||
{file = "griffe-1.5.4-py3-none-any.whl", hash = "sha256:ed33af890586a5bebc842fcb919fc694b3dc1bc55b7d9e0228de41ce566b4a1d"},
|
||||
{file = "griffe-1.5.4.tar.gz", hash = "sha256:073e78ad3e10c8378c2f798bd4ef87b92d8411e9916e157fd366a17cc4fd4e52"},
|
||||
{file = "griffe-1.5.6-py3-none-any.whl", hash = "sha256:b2a3afe497c6c1f952e54a23095ecc09435016293e77af8478ed65df1022a394"},
|
||||
{file = "griffe-1.5.6.tar.gz", hash = "sha256:181f6666d5aceb6cd6e2da5a2b646cfb431e47a0da1fda283845734b67e10944"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
@@ -502,30 +502,30 @@ files = [
|
||||
|
||||
[[package]]
|
||||
name = "h2"
|
||||
version = "4.1.0"
|
||||
description = "HTTP/2 State-Machine based protocol implementation"
|
||||
version = "4.2.0"
|
||||
description = "Pure-Python HTTP/2 protocol implementation"
|
||||
optional = false
|
||||
python-versions = ">=3.6.1"
|
||||
python-versions = ">=3.9"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "h2-4.1.0-py3-none-any.whl", hash = "sha256:03a46bcf682256c95b5fd9e9a99c1323584c3eec6440d379b9903d709476bc6d"},
|
||||
{file = "h2-4.1.0.tar.gz", hash = "sha256:a83aca08fbe7aacb79fec788c9c0bac936343560ed9ec18b82a13a12c28d2abb"},
|
||||
{file = "h2-4.2.0-py3-none-any.whl", hash = "sha256:479a53ad425bb29af087f3458a61d30780bc818e4ebcf01f0b536ba916462ed0"},
|
||||
{file = "h2-4.2.0.tar.gz", hash = "sha256:c8a52129695e88b1a0578d8d2cc6842bbd79128ac685463b887ee278126ad01f"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
hpack = ">=4.0,<5"
|
||||
hyperframe = ">=6.0,<7"
|
||||
hpack = ">=4.1,<5"
|
||||
hyperframe = ">=6.1,<7"
|
||||
|
||||
[[package]]
|
||||
name = "hpack"
|
||||
version = "4.0.0"
|
||||
description = "Pure-Python HPACK header compression"
|
||||
version = "4.1.0"
|
||||
description = "Pure-Python HPACK header encoding"
|
||||
optional = false
|
||||
python-versions = ">=3.6.1"
|
||||
python-versions = ">=3.9"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "hpack-4.0.0-py3-none-any.whl", hash = "sha256:84a076fad3dc9a9f8063ccb8041ef100867b1878b25ef0ee63847a5d53818a6c"},
|
||||
{file = "hpack-4.0.0.tar.gz", hash = "sha256:fc41de0c63e687ebffde81187a948221294896f6bdc0ae2312708df339430095"},
|
||||
{file = "hpack-4.1.0-py3-none-any.whl", hash = "sha256:157ac792668d995c657d93111f46b4535ed114f0c9c8d672271bbec7eae1b496"},
|
||||
{file = "hpack-4.1.0.tar.gz", hash = "sha256:ec5eca154f7056aa06f196a557655c5b009b382873ac8d1e66e79e87535f1dca"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -577,26 +577,26 @@ zstd = ["zstandard (>=0.18.0)"]
|
||||
|
||||
[[package]]
|
||||
name = "hyperframe"
|
||||
version = "6.0.1"
|
||||
description = "HTTP/2 framing layer for Python"
|
||||
version = "6.1.0"
|
||||
description = "Pure-Python HTTP/2 framing"
|
||||
optional = false
|
||||
python-versions = ">=3.6.1"
|
||||
python-versions = ">=3.9"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "hyperframe-6.0.1-py3-none-any.whl", hash = "sha256:0ec6bafd80d8ad2195c4f03aacba3a8265e57bc4cff261e802bf39970ed02a15"},
|
||||
{file = "hyperframe-6.0.1.tar.gz", hash = "sha256:ae510046231dc8e9ecb1a6586f63d2347bf4c8905914aa84ba585ae85f28a914"},
|
||||
{file = "hyperframe-6.1.0-py3-none-any.whl", hash = "sha256:b03380493a519fce58ea5af42e4a42317bf9bd425596f7a0835ffce80f1a42e5"},
|
||||
{file = "hyperframe-6.1.0.tar.gz", hash = "sha256:f630908a00854a7adeabd6382b43923a4c4cd4b821fcb527e6ab9e15382a3b08"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "identify"
|
||||
version = "2.6.5"
|
||||
version = "2.6.6"
|
||||
description = "File identification library for Python"
|
||||
optional = false
|
||||
python-versions = ">=3.9"
|
||||
groups = ["dev"]
|
||||
files = [
|
||||
{file = "identify-2.6.5-py2.py3-none-any.whl", hash = "sha256:14181a47091eb75b337af4c23078c9d09225cd4c48929f521f3bf16b09d02566"},
|
||||
{file = "identify-2.6.5.tar.gz", hash = "sha256:c10b33f250e5bba374fae86fb57f3adcebf1161bce7cdf92031915fd480c13bc"},
|
||||
{file = "identify-2.6.6-py2.py3-none-any.whl", hash = "sha256:cbd1810bce79f8b671ecb20f53ee0ae8e86ae84b557de31d89709dc2a48ba881"},
|
||||
{file = "identify-2.6.6.tar.gz", hash = "sha256:7bec12768ed44ea4761efb47806f0a41f86e7c0a5fdf5950d4648c90eca7e251"},
|
||||
]
|
||||
|
||||
[package.extras]
|
||||
@@ -619,15 +619,15 @@ all = ["flake8 (>=7.1.1)", "mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2
|
||||
|
||||
[[package]]
|
||||
name = "importlib-metadata"
|
||||
version = "8.5.0"
|
||||
version = "8.6.1"
|
||||
description = "Read metadata from Python packages"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
python-versions = ">=3.9"
|
||||
groups = ["docs"]
|
||||
markers = "python_version < \"3.10\""
|
||||
files = [
|
||||
{file = "importlib_metadata-8.5.0-py3-none-any.whl", hash = "sha256:45e54197d28b7a7f1559e60b95e7c567032b602131fbd588f1497f47880aa68b"},
|
||||
{file = "importlib_metadata-8.5.0.tar.gz", hash = "sha256:71522656f0abace1d072b9e5481a48f07c138e00f079c38c8f883823f9c26bd7"},
|
||||
{file = "importlib_metadata-8.6.1-py3-none-any.whl", hash = "sha256:02a89390c1e15fdfdc0d7c6b25cb3e62650d0494005c97d6f148bf5b9787525e"},
|
||||
{file = "importlib_metadata-8.6.1.tar.gz", hash = "sha256:310b41d755445d74569f993ccfc22838295d9fe005425094fad953d7f15c8580"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
@@ -639,7 +639,7 @@ cover = ["pytest-cov"]
|
||||
doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"]
|
||||
enabler = ["pytest-enabler (>=2.2)"]
|
||||
perf = ["ipython"]
|
||||
test = ["flufl.flake8", "importlib-resources (>=1.3)", "jaraco.test (>=5.4)", "packaging", "pyfakefs", "pytest (>=6,!=8.1.*)", "pytest-perf (>=0.9.2)"]
|
||||
test = ["flufl.flake8", "importlib_resources (>=1.3)", "jaraco.test (>=5.4)", "packaging", "pyfakefs", "pytest (>=6,!=8.1.*)", "pytest-perf (>=0.9.2)"]
|
||||
type = ["pytest-mypy"]
|
||||
|
||||
[[package]]
|
||||
@@ -846,14 +846,14 @@ pyyaml = ">=5.1"
|
||||
|
||||
[[package]]
|
||||
name = "mkdocs-material"
|
||||
version = "9.5.49"
|
||||
version = "9.6.2"
|
||||
description = "Documentation that simply works"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
groups = ["docs"]
|
||||
files = [
|
||||
{file = "mkdocs_material-9.5.49-py3-none-any.whl", hash = "sha256:c3c2d8176b18198435d3a3e119011922f3e11424074645c24019c2dcf08a360e"},
|
||||
{file = "mkdocs_material-9.5.49.tar.gz", hash = "sha256:3671bb282b4f53a1c72e08adbe04d2481a98f85fed392530051f80ff94a9621d"},
|
||||
{file = "mkdocs_material-9.6.2-py3-none-any.whl", hash = "sha256:71d90dbd63b393ad11a4d90151dfe3dcbfcd802c0f29ce80bebd9bbac6abc753"},
|
||||
{file = "mkdocs_material-9.6.2.tar.gz", hash = "sha256:a3de1c5d4c745f10afa78b1a02f917b9dce0808fb206adc0f5bb48b58c1ca21f"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
@@ -870,7 +870,7 @@ regex = ">=2022.4"
|
||||
requests = ">=2.26,<3.0"
|
||||
|
||||
[package.extras]
|
||||
git = ["mkdocs-git-committers-plugin-2 (>=1.1,<2.0)", "mkdocs-git-revision-date-localized-plugin (>=1.2.4,<2.0)"]
|
||||
git = ["mkdocs-git-committers-plugin-2 (>=1.1,<3)", "mkdocs-git-revision-date-localized-plugin (>=1.2.4,<2.0)"]
|
||||
imaging = ["cairosvg (>=2.6,<3.0)", "pillow (>=10.2,<11.0)"]
|
||||
recommended = ["mkdocs-minify-plugin (>=0.7,<1.0)", "mkdocs-redirects (>=1.2,<2.0)", "mkdocs-rss-plugin (>=1.6,<2.0)"]
|
||||
|
||||
@@ -1127,14 +1127,14 @@ type = ["mypy (>=1.11.2)"]
|
||||
|
||||
[[package]]
|
||||
name = "pre-commit"
|
||||
version = "4.0.1"
|
||||
version = "4.1.0"
|
||||
description = "A framework for managing and maintaining multi-language pre-commit hooks."
|
||||
optional = false
|
||||
python-versions = ">=3.9"
|
||||
groups = ["dev"]
|
||||
files = [
|
||||
{file = "pre_commit-4.0.1-py2.py3-none-any.whl", hash = "sha256:efde913840816312445dc98787724647c65473daefe420785f885e8ed9a06878"},
|
||||
{file = "pre_commit-4.0.1.tar.gz", hash = "sha256:80905ac375958c0444c65e9cebebd948b3cdb518f335a091a670a89d652139d2"},
|
||||
{file = "pre_commit-4.1.0-py2.py3-none-any.whl", hash = "sha256:d29e7cb346295bcc1cc75fc3e92e343495e3ea0196c9ec6ba53f49f10ab6ae7b"},
|
||||
{file = "pre_commit-4.1.0.tar.gz", hash = "sha256:ae3f018575a588e30dfddfab9a05448bfbd6b73d78709617b5a2b853549716d4"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
@@ -1177,14 +1177,14 @@ files = [
|
||||
|
||||
[[package]]
|
||||
name = "pydantic"
|
||||
version = "2.10.5"
|
||||
version = "2.10.6"
|
||||
description = "Data validation using Python type hints"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "pydantic-2.10.5-py3-none-any.whl", hash = "sha256:4dd4e322dbe55472cb7ca7e73f4b63574eecccf2835ffa2af9021ce113c83c53"},
|
||||
{file = "pydantic-2.10.5.tar.gz", hash = "sha256:278b38dbbaec562011d659ee05f63346951b3a248a6f3642e1bc68894ea2b4ff"},
|
||||
{file = "pydantic-2.10.6-py3-none-any.whl", hash = "sha256:427d664bf0b8a2b34ff5dd0f5a18df00591adcee7198fbd71981054cef37b584"},
|
||||
{file = "pydantic-2.10.6.tar.gz", hash = "sha256:ca5daa827cce33de7a42be142548b0096bf05a7e7b365aebfa5f8eeec7128236"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
@@ -1326,14 +1326,14 @@ windows-terminal = ["colorama (>=0.4.6)"]
|
||||
|
||||
[[package]]
|
||||
name = "pymdown-extensions"
|
||||
version = "10.14"
|
||||
version = "10.14.3"
|
||||
description = "Extension pack for Python Markdown."
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
groups = ["docs"]
|
||||
files = [
|
||||
{file = "pymdown_extensions-10.14-py3-none-any.whl", hash = "sha256:202481f716cc8250e4be8fce997781ebf7917701b59652458ee47f2401f818b5"},
|
||||
{file = "pymdown_extensions-10.14.tar.gz", hash = "sha256:741bd7c4ff961ba40b7528d32284c53bc436b8b1645e8e37c3e57770b8700a34"},
|
||||
{file = "pymdown_extensions-10.14.3-py3-none-any.whl", hash = "sha256:05e0bee73d64b9c71a4ae17c72abc2f700e8bc8403755a00580b49a4e9f189e9"},
|
||||
{file = "pymdown_extensions-10.14.3.tar.gz", hash = "sha256:41e576ce3f5d650be59e900e4ceff231e0aed2a88cf30acaee41e02f063a061b"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
@@ -1674,14 +1674,14 @@ zstd = ["zstandard (>=0.18.0)"]
|
||||
|
||||
[[package]]
|
||||
name = "virtualenv"
|
||||
version = "20.28.1"
|
||||
version = "20.29.1"
|
||||
description = "Virtual Python Environment builder"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
groups = ["dev"]
|
||||
files = [
|
||||
{file = "virtualenv-20.28.1-py3-none-any.whl", hash = "sha256:412773c85d4dab0409b83ec36f7a6499e72eaf08c80e81e9576bca61831c71cb"},
|
||||
{file = "virtualenv-20.28.1.tar.gz", hash = "sha256:5d34ab240fdb5d21549b76f9e8ff3af28252f5499fb6d6f031adac4e5a8c5329"},
|
||||
{file = "virtualenv-20.29.1-py3-none-any.whl", hash = "sha256:4e4cb403c0b0da39e13b46b1b2476e505cb0046b25f242bee80f62bf990b2779"},
|
||||
{file = "virtualenv-20.29.1.tar.gz", hash = "sha256:b8b8970138d32fb606192cb97f6cd4bb644fa486be9308fb9b63f81091b5dc35"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
@@ -1759,5 +1759,5 @@ type = ["pytest-mypy"]
|
||||
|
||||
[metadata]
|
||||
lock-version = "2.1"
|
||||
python-versions = "^3.9"
|
||||
content-hash = "c0aa00dd5f3b52bbac53eb765be2bca2ec7f9429e835d6b2fe6bf207f2f39974"
|
||||
python-versions = ">3.9, <4.0"
|
||||
content-hash = "67a8e0d34c0d1af0f8e4d617d80fd5afc8d197e5d5444f78fd82e4f716a52965"
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
# See the License for the specific language governing permissions and -
|
||||
# limitations under the License. -
|
||||
# ------------------------------------------------------------------------------
|
||||
import importlib.metadata
|
||||
|
||||
from pyasic import settings
|
||||
from pyasic.config import MinerConfig
|
||||
from pyasic.data import MinerData
|
||||
@@ -22,3 +24,5 @@ from pyasic.network import MinerNetwork
|
||||
from pyasic.rpc import *
|
||||
from pyasic.ssh import *
|
||||
from pyasic.web import *
|
||||
|
||||
__version__ = importlib.metadata.version("pyasic")
|
||||
|
||||
@@ -143,12 +143,12 @@ class MinerConfig(BaseModel):
|
||||
**self.pools.as_mara(user_suffix=user_suffix),
|
||||
}
|
||||
|
||||
def as_bitaxe(self, user_suffix: str | None = None) -> dict:
|
||||
def as_espminer(self, user_suffix: str | None = None) -> dict:
|
||||
return {
|
||||
**self.fan_mode.as_bitaxe(),
|
||||
**self.temperature.as_bitaxe(),
|
||||
**self.mining_mode.as_bitaxe(),
|
||||
**self.pools.as_bitaxe(user_suffix=user_suffix),
|
||||
**self.fan_mode.as_espminer(),
|
||||
**self.temperature.as_espminer(),
|
||||
**self.mining_mode.as_espminer(),
|
||||
**self.pools.as_espminer(user_suffix=user_suffix),
|
||||
}
|
||||
|
||||
def as_luxos(self, user_suffix: str | None = None) -> dict:
|
||||
@@ -272,10 +272,10 @@ class MinerConfig(BaseModel):
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def from_bitaxe(cls, web_system_info: dict) -> "MinerConfig":
|
||||
def from_espminer(cls, web_system_info: dict) -> "MinerConfig":
|
||||
return cls(
|
||||
pools=PoolConfig.from_bitaxe(web_system_info),
|
||||
fan_mode=FanModeConfig.from_bitaxe(web_system_info),
|
||||
pools=PoolConfig.from_espminer(web_system_info),
|
||||
fan_mode=FanModeConfig.from_espminer(web_system_info),
|
||||
)
|
||||
|
||||
@classmethod
|
||||
|
||||
@@ -61,8 +61,8 @@ class MinerConfigOption(Enum):
|
||||
def as_mara(self) -> dict:
|
||||
return self.value.as_mara()
|
||||
|
||||
def as_bitaxe(self) -> dict:
|
||||
return self.value.as_bitaxe()
|
||||
def as_espminer(self) -> dict:
|
||||
return self.value.as_espminer()
|
||||
|
||||
def as_luxos(self) -> dict:
|
||||
return self.value.as_luxos()
|
||||
@@ -125,7 +125,7 @@ class MinerConfigValue(BaseModel):
|
||||
def as_mara(self) -> dict:
|
||||
return {}
|
||||
|
||||
def as_bitaxe(self) -> dict:
|
||||
def as_espminer(self) -> dict:
|
||||
return {}
|
||||
|
||||
def as_luxos(self) -> dict:
|
||||
|
||||
@@ -81,7 +81,7 @@ class FanModeNormal(MinerConfigValue):
|
||||
},
|
||||
}
|
||||
|
||||
def as_bitaxe(self) -> dict:
|
||||
def as_espminer(self) -> dict:
|
||||
return {"autoFanspeed": 1}
|
||||
|
||||
def as_luxos(self) -> dict:
|
||||
@@ -156,7 +156,7 @@ class FanModeManual(MinerConfigValue):
|
||||
},
|
||||
}
|
||||
|
||||
def as_bitaxe(self) -> dict:
|
||||
def as_espminer(self) -> dict:
|
||||
return {"autoFanspeed": 0, "fanspeed": self.speed}
|
||||
|
||||
def as_luxos(self) -> dict:
|
||||
@@ -342,7 +342,7 @@ class FanModeConfig(MinerConfigOption):
|
||||
return cls.default()
|
||||
|
||||
@classmethod
|
||||
def from_bitaxe(cls, web_system_info: dict):
|
||||
def from_espminer(cls, web_system_info: dict):
|
||||
if web_system_info["autofanspeed"] == 1:
|
||||
return cls.normal()
|
||||
else:
|
||||
|
||||
@@ -371,11 +371,7 @@ class MiningModePreset(MinerConfigValue):
|
||||
def from_luxos(
|
||||
cls, rpc_config: dict, rpc_profiles: list[dict]
|
||||
) -> "MiningModePreset":
|
||||
active_preset = None
|
||||
active_profile = rpc_config["CONFIG"][0]["Profile"]
|
||||
for profile in rpc_profiles["PROFILES"]:
|
||||
if profile["Profile Name"] == active_profile:
|
||||
active_preset = profile
|
||||
active_preset = cls.get_active_preset_from_luxos(rpc_config, rpc_profiles)
|
||||
return cls(
|
||||
active_preset=MiningPreset.from_luxos(active_preset),
|
||||
available_presets=[
|
||||
@@ -383,6 +379,17 @@ class MiningModePreset(MinerConfigValue):
|
||||
],
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def get_active_preset_from_luxos(
|
||||
cls, rpc_config: dict, rpc_profiles: list[dict]
|
||||
) -> dict:
|
||||
active_preset = None
|
||||
active_profile = rpc_config["CONFIG"][0]["Profile"]
|
||||
for profile in rpc_profiles["PROFILES"]:
|
||||
if profile["Profile Name"] == active_profile:
|
||||
active_preset = profile
|
||||
return active_preset
|
||||
|
||||
|
||||
class ManualBoardSettings(MinerConfigValue):
|
||||
freq: float
|
||||
@@ -705,7 +712,11 @@ class MiningModeConfig(MinerConfigOption):
|
||||
|
||||
@classmethod
|
||||
def from_luxos(cls, rpc_config: dict, rpc_profiles: dict):
|
||||
return MiningModePreset.from_luxos(rpc_config, rpc_profiles)
|
||||
preset_info = MiningModePreset.from_luxos(rpc_config, rpc_profiles)
|
||||
return cls.preset(
|
||||
active_preset=preset_info.active_preset,
|
||||
available_presets=preset_info.available_presets,
|
||||
)
|
||||
|
||||
|
||||
MiningMode = TypeVar(
|
||||
|
||||
@@ -102,7 +102,7 @@ class Pool(MinerConfigValue):
|
||||
"pass": self.password,
|
||||
}
|
||||
|
||||
def as_bitaxe(self, user_suffix: str | None = None) -> dict:
|
||||
def as_espminer(self, user_suffix: str | None = None) -> dict:
|
||||
return {
|
||||
"stratumURL": self.url,
|
||||
"stratumUser": f"{self.user}{user_suffix or ''}",
|
||||
@@ -192,7 +192,7 @@ class Pool(MinerConfigValue):
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def from_bitaxe(cls, web_system_info: dict) -> "Pool":
|
||||
def from_espminer(cls, web_system_info: dict) -> "Pool":
|
||||
url = f"stratum+tcp://{web_system_info['stratumURL']}:{web_system_info['stratumPort']}"
|
||||
return cls(
|
||||
url=url,
|
||||
@@ -306,8 +306,8 @@ class PoolGroup(MinerConfigValue):
|
||||
def as_mara(self, user_suffix: str | None = None) -> list:
|
||||
return [p.as_mara(user_suffix=user_suffix) for p in self.pools]
|
||||
|
||||
def as_bitaxe(self, user_suffix: str | None = None) -> dict:
|
||||
return self.pools[0].as_bitaxe(user_suffix=user_suffix)
|
||||
def as_espminer(self, user_suffix: str | None = None) -> dict:
|
||||
return self.pools[0].as_espminer(user_suffix=user_suffix)
|
||||
|
||||
def as_boser(self, user_suffix: str | None = None) -> PoolGroupConfiguration:
|
||||
return PoolGroupConfiguration(
|
||||
@@ -395,8 +395,8 @@ class PoolGroup(MinerConfigValue):
|
||||
return cls(pools=[Pool.from_mara(pool_conf) for pool_conf in web_config_pools])
|
||||
|
||||
@classmethod
|
||||
def from_bitaxe(cls, web_system_info: dict) -> "PoolGroup":
|
||||
return cls(pools=[Pool.from_bitaxe(web_system_info)])
|
||||
def from_espminer(cls, web_system_info: dict) -> "PoolGroup":
|
||||
return cls(pools=[Pool.from_espminer(web_system_info)])
|
||||
|
||||
@classmethod
|
||||
def from_iceriver(cls, web_userpanel: dict) -> "PoolGroup":
|
||||
@@ -507,8 +507,8 @@ class PoolConfig(MinerConfigValue):
|
||||
return {"pools": self.groups[0].as_mara(user_suffix=user_suffix)}
|
||||
return {"pools": []}
|
||||
|
||||
def as_bitaxe(self, user_suffix: str | None = None) -> dict:
|
||||
return self.groups[0].as_bitaxe(user_suffix=user_suffix)
|
||||
def as_espminer(self, user_suffix: str | None = None) -> dict:
|
||||
return self.groups[0].as_espminer(user_suffix=user_suffix)
|
||||
|
||||
def as_luxos(self, user_suffix: str | None = None) -> dict:
|
||||
return {}
|
||||
@@ -576,8 +576,8 @@ class PoolConfig(MinerConfigValue):
|
||||
return cls(groups=[PoolGroup.from_mara(web_config["pools"])])
|
||||
|
||||
@classmethod
|
||||
def from_bitaxe(cls, web_system_info: dict) -> "PoolConfig":
|
||||
return cls(groups=[PoolGroup.from_bitaxe(web_system_info)])
|
||||
def from_espminer(cls, web_system_info: dict) -> "PoolConfig":
|
||||
return cls(groups=[PoolGroup.from_espminer(web_system_info)])
|
||||
|
||||
@classmethod
|
||||
def from_iceriver(cls, web_userpanel: dict) -> "PoolConfig":
|
||||
|
||||
@@ -18,9 +18,15 @@ from typing import TypeVar
|
||||
|
||||
from .bos import BraiinsOSError
|
||||
from .innosilicon import InnosiliconError
|
||||
from .vnish import VnishError
|
||||
from .whatsminer import WhatsminerError
|
||||
from .X19 import X19Error
|
||||
|
||||
MinerErrorData = TypeVar(
|
||||
"MinerErrorData", WhatsminerError, BraiinsOSError, X19Error, InnosiliconError
|
||||
"MinerErrorData",
|
||||
WhatsminerError,
|
||||
BraiinsOSError,
|
||||
X19Error,
|
||||
InnosiliconError,
|
||||
VnishError,
|
||||
)
|
||||
|
||||
28
pyasic/data/error_codes/vnish.py
Normal file
28
pyasic/data/error_codes/vnish.py
Normal file
@@ -0,0 +1,28 @@
|
||||
# ------------------------------------------------------------------------------
|
||||
# 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.data.error_codes.base import BaseMinerError
|
||||
|
||||
|
||||
class VnishError(BaseMinerError):
|
||||
"""A Dataclass to handle error codes of Vnish miners.
|
||||
|
||||
Attributes:
|
||||
error_message: The error message as a string.
|
||||
error_code: The error code as an int. 0 if the message is not assigned a code.
|
||||
"""
|
||||
|
||||
error_message: str
|
||||
error_code: int = 0
|
||||
@@ -26,6 +26,7 @@ class MinerMake(str, Enum):
|
||||
AURADINE = "Auradine"
|
||||
EPIC = "ePIC"
|
||||
BITAXE = "BitAxe"
|
||||
LUCKYMINER = "LuckyMiner"
|
||||
ICERIVER = "IceRiver"
|
||||
HAMMER = "Hammer"
|
||||
VOLCMINER = "VolcMiner"
|
||||
|
||||
@@ -59,6 +59,7 @@ class AntminerModels(MinerModelType):
|
||||
T19 = "T19"
|
||||
S21 = "S21"
|
||||
S21Pro = "S21 Pro"
|
||||
S21Hydro = "S21 Hydro"
|
||||
T21 = "T21"
|
||||
|
||||
def __str__(self):
|
||||
@@ -507,6 +508,14 @@ class BitAxeModels(MinerModelType):
|
||||
return self.value
|
||||
|
||||
|
||||
class LuckyMinerModels(MinerModelType):
|
||||
LV07 = "LV07"
|
||||
LV08 = "LV08"
|
||||
|
||||
def __str__(self):
|
||||
return self.value
|
||||
|
||||
|
||||
class IceRiverModels(MinerModelType):
|
||||
KS0 = "KS0"
|
||||
KS1 = "KS1"
|
||||
@@ -550,6 +559,7 @@ class MinerModel:
|
||||
AURADINE = AuradineModels
|
||||
EPIC = ePICModels
|
||||
BITAXE = BitAxeModels
|
||||
LUCKYMINER = LuckyMinerModels
|
||||
ICERIVER = IceRiverModels
|
||||
HAMMER = HammerModels
|
||||
VOLCMINER = VolcMinerModels
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
from pyasic.miners.backends import AntminerModern
|
||||
from pyasic.miners.device.models import S21, S21Pro
|
||||
from pyasic.miners.device.models import S21, S21Hydro, S21Pro
|
||||
|
||||
|
||||
class BMMinerS21(AntminerModern, S21):
|
||||
@@ -24,3 +24,7 @@ class BMMinerS21(AntminerModern, S21):
|
||||
|
||||
class BMMinerS21Pro(AntminerModern, S21Pro):
|
||||
pass
|
||||
|
||||
|
||||
class BMMinerS21Hydro(AntminerModern, S21Hydro):
|
||||
pass
|
||||
|
||||
@@ -13,5 +13,5 @@
|
||||
# See the License for the specific language governing permissions and -
|
||||
# limitations under the License. -
|
||||
# ------------------------------------------------------------------------------
|
||||
from .S21 import BMMinerS21, BMMinerS21Pro
|
||||
from .S21 import BMMinerS21, BMMinerS21Hydro, BMMinerS21Pro
|
||||
from .T21 import BMMinerT21
|
||||
|
||||
@@ -15,8 +15,12 @@
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
from pyasic.miners.backends import BOSer
|
||||
from pyasic.miners.device.models import S21
|
||||
from pyasic.miners.device.models import S21, S21Pro
|
||||
|
||||
|
||||
class BOSMinerS21(BOSer, S21):
|
||||
pass
|
||||
|
||||
|
||||
class BOSMinerS21Pro(BOSer, S21Pro):
|
||||
pass
|
||||
|
||||
@@ -14,5 +14,5 @@
|
||||
# limitations under the License. -
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
from .S21 import BOSMinerS21
|
||||
from .S21 import BOSMinerS21, BOSMinerS21Pro
|
||||
from .T21 import BOSMinerT21
|
||||
|
||||
@@ -27,6 +27,7 @@ from pyasic.miners.device.models import (
|
||||
S19jNoPIC,
|
||||
S19jPro,
|
||||
S19KPro,
|
||||
S19NoPIC,
|
||||
S19Plus,
|
||||
S19Pro,
|
||||
S19ProHydro,
|
||||
@@ -39,6 +40,10 @@ class HiveonS19(HiveonModern, S19):
|
||||
pass
|
||||
|
||||
|
||||
class HiveonS19NoPIC(HiveonModern, S19NoPIC):
|
||||
pass
|
||||
|
||||
|
||||
class HiveonS19Plus(HiveonModern, S19Plus):
|
||||
pass
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ from .S19 import (
|
||||
HiveonS19jPro,
|
||||
HiveonS19KPro,
|
||||
HiveonS19L,
|
||||
HiveonS19NoPIC,
|
||||
HiveonS19Plus,
|
||||
HiveonS19Pro,
|
||||
HiveonS19ProHydro,
|
||||
|
||||
@@ -20,6 +20,7 @@ from pyasic.miners.device.models import (
|
||||
S19XP,
|
||||
S19a,
|
||||
S19aPro,
|
||||
S19i,
|
||||
S19j,
|
||||
S19jPro,
|
||||
S19kPro,
|
||||
@@ -53,6 +54,10 @@ class VNishS19aPro(VNish, S19aPro):
|
||||
pass
|
||||
|
||||
|
||||
class VNishS19i(VNish, S19i):
|
||||
pass
|
||||
|
||||
|
||||
class VNishS19j(VNish, S19j):
|
||||
pass
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ from .S19 import (
|
||||
VNishS19,
|
||||
VNishS19a,
|
||||
VNishS19aPro,
|
||||
VNishS19i,
|
||||
VNishS19j,
|
||||
VNishS19jPro,
|
||||
VNishS19kPro,
|
||||
|
||||
@@ -13,10 +13,91 @@
|
||||
# See the License for the specific language governing permissions and -
|
||||
# limitations under the License. -
|
||||
# ------------------------------------------------------------------------------
|
||||
from typing import Optional
|
||||
|
||||
from pyasic import APIError
|
||||
from pyasic.miners.backends import AvalonMiner
|
||||
from pyasic.miners.data import (
|
||||
DataFunction,
|
||||
DataLocations,
|
||||
DataOptions,
|
||||
RPCAPICommand,
|
||||
WebAPICommand,
|
||||
)
|
||||
from pyasic.miners.device.models import AvalonNano3
|
||||
from pyasic.web.avalonminer import AvalonMinerWebAPI
|
||||
|
||||
AVALON_NANO_DATA_LOC = DataLocations(
|
||||
**{
|
||||
str(DataOptions.MAC): DataFunction(
|
||||
"_get_mac",
|
||||
[WebAPICommand("web_minerinfo", "get_minerinfo")],
|
||||
),
|
||||
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_devs", "devs")],
|
||||
),
|
||||
str(DataOptions.EXPECTED_HASHRATE): DataFunction(
|
||||
"_get_expected_hashrate",
|
||||
[RPCAPICommand("rpc_stats", "stats")],
|
||||
),
|
||||
str(DataOptions.HASHBOARDS): DataFunction(
|
||||
"_get_hashboards",
|
||||
[RPCAPICommand("rpc_stats", "stats")],
|
||||
),
|
||||
str(DataOptions.ENVIRONMENT_TEMP): DataFunction(
|
||||
"_get_env_temp",
|
||||
[RPCAPICommand("rpc_stats", "stats")],
|
||||
),
|
||||
str(DataOptions.WATTAGE_LIMIT): DataFunction(
|
||||
"_get_wattage_limit",
|
||||
[RPCAPICommand("rpc_stats", "stats")],
|
||||
),
|
||||
str(DataOptions.FANS): DataFunction(
|
||||
"_get_fans",
|
||||
[RPCAPICommand("rpc_stats", "stats")],
|
||||
),
|
||||
str(DataOptions.FAULT_LIGHT): DataFunction(
|
||||
"_get_fault_light",
|
||||
[RPCAPICommand("rpc_stats", "stats")],
|
||||
),
|
||||
str(DataOptions.UPTIME): DataFunction(
|
||||
"_get_uptime",
|
||||
[RPCAPICommand("rpc_stats", "stats")],
|
||||
),
|
||||
str(DataOptions.POOLS): DataFunction(
|
||||
"_get_pools",
|
||||
[RPCAPICommand("rpc_pools", "pools")],
|
||||
),
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
class CGMinerAvalonNano3(AvalonMiner, AvalonNano3):
|
||||
pass
|
||||
_web_cls = AvalonMinerWebAPI
|
||||
web: AvalonMinerWebAPI
|
||||
|
||||
data_locations = AVALON_NANO_DATA_LOC
|
||||
|
||||
async def _get_mac(self, web_minerinfo: dict) -> Optional[dict]:
|
||||
if web_minerinfo is None:
|
||||
try:
|
||||
web_minerinfo = await self.web.minerinfo()
|
||||
except APIError:
|
||||
pass
|
||||
|
||||
if web_minerinfo is not None:
|
||||
try:
|
||||
mac = web_minerinfo.get("mac")
|
||||
if mac is not None:
|
||||
return mac.upper()
|
||||
except (KeyError, ValueError):
|
||||
pass
|
||||
|
||||
@@ -28,6 +28,7 @@ from .hammer import BlackMiner
|
||||
from .hiveon import HiveonModern, HiveonOld
|
||||
from .iceriver import IceRiver
|
||||
from .innosilicon import Innosilicon
|
||||
from .luckyminer import LuckyMiner
|
||||
from .luxminer import LUXMiner
|
||||
from .marathon import MaraMiner
|
||||
from .unknown import UnknownMiner
|
||||
|
||||
@@ -1,235 +1,7 @@
|
||||
from typing import List, Optional
|
||||
|
||||
from pyasic import APIError, MinerConfig
|
||||
from pyasic.data import Fan, HashBoard
|
||||
from pyasic.device.algorithm import AlgoHashRate
|
||||
from pyasic.device.firmware import MinerFirmware
|
||||
from pyasic.miners.base import BaseMiner
|
||||
from pyasic.miners.data import DataFunction, DataLocations, DataOptions, WebAPICommand
|
||||
from pyasic.web.bitaxe import BitAxeWebAPI
|
||||
|
||||
BITAXE_DATA_LOC = DataLocations(
|
||||
**{
|
||||
str(DataOptions.HASHRATE): DataFunction(
|
||||
"_get_hashrate",
|
||||
[WebAPICommand("web_system_info", "system/info")],
|
||||
),
|
||||
str(DataOptions.EXPECTED_HASHRATE): DataFunction(
|
||||
"_get_expected_hashrate",
|
||||
[WebAPICommand("web_system_info", "system/info")],
|
||||
),
|
||||
str(DataOptions.WATTAGE): DataFunction(
|
||||
"_get_wattage",
|
||||
[WebAPICommand("web_system_info", "system/info")],
|
||||
),
|
||||
str(DataOptions.UPTIME): DataFunction(
|
||||
"_get_uptime",
|
||||
[WebAPICommand("web_system_info", "system/info")],
|
||||
),
|
||||
str(DataOptions.HASHBOARDS): DataFunction(
|
||||
"_get_hashboards",
|
||||
[WebAPICommand("web_system_info", "system/info")],
|
||||
),
|
||||
str(DataOptions.HOSTNAME): DataFunction(
|
||||
"_get_hostname",
|
||||
[WebAPICommand("web_system_info", "system/info")],
|
||||
),
|
||||
str(DataOptions.FANS): DataFunction(
|
||||
"_get_fans",
|
||||
[WebAPICommand("web_system_info", "system/info")],
|
||||
),
|
||||
str(DataOptions.FW_VERSION): DataFunction(
|
||||
"_get_fw_ver",
|
||||
[WebAPICommand("web_system_info", "system/info")],
|
||||
),
|
||||
str(DataOptions.API_VERSION): DataFunction(
|
||||
"_get_api_ver",
|
||||
[WebAPICommand("web_system_info", "system/info")],
|
||||
),
|
||||
str(DataOptions.MAC): DataFunction(
|
||||
"_get_mac",
|
||||
[WebAPICommand("web_system_info", "system/info")],
|
||||
),
|
||||
}
|
||||
)
|
||||
from pyasic.miners.backends.espminer import ESPMiner
|
||||
|
||||
|
||||
class BitAxe(BaseMiner):
|
||||
class BitAxe(ESPMiner):
|
||||
"""Handler for BitAxe"""
|
||||
|
||||
web: BitAxeWebAPI
|
||||
_web_cls = BitAxeWebAPI
|
||||
|
||||
firmware = MinerFirmware.STOCK
|
||||
|
||||
data_locations = BITAXE_DATA_LOC
|
||||
|
||||
async def reboot(self) -> bool:
|
||||
await self.web.restart()
|
||||
return True
|
||||
|
||||
async def get_config(self) -> MinerConfig:
|
||||
web_system_info = await self.web.system_info()
|
||||
return MinerConfig.from_bitaxe(web_system_info)
|
||||
|
||||
async def send_config(self, config: MinerConfig, user_suffix: str = None) -> None:
|
||||
await self.web.update_settings(**config.as_bitaxe())
|
||||
|
||||
async def _get_wattage(self, web_system_info: dict = None) -> Optional[int]:
|
||||
if web_system_info is None:
|
||||
try:
|
||||
web_system_info = await self.web.system_info()
|
||||
except APIError:
|
||||
pass
|
||||
if web_system_info is not None:
|
||||
try:
|
||||
return round(web_system_info["power"])
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
async def _get_hashrate(
|
||||
self, web_system_info: dict = None
|
||||
) -> Optional[AlgoHashRate]:
|
||||
if web_system_info is None:
|
||||
try:
|
||||
web_system_info = await self.web.system_info()
|
||||
except APIError:
|
||||
pass
|
||||
|
||||
if web_system_info is not None:
|
||||
try:
|
||||
return self.algo.hashrate(
|
||||
rate=float(web_system_info["hashRate"]), unit=self.algo.unit.GH
|
||||
).into(self.algo.unit.default)
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
async def _get_expected_hashrate(
|
||||
self, web_system_info: dict = None
|
||||
) -> Optional[AlgoHashRate]:
|
||||
if web_system_info is None:
|
||||
try:
|
||||
web_system_info = await self.web.system_info()
|
||||
except APIError:
|
||||
pass
|
||||
|
||||
if web_system_info is not None:
|
||||
try:
|
||||
expected_hashrate = (
|
||||
web_system_info.get("smallCoreCount")
|
||||
* web_system_info.get("asicCount")
|
||||
* web_system_info.get("frequency")
|
||||
)
|
||||
|
||||
return self.algo.hashrate(
|
||||
rate=float(expected_hashrate), unit=self.algo.unit.MH
|
||||
).into(self.algo.unit.default)
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
async def _get_uptime(self, web_system_info: dict = None) -> Optional[int]:
|
||||
if web_system_info is None:
|
||||
try:
|
||||
web_system_info = await self.web.system_info()
|
||||
except APIError:
|
||||
pass
|
||||
|
||||
if web_system_info is not None:
|
||||
try:
|
||||
return web_system_info["uptimeSeconds"]
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
async def _get_hashboards(self, web_system_info: dict = None) -> List[HashBoard]:
|
||||
if web_system_info is None:
|
||||
try:
|
||||
web_system_info = await self.web.system_info()
|
||||
except APIError:
|
||||
pass
|
||||
|
||||
if web_system_info is not None:
|
||||
try:
|
||||
return [
|
||||
HashBoard(
|
||||
hashrate=self.algo.hashrate(
|
||||
rate=float(web_system_info["hashRate"]),
|
||||
unit=self.algo.unit.GH,
|
||||
).into(self.algo.unit.default),
|
||||
chip_temp=web_system_info.get("temp"),
|
||||
temp=web_system_info.get("vrTemp"),
|
||||
chips=web_system_info.get("asicCount", 1),
|
||||
expected_chips=self.expected_chips,
|
||||
missing=False,
|
||||
active=True,
|
||||
voltage=web_system_info.get("voltage"),
|
||||
)
|
||||
]
|
||||
except KeyError:
|
||||
pass
|
||||
return []
|
||||
|
||||
async def _get_fans(self, web_system_info: dict = None) -> List[Fan]:
|
||||
if web_system_info is None:
|
||||
try:
|
||||
web_system_info = await self.web.system_info()
|
||||
except APIError:
|
||||
pass
|
||||
|
||||
if web_system_info is not None:
|
||||
try:
|
||||
return [Fan(speed=web_system_info["fanrpm"])]
|
||||
except KeyError:
|
||||
pass
|
||||
return []
|
||||
|
||||
async def _get_hostname(self, web_system_info: dict = None) -> Optional[str]:
|
||||
if web_system_info is None:
|
||||
try:
|
||||
web_system_info = await self.web.system_info()
|
||||
except APIError:
|
||||
pass
|
||||
|
||||
if web_system_info is not None:
|
||||
try:
|
||||
return web_system_info["hostname"]
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
async def _get_api_ver(self, web_system_info: dict = None) -> Optional[str]:
|
||||
if web_system_info is None:
|
||||
try:
|
||||
web_system_info = await self.web.system_info()
|
||||
except APIError:
|
||||
pass
|
||||
|
||||
if web_system_info is not None:
|
||||
try:
|
||||
return web_system_info["version"]
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
async def _get_fw_ver(self, web_system_info: dict = None) -> Optional[str]:
|
||||
if web_system_info is None:
|
||||
try:
|
||||
web_system_info = await self.web.system_info()
|
||||
except APIError:
|
||||
pass
|
||||
|
||||
if web_system_info is not None:
|
||||
try:
|
||||
return web_system_info["version"]
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
async def _get_mac(self, web_system_info: dict = None) -> Optional[str]:
|
||||
if web_system_info is None:
|
||||
try:
|
||||
web_system_info = await self.web.system_info()
|
||||
except APIError:
|
||||
pass
|
||||
|
||||
if web_system_info is not None:
|
||||
try:
|
||||
return web_system_info["macAddr"].upper()
|
||||
except KeyError:
|
||||
pass
|
||||
pass
|
||||
|
||||
235
pyasic/miners/backends/espminer.py
Normal file
235
pyasic/miners/backends/espminer.py
Normal file
@@ -0,0 +1,235 @@
|
||||
from typing import List, Optional
|
||||
|
||||
from pyasic import APIError, MinerConfig
|
||||
from pyasic.data import Fan, HashBoard
|
||||
from pyasic.device.algorithm import AlgoHashRate
|
||||
from pyasic.device.firmware import MinerFirmware
|
||||
from pyasic.miners.base import BaseMiner
|
||||
from pyasic.miners.data import DataFunction, DataLocations, DataOptions, WebAPICommand
|
||||
from pyasic.web.espminer import ESPMinerWebAPI
|
||||
|
||||
ESPMINER_DATA_LOC = DataLocations(
|
||||
**{
|
||||
str(DataOptions.HASHRATE): DataFunction(
|
||||
"_get_hashrate",
|
||||
[WebAPICommand("web_system_info", "system/info")],
|
||||
),
|
||||
str(DataOptions.EXPECTED_HASHRATE): DataFunction(
|
||||
"_get_expected_hashrate",
|
||||
[WebAPICommand("web_system_info", "system/info")],
|
||||
),
|
||||
str(DataOptions.WATTAGE): DataFunction(
|
||||
"_get_wattage",
|
||||
[WebAPICommand("web_system_info", "system/info")],
|
||||
),
|
||||
str(DataOptions.UPTIME): DataFunction(
|
||||
"_get_uptime",
|
||||
[WebAPICommand("web_system_info", "system/info")],
|
||||
),
|
||||
str(DataOptions.HASHBOARDS): DataFunction(
|
||||
"_get_hashboards",
|
||||
[WebAPICommand("web_system_info", "system/info")],
|
||||
),
|
||||
str(DataOptions.HOSTNAME): DataFunction(
|
||||
"_get_hostname",
|
||||
[WebAPICommand("web_system_info", "system/info")],
|
||||
),
|
||||
str(DataOptions.FANS): DataFunction(
|
||||
"_get_fans",
|
||||
[WebAPICommand("web_system_info", "system/info")],
|
||||
),
|
||||
str(DataOptions.FW_VERSION): DataFunction(
|
||||
"_get_fw_ver",
|
||||
[WebAPICommand("web_system_info", "system/info")],
|
||||
),
|
||||
str(DataOptions.API_VERSION): DataFunction(
|
||||
"_get_api_ver",
|
||||
[WebAPICommand("web_system_info", "system/info")],
|
||||
),
|
||||
str(DataOptions.MAC): DataFunction(
|
||||
"_get_mac",
|
||||
[WebAPICommand("web_system_info", "system/info")],
|
||||
),
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
class ESPMiner(BaseMiner):
|
||||
"""Handler for ESPMiner"""
|
||||
|
||||
web: ESPMinerWebAPI
|
||||
_web_cls = ESPMinerWebAPI
|
||||
|
||||
firmware = MinerFirmware.STOCK
|
||||
|
||||
data_locations = ESPMINER_DATA_LOC
|
||||
|
||||
async def reboot(self) -> bool:
|
||||
await self.web.restart()
|
||||
return True
|
||||
|
||||
async def get_config(self) -> MinerConfig:
|
||||
web_system_info = await self.web.system_info()
|
||||
return MinerConfig.from_espminer(web_system_info)
|
||||
|
||||
async def send_config(self, config: MinerConfig, user_suffix: str = None) -> None:
|
||||
await self.web.update_settings(**config.as_espminer())
|
||||
|
||||
async def _get_wattage(self, web_system_info: dict = None) -> Optional[int]:
|
||||
if web_system_info is None:
|
||||
try:
|
||||
web_system_info = await self.web.system_info()
|
||||
except APIError:
|
||||
pass
|
||||
if web_system_info is not None:
|
||||
try:
|
||||
return round(web_system_info["power"])
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
async def _get_hashrate(
|
||||
self, web_system_info: dict = None
|
||||
) -> Optional[AlgoHashRate]:
|
||||
if web_system_info is None:
|
||||
try:
|
||||
web_system_info = await self.web.system_info()
|
||||
except APIError:
|
||||
pass
|
||||
|
||||
if web_system_info is not None:
|
||||
try:
|
||||
return self.algo.hashrate(
|
||||
rate=float(web_system_info["hashRate"]), unit=self.algo.unit.GH
|
||||
).into(self.algo.unit.default)
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
async def _get_expected_hashrate(
|
||||
self, web_system_info: dict = None
|
||||
) -> Optional[AlgoHashRate]:
|
||||
if web_system_info is None:
|
||||
try:
|
||||
web_system_info = await self.web.system_info()
|
||||
except APIError:
|
||||
pass
|
||||
|
||||
if web_system_info is not None:
|
||||
try:
|
||||
expected_hashrate = (
|
||||
web_system_info.get("smallCoreCount")
|
||||
* web_system_info.get("asicCount")
|
||||
* web_system_info.get("frequency")
|
||||
)
|
||||
|
||||
return self.algo.hashrate(
|
||||
rate=float(expected_hashrate), unit=self.algo.unit.MH
|
||||
).into(self.algo.unit.default)
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
async def _get_uptime(self, web_system_info: dict = None) -> Optional[int]:
|
||||
if web_system_info is None:
|
||||
try:
|
||||
web_system_info = await self.web.system_info()
|
||||
except APIError:
|
||||
pass
|
||||
|
||||
if web_system_info is not None:
|
||||
try:
|
||||
return web_system_info["uptimeSeconds"]
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
async def _get_hashboards(self, web_system_info: dict = None) -> List[HashBoard]:
|
||||
if web_system_info is None:
|
||||
try:
|
||||
web_system_info = await self.web.system_info()
|
||||
except APIError:
|
||||
pass
|
||||
|
||||
if web_system_info is not None:
|
||||
try:
|
||||
return [
|
||||
HashBoard(
|
||||
hashrate=self.algo.hashrate(
|
||||
rate=float(web_system_info["hashRate"]),
|
||||
unit=self.algo.unit.GH,
|
||||
).into(self.algo.unit.default),
|
||||
chip_temp=web_system_info.get("temp"),
|
||||
temp=web_system_info.get("vrTemp"),
|
||||
chips=web_system_info.get("asicCount", 1),
|
||||
expected_chips=self.expected_chips,
|
||||
missing=False,
|
||||
active=True,
|
||||
voltage=web_system_info.get("voltage"),
|
||||
)
|
||||
]
|
||||
except KeyError:
|
||||
pass
|
||||
return []
|
||||
|
||||
async def _get_fans(self, web_system_info: dict = None) -> List[Fan]:
|
||||
if web_system_info is None:
|
||||
try:
|
||||
web_system_info = await self.web.system_info()
|
||||
except APIError:
|
||||
pass
|
||||
|
||||
if web_system_info is not None:
|
||||
try:
|
||||
return [Fan(speed=web_system_info["fanrpm"])]
|
||||
except KeyError:
|
||||
pass
|
||||
return []
|
||||
|
||||
async def _get_hostname(self, web_system_info: dict = None) -> Optional[str]:
|
||||
if web_system_info is None:
|
||||
try:
|
||||
web_system_info = await self.web.system_info()
|
||||
except APIError:
|
||||
pass
|
||||
|
||||
if web_system_info is not None:
|
||||
try:
|
||||
return web_system_info["hostname"]
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
async def _get_api_ver(self, web_system_info: dict = None) -> Optional[str]:
|
||||
if web_system_info is None:
|
||||
try:
|
||||
web_system_info = await self.web.system_info()
|
||||
except APIError:
|
||||
pass
|
||||
|
||||
if web_system_info is not None:
|
||||
try:
|
||||
return web_system_info["version"]
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
async def _get_fw_ver(self, web_system_info: dict = None) -> Optional[str]:
|
||||
if web_system_info is None:
|
||||
try:
|
||||
web_system_info = await self.web.system_info()
|
||||
except APIError:
|
||||
pass
|
||||
|
||||
if web_system_info is not None:
|
||||
try:
|
||||
return web_system_info["version"]
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
async def _get_mac(self, web_system_info: dict = None) -> Optional[str]:
|
||||
if web_system_info is None:
|
||||
try:
|
||||
web_system_info = await self.web.system_info()
|
||||
except APIError:
|
||||
pass
|
||||
|
||||
if web_system_info is not None:
|
||||
try:
|
||||
return web_system_info["macAddr"].upper()
|
||||
except KeyError:
|
||||
pass
|
||||
7
pyasic/miners/backends/luckyminer.py
Normal file
7
pyasic/miners/backends/luckyminer.py
Normal file
@@ -0,0 +1,7 @@
|
||||
from pyasic.miners.backends.espminer import ESPMiner
|
||||
|
||||
|
||||
class LuckyMiner(ESPMiner):
|
||||
"""Handler for LuckyMiner"""
|
||||
|
||||
pass
|
||||
@@ -17,6 +17,7 @@ import logging
|
||||
from typing import List, Optional
|
||||
|
||||
from pyasic.config import MinerConfig
|
||||
from pyasic.config.mining import MiningModePreset
|
||||
from pyasic.data import Fan, HashBoard
|
||||
from pyasic.data.pools import PoolMetrics, PoolUrl
|
||||
from pyasic.device.algorithm import AlgoHashRate
|
||||
@@ -47,6 +48,13 @@ LUXMINER_DATA_LOC = DataLocations(
|
||||
"_get_wattage",
|
||||
[RPCAPICommand("rpc_power", "power")],
|
||||
),
|
||||
str(DataOptions.WATTAGE_LIMIT): DataFunction(
|
||||
"_get_wattage_limit",
|
||||
[
|
||||
RPCAPICommand("rpc_config", "config"),
|
||||
RPCAPICommand("rpc_profiles", "profiles"),
|
||||
],
|
||||
),
|
||||
str(DataOptions.FANS): DataFunction(
|
||||
"_get_fans",
|
||||
[RPCAPICommand("rpc_fans", "fans")],
|
||||
@@ -151,7 +159,7 @@ class LUXMiner(LuxOSFirmware):
|
||||
bool: True if the firmware upgrade was successfully initiated, False otherwise.
|
||||
"""
|
||||
try:
|
||||
await self.rpc.upgraderun()
|
||||
await self.rpc.updaterun()
|
||||
logging.info(f"{self.ip}: Firmware upgrade initiated successfully.")
|
||||
return True
|
||||
|
||||
@@ -289,6 +297,17 @@ class LUXMiner(LuxOSFirmware):
|
||||
except (LookupError, ValueError, TypeError):
|
||||
pass
|
||||
|
||||
async def _get_wattage_limit(
|
||||
self, rpc_config: dict = None, rpc_profiles: list[dict] = None
|
||||
) -> Optional[int]:
|
||||
try:
|
||||
active_preset = MiningModePreset.get_active_preset_from_luxos(
|
||||
rpc_config, rpc_profiles
|
||||
)
|
||||
return active_preset.power
|
||||
except (LookupError, ValueError, TypeError):
|
||||
pass
|
||||
|
||||
async def _get_fans(self, rpc_fans: dict = None) -> List[Fan]:
|
||||
if rpc_fans is None:
|
||||
try:
|
||||
|
||||
@@ -15,9 +15,10 @@
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
import logging
|
||||
from typing import Optional
|
||||
from typing import List, Optional
|
||||
|
||||
from pyasic import MinerConfig
|
||||
from pyasic.data.error_codes import MinerErrorData, VnishError
|
||||
from pyasic.device.algorithm import AlgoHashRate
|
||||
from pyasic.errors import APIError
|
||||
from pyasic.miners.backends.bmminer import BMMiner
|
||||
@@ -85,6 +86,10 @@ VNISH_DATA_LOC = DataLocations(
|
||||
"_get_pools",
|
||||
[RPCAPICommand("rpc_pools", "pools")],
|
||||
),
|
||||
str(DataOptions.ERRORS): DataFunction(
|
||||
"_get_errors",
|
||||
[WebAPICommand("web_summary", "summary")],
|
||||
),
|
||||
}
|
||||
)
|
||||
|
||||
@@ -266,6 +271,24 @@ class VNish(VNishFirmware, BMMiner):
|
||||
except LookupError:
|
||||
pass
|
||||
|
||||
async def _get_errors(self, web_summary: dict = None) -> List[MinerErrorData]:
|
||||
errors = []
|
||||
if web_summary is None:
|
||||
try:
|
||||
web_summary = await self.web.summary()
|
||||
except APIError:
|
||||
return errors
|
||||
|
||||
if web_summary is not None:
|
||||
chains = web_summary.get("miner", {}).get("chains", [])
|
||||
for chain in chains:
|
||||
state = chain.get("status", {}).get("state")
|
||||
description = chain.get("status", {}).get("description", "")
|
||||
if state == "failure":
|
||||
errors.append(VnishError(error_message=description))
|
||||
|
||||
return errors
|
||||
|
||||
async def get_config(self) -> MinerConfig:
|
||||
try:
|
||||
web_settings = await self.web.settings()
|
||||
|
||||
@@ -50,6 +50,10 @@ class BitAxeMake(BaseMiner):
|
||||
make = MinerMake.BITAXE
|
||||
|
||||
|
||||
class LuckyMinerMake(BaseMiner):
|
||||
make = MinerMake.LUCKYMINER
|
||||
|
||||
|
||||
class IceRiverMake(BaseMiner):
|
||||
make = MinerMake.ICERIVER
|
||||
|
||||
|
||||
@@ -34,3 +34,12 @@ class S21Pro(AntMinerMake):
|
||||
expected_fans = 4
|
||||
expected_hashboards = 3
|
||||
algo = MinerAlgo.SHA256
|
||||
|
||||
|
||||
class S21Hydro(AntMinerMake):
|
||||
raw_model = MinerModel.ANTMINER.S21Hydro
|
||||
|
||||
expected_chips = 216
|
||||
expected_hashboards = 2
|
||||
expected_fans = 0
|
||||
algo = MinerAlgo.SHA256
|
||||
|
||||
@@ -14,5 +14,5 @@
|
||||
# limitations under the License. -
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
from .S21 import S21, S21Pro
|
||||
from .S21 import S21, S21Hydro, S21Pro
|
||||
from .T21 import T21
|
||||
|
||||
12
pyasic/miners/device/models/luckyminer/LV/LV07.py
Normal file
12
pyasic/miners/device/models/luckyminer/LV/LV07.py
Normal file
@@ -0,0 +1,12 @@
|
||||
from pyasic.device.algorithm import MinerAlgo
|
||||
from pyasic.device.models import MinerModel
|
||||
from pyasic.miners.device.makes import LuckyMinerMake
|
||||
|
||||
|
||||
class LV07(LuckyMinerMake):
|
||||
raw_model = MinerModel.LUCKYMINER.LV07
|
||||
|
||||
expected_hashboards = 1
|
||||
expected_chips = 1
|
||||
expected_fans = 1
|
||||
algo = MinerAlgo.SHA256
|
||||
12
pyasic/miners/device/models/luckyminer/LV/LV08.py
Normal file
12
pyasic/miners/device/models/luckyminer/LV/LV08.py
Normal file
@@ -0,0 +1,12 @@
|
||||
from pyasic.device.algorithm import MinerAlgo
|
||||
from pyasic.device.models import MinerModel
|
||||
from pyasic.miners.device.makes import LuckyMinerMake
|
||||
|
||||
|
||||
class LV08(LuckyMinerMake):
|
||||
raw_model = MinerModel.LUCKYMINER.LV08
|
||||
|
||||
expected_hashboards = 1
|
||||
expected_chips = 1
|
||||
expected_fans = 1
|
||||
algo = MinerAlgo.SHA256
|
||||
2
pyasic/miners/device/models/luckyminer/LV/__init__.py
Normal file
2
pyasic/miners/device/models/luckyminer/LV/__init__.py
Normal file
@@ -0,0 +1,2 @@
|
||||
from .LV07 import LV07
|
||||
from .LV08 import LV08
|
||||
1
pyasic/miners/device/models/luckyminer/__init__.py
Normal file
1
pyasic/miners/device/models/luckyminer/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from .LV import *
|
||||
@@ -41,6 +41,7 @@ from pyasic.miners.goldshell import *
|
||||
from pyasic.miners.hammer import *
|
||||
from pyasic.miners.iceriver import *
|
||||
from pyasic.miners.innosilicon import *
|
||||
from pyasic.miners.luckyminer import *
|
||||
from pyasic.miners.volcminer import *
|
||||
from pyasic.miners.whatsminer import *
|
||||
|
||||
@@ -62,6 +63,7 @@ class MinerTypes(enum.Enum):
|
||||
ICERIVER = 13
|
||||
HAMMER = 14
|
||||
VOLCMINER = 15
|
||||
LUCKYMINER = 16
|
||||
|
||||
|
||||
MINER_CLASSES = {
|
||||
@@ -117,6 +119,7 @@ MINER_CLASSES = {
|
||||
"ANTMINER BHB68606": BMMinerS21, # ???
|
||||
"ANTMINER S21 PRO": BMMinerS21Pro,
|
||||
"ANTMINER T21": BMMinerT21,
|
||||
"ANTMINER S21 HYD.": BMMinerS21Hydro,
|
||||
},
|
||||
MinerTypes.WHATSMINER: {
|
||||
None: type("WhatsminerUnknown", (BTMiner, WhatsMinerMake), {}),
|
||||
@@ -544,6 +547,7 @@ MINER_CLASSES = {
|
||||
"ANTMINER S19 PRO+ HYD.": BOSMinerS19ProPlusHydro,
|
||||
"ANTMINER T19": BOSMinerT19,
|
||||
"ANTMINER S21": BOSMinerS21,
|
||||
"ANTMINER S21 PRO": BOSMinerS21Pro,
|
||||
"ANTMINER T21": BOSMinerT21,
|
||||
"BRAIINS MINI MINER BMM 100": BraiinsBMM100,
|
||||
"BRAIINS MINI MINER BMM 101": BraiinsBMM101,
|
||||
@@ -559,6 +563,7 @@ MINER_CLASSES = {
|
||||
"ANTMINER S19NOPIC": VNishS19NoPIC,
|
||||
"ANTMINER S19 PRO": VNishS19Pro,
|
||||
"ANTMINER S19J": VNishS19j,
|
||||
"ANTMINER S19I": VNishS19i,
|
||||
"ANTMINER S19J PRO": VNishS19jPro,
|
||||
"ANTMINER S19J PRO A": VNishS19jPro,
|
||||
"ANTMINER S19J PRO BB": VNishS19jPro,
|
||||
@@ -591,6 +596,7 @@ MINER_CLASSES = {
|
||||
"ANTMINER T9": HiveonT9,
|
||||
"ANTMINER S19JPRO": HiveonS19jPro,
|
||||
"ANTMINER S19": HiveonS19,
|
||||
"ANTMINER S19X88": HiveonS19NoPIC,
|
||||
},
|
||||
MinerTypes.LUX_OS: {
|
||||
None: LUXMiner,
|
||||
@@ -633,6 +639,11 @@ MINER_CLASSES = {
|
||||
"BM1397": BitAxeMax,
|
||||
"BM1370": BitAxeGamma,
|
||||
},
|
||||
MinerTypes.LUCKYMINER: {
|
||||
None: LuckyMiner,
|
||||
"LV08": LuckyMinerLV08,
|
||||
"LV07": LuckyMinerLV07,
|
||||
},
|
||||
MinerTypes.ICERIVER: {
|
||||
None: type("IceRiverUnknown", (IceRiver, IceRiverMake), {}),
|
||||
"KS0": IceRiverKS0,
|
||||
@@ -730,6 +741,7 @@ class MinerFactory:
|
||||
MinerTypes.AURADINE: self.get_miner_model_auradine,
|
||||
MinerTypes.MARATHON: self.get_miner_model_marathon,
|
||||
MinerTypes.BITAXE: self.get_miner_model_bitaxe,
|
||||
MinerTypes.LUCKYMINER: self.get_miner_model_luckyminer,
|
||||
MinerTypes.ICERIVER: self.get_miner_model_iceriver,
|
||||
MinerTypes.HAMMER: self.get_miner_model_hammer,
|
||||
MinerTypes.VOLCMINER: self.get_miner_model_volcminer,
|
||||
@@ -832,6 +844,8 @@ class MinerFactory:
|
||||
return MinerTypes.ICERIVER
|
||||
if "AxeOS" in web_text:
|
||||
return MinerTypes.BITAXE
|
||||
if "Lucky miner" in web_text:
|
||||
return MinerTypes.LUCKYMINER
|
||||
if "cloud-box" in web_text:
|
||||
return MinerTypes.GOLDSHELL
|
||||
if "AnthillOS" in web_text:
|
||||
@@ -876,6 +890,7 @@ class MinerFactory:
|
||||
await writer.drain()
|
||||
|
||||
# loop to receive all the data
|
||||
timeouts_remaining = max(1, int(settings.get("factory_get_timeout", 3)))
|
||||
while True:
|
||||
try:
|
||||
d = await asyncio.wait_for(reader.read(4096), timeout=1)
|
||||
@@ -883,7 +898,10 @@ class MinerFactory:
|
||||
break
|
||||
data += d
|
||||
except asyncio.TimeoutError:
|
||||
pass
|
||||
timeouts_remaining -= 1
|
||||
if not timeouts_remaining:
|
||||
logger.warning(f"{ip}: Socket ping timeout.")
|
||||
break
|
||||
except ConnectionResetError:
|
||||
return
|
||||
except asyncio.CancelledError:
|
||||
@@ -1291,6 +1309,18 @@ class MinerFactory:
|
||||
except (TypeError, LookupError):
|
||||
pass
|
||||
|
||||
async def get_miner_model_luckyminer(self, ip: str) -> str | None:
|
||||
web_json_data = await self.send_web_command(ip, "/api/system/info")
|
||||
|
||||
try:
|
||||
miner_model = web_json_data["minerModel"]
|
||||
if miner_model == "":
|
||||
return None
|
||||
|
||||
return miner_model
|
||||
except (TypeError, LookupError):
|
||||
pass
|
||||
|
||||
async def get_miner_model_iceriver(self, ip: str) -> str | None:
|
||||
async with httpx.AsyncClient(transport=settings.transport()) as client:
|
||||
try:
|
||||
|
||||
1
pyasic/miners/luckyminer/__init__.py
Normal file
1
pyasic/miners/luckyminer/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from .espminer import *
|
||||
6
pyasic/miners/luckyminer/espminer/LV/LV07.py
Normal file
6
pyasic/miners/luckyminer/espminer/LV/LV07.py
Normal file
@@ -0,0 +1,6 @@
|
||||
from pyasic.miners.backends.luckyminer import LuckyMiner
|
||||
from pyasic.miners.device.models.luckyminer import LV07
|
||||
|
||||
|
||||
class LuckyMinerLV07(LuckyMiner, LV07):
|
||||
pass
|
||||
6
pyasic/miners/luckyminer/espminer/LV/LV08.py
Normal file
6
pyasic/miners/luckyminer/espminer/LV/LV08.py
Normal file
@@ -0,0 +1,6 @@
|
||||
from pyasic.miners.backends.luckyminer import LuckyMiner
|
||||
from pyasic.miners.device.models.luckyminer import LV08
|
||||
|
||||
|
||||
class LuckyMinerLV08(LuckyMiner, LV08):
|
||||
pass
|
||||
2
pyasic/miners/luckyminer/espminer/LV/__init__.py
Normal file
2
pyasic/miners/luckyminer/espminer/LV/__init__.py
Normal file
@@ -0,0 +1,2 @@
|
||||
from .LV07 import LuckyMinerLV07
|
||||
from .LV08 import LuckyMinerLV08
|
||||
1
pyasic/miners/luckyminer/espminer/__init__.py
Normal file
1
pyasic/miners/luckyminer/espminer/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from .LV import *
|
||||
@@ -574,9 +574,6 @@ class LUXMinerRPCAPI(BaseMinerRPCAPI):
|
||||
<details>
|
||||
<summary>Expand</summary>
|
||||
|
||||
Parameters:
|
||||
session_id: Session id from the logon command.
|
||||
|
||||
Returns:
|
||||
Confirmation of logging off a session.
|
||||
</details>
|
||||
@@ -844,7 +841,7 @@ class LUXMinerRPCAPI(BaseMinerRPCAPI):
|
||||
"""
|
||||
return await self.send_privileged_command("voltageset", board_n, voltage)
|
||||
|
||||
async def upgraderun(self):
|
||||
async def updaterun(self) -> dict:
|
||||
"""
|
||||
Send the 'updaterun' command to the miner.
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ _settings = { # defaults
|
||||
"default_whatsminer_rpc_password": "admin",
|
||||
"default_innosilicon_web_password": "admin",
|
||||
"default_antminer_web_password": "root",
|
||||
"default_hammer_web_password": "ltc@dog",
|
||||
"default_hammer_web_password": "root",
|
||||
"default_volcminer_web_password": "ltc@dog",
|
||||
"default_bosminer_web_password": "root",
|
||||
"default_vnish_web_password": "admin",
|
||||
|
||||
@@ -268,11 +268,11 @@ class AuradineWebAPI(BaseWebAPI):
|
||||
"""
|
||||
return await self.send_command("mode")
|
||||
|
||||
async def set_mode(self, **kwargs) -> dict:
|
||||
async def set_mode(self, **kwargs: Any) -> dict:
|
||||
"""Set the operational mode of the Auradine miner.
|
||||
|
||||
Args:
|
||||
**kwargs: Mode settings specified as keyword arguments.
|
||||
**kwargs (Any): Mode settings specified as keyword arguments.
|
||||
|
||||
Returns:
|
||||
dict: A dictionary indicating the result of the mode setting operation.
|
||||
@@ -287,11 +287,11 @@ class AuradineWebAPI(BaseWebAPI):
|
||||
"""
|
||||
return await self.send_command("network")
|
||||
|
||||
async def set_network(self, **kwargs) -> dict:
|
||||
async def set_network(self, **kwargs: Any) -> dict:
|
||||
"""Set the network configuration of the Auradine miner.
|
||||
|
||||
Args:
|
||||
**kwargs: Network settings specified as keyword arguments.
|
||||
**kwargs (Any): Network settings specified as keyword arguments.
|
||||
|
||||
Returns:
|
||||
dict: A dictionary indicating the result of the network configuration.
|
||||
|
||||
110
pyasic/web/avalonminer.py
Normal file
110
pyasic/web/avalonminer.py
Normal file
@@ -0,0 +1,110 @@
|
||||
# ------------------------------------------------------------------------------
|
||||
# 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 __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
import hashlib
|
||||
import json
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
import aiofiles
|
||||
import httpx
|
||||
|
||||
from pyasic import settings
|
||||
from pyasic.web.base import BaseWebAPI
|
||||
|
||||
|
||||
class AvalonMinerWebAPI(BaseWebAPI):
|
||||
def __init__(self, ip: str) -> None:
|
||||
"""Initialize the modern Avalonminer API client with a specific IP address.
|
||||
|
||||
Args:
|
||||
ip (str): IP address of the Avalonminer device.
|
||||
"""
|
||||
super().__init__(ip)
|
||||
self.username = "root"
|
||||
self.pwd = settings.get("default_avalonminer_web_password", "root")
|
||||
|
||||
async def send_command(
|
||||
self,
|
||||
command: str | bytes,
|
||||
ignore_errors: bool = False,
|
||||
allow_warning: bool = True,
|
||||
**parameters: Any,
|
||||
) -> dict:
|
||||
"""Send a command to the Avalonminer device using HTTP digest authentication.
|
||||
|
||||
Args:
|
||||
command (str | bytes): The CGI command to send.
|
||||
ignore_errors (bool): If True, ignore any HTTP errors.
|
||||
allow_warning (bool): If True, proceed with warnings.
|
||||
**parameters: Arbitrary keyword arguments to be sent as parameters in the request.
|
||||
|
||||
Returns:
|
||||
dict: The JSON response from the device or an empty dictionary if an error occurs.
|
||||
"""
|
||||
cookie_data = "ff0000ff" + hashlib.sha256(self.pwd.encode()).hexdigest()[:24]
|
||||
|
||||
url = f"http://{self.ip}:{self.port}/{command}.cgi"
|
||||
try:
|
||||
async with httpx.AsyncClient(transport=settings.transport()) as client:
|
||||
client.cookies.set("auth", cookie_data)
|
||||
resp = await client.get(url)
|
||||
raw_data = resp.text.replace("minerinfoCallback(", "").replace(");", "")
|
||||
return json.loads(raw_data)
|
||||
except httpx.HTTPError:
|
||||
pass
|
||||
return {}
|
||||
|
||||
async def multicommand(
|
||||
self, *commands: str, ignore_errors: bool = False, allow_warning: bool = True
|
||||
) -> dict:
|
||||
async with httpx.AsyncClient(transport=settings.transport()) as client:
|
||||
cookie_data = (
|
||||
"ff0000ff" + hashlib.sha256(self.pwd.encode()).hexdigest()[:24]
|
||||
)
|
||||
client.cookies.set("auth", cookie_data)
|
||||
tasks = [
|
||||
asyncio.create_task(self._handle_multicommand(client, command))
|
||||
for command in commands
|
||||
]
|
||||
all_data = await asyncio.gather(*tasks)
|
||||
|
||||
data = {}
|
||||
for item in all_data:
|
||||
data.update(item)
|
||||
|
||||
data["multicommand"] = True
|
||||
return data
|
||||
|
||||
async def _handle_multicommand(
|
||||
self, client: httpx.AsyncClient, command: str
|
||||
) -> dict:
|
||||
try:
|
||||
url = f"http://{self.ip}:{self.port}/{command}.cgi"
|
||||
resp = await client.get(url)
|
||||
raw_data = resp.text.replace("minerinfoCallback(", "").replace(");", "")
|
||||
return json.loads(raw_data)
|
||||
except httpx.HTTPError:
|
||||
pass
|
||||
return {}
|
||||
|
||||
async def minerinfo(self):
|
||||
return await self.send_command("get_minerinfo")
|
||||
|
||||
async def home(self):
|
||||
return await self.send_command("get_home")
|
||||
@@ -39,7 +39,7 @@ class ApiVersionServiceStub(betterproto.ServiceStub):
|
||||
*,
|
||||
timeout: Optional[float] = None,
|
||||
deadline: Optional["Deadline"] = None,
|
||||
metadata: Optional["MetadataLike"] = None
|
||||
metadata: Optional["MetadataLike"] = None,
|
||||
) -> "ApiVersion":
|
||||
return await self._unary_unary(
|
||||
"/braiins.bos.ApiVersionService/GetApiVersion",
|
||||
|
||||
@@ -1706,7 +1706,7 @@ class ActionsServiceStub(betterproto.ServiceStub):
|
||||
*,
|
||||
timeout: Optional[float] = None,
|
||||
deadline: Optional["Deadline"] = None,
|
||||
metadata: Optional["MetadataLike"] = None
|
||||
metadata: Optional["MetadataLike"] = None,
|
||||
) -> "StartResponse":
|
||||
return await self._unary_unary(
|
||||
"/braiins.bos.v1.ActionsService/Start",
|
||||
@@ -1723,7 +1723,7 @@ class ActionsServiceStub(betterproto.ServiceStub):
|
||||
*,
|
||||
timeout: Optional[float] = None,
|
||||
deadline: Optional["Deadline"] = None,
|
||||
metadata: Optional["MetadataLike"] = None
|
||||
metadata: Optional["MetadataLike"] = None,
|
||||
) -> "StopResponse":
|
||||
return await self._unary_unary(
|
||||
"/braiins.bos.v1.ActionsService/Stop",
|
||||
@@ -1740,7 +1740,7 @@ class ActionsServiceStub(betterproto.ServiceStub):
|
||||
*,
|
||||
timeout: Optional[float] = None,
|
||||
deadline: Optional["Deadline"] = None,
|
||||
metadata: Optional["MetadataLike"] = None
|
||||
metadata: Optional["MetadataLike"] = None,
|
||||
) -> "PauseMiningResponse":
|
||||
return await self._unary_unary(
|
||||
"/braiins.bos.v1.ActionsService/PauseMining",
|
||||
@@ -1757,7 +1757,7 @@ class ActionsServiceStub(betterproto.ServiceStub):
|
||||
*,
|
||||
timeout: Optional[float] = None,
|
||||
deadline: Optional["Deadline"] = None,
|
||||
metadata: Optional["MetadataLike"] = None
|
||||
metadata: Optional["MetadataLike"] = None,
|
||||
) -> "ResumeMiningResponse":
|
||||
return await self._unary_unary(
|
||||
"/braiins.bos.v1.ActionsService/ResumeMining",
|
||||
@@ -1774,7 +1774,7 @@ class ActionsServiceStub(betterproto.ServiceStub):
|
||||
*,
|
||||
timeout: Optional[float] = None,
|
||||
deadline: Optional["Deadline"] = None,
|
||||
metadata: Optional["MetadataLike"] = None
|
||||
metadata: Optional["MetadataLike"] = None,
|
||||
) -> "RestartResponse":
|
||||
return await self._unary_unary(
|
||||
"/braiins.bos.v1.ActionsService/Restart",
|
||||
@@ -1791,7 +1791,7 @@ class ActionsServiceStub(betterproto.ServiceStub):
|
||||
*,
|
||||
timeout: Optional[float] = None,
|
||||
deadline: Optional["Deadline"] = None,
|
||||
metadata: Optional["MetadataLike"] = None
|
||||
metadata: Optional["MetadataLike"] = None,
|
||||
) -> "RebootResponse":
|
||||
return await self._unary_unary(
|
||||
"/braiins.bos.v1.ActionsService/Reboot",
|
||||
@@ -1808,7 +1808,7 @@ class ActionsServiceStub(betterproto.ServiceStub):
|
||||
*,
|
||||
timeout: Optional[float] = None,
|
||||
deadline: Optional["Deadline"] = None,
|
||||
metadata: Optional["MetadataLike"] = None
|
||||
metadata: Optional["MetadataLike"] = None,
|
||||
) -> "LocateDeviceStatusResponse":
|
||||
return await self._unary_unary(
|
||||
"/braiins.bos.v1.ActionsService/SetLocateDeviceStatus",
|
||||
@@ -1825,7 +1825,7 @@ class ActionsServiceStub(betterproto.ServiceStub):
|
||||
*,
|
||||
timeout: Optional[float] = None,
|
||||
deadline: Optional["Deadline"] = None,
|
||||
metadata: Optional["MetadataLike"] = None
|
||||
metadata: Optional["MetadataLike"] = None,
|
||||
) -> "LocateDeviceStatusResponse":
|
||||
return await self._unary_unary(
|
||||
"/braiins.bos.v1.ActionsService/GetLocateDeviceStatus",
|
||||
@@ -1844,7 +1844,7 @@ class AuthenticationServiceStub(betterproto.ServiceStub):
|
||||
*,
|
||||
timeout: Optional[float] = None,
|
||||
deadline: Optional["Deadline"] = None,
|
||||
metadata: Optional["MetadataLike"] = None
|
||||
metadata: Optional["MetadataLike"] = None,
|
||||
) -> "LoginResponse":
|
||||
return await self._unary_unary(
|
||||
"/braiins.bos.v1.AuthenticationService/Login",
|
||||
@@ -1861,7 +1861,7 @@ class AuthenticationServiceStub(betterproto.ServiceStub):
|
||||
*,
|
||||
timeout: Optional[float] = None,
|
||||
deadline: Optional["Deadline"] = None,
|
||||
metadata: Optional["MetadataLike"] = None
|
||||
metadata: Optional["MetadataLike"] = None,
|
||||
) -> "SetPasswordResponse":
|
||||
return await self._unary_unary(
|
||||
"/braiins.bos.v1.AuthenticationService/SetPassword",
|
||||
@@ -1880,7 +1880,7 @@ class CoolingServiceStub(betterproto.ServiceStub):
|
||||
*,
|
||||
timeout: Optional[float] = None,
|
||||
deadline: Optional["Deadline"] = None,
|
||||
metadata: Optional["MetadataLike"] = None
|
||||
metadata: Optional["MetadataLike"] = None,
|
||||
) -> "GetCoolingStateResponse":
|
||||
return await self._unary_unary(
|
||||
"/braiins.bos.v1.CoolingService/GetCoolingState",
|
||||
@@ -1897,7 +1897,7 @@ class CoolingServiceStub(betterproto.ServiceStub):
|
||||
*,
|
||||
timeout: Optional[float] = None,
|
||||
deadline: Optional["Deadline"] = None,
|
||||
metadata: Optional["MetadataLike"] = None
|
||||
metadata: Optional["MetadataLike"] = None,
|
||||
) -> "SetImmersionModeResponse":
|
||||
return await self._unary_unary(
|
||||
"/braiins.bos.v1.CoolingService/SetImmersionMode",
|
||||
@@ -1916,7 +1916,7 @@ class PerformanceServiceStub(betterproto.ServiceStub):
|
||||
*,
|
||||
timeout: Optional[float] = None,
|
||||
deadline: Optional["Deadline"] = None,
|
||||
metadata: Optional["MetadataLike"] = None
|
||||
metadata: Optional["MetadataLike"] = None,
|
||||
) -> "GetTunerStateResponse":
|
||||
return await self._unary_unary(
|
||||
"/braiins.bos.v1.PerformanceService/GetTunerState",
|
||||
@@ -1933,7 +1933,7 @@ class PerformanceServiceStub(betterproto.ServiceStub):
|
||||
*,
|
||||
timeout: Optional[float] = None,
|
||||
deadline: Optional["Deadline"] = None,
|
||||
metadata: Optional["MetadataLike"] = None
|
||||
metadata: Optional["MetadataLike"] = None,
|
||||
) -> "ListTargetProfilesResponse":
|
||||
return await self._unary_unary(
|
||||
"/braiins.bos.v1.PerformanceService/ListTargetProfiles",
|
||||
@@ -1950,7 +1950,7 @@ class PerformanceServiceStub(betterproto.ServiceStub):
|
||||
*,
|
||||
timeout: Optional[float] = None,
|
||||
deadline: Optional["Deadline"] = None,
|
||||
metadata: Optional["MetadataLike"] = None
|
||||
metadata: Optional["MetadataLike"] = None,
|
||||
) -> "SetPowerTargetResponse":
|
||||
return await self._unary_unary(
|
||||
"/braiins.bos.v1.PerformanceService/SetDefaultPowerTarget",
|
||||
@@ -1967,7 +1967,7 @@ class PerformanceServiceStub(betterproto.ServiceStub):
|
||||
*,
|
||||
timeout: Optional[float] = None,
|
||||
deadline: Optional["Deadline"] = None,
|
||||
metadata: Optional["MetadataLike"] = None
|
||||
metadata: Optional["MetadataLike"] = None,
|
||||
) -> "SetPowerTargetResponse":
|
||||
return await self._unary_unary(
|
||||
"/braiins.bos.v1.PerformanceService/SetPowerTarget",
|
||||
@@ -1984,7 +1984,7 @@ class PerformanceServiceStub(betterproto.ServiceStub):
|
||||
*,
|
||||
timeout: Optional[float] = None,
|
||||
deadline: Optional["Deadline"] = None,
|
||||
metadata: Optional["MetadataLike"] = None
|
||||
metadata: Optional["MetadataLike"] = None,
|
||||
) -> "SetPowerTargetResponse":
|
||||
return await self._unary_unary(
|
||||
"/braiins.bos.v1.PerformanceService/IncrementPowerTarget",
|
||||
@@ -2001,7 +2001,7 @@ class PerformanceServiceStub(betterproto.ServiceStub):
|
||||
*,
|
||||
timeout: Optional[float] = None,
|
||||
deadline: Optional["Deadline"] = None,
|
||||
metadata: Optional["MetadataLike"] = None
|
||||
metadata: Optional["MetadataLike"] = None,
|
||||
) -> "SetPowerTargetResponse":
|
||||
return await self._unary_unary(
|
||||
"/braiins.bos.v1.PerformanceService/DecrementPowerTarget",
|
||||
@@ -2018,7 +2018,7 @@ class PerformanceServiceStub(betterproto.ServiceStub):
|
||||
*,
|
||||
timeout: Optional[float] = None,
|
||||
deadline: Optional["Deadline"] = None,
|
||||
metadata: Optional["MetadataLike"] = None
|
||||
metadata: Optional["MetadataLike"] = None,
|
||||
) -> "SetHashrateTargetResponse":
|
||||
return await self._unary_unary(
|
||||
"/braiins.bos.v1.PerformanceService/SetDefaultHashrateTarget",
|
||||
@@ -2035,7 +2035,7 @@ class PerformanceServiceStub(betterproto.ServiceStub):
|
||||
*,
|
||||
timeout: Optional[float] = None,
|
||||
deadline: Optional["Deadline"] = None,
|
||||
metadata: Optional["MetadataLike"] = None
|
||||
metadata: Optional["MetadataLike"] = None,
|
||||
) -> "SetHashrateTargetResponse":
|
||||
return await self._unary_unary(
|
||||
"/braiins.bos.v1.PerformanceService/SetHashrateTarget",
|
||||
@@ -2052,7 +2052,7 @@ class PerformanceServiceStub(betterproto.ServiceStub):
|
||||
*,
|
||||
timeout: Optional[float] = None,
|
||||
deadline: Optional["Deadline"] = None,
|
||||
metadata: Optional["MetadataLike"] = None
|
||||
metadata: Optional["MetadataLike"] = None,
|
||||
) -> "SetHashrateTargetResponse":
|
||||
return await self._unary_unary(
|
||||
"/braiins.bos.v1.PerformanceService/IncrementHashrateTarget",
|
||||
@@ -2069,7 +2069,7 @@ class PerformanceServiceStub(betterproto.ServiceStub):
|
||||
*,
|
||||
timeout: Optional[float] = None,
|
||||
deadline: Optional["Deadline"] = None,
|
||||
metadata: Optional["MetadataLike"] = None
|
||||
metadata: Optional["MetadataLike"] = None,
|
||||
) -> "SetHashrateTargetResponse":
|
||||
return await self._unary_unary(
|
||||
"/braiins.bos.v1.PerformanceService/DecrementHashrateTarget",
|
||||
@@ -2086,7 +2086,7 @@ class PerformanceServiceStub(betterproto.ServiceStub):
|
||||
*,
|
||||
timeout: Optional[float] = None,
|
||||
deadline: Optional["Deadline"] = None,
|
||||
metadata: Optional["MetadataLike"] = None
|
||||
metadata: Optional["MetadataLike"] = None,
|
||||
) -> "SetDpsResponse":
|
||||
return await self._unary_unary(
|
||||
"/braiins.bos.v1.PerformanceService/SetDPS",
|
||||
@@ -2103,7 +2103,7 @@ class PerformanceServiceStub(betterproto.ServiceStub):
|
||||
*,
|
||||
timeout: Optional[float] = None,
|
||||
deadline: Optional["Deadline"] = None,
|
||||
metadata: Optional["MetadataLike"] = None
|
||||
metadata: Optional["MetadataLike"] = None,
|
||||
) -> "PerformanceMode":
|
||||
return await self._unary_unary(
|
||||
"/braiins.bos.v1.PerformanceService/SetPerformanceMode",
|
||||
@@ -2120,7 +2120,7 @@ class PerformanceServiceStub(betterproto.ServiceStub):
|
||||
*,
|
||||
timeout: Optional[float] = None,
|
||||
deadline: Optional["Deadline"] = None,
|
||||
metadata: Optional["MetadataLike"] = None
|
||||
metadata: Optional["MetadataLike"] = None,
|
||||
) -> "PerformanceMode":
|
||||
return await self._unary_unary(
|
||||
"/braiins.bos.v1.PerformanceService/GetActivePerformanceMode",
|
||||
@@ -2137,7 +2137,7 @@ class PerformanceServiceStub(betterproto.ServiceStub):
|
||||
*,
|
||||
timeout: Optional[float] = None,
|
||||
deadline: Optional["Deadline"] = None,
|
||||
metadata: Optional["MetadataLike"] = None
|
||||
metadata: Optional["MetadataLike"] = None,
|
||||
) -> "RemoveTunedProfilesResponse":
|
||||
return await self._unary_unary(
|
||||
"/braiins.bos.v1.PerformanceService/RemoveTunedProfiles",
|
||||
@@ -2156,7 +2156,7 @@ class PoolServiceStub(betterproto.ServiceStub):
|
||||
*,
|
||||
timeout: Optional[float] = None,
|
||||
deadline: Optional["Deadline"] = None,
|
||||
metadata: Optional["MetadataLike"] = None
|
||||
metadata: Optional["MetadataLike"] = None,
|
||||
) -> "GetPoolGroupsResponse":
|
||||
return await self._unary_unary(
|
||||
"/braiins.bos.v1.PoolService/GetPoolGroups",
|
||||
@@ -2173,7 +2173,7 @@ class PoolServiceStub(betterproto.ServiceStub):
|
||||
*,
|
||||
timeout: Optional[float] = None,
|
||||
deadline: Optional["Deadline"] = None,
|
||||
metadata: Optional["MetadataLike"] = None
|
||||
metadata: Optional["MetadataLike"] = None,
|
||||
) -> "CreatePoolGroupResponse":
|
||||
return await self._unary_unary(
|
||||
"/braiins.bos.v1.PoolService/CreatePoolGroup",
|
||||
@@ -2190,7 +2190,7 @@ class PoolServiceStub(betterproto.ServiceStub):
|
||||
*,
|
||||
timeout: Optional[float] = None,
|
||||
deadline: Optional["Deadline"] = None,
|
||||
metadata: Optional["MetadataLike"] = None
|
||||
metadata: Optional["MetadataLike"] = None,
|
||||
) -> "UpdatePoolGroupResponse":
|
||||
return await self._unary_unary(
|
||||
"/braiins.bos.v1.PoolService/UpdatePoolGroup",
|
||||
@@ -2207,7 +2207,7 @@ class PoolServiceStub(betterproto.ServiceStub):
|
||||
*,
|
||||
timeout: Optional[float] = None,
|
||||
deadline: Optional["Deadline"] = None,
|
||||
metadata: Optional["MetadataLike"] = None
|
||||
metadata: Optional["MetadataLike"] = None,
|
||||
) -> "RemovePoolGroupResponse":
|
||||
return await self._unary_unary(
|
||||
"/braiins.bos.v1.PoolService/RemovePoolGroup",
|
||||
@@ -2224,7 +2224,7 @@ class PoolServiceStub(betterproto.ServiceStub):
|
||||
*,
|
||||
timeout: Optional[float] = None,
|
||||
deadline: Optional["Deadline"] = None,
|
||||
metadata: Optional["MetadataLike"] = None
|
||||
metadata: Optional["MetadataLike"] = None,
|
||||
) -> "SetPoolGroupsResponse":
|
||||
return await self._unary_unary(
|
||||
"/braiins.bos.v1.PoolService/SetPoolGroups",
|
||||
@@ -2243,7 +2243,7 @@ class ConfigurationServiceStub(betterproto.ServiceStub):
|
||||
*,
|
||||
timeout: Optional[float] = None,
|
||||
deadline: Optional["Deadline"] = None,
|
||||
metadata: Optional["MetadataLike"] = None
|
||||
metadata: Optional["MetadataLike"] = None,
|
||||
) -> "GetMinerConfigurationResponse":
|
||||
return await self._unary_unary(
|
||||
"/braiins.bos.v1.ConfigurationService/GetMinerConfiguration",
|
||||
@@ -2260,7 +2260,7 @@ class ConfigurationServiceStub(betterproto.ServiceStub):
|
||||
*,
|
||||
timeout: Optional[float] = None,
|
||||
deadline: Optional["Deadline"] = None,
|
||||
metadata: Optional["MetadataLike"] = None
|
||||
metadata: Optional["MetadataLike"] = None,
|
||||
) -> "GetConstraintsResponse":
|
||||
return await self._unary_unary(
|
||||
"/braiins.bos.v1.ConfigurationService/GetConstraints",
|
||||
@@ -2279,7 +2279,7 @@ class LicenseServiceStub(betterproto.ServiceStub):
|
||||
*,
|
||||
timeout: Optional[float] = None,
|
||||
deadline: Optional["Deadline"] = None,
|
||||
metadata: Optional["MetadataLike"] = None
|
||||
metadata: Optional["MetadataLike"] = None,
|
||||
) -> "GetLicenseStateResponse":
|
||||
return await self._unary_unary(
|
||||
"/braiins.bos.v1.LicenseService/GetLicenseState",
|
||||
@@ -2298,7 +2298,7 @@ class MinerServiceStub(betterproto.ServiceStub):
|
||||
*,
|
||||
timeout: Optional[float] = None,
|
||||
deadline: Optional["Deadline"] = None,
|
||||
metadata: Optional["MetadataLike"] = None
|
||||
metadata: Optional["MetadataLike"] = None,
|
||||
) -> AsyncIterator[GetMinerStatusResponse]:
|
||||
async for response in self._unary_stream(
|
||||
"/braiins.bos.v1.MinerService/GetMinerStatus",
|
||||
@@ -2316,7 +2316,7 @@ class MinerServiceStub(betterproto.ServiceStub):
|
||||
*,
|
||||
timeout: Optional[float] = None,
|
||||
deadline: Optional["Deadline"] = None,
|
||||
metadata: Optional["MetadataLike"] = None
|
||||
metadata: Optional["MetadataLike"] = None,
|
||||
) -> "GetMinerDetailsResponse":
|
||||
return await self._unary_unary(
|
||||
"/braiins.bos.v1.MinerService/GetMinerDetails",
|
||||
@@ -2333,7 +2333,7 @@ class MinerServiceStub(betterproto.ServiceStub):
|
||||
*,
|
||||
timeout: Optional[float] = None,
|
||||
deadline: Optional["Deadline"] = None,
|
||||
metadata: Optional["MetadataLike"] = None
|
||||
metadata: Optional["MetadataLike"] = None,
|
||||
) -> "GetMinerStatsResponse":
|
||||
return await self._unary_unary(
|
||||
"/braiins.bos.v1.MinerService/GetMinerStats",
|
||||
@@ -2350,7 +2350,7 @@ class MinerServiceStub(betterproto.ServiceStub):
|
||||
*,
|
||||
timeout: Optional[float] = None,
|
||||
deadline: Optional["Deadline"] = None,
|
||||
metadata: Optional["MetadataLike"] = None
|
||||
metadata: Optional["MetadataLike"] = None,
|
||||
) -> "GetErrorsResponse":
|
||||
return await self._unary_unary(
|
||||
"/braiins.bos.v1.MinerService/GetErrors",
|
||||
@@ -2367,7 +2367,7 @@ class MinerServiceStub(betterproto.ServiceStub):
|
||||
*,
|
||||
timeout: Optional[float] = None,
|
||||
deadline: Optional["Deadline"] = None,
|
||||
metadata: Optional["MetadataLike"] = None
|
||||
metadata: Optional["MetadataLike"] = None,
|
||||
) -> "GetHashboardsResponse":
|
||||
return await self._unary_unary(
|
||||
"/braiins.bos.v1.MinerService/GetHashboards",
|
||||
@@ -2384,7 +2384,7 @@ class MinerServiceStub(betterproto.ServiceStub):
|
||||
*,
|
||||
timeout: Optional[float] = None,
|
||||
deadline: Optional["Deadline"] = None,
|
||||
metadata: Optional["MetadataLike"] = None
|
||||
metadata: Optional["MetadataLike"] = None,
|
||||
) -> AsyncIterator[GetSupportArchiveResponse]:
|
||||
async for response in self._unary_stream(
|
||||
"/braiins.bos.v1.MinerService/GetSupportArchive",
|
||||
@@ -2402,7 +2402,7 @@ class MinerServiceStub(betterproto.ServiceStub):
|
||||
*,
|
||||
timeout: Optional[float] = None,
|
||||
deadline: Optional["Deadline"] = None,
|
||||
metadata: Optional["MetadataLike"] = None
|
||||
metadata: Optional["MetadataLike"] = None,
|
||||
) -> "EnableHashboardsResponse":
|
||||
return await self._unary_unary(
|
||||
"/braiins.bos.v1.MinerService/EnableHashboards",
|
||||
@@ -2419,7 +2419,7 @@ class MinerServiceStub(betterproto.ServiceStub):
|
||||
*,
|
||||
timeout: Optional[float] = None,
|
||||
deadline: Optional["Deadline"] = None,
|
||||
metadata: Optional["MetadataLike"] = None
|
||||
metadata: Optional["MetadataLike"] = None,
|
||||
) -> "DisableHashboardsResponse":
|
||||
return await self._unary_unary(
|
||||
"/braiins.bos.v1.MinerService/DisableHashboards",
|
||||
@@ -2438,7 +2438,7 @@ class NetworkServiceStub(betterproto.ServiceStub):
|
||||
*,
|
||||
timeout: Optional[float] = None,
|
||||
deadline: Optional["Deadline"] = None,
|
||||
metadata: Optional["MetadataLike"] = None
|
||||
metadata: Optional["MetadataLike"] = None,
|
||||
) -> "GetNetworkConfigurationResponse":
|
||||
return await self._unary_unary(
|
||||
"/braiins.bos.v1.NetworkService/GetNetworkConfiguration",
|
||||
@@ -2455,7 +2455,7 @@ class NetworkServiceStub(betterproto.ServiceStub):
|
||||
*,
|
||||
timeout: Optional[float] = None,
|
||||
deadline: Optional["Deadline"] = None,
|
||||
metadata: Optional["MetadataLike"] = None
|
||||
metadata: Optional["MetadataLike"] = None,
|
||||
) -> "SetNetworkConfigurationResponse":
|
||||
return await self._unary_unary(
|
||||
"/braiins.bos.v1.NetworkService/SetNetworkConfiguration",
|
||||
@@ -2472,7 +2472,7 @@ class NetworkServiceStub(betterproto.ServiceStub):
|
||||
*,
|
||||
timeout: Optional[float] = None,
|
||||
deadline: Optional["Deadline"] = None,
|
||||
metadata: Optional["MetadataLike"] = None
|
||||
metadata: Optional["MetadataLike"] = None,
|
||||
) -> "GetNetworkInfoResponse":
|
||||
return await self._unary_unary(
|
||||
"/braiins.bos.v1.NetworkService/GetNetworkInfo",
|
||||
|
||||
@@ -10,7 +10,7 @@ from pyasic import APIError, settings
|
||||
from pyasic.web.base import BaseWebAPI
|
||||
|
||||
|
||||
class BitAxeWebAPI(BaseWebAPI):
|
||||
class ESPMinerWebAPI(BaseWebAPI):
|
||||
async def send_command(
|
||||
self,
|
||||
command: str | bytes,
|
||||
7
pyasic/web/luckyminer.py
Normal file
7
pyasic/web/luckyminer.py
Normal file
@@ -0,0 +1,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from .bitaxe import ESPMinerWebAPI
|
||||
|
||||
|
||||
class LuckyMinerWebAPI(ESPMinerWebAPI):
|
||||
pass
|
||||
@@ -1,23 +1,58 @@
|
||||
[tool.poetry]
|
||||
[project]
|
||||
name = "pyasic"
|
||||
version = "0.69.2"
|
||||
description = "A simplified and standardized interface for Bitcoin ASICs."
|
||||
authors = ["UpstreamData <brett@upstreamdata.ca>"]
|
||||
repository = "https://github.com/UpstreamData/pyasic"
|
||||
documentation = "https://pyasic.readthedocs.io/en/latest/"
|
||||
readme = "README.md"
|
||||
version = "0.71.3"
|
||||
|
||||
[tool.poetry.dependencies]
|
||||
python = "^3.9"
|
||||
httpx = ">=0.26.0"
|
||||
asyncssh = ">=2.17.0"
|
||||
passlib = ">=1.7.4"
|
||||
pyaml = ">=23.12.0"
|
||||
tomli = { version = ">=2.0.1", python = "<3.11" }
|
||||
tomli-w = "^1.0.0"
|
||||
aiofiles = ">=23.2.1"
|
||||
betterproto = "2.0.0b7"
|
||||
pydantic = "^2.9.2"
|
||||
description = "A simplified and standardized interface for Bitcoin ASICs."
|
||||
authors = [{name = "UpstreamData", email = "brett@upstreamdata.ca"}]
|
||||
repository = "https://github.com/UpstreamData/pyasic"
|
||||
|
||||
homepage = "https://docs.pyasic.org"
|
||||
source = "https://github.com/UpstreamData/pyasic"
|
||||
documentation = "https://docs.pyasic.org"
|
||||
issues = "https://github.com/UpstreamData/pyasic/issues"
|
||||
readme = {file = "README.md", content-type = "text/markdown"}
|
||||
license = "Apache 2.0"
|
||||
license-files = ["LICEN[CS]E.*"]
|
||||
|
||||
keywords = [
|
||||
"python",
|
||||
"asic",
|
||||
"bitcoin",
|
||||
"whatsminer",
|
||||
"antminer",
|
||||
"braiins-os",
|
||||
"vnish",
|
||||
"luxos"
|
||||
]
|
||||
classifiers = [
|
||||
"Development Status :: 4 - Beta",
|
||||
|
||||
"Intended Audience :: Developers",
|
||||
|
||||
"License :: OSI Approved :: Apache Software License",
|
||||
|
||||
"Programming Language :: Python",
|
||||
"Programming Language :: Python :: 3",
|
||||
"Programming Language :: Python :: 3.9",
|
||||
"Programming Language :: Python :: 3.10",
|
||||
"Programming Language :: Python :: 3.11",
|
||||
"Programming Language :: Python :: 3.12",
|
||||
"Programming Language :: Python :: 3.13",
|
||||
]
|
||||
|
||||
requires-python = ">3.9, <4.0"
|
||||
dependencies = [
|
||||
"httpx>=0.26.0",
|
||||
"asyncssh>=2.17.0",
|
||||
"cryptography>=39.0",
|
||||
"passlib>=1.7.4",
|
||||
"pyaml>=23.12.0",
|
||||
"tomli (>=2.2.1,<3.0.0) ; python_version < '3.11'",
|
||||
"tomli-w>=1.0.0",
|
||||
"aiofiles>=23.2.1",
|
||||
"betterproto==2.0.0b7",
|
||||
"pydantic>=2.9.2",
|
||||
]
|
||||
|
||||
[tool.poetry.group.dev]
|
||||
optional = true
|
||||
@@ -36,7 +71,7 @@ mkdocs-material = "^9.5.39"
|
||||
|
||||
|
||||
[build-system]
|
||||
requires = ["poetry-core>=1.0.0"]
|
||||
requires = ["poetry-core>=2.0.0"]
|
||||
build-backend = "poetry.core.masonry.api"
|
||||
|
||||
[tool.isort]
|
||||
|
||||
Reference in New Issue
Block a user