Compare commits

...

27 Commits

Author SHA1 Message Date
b-rowan
35af74ad1a version: bump version number 2025-01-30 07:14:50 -07:00
Erik Olof Gunnar Andersson
15fa91fb98 bug: don’t timeout forever on _socket_ping (#288)
* Don't timeout forever on _socket_ping

* Use factory_get_timeout to configure number of allowed retries

* Add warning log
2025-01-30 07:05:29 -07:00
James Hilliard
084987a3e1 bug: Add cryptography direct dependency (#286) 2025-01-29 10:01:10 -07:00
b-rowan
e93cc77a58 ci: update pre-commit hooks 2025-01-28 21:29:43 -07:00
b-rowan
788d43c51c version: bump version number 2025-01-28 21:27:17 -07:00
Adrian
74c22b82ce bug: add miner algo type for S21 Hydro (#285) 2025-01-28 21:20:39 -07:00
Upstream Data
1f46ce1b9a version: bump version number 2025-01-28 09:36:56 -07:00
Adrian
7964336a0c feature: add support for S21 Hydro (#283) 2025-01-28 09:36:15 -07:00
Upstream Data
a24fc07c2a ci: update pre-commit to run docs generation when committing. 2025-01-28 08:51:13 -07:00
Upstream Data
4c64481d3b bug: do not run unittest when running in precommit.ci 2025-01-28 08:33:02 -07:00
Upstream Data
66fb5834f0 version: bump version number 2025-01-23 13:37:28 -07:00
Upstream Data
db05cc1d97 feature: add support for S21 Pro BOS 2025-01-23 13:37:04 -07:00
Brett Rowan
418e3ce26e Merge pull request #281 from UpstreamData/fix_hammer_pass 2025-01-23 07:42:20 -07:00
John-Paul Compagnone
5a0bb11a44 fix hammer default password 2025-01-23 08:35:37 -05:00
Upstream Data
39f9d087db version: bump version number 2025-01-20 09:27:40 -07:00
Upstream Data
067a376f94 feature: add support for luckyminer LV08 2025-01-20 09:27:16 -07:00
Upstream Data
a5d6e122f9 version: bump version number 2025-01-20 09:01:04 -07:00
Upstream Data
b160fd75ba refactor: reformat some files 2025-01-20 09:00:45 -07:00
Upstream Data
d1007d3ae8 version: bump version number 2025-01-20 08:58:14 -07:00
Upstream Data
33803e89e2 feature: add support for Vnish S19i
Fixes: #279
2025-01-20 08:21:24 -07:00
Upstream Data
10a44b9877 bug: fix invlaid import in luxminer.py 2025-01-20 08:21:12 -07:00
pre-commit-ci[bot]
bbd883f639 [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
2025-01-19 08:18:27 -07:00
Wilfred Allyn
8e2ad478e9 refactor: simplify get_wattage_limit for luxos 2025-01-19 08:18:27 -07:00
Wilfred Allyn
957981a9c6 feature: get active preset from luxos 2025-01-19 08:18:27 -07:00
Wilfred Allyn
13a67dfdd1 feature: add _get_wattage_limit for luxos 2025-01-19 08:18:27 -07:00
Wilfred Allyn
e86f2b62c5 docs: fix issues for docs warnings 2025-01-18 08:03:11 -07:00
Wilfred Allyn
88b4d2cac3 docs: add instructions for building docs locally 2025-01-17 09:31:36 -07:00
46 changed files with 670 additions and 399 deletions

View File

@@ -1,7 +1,15 @@
ci: ci:
skip: skip:
- poetry-lock
- unittest - unittest
- generate-docs
repos: 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 - repo: https://github.com/pre-commit/pre-commit-hooks
rev: v5.0.0 rev: v5.0.0
hooks: hooks:
@@ -15,11 +23,11 @@ repos:
exclude: ^mkdocs\.yml$ exclude: ^mkdocs\.yml$
- id: check-added-large-files - id: check-added-large-files
- repo: https://github.com/psf/black - repo: https://github.com/psf/black
rev: 24.10.0 rev: 25.1.0
hooks: hooks:
- id: black - id: black
- repo: https://github.com/pycqa/isort - repo: https://github.com/pycqa/isort
rev: 5.13.2 rev: 6.0.0
hooks: hooks:
- id: isort - id: isort
name: isort (python) name: isort (python)
@@ -30,6 +38,12 @@ repos:
name: unittest name: unittest
entry: python -m unittest discover entry: python -m unittest discover
language: system language: system
'types': [python] types: [ python ]
args: ["-p '*test.py'"] # Probably this option is absolutely not needed. args: ["-p '*test.py'"] # Probably this option is absolutely not needed.
pass_filenames: false pass_filenames: false
- id: generate-docs
name: generate-docs
entry: python docs/generate_miners.py
language: system
types: [ python ]
pass_filenames: false

View File

@@ -50,6 +50,13 @@ poetry install --with dev
pre-commit install pre-commit install
``` ```
##### Building Documentation Locally
```
poetry install --with docs
python docs/generate_miners.py
poetry run mkdocs serve
```
--- ---
## Getting started ## Getting started

View File

@@ -2,6 +2,7 @@ import asyncio
import importlib import importlib
import os import os
import warnings import warnings
from pathlib import Path
from pyasic.miners.factory import MINER_CLASSES, MinerTypes from pyasic.miners.factory import MINER_CLASSES, MinerTypes
@@ -51,12 +52,15 @@ def backend_str(backend: MinerTypes) -> str:
return "Mara Firmware Miners" return "Mara Firmware Miners"
case MinerTypes.BITAXE: case MinerTypes.BITAXE:
return "Stock Firmware BitAxe Miners" return "Stock Firmware BitAxe Miners"
case MinerTypes.LUCKYMINER:
return "Stock Firmware Lucky Miners"
case MinerTypes.ICERIVER: case MinerTypes.ICERIVER:
return "Stock Firmware IceRiver Miners" return "Stock Firmware IceRiver Miners"
case MinerTypes.HAMMER: case MinerTypes.HAMMER:
return "Stock Firmware Hammer Miners" return "Stock Firmware Hammer Miners"
case MinerTypes.VOLCMINER: case MinerTypes.VOLCMINER:
return "Stock Firmware Volcminers" return "Stock Firmware Volcminers"
raise TypeError("Unknown miner backend, cannot generate docs")
def create_url_str(mtype: str): def create_url_str(mtype: str):
@@ -135,14 +139,14 @@ for m in MINER_CLASSES:
done.append(miner) done.append(miner)
async def create_directory_structure(directory, data): def create_directory_structure(directory, data):
if not os.path.exists(directory): if not os.path.exists(directory):
os.makedirs(directory) os.makedirs(directory)
for key, value in data.items(): for key, value in data.items():
subdirectory = os.path.join(directory, key) subdirectory = os.path.join(directory, key)
if isinstance(value, dict): if isinstance(value, dict):
await create_directory_structure(subdirectory, value) create_directory_structure(subdirectory, value)
elif isinstance(value, list): elif isinstance(value, list):
file_path = os.path.join(subdirectory + ".md") 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: with open(os.path.join(directory, "supported_types.md"), "w") as file:
file.write(SUPPORTED_TYPES_HEADER) file.write(SUPPORTED_TYPES_HEADER)
for mback in MINER_CLASSES: for mback in MINER_CLASSES:
@@ -180,7 +184,7 @@ async def create_supported_types(directory):
for mtype in backend_types: for mtype in backend_types:
file.write(MINER_TYPE_HEADER.format(mtype)) file.write(MINER_TYPE_HEADER.format(mtype))
for minstance in backend_types[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( file.write(
MINER_DETAILS.format( MINER_DETAILS.format(
make(minstance), mtype, create_url_str(model), model make(minstance), mtype, create_url_str(model), model
@@ -190,6 +194,7 @@ async def create_supported_types(directory):
file.write(BACKEND_TYPE_CLOSER) file.write(BACKEND_TYPE_CLOSER)
root_directory = os.path.join(os.getcwd(), "miners") if __name__ == "__main__":
asyncio.run(create_directory_structure(root_directory, m_data)) root_directory = Path(__file__).parent.joinpath("miners")
asyncio.run(create_supported_types(root_directory)) create_directory_structure(root_directory, m_data)
create_supported_types(root_directory)

View File

@@ -495,6 +495,19 @@
show_root_heading: false show_root_heading: false
heading_level: 0 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) ## S19j (VNish)
- [x] Shutdowns - [x] Shutdowns

View File

@@ -14,6 +14,19 @@
show_root_heading: false show_root_heading: false
heading_level: 0 heading_level: 0
## S21 Hydro (Stock)
- [x] Shutdowns
- [x] Power Modes
- [ ] Setpoints
- [ ] Presets
::: pyasic.miners.antminer.bmminer.X21.S21.BMMinerS21Hydro
handler: python
options:
show_root_heading: false
heading_level: 0
## S21 Pro (Stock) ## S21 Pro (Stock)
- [x] Shutdowns - [x] Shutdowns
@@ -53,6 +66,19 @@
show_root_heading: false show_root_heading: false
heading_level: 0 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+) ## T21 (BOS+)
- [x] Shutdowns - [x] Shutdowns

View File

@@ -0,0 +1,16 @@
# pyasic
## LV Models
## LV08 (Stock)
- [ ] Shutdowns
- [ ] Power Modes
- [ ] Setpoints
- [ ] Presets
::: pyasic.miners.luckyminer.espminer.LV.LV08.LuckyMinerLV08
handler: python
options:
show_root_heading: false
heading_level: 0

View File

@@ -105,6 +105,7 @@ details {
<li><a href="../antminer/X21#s21-stock">S21 (Stock)</a></li> <li><a href="../antminer/X21#s21-stock">S21 (Stock)</a></li>
<li><a href="../antminer/X21#s21-pro-stock">S21 Pro (Stock)</a></li> <li><a href="../antminer/X21#s21-pro-stock">S21 Pro (Stock)</a></li>
<li><a href="../antminer/X21#t21-stock">T21 (Stock)</a></li> <li><a href="../antminer/X21#t21-stock">T21 (Stock)</a></li>
<li><a href="../antminer/X21#s21-hydro-stock">S21 Hydro (Stock)</a></li>
</ul> </ul>
</details> </details>
</ul> </ul>
@@ -652,6 +653,7 @@ details {
<summary>X21 Series:</summary> <summary>X21 Series:</summary>
<ul> <ul>
<li><a href="../antminer/X21#s21-bos_1">S21 (BOS+)</a></li> <li><a href="../antminer/X21#s21-bos_1">S21 (BOS+)</a></li>
<li><a href="../antminer/X21#s21-pro-bos_1">S21 Pro (BOS+)</a></li>
<li><a href="../antminer/X21#t21-bos_1">T21 (BOS+)</a></li> <li><a href="../antminer/X21#t21-bos_1">T21 (BOS+)</a></li>
</ul> </ul>
</details> </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-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#s19-pro-vnish">S19 Pro (VNish)</a></li>
<li><a href="../antminer/X19#s19j-vnish">S19j (VNish)</a></li> <li><a href="../antminer/X19#s19j-vnish">S19j (VNish)</a></li>
<li><a href="../antminer/X19#s19i-vnish">S19i (VNish)</a></li>
<li><a href="../antminer/X19#s19j-pro-vnish">S19j Pro (VNish)</a></li> <li><a href="../antminer/X19#s19j-pro-vnish">S19j Pro (VNish)</a></li>
<li><a href="../antminer/X19#s19j-pro-vnish">S19j Pro (VNish)</a></li> <li><a href="../antminer/X19#s19j-pro-vnish">S19j Pro (VNish)</a></li>
<li><a href="../antminer/X19#s19j-pro-vnish">S19j Pro (VNish)</a></li> <li><a href="../antminer/X19#s19j-pro-vnish">S19j Pro (VNish)</a></li>
@@ -859,6 +862,17 @@ details {
</ul> </ul>
</details> </details>
<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>
</ul>
</details>
</ul>
</details>
<details>
<summary>Stock Firmware IceRiver Miners:</summary> <summary>Stock Firmware IceRiver Miners:</summary>
<ul> <ul>
<details> <details>

92
poetry.lock generated
View File

@@ -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]] [[package]]
name = "aiofiles" name = "aiofiles"
@@ -422,19 +422,19 @@ test = ["pytest (>=6)"]
[[package]] [[package]]
name = "filelock" name = "filelock"
version = "3.16.1" version = "3.17.0"
description = "A platform independent file lock." description = "A platform independent file lock."
optional = false optional = false
python-versions = ">=3.8" python-versions = ">=3.9"
groups = ["dev"] groups = ["dev"]
files = [ files = [
{file = "filelock-3.16.1-py3-none-any.whl", hash = "sha256:2082e5703d51fbf98ea75855d9d5527e33d8ff23099bec374a134febee6946b0"}, {file = "filelock-3.17.0-py3-none-any.whl", hash = "sha256:533dc2f7ba78dc2f0f531fc6c4940addf7b70a481e269a5a3b93be94ffbe8338"},
{file = "filelock-3.16.1.tar.gz", hash = "sha256:c249fbfcd5db47e5e2d6d62198e565475ee65e4831e2561c8e313fa7eb961435"}, {file = "filelock-3.17.0.tar.gz", hash = "sha256:ee4e77401ef576ebb38cd7f13b9b28893194acc20a8e68e18730ba9c0e54660e"},
] ]
[package.extras] [package.extras]
docs = ["furo (>=2024.8.6)", "sphinx (>=8.0.2)", "sphinx-autodoc-typehints (>=2.4.1)"] docs = ["furo (>=2024.8.6)", "sphinx (>=8.1.3)", "sphinx-autodoc-typehints (>=3)"]
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)"] 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)"] typing = ["typing-extensions (>=4.12.2)"]
[[package]] [[package]]
@@ -457,14 +457,14 @@ dev = ["flake8", "markdown", "twine", "wheel"]
[[package]] [[package]]
name = "griffe" name = "griffe"
version = "1.5.4" version = "1.5.5"
description = "Signatures for entire Python programs. Extract the structure, the frame, the skeleton of your project, to generate API documentation or find breaking changes in your API." description = "Signatures for entire Python programs. Extract the structure, the frame, the skeleton of your project, to generate API documentation or find breaking changes in your API."
optional = false optional = false
python-versions = ">=3.9" python-versions = ">=3.9"
groups = ["docs"] groups = ["docs"]
files = [ files = [
{file = "griffe-1.5.4-py3-none-any.whl", hash = "sha256:ed33af890586a5bebc842fcb919fc694b3dc1bc55b7d9e0228de41ce566b4a1d"}, {file = "griffe-1.5.5-py3-none-any.whl", hash = "sha256:2761b1e8876c6f1f9ab1af274df93ea6bbadd65090de5f38f4cb5cc84897c7dd"},
{file = "griffe-1.5.4.tar.gz", hash = "sha256:073e78ad3e10c8378c2f798bd4ef87b92d8411e9916e157fd366a17cc4fd4e52"}, {file = "griffe-1.5.5.tar.gz", hash = "sha256:35ee5b38b93d6a839098aad0f92207e6ad6b70c3e8866c08ca669275b8cba585"},
] ]
[package.dependencies] [package.dependencies]
@@ -518,14 +518,14 @@ hyperframe = ">=6.0,<7"
[[package]] [[package]]
name = "hpack" name = "hpack"
version = "4.0.0" version = "4.1.0"
description = "Pure-Python HPACK header compression" description = "Pure-Python HPACK header encoding"
optional = false optional = false
python-versions = ">=3.6.1" python-versions = ">=3.9"
groups = ["main"] groups = ["main"]
files = [ files = [
{file = "hpack-4.0.0-py3-none-any.whl", hash = "sha256:84a076fad3dc9a9f8063ccb8041ef100867b1878b25ef0ee63847a5d53818a6c"}, {file = "hpack-4.1.0-py3-none-any.whl", hash = "sha256:157ac792668d995c657d93111f46b4535ed114f0c9c8d672271bbec7eae1b496"},
{file = "hpack-4.0.0.tar.gz", hash = "sha256:fc41de0c63e687ebffde81187a948221294896f6bdc0ae2312708df339430095"}, {file = "hpack-4.1.0.tar.gz", hash = "sha256:ec5eca154f7056aa06f196a557655c5b009b382873ac8d1e66e79e87535f1dca"},
] ]
[[package]] [[package]]
@@ -577,26 +577,26 @@ zstd = ["zstandard (>=0.18.0)"]
[[package]] [[package]]
name = "hyperframe" name = "hyperframe"
version = "6.0.1" version = "6.1.0"
description = "HTTP/2 framing layer for Python" description = "Pure-Python HTTP/2 framing"
optional = false optional = false
python-versions = ">=3.6.1" python-versions = ">=3.9"
groups = ["main"] groups = ["main"]
files = [ files = [
{file = "hyperframe-6.0.1-py3-none-any.whl", hash = "sha256:0ec6bafd80d8ad2195c4f03aacba3a8265e57bc4cff261e802bf39970ed02a15"}, {file = "hyperframe-6.1.0-py3-none-any.whl", hash = "sha256:b03380493a519fce58ea5af42e4a42317bf9bd425596f7a0835ffce80f1a42e5"},
{file = "hyperframe-6.0.1.tar.gz", hash = "sha256:ae510046231dc8e9ecb1a6586f63d2347bf4c8905914aa84ba585ae85f28a914"}, {file = "hyperframe-6.1.0.tar.gz", hash = "sha256:f630908a00854a7adeabd6382b43923a4c4cd4b821fcb527e6ab9e15382a3b08"},
] ]
[[package]] [[package]]
name = "identify" name = "identify"
version = "2.6.5" version = "2.6.6"
description = "File identification library for Python" description = "File identification library for Python"
optional = false optional = false
python-versions = ">=3.9" python-versions = ">=3.9"
groups = ["dev"] groups = ["dev"]
files = [ files = [
{file = "identify-2.6.5-py2.py3-none-any.whl", hash = "sha256:14181a47091eb75b337af4c23078c9d09225cd4c48929f521f3bf16b09d02566"}, {file = "identify-2.6.6-py2.py3-none-any.whl", hash = "sha256:cbd1810bce79f8b671ecb20f53ee0ae8e86ae84b557de31d89709dc2a48ba881"},
{file = "identify-2.6.5.tar.gz", hash = "sha256:c10b33f250e5bba374fae86fb57f3adcebf1161bce7cdf92031915fd480c13bc"}, {file = "identify-2.6.6.tar.gz", hash = "sha256:7bec12768ed44ea4761efb47806f0a41f86e7c0a5fdf5950d4648c90eca7e251"},
] ]
[package.extras] [package.extras]
@@ -619,15 +619,15 @@ all = ["flake8 (>=7.1.1)", "mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2
[[package]] [[package]]
name = "importlib-metadata" name = "importlib-metadata"
version = "8.5.0" version = "8.6.1"
description = "Read metadata from Python packages" description = "Read metadata from Python packages"
optional = false optional = false
python-versions = ">=3.8" python-versions = ">=3.9"
groups = ["docs"] groups = ["docs"]
markers = "python_version < \"3.10\"" markers = "python_version < \"3.10\""
files = [ files = [
{file = "importlib_metadata-8.5.0-py3-none-any.whl", hash = "sha256:45e54197d28b7a7f1559e60b95e7c567032b602131fbd588f1497f47880aa68b"}, {file = "importlib_metadata-8.6.1-py3-none-any.whl", hash = "sha256:02a89390c1e15fdfdc0d7c6b25cb3e62650d0494005c97d6f148bf5b9787525e"},
{file = "importlib_metadata-8.5.0.tar.gz", hash = "sha256:71522656f0abace1d072b9e5481a48f07c138e00f079c38c8f883823f9c26bd7"}, {file = "importlib_metadata-8.6.1.tar.gz", hash = "sha256:310b41d755445d74569f993ccfc22838295d9fe005425094fad953d7f15c8580"},
] ]
[package.dependencies] [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"] doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"]
enabler = ["pytest-enabler (>=2.2)"] enabler = ["pytest-enabler (>=2.2)"]
perf = ["ipython"] 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"] type = ["pytest-mypy"]
[[package]] [[package]]
@@ -846,14 +846,14 @@ pyyaml = ">=5.1"
[[package]] [[package]]
name = "mkdocs-material" name = "mkdocs-material"
version = "9.5.49" version = "9.5.50"
description = "Documentation that simply works" description = "Documentation that simply works"
optional = false optional = false
python-versions = ">=3.8" python-versions = ">=3.8"
groups = ["docs"] groups = ["docs"]
files = [ files = [
{file = "mkdocs_material-9.5.49-py3-none-any.whl", hash = "sha256:c3c2d8176b18198435d3a3e119011922f3e11424074645c24019c2dcf08a360e"}, {file = "mkdocs_material-9.5.50-py3-none-any.whl", hash = "sha256:f24100f234741f4d423a9d672a909d859668a4f404796be3cf035f10d6050385"},
{file = "mkdocs_material-9.5.49.tar.gz", hash = "sha256:3671bb282b4f53a1c72e08adbe04d2481a98f85fed392530051f80ff94a9621d"}, {file = "mkdocs_material-9.5.50.tar.gz", hash = "sha256:ae5fe16f3d7c9ccd05bb6916a7da7420cf99a9ce5e33debd9d40403a090d5825"},
] ]
[package.dependencies] [package.dependencies]
@@ -870,7 +870,7 @@ regex = ">=2022.4"
requests = ">=2.26,<3.0" requests = ">=2.26,<3.0"
[package.extras] [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)"] 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)"] 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]] [[package]]
name = "pre-commit" name = "pre-commit"
version = "4.0.1" version = "4.1.0"
description = "A framework for managing and maintaining multi-language pre-commit hooks." description = "A framework for managing and maintaining multi-language pre-commit hooks."
optional = false optional = false
python-versions = ">=3.9" python-versions = ">=3.9"
groups = ["dev"] groups = ["dev"]
files = [ files = [
{file = "pre_commit-4.0.1-py2.py3-none-any.whl", hash = "sha256:efde913840816312445dc98787724647c65473daefe420785f885e8ed9a06878"}, {file = "pre_commit-4.1.0-py2.py3-none-any.whl", hash = "sha256:d29e7cb346295bcc1cc75fc3e92e343495e3ea0196c9ec6ba53f49f10ab6ae7b"},
{file = "pre_commit-4.0.1.tar.gz", hash = "sha256:80905ac375958c0444c65e9cebebd948b3cdb518f335a091a670a89d652139d2"}, {file = "pre_commit-4.1.0.tar.gz", hash = "sha256:ae3f018575a588e30dfddfab9a05448bfbd6b73d78709617b5a2b853549716d4"},
] ]
[package.dependencies] [package.dependencies]
@@ -1177,14 +1177,14 @@ files = [
[[package]] [[package]]
name = "pydantic" name = "pydantic"
version = "2.10.5" version = "2.10.6"
description = "Data validation using Python type hints" description = "Data validation using Python type hints"
optional = false optional = false
python-versions = ">=3.8" python-versions = ">=3.8"
groups = ["main"] groups = ["main"]
files = [ files = [
{file = "pydantic-2.10.5-py3-none-any.whl", hash = "sha256:4dd4e322dbe55472cb7ca7e73f4b63574eecccf2835ffa2af9021ce113c83c53"}, {file = "pydantic-2.10.6-py3-none-any.whl", hash = "sha256:427d664bf0b8a2b34ff5dd0f5a18df00591adcee7198fbd71981054cef37b584"},
{file = "pydantic-2.10.5.tar.gz", hash = "sha256:278b38dbbaec562011d659ee05f63346951b3a248a6f3642e1bc68894ea2b4ff"}, {file = "pydantic-2.10.6.tar.gz", hash = "sha256:ca5daa827cce33de7a42be142548b0096bf05a7e7b365aebfa5f8eeec7128236"},
] ]
[package.dependencies] [package.dependencies]
@@ -1326,14 +1326,14 @@ windows-terminal = ["colorama (>=0.4.6)"]
[[package]] [[package]]
name = "pymdown-extensions" name = "pymdown-extensions"
version = "10.14" version = "10.14.1"
description = "Extension pack for Python Markdown." description = "Extension pack for Python Markdown."
optional = false optional = false
python-versions = ">=3.8" python-versions = ">=3.8"
groups = ["docs"] groups = ["docs"]
files = [ files = [
{file = "pymdown_extensions-10.14-py3-none-any.whl", hash = "sha256:202481f716cc8250e4be8fce997781ebf7917701b59652458ee47f2401f818b5"}, {file = "pymdown_extensions-10.14.1-py3-none-any.whl", hash = "sha256:637951cbfbe9874ba28134fb3ce4b8bcadd6aca89ac4998ec29dcbafd554ae08"},
{file = "pymdown_extensions-10.14.tar.gz", hash = "sha256:741bd7c4ff961ba40b7528d32284c53bc436b8b1645e8e37c3e57770b8700a34"}, {file = "pymdown_extensions-10.14.1.tar.gz", hash = "sha256:b65801996a0cd4f42a3110810c306c45b7313c09b0610a6f773730f2a9e3c96b"},
] ]
[package.dependencies] [package.dependencies]
@@ -1674,14 +1674,14 @@ zstd = ["zstandard (>=0.18.0)"]
[[package]] [[package]]
name = "virtualenv" name = "virtualenv"
version = "20.28.1" version = "20.29.1"
description = "Virtual Python Environment builder" description = "Virtual Python Environment builder"
optional = false optional = false
python-versions = ">=3.8" python-versions = ">=3.8"
groups = ["dev"] groups = ["dev"]
files = [ files = [
{file = "virtualenv-20.28.1-py3-none-any.whl", hash = "sha256:412773c85d4dab0409b83ec36f7a6499e72eaf08c80e81e9576bca61831c71cb"}, {file = "virtualenv-20.29.1-py3-none-any.whl", hash = "sha256:4e4cb403c0b0da39e13b46b1b2476e505cb0046b25f242bee80f62bf990b2779"},
{file = "virtualenv-20.28.1.tar.gz", hash = "sha256:5d34ab240fdb5d21549b76f9e8ff3af28252f5499fb6d6f031adac4e5a8c5329"}, {file = "virtualenv-20.29.1.tar.gz", hash = "sha256:b8b8970138d32fb606192cb97f6cd4bb644fa486be9308fb9b63f81091b5dc35"},
] ]
[package.dependencies] [package.dependencies]
@@ -1759,5 +1759,5 @@ type = ["pytest-mypy"]
[metadata] [metadata]
lock-version = "2.1" lock-version = "2.1"
python-versions = "^3.9" python-versions = ">3.9, <4.0"
content-hash = "c0aa00dd5f3b52bbac53eb765be2bca2ec7f9429e835d6b2fe6bf207f2f39974" content-hash = "67a8e0d34c0d1af0f8e4d617d80fd5afc8d197e5d5444f78fd82e4f716a52965"

View File

@@ -13,6 +13,8 @@
# See the License for the specific language governing permissions and - # See the License for the specific language governing permissions and -
# limitations under the License. - # limitations under the License. -
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
import importlib.metadata
from pyasic import settings from pyasic import settings
from pyasic.config import MinerConfig from pyasic.config import MinerConfig
from pyasic.data import MinerData from pyasic.data import MinerData
@@ -22,3 +24,5 @@ from pyasic.network import MinerNetwork
from pyasic.rpc import * from pyasic.rpc import *
from pyasic.ssh import * from pyasic.ssh import *
from pyasic.web import * from pyasic.web import *
__version__ = importlib.metadata.version("pyasic")

View File

@@ -143,12 +143,12 @@ class MinerConfig(BaseModel):
**self.pools.as_mara(user_suffix=user_suffix), **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 { return {
**self.fan_mode.as_bitaxe(), **self.fan_mode.as_espminer(),
**self.temperature.as_bitaxe(), **self.temperature.as_espminer(),
**self.mining_mode.as_bitaxe(), **self.mining_mode.as_espminer(),
**self.pools.as_bitaxe(user_suffix=user_suffix), **self.pools.as_espminer(user_suffix=user_suffix),
} }
def as_luxos(self, user_suffix: str | None = None) -> dict: def as_luxos(self, user_suffix: str | None = None) -> dict:
@@ -272,10 +272,10 @@ class MinerConfig(BaseModel):
) )
@classmethod @classmethod
def from_bitaxe(cls, web_system_info: dict) -> "MinerConfig": def from_espminer(cls, web_system_info: dict) -> "MinerConfig":
return cls( return cls(
pools=PoolConfig.from_bitaxe(web_system_info), pools=PoolConfig.from_espminer(web_system_info),
fan_mode=FanModeConfig.from_bitaxe(web_system_info), fan_mode=FanModeConfig.from_espminer(web_system_info),
) )
@classmethod @classmethod

View File

@@ -61,8 +61,8 @@ class MinerConfigOption(Enum):
def as_mara(self) -> dict: def as_mara(self) -> dict:
return self.value.as_mara() return self.value.as_mara()
def as_bitaxe(self) -> dict: def as_espminer(self) -> dict:
return self.value.as_bitaxe() return self.value.as_espminer()
def as_luxos(self) -> dict: def as_luxos(self) -> dict:
return self.value.as_luxos() return self.value.as_luxos()
@@ -125,7 +125,7 @@ class MinerConfigValue(BaseModel):
def as_mara(self) -> dict: def as_mara(self) -> dict:
return {} return {}
def as_bitaxe(self) -> dict: def as_espminer(self) -> dict:
return {} return {}
def as_luxos(self) -> dict: def as_luxos(self) -> dict:

View File

@@ -81,7 +81,7 @@ class FanModeNormal(MinerConfigValue):
}, },
} }
def as_bitaxe(self) -> dict: def as_espminer(self) -> dict:
return {"autoFanspeed": 1} return {"autoFanspeed": 1}
def as_luxos(self) -> dict: 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} return {"autoFanspeed": 0, "fanspeed": self.speed}
def as_luxos(self) -> dict: def as_luxos(self) -> dict:
@@ -342,7 +342,7 @@ class FanModeConfig(MinerConfigOption):
return cls.default() return cls.default()
@classmethod @classmethod
def from_bitaxe(cls, web_system_info: dict): def from_espminer(cls, web_system_info: dict):
if web_system_info["autofanspeed"] == 1: if web_system_info["autofanspeed"] == 1:
return cls.normal() return cls.normal()
else: else:

View File

@@ -371,11 +371,7 @@ class MiningModePreset(MinerConfigValue):
def from_luxos( def from_luxos(
cls, rpc_config: dict, rpc_profiles: list[dict] cls, rpc_config: dict, rpc_profiles: list[dict]
) -> "MiningModePreset": ) -> "MiningModePreset":
active_preset = None active_preset = cls.get_active_preset_from_luxos(rpc_config, rpc_profiles)
active_profile = rpc_config["CONFIG"][0]["Profile"]
for profile in rpc_profiles["PROFILES"]:
if profile["Profile Name"] == active_profile:
active_preset = profile
return cls( return cls(
active_preset=MiningPreset.from_luxos(active_preset), active_preset=MiningPreset.from_luxos(active_preset),
available_presets=[ 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): class ManualBoardSettings(MinerConfigValue):
freq: float freq: float
@@ -705,7 +712,11 @@ class MiningModeConfig(MinerConfigOption):
@classmethod @classmethod
def from_luxos(cls, rpc_config: dict, rpc_profiles: dict): 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( MiningMode = TypeVar(

View File

@@ -102,7 +102,7 @@ class Pool(MinerConfigValue):
"pass": self.password, "pass": self.password,
} }
def as_bitaxe(self, user_suffix: str | None = None) -> dict: def as_espminer(self, user_suffix: str | None = None) -> dict:
return { return {
"stratumURL": self.url, "stratumURL": self.url,
"stratumUser": f"{self.user}{user_suffix or ''}", "stratumUser": f"{self.user}{user_suffix or ''}",
@@ -192,7 +192,7 @@ class Pool(MinerConfigValue):
) )
@classmethod @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']}" url = f"stratum+tcp://{web_system_info['stratumURL']}:{web_system_info['stratumPort']}"
return cls( return cls(
url=url, url=url,
@@ -306,8 +306,8 @@ class PoolGroup(MinerConfigValue):
def as_mara(self, user_suffix: str | None = None) -> list: def as_mara(self, user_suffix: str | None = None) -> list:
return [p.as_mara(user_suffix=user_suffix) for p in self.pools] return [p.as_mara(user_suffix=user_suffix) for p in self.pools]
def as_bitaxe(self, user_suffix: str | None = None) -> dict: def as_espminer(self, user_suffix: str | None = None) -> dict:
return self.pools[0].as_bitaxe(user_suffix=user_suffix) return self.pools[0].as_espminer(user_suffix=user_suffix)
def as_boser(self, user_suffix: str | None = None) -> PoolGroupConfiguration: def as_boser(self, user_suffix: str | None = None) -> PoolGroupConfiguration:
return 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]) return cls(pools=[Pool.from_mara(pool_conf) for pool_conf in web_config_pools])
@classmethod @classmethod
def from_bitaxe(cls, web_system_info: dict) -> "PoolGroup": def from_espminer(cls, web_system_info: dict) -> "PoolGroup":
return cls(pools=[Pool.from_bitaxe(web_system_info)]) return cls(pools=[Pool.from_espminer(web_system_info)])
@classmethod @classmethod
def from_iceriver(cls, web_userpanel: dict) -> "PoolGroup": 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": self.groups[0].as_mara(user_suffix=user_suffix)}
return {"pools": []} return {"pools": []}
def as_bitaxe(self, user_suffix: str | None = None) -> dict: def as_espminer(self, user_suffix: str | None = None) -> dict:
return self.groups[0].as_bitaxe(user_suffix=user_suffix) return self.groups[0].as_espminer(user_suffix=user_suffix)
def as_luxos(self, user_suffix: str | None = None) -> dict: def as_luxos(self, user_suffix: str | None = None) -> dict:
return {} return {}
@@ -576,8 +576,8 @@ class PoolConfig(MinerConfigValue):
return cls(groups=[PoolGroup.from_mara(web_config["pools"])]) return cls(groups=[PoolGroup.from_mara(web_config["pools"])])
@classmethod @classmethod
def from_bitaxe(cls, web_system_info: dict) -> "PoolConfig": def from_espminer(cls, web_system_info: dict) -> "PoolConfig":
return cls(groups=[PoolGroup.from_bitaxe(web_system_info)]) return cls(groups=[PoolGroup.from_espminer(web_system_info)])
@classmethod @classmethod
def from_iceriver(cls, web_userpanel: dict) -> "PoolConfig": def from_iceriver(cls, web_userpanel: dict) -> "PoolConfig":

View File

@@ -26,6 +26,7 @@ class MinerMake(str, Enum):
AURADINE = "Auradine" AURADINE = "Auradine"
EPIC = "ePIC" EPIC = "ePIC"
BITAXE = "BitAxe" BITAXE = "BitAxe"
LUCKYMINER = "LuckyMiner"
ICERIVER = "IceRiver" ICERIVER = "IceRiver"
HAMMER = "Hammer" HAMMER = "Hammer"
VOLCMINER = "VolcMiner" VOLCMINER = "VolcMiner"

View File

@@ -59,6 +59,7 @@ class AntminerModels(MinerModelType):
T19 = "T19" T19 = "T19"
S21 = "S21" S21 = "S21"
S21Pro = "S21 Pro" S21Pro = "S21 Pro"
S21Hydro = "S21 Hydro"
T21 = "T21" T21 = "T21"
def __str__(self): def __str__(self):
@@ -507,6 +508,13 @@ class BitAxeModels(MinerModelType):
return self.value return self.value
class LuckyMinerModels(MinerModelType):
BM1366 = "LV08"
def __str__(self):
return self.value
class IceRiverModels(MinerModelType): class IceRiverModels(MinerModelType):
KS0 = "KS0" KS0 = "KS0"
KS1 = "KS1" KS1 = "KS1"
@@ -550,6 +558,7 @@ class MinerModel:
AURADINE = AuradineModels AURADINE = AuradineModels
EPIC = ePICModels EPIC = ePICModels
BITAXE = BitAxeModels BITAXE = BitAxeModels
LUCKYMINER = LuckyMinerModels
ICERIVER = IceRiverModels ICERIVER = IceRiverModels
HAMMER = HammerModels HAMMER = HammerModels
VOLCMINER = VolcMinerModels VOLCMINER = VolcMinerModels

View File

@@ -15,7 +15,7 @@
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
from pyasic.miners.backends import AntminerModern from pyasic.miners.backends import AntminerModern
from pyasic.miners.device.models import S21, S21Pro from pyasic.miners.device.models import S21, S21Hydro, S21Pro
class BMMinerS21(AntminerModern, S21): class BMMinerS21(AntminerModern, S21):
@@ -24,3 +24,7 @@ class BMMinerS21(AntminerModern, S21):
class BMMinerS21Pro(AntminerModern, S21Pro): class BMMinerS21Pro(AntminerModern, S21Pro):
pass pass
class BMMinerS21Hydro(AntminerModern, S21Hydro):
pass

View File

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

View File

@@ -15,8 +15,12 @@
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
from pyasic.miners.backends import BOSer 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): class BOSMinerS21(BOSer, S21):
pass pass
class BOSMinerS21Pro(BOSer, S21Pro):
pass

View File

@@ -14,5 +14,5 @@
# limitations under the License. - # limitations under the License. -
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
from .S21 import BOSMinerS21 from .S21 import BOSMinerS21, BOSMinerS21Pro
from .T21 import BOSMinerT21 from .T21 import BOSMinerT21

View File

@@ -20,6 +20,7 @@ from pyasic.miners.device.models import (
S19XP, S19XP,
S19a, S19a,
S19aPro, S19aPro,
S19i,
S19j, S19j,
S19jPro, S19jPro,
S19kPro, S19kPro,
@@ -53,6 +54,10 @@ class VNishS19aPro(VNish, S19aPro):
pass pass
class VNishS19i(VNish, S19i):
pass
class VNishS19j(VNish, S19j): class VNishS19j(VNish, S19j):
pass pass

View File

@@ -18,6 +18,7 @@ from .S19 import (
VNishS19, VNishS19,
VNishS19a, VNishS19a,
VNishS19aPro, VNishS19aPro,
VNishS19i,
VNishS19j, VNishS19j,
VNishS19jPro, VNishS19jPro,
VNishS19kPro, VNishS19kPro,

View File

@@ -28,6 +28,7 @@ from .hammer import BlackMiner
from .hiveon import HiveonModern, HiveonOld from .hiveon import HiveonModern, HiveonOld
from .iceriver import IceRiver from .iceriver import IceRiver
from .innosilicon import Innosilicon from .innosilicon import Innosilicon
from .luckyminer import LuckyMiner
from .luxminer import LUXMiner from .luxminer import LUXMiner
from .marathon import MaraMiner from .marathon import MaraMiner
from .unknown import UnknownMiner from .unknown import UnknownMiner

View File

@@ -1,235 +1,7 @@
from typing import List, Optional from pyasic.miners.backends.espminer import ESPMiner
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")],
),
}
)
class BitAxe(BaseMiner): class BitAxe(ESPMiner):
"""Handler for BitAxe""" """Handler for BitAxe"""
web: BitAxeWebAPI pass
_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

View 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

View File

@@ -0,0 +1,7 @@
from pyasic.miners.backends.espminer import ESPMiner
class LuckyMiner(ESPMiner):
"""Handler for LuckyMiner"""
pass

View File

@@ -17,6 +17,7 @@ import logging
from typing import List, Optional from typing import List, Optional
from pyasic.config import MinerConfig from pyasic.config import MinerConfig
from pyasic.config.mining import MiningModePreset
from pyasic.data import Fan, HashBoard from pyasic.data import Fan, HashBoard
from pyasic.data.pools import PoolMetrics, PoolUrl from pyasic.data.pools import PoolMetrics, PoolUrl
from pyasic.device.algorithm import AlgoHashRate from pyasic.device.algorithm import AlgoHashRate
@@ -47,6 +48,13 @@ LUXMINER_DATA_LOC = DataLocations(
"_get_wattage", "_get_wattage",
[RPCAPICommand("rpc_power", "power")], [RPCAPICommand("rpc_power", "power")],
), ),
str(DataOptions.WATTAGE_LIMIT): DataFunction(
"_get_wattage_limit",
[
RPCAPICommand("rpc_config", "config"),
RPCAPICommand("rpc_profiles", "profiles"),
],
),
str(DataOptions.FANS): DataFunction( str(DataOptions.FANS): DataFunction(
"_get_fans", "_get_fans",
[RPCAPICommand("rpc_fans", "fans")], [RPCAPICommand("rpc_fans", "fans")],
@@ -151,7 +159,7 @@ class LUXMiner(LuxOSFirmware):
bool: True if the firmware upgrade was successfully initiated, False otherwise. bool: True if the firmware upgrade was successfully initiated, False otherwise.
""" """
try: try:
await self.rpc.upgraderun() await self.rpc.updaterun()
logging.info(f"{self.ip}: Firmware upgrade initiated successfully.") logging.info(f"{self.ip}: Firmware upgrade initiated successfully.")
return True return True
@@ -289,6 +297,17 @@ class LUXMiner(LuxOSFirmware):
except (LookupError, ValueError, TypeError): except (LookupError, ValueError, TypeError):
pass 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]: async def _get_fans(self, rpc_fans: dict = None) -> List[Fan]:
if rpc_fans is None: if rpc_fans is None:
try: try:

View File

@@ -50,6 +50,10 @@ class BitAxeMake(BaseMiner):
make = MinerMake.BITAXE make = MinerMake.BITAXE
class LuckyMinerMake(BaseMiner):
make = MinerMake.LUCKYMINER
class IceRiverMake(BaseMiner): class IceRiverMake(BaseMiner):
make = MinerMake.ICERIVER make = MinerMake.ICERIVER

View File

@@ -34,3 +34,12 @@ class S21Pro(AntMinerMake):
expected_fans = 4 expected_fans = 4
expected_hashboards = 3 expected_hashboards = 3
algo = MinerAlgo.SHA256 algo = MinerAlgo.SHA256
class S21Hydro(AntMinerMake):
raw_model = MinerModel.ANTMINER.S21Hydro
expected_chips = 216
expected_hashboards = 2
expected_fans = 0
algo = MinerAlgo.SHA256

View File

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

View 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.BM1366
expected_hashboards = 1
expected_chips = 1
expected_fans = 1
algo = MinerAlgo.SHA256

View File

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

View File

@@ -0,0 +1 @@
from .LV import *

View File

@@ -41,6 +41,7 @@ from pyasic.miners.goldshell import *
from pyasic.miners.hammer import * from pyasic.miners.hammer import *
from pyasic.miners.iceriver import * from pyasic.miners.iceriver import *
from pyasic.miners.innosilicon import * from pyasic.miners.innosilicon import *
from pyasic.miners.luckyminer import *
from pyasic.miners.volcminer import * from pyasic.miners.volcminer import *
from pyasic.miners.whatsminer import * from pyasic.miners.whatsminer import *
@@ -62,6 +63,7 @@ class MinerTypes(enum.Enum):
ICERIVER = 13 ICERIVER = 13
HAMMER = 14 HAMMER = 14
VOLCMINER = 15 VOLCMINER = 15
LUCKYMINER = 16
MINER_CLASSES = { MINER_CLASSES = {
@@ -117,6 +119,7 @@ MINER_CLASSES = {
"ANTMINER BHB68606": BMMinerS21, # ??? "ANTMINER BHB68606": BMMinerS21, # ???
"ANTMINER S21 PRO": BMMinerS21Pro, "ANTMINER S21 PRO": BMMinerS21Pro,
"ANTMINER T21": BMMinerT21, "ANTMINER T21": BMMinerT21,
"ANTMINER S21 HYD.": BMMinerS21Hydro,
}, },
MinerTypes.WHATSMINER: { MinerTypes.WHATSMINER: {
None: type("WhatsminerUnknown", (BTMiner, WhatsMinerMake), {}), None: type("WhatsminerUnknown", (BTMiner, WhatsMinerMake), {}),
@@ -544,6 +547,7 @@ MINER_CLASSES = {
"ANTMINER S19 PRO+ HYD.": BOSMinerS19ProPlusHydro, "ANTMINER S19 PRO+ HYD.": BOSMinerS19ProPlusHydro,
"ANTMINER T19": BOSMinerT19, "ANTMINER T19": BOSMinerT19,
"ANTMINER S21": BOSMinerS21, "ANTMINER S21": BOSMinerS21,
"ANTMINER S21 PRO": BOSMinerS21Pro,
"ANTMINER T21": BOSMinerT21, "ANTMINER T21": BOSMinerT21,
"BRAIINS MINI MINER BMM 100": BraiinsBMM100, "BRAIINS MINI MINER BMM 100": BraiinsBMM100,
"BRAIINS MINI MINER BMM 101": BraiinsBMM101, "BRAIINS MINI MINER BMM 101": BraiinsBMM101,
@@ -559,6 +563,7 @@ MINER_CLASSES = {
"ANTMINER S19NOPIC": VNishS19NoPIC, "ANTMINER S19NOPIC": VNishS19NoPIC,
"ANTMINER S19 PRO": VNishS19Pro, "ANTMINER S19 PRO": VNishS19Pro,
"ANTMINER S19J": VNishS19j, "ANTMINER S19J": VNishS19j,
"ANTMINER S19I": VNishS19i,
"ANTMINER S19J PRO": VNishS19jPro, "ANTMINER S19J PRO": VNishS19jPro,
"ANTMINER S19J PRO A": VNishS19jPro, "ANTMINER S19J PRO A": VNishS19jPro,
"ANTMINER S19J PRO BB": VNishS19jPro, "ANTMINER S19J PRO BB": VNishS19jPro,
@@ -633,6 +638,10 @@ MINER_CLASSES = {
"BM1397": BitAxeMax, "BM1397": BitAxeMax,
"BM1370": BitAxeGamma, "BM1370": BitAxeGamma,
}, },
MinerTypes.LUCKYMINER: {
None: LuckyMiner,
"BM1366": LuckyMinerLV08,
},
MinerTypes.ICERIVER: { MinerTypes.ICERIVER: {
None: type("IceRiverUnknown", (IceRiver, IceRiverMake), {}), None: type("IceRiverUnknown", (IceRiver, IceRiverMake), {}),
"KS0": IceRiverKS0, "KS0": IceRiverKS0,
@@ -730,6 +739,7 @@ class MinerFactory:
MinerTypes.AURADINE: self.get_miner_model_auradine, MinerTypes.AURADINE: self.get_miner_model_auradine,
MinerTypes.MARATHON: self.get_miner_model_marathon, MinerTypes.MARATHON: self.get_miner_model_marathon,
MinerTypes.BITAXE: self.get_miner_model_bitaxe, MinerTypes.BITAXE: self.get_miner_model_bitaxe,
MinerTypes.LUCKYMINER: self.get_miner_model_luckyminer,
MinerTypes.ICERIVER: self.get_miner_model_iceriver, MinerTypes.ICERIVER: self.get_miner_model_iceriver,
MinerTypes.HAMMER: self.get_miner_model_hammer, MinerTypes.HAMMER: self.get_miner_model_hammer,
MinerTypes.VOLCMINER: self.get_miner_model_volcminer, MinerTypes.VOLCMINER: self.get_miner_model_volcminer,
@@ -832,6 +842,8 @@ class MinerFactory:
return MinerTypes.ICERIVER return MinerTypes.ICERIVER
if "AxeOS" in web_text: if "AxeOS" in web_text:
return MinerTypes.BITAXE return MinerTypes.BITAXE
if "Lucky miner" in web_text:
return MinerTypes.LUCKYMINER
if "cloud-box" in web_text: if "cloud-box" in web_text:
return MinerTypes.GOLDSHELL return MinerTypes.GOLDSHELL
if "AnthillOS" in web_text: if "AnthillOS" in web_text:
@@ -876,6 +888,7 @@ class MinerFactory:
await writer.drain() await writer.drain()
# loop to receive all the data # loop to receive all the data
timeouts_remaining = max(1, int(settings.get("factory_get_timeout", 3)))
while True: while True:
try: try:
d = await asyncio.wait_for(reader.read(4096), timeout=1) d = await asyncio.wait_for(reader.read(4096), timeout=1)
@@ -883,7 +896,10 @@ class MinerFactory:
break break
data += d data += d
except asyncio.TimeoutError: except asyncio.TimeoutError:
pass timeouts_remaining -= 1
if not timeouts_remaining:
logger.warning(f"{ip}: Socket ping timeout.")
break
except ConnectionResetError: except ConnectionResetError:
return return
except asyncio.CancelledError: except asyncio.CancelledError:
@@ -1291,6 +1307,18 @@ class MinerFactory:
except (TypeError, LookupError): except (TypeError, LookupError):
pass 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["ASICModel"]
if miner_model == "":
return None
return miner_model
except (TypeError, LookupError):
pass
async def get_miner_model_iceriver(self, ip: str) -> str | None: async def get_miner_model_iceriver(self, ip: str) -> str | None:
async with httpx.AsyncClient(transport=settings.transport()) as client: async with httpx.AsyncClient(transport=settings.transport()) as client:
try: try:

View File

@@ -0,0 +1 @@
from .espminer import *

View 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

View File

@@ -0,0 +1 @@
from .LV08 import LuckyMinerLV08

View File

@@ -0,0 +1 @@
from .LV import *

View File

@@ -574,9 +574,6 @@ class LUXMinerRPCAPI(BaseMinerRPCAPI):
<details> <details>
<summary>Expand</summary> <summary>Expand</summary>
Parameters:
session_id: Session id from the logon command.
Returns: Returns:
Confirmation of logging off a session. Confirmation of logging off a session.
</details> </details>
@@ -844,7 +841,7 @@ class LUXMinerRPCAPI(BaseMinerRPCAPI):
""" """
return await self.send_privileged_command("voltageset", board_n, voltage) 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. Send the 'updaterun' command to the miner.

View File

@@ -31,7 +31,7 @@ _settings = { # defaults
"default_whatsminer_rpc_password": "admin", "default_whatsminer_rpc_password": "admin",
"default_innosilicon_web_password": "admin", "default_innosilicon_web_password": "admin",
"default_antminer_web_password": "root", "default_antminer_web_password": "root",
"default_hammer_web_password": "ltc@dog", "default_hammer_web_password": "root",
"default_volcminer_web_password": "ltc@dog", "default_volcminer_web_password": "ltc@dog",
"default_bosminer_web_password": "root", "default_bosminer_web_password": "root",
"default_vnish_web_password": "admin", "default_vnish_web_password": "admin",

View File

@@ -268,11 +268,11 @@ class AuradineWebAPI(BaseWebAPI):
""" """
return await self.send_command("mode") 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. """Set the operational mode of the Auradine miner.
Args: Args:
**kwargs: Mode settings specified as keyword arguments. **kwargs (Any): Mode settings specified as keyword arguments.
Returns: Returns:
dict: A dictionary indicating the result of the mode setting operation. dict: A dictionary indicating the result of the mode setting operation.
@@ -287,11 +287,11 @@ class AuradineWebAPI(BaseWebAPI):
""" """
return await self.send_command("network") 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. """Set the network configuration of the Auradine miner.
Args: Args:
**kwargs: Network settings specified as keyword arguments. **kwargs (Any): Network settings specified as keyword arguments.
Returns: Returns:
dict: A dictionary indicating the result of the network configuration. dict: A dictionary indicating the result of the network configuration.

View File

@@ -39,7 +39,7 @@ class ApiVersionServiceStub(betterproto.ServiceStub):
*, *,
timeout: Optional[float] = None, timeout: Optional[float] = None,
deadline: Optional["Deadline"] = None, deadline: Optional["Deadline"] = None,
metadata: Optional["MetadataLike"] = None metadata: Optional["MetadataLike"] = None,
) -> "ApiVersion": ) -> "ApiVersion":
return await self._unary_unary( return await self._unary_unary(
"/braiins.bos.ApiVersionService/GetApiVersion", "/braiins.bos.ApiVersionService/GetApiVersion",

View File

@@ -1706,7 +1706,7 @@ class ActionsServiceStub(betterproto.ServiceStub):
*, *,
timeout: Optional[float] = None, timeout: Optional[float] = None,
deadline: Optional["Deadline"] = None, deadline: Optional["Deadline"] = None,
metadata: Optional["MetadataLike"] = None metadata: Optional["MetadataLike"] = None,
) -> "StartResponse": ) -> "StartResponse":
return await self._unary_unary( return await self._unary_unary(
"/braiins.bos.v1.ActionsService/Start", "/braiins.bos.v1.ActionsService/Start",
@@ -1723,7 +1723,7 @@ class ActionsServiceStub(betterproto.ServiceStub):
*, *,
timeout: Optional[float] = None, timeout: Optional[float] = None,
deadline: Optional["Deadline"] = None, deadline: Optional["Deadline"] = None,
metadata: Optional["MetadataLike"] = None metadata: Optional["MetadataLike"] = None,
) -> "StopResponse": ) -> "StopResponse":
return await self._unary_unary( return await self._unary_unary(
"/braiins.bos.v1.ActionsService/Stop", "/braiins.bos.v1.ActionsService/Stop",
@@ -1740,7 +1740,7 @@ class ActionsServiceStub(betterproto.ServiceStub):
*, *,
timeout: Optional[float] = None, timeout: Optional[float] = None,
deadline: Optional["Deadline"] = None, deadline: Optional["Deadline"] = None,
metadata: Optional["MetadataLike"] = None metadata: Optional["MetadataLike"] = None,
) -> "PauseMiningResponse": ) -> "PauseMiningResponse":
return await self._unary_unary( return await self._unary_unary(
"/braiins.bos.v1.ActionsService/PauseMining", "/braiins.bos.v1.ActionsService/PauseMining",
@@ -1757,7 +1757,7 @@ class ActionsServiceStub(betterproto.ServiceStub):
*, *,
timeout: Optional[float] = None, timeout: Optional[float] = None,
deadline: Optional["Deadline"] = None, deadline: Optional["Deadline"] = None,
metadata: Optional["MetadataLike"] = None metadata: Optional["MetadataLike"] = None,
) -> "ResumeMiningResponse": ) -> "ResumeMiningResponse":
return await self._unary_unary( return await self._unary_unary(
"/braiins.bos.v1.ActionsService/ResumeMining", "/braiins.bos.v1.ActionsService/ResumeMining",
@@ -1774,7 +1774,7 @@ class ActionsServiceStub(betterproto.ServiceStub):
*, *,
timeout: Optional[float] = None, timeout: Optional[float] = None,
deadline: Optional["Deadline"] = None, deadline: Optional["Deadline"] = None,
metadata: Optional["MetadataLike"] = None metadata: Optional["MetadataLike"] = None,
) -> "RestartResponse": ) -> "RestartResponse":
return await self._unary_unary( return await self._unary_unary(
"/braiins.bos.v1.ActionsService/Restart", "/braiins.bos.v1.ActionsService/Restart",
@@ -1791,7 +1791,7 @@ class ActionsServiceStub(betterproto.ServiceStub):
*, *,
timeout: Optional[float] = None, timeout: Optional[float] = None,
deadline: Optional["Deadline"] = None, deadline: Optional["Deadline"] = None,
metadata: Optional["MetadataLike"] = None metadata: Optional["MetadataLike"] = None,
) -> "RebootResponse": ) -> "RebootResponse":
return await self._unary_unary( return await self._unary_unary(
"/braiins.bos.v1.ActionsService/Reboot", "/braiins.bos.v1.ActionsService/Reboot",
@@ -1808,7 +1808,7 @@ class ActionsServiceStub(betterproto.ServiceStub):
*, *,
timeout: Optional[float] = None, timeout: Optional[float] = None,
deadline: Optional["Deadline"] = None, deadline: Optional["Deadline"] = None,
metadata: Optional["MetadataLike"] = None metadata: Optional["MetadataLike"] = None,
) -> "LocateDeviceStatusResponse": ) -> "LocateDeviceStatusResponse":
return await self._unary_unary( return await self._unary_unary(
"/braiins.bos.v1.ActionsService/SetLocateDeviceStatus", "/braiins.bos.v1.ActionsService/SetLocateDeviceStatus",
@@ -1825,7 +1825,7 @@ class ActionsServiceStub(betterproto.ServiceStub):
*, *,
timeout: Optional[float] = None, timeout: Optional[float] = None,
deadline: Optional["Deadline"] = None, deadline: Optional["Deadline"] = None,
metadata: Optional["MetadataLike"] = None metadata: Optional["MetadataLike"] = None,
) -> "LocateDeviceStatusResponse": ) -> "LocateDeviceStatusResponse":
return await self._unary_unary( return await self._unary_unary(
"/braiins.bos.v1.ActionsService/GetLocateDeviceStatus", "/braiins.bos.v1.ActionsService/GetLocateDeviceStatus",
@@ -1844,7 +1844,7 @@ class AuthenticationServiceStub(betterproto.ServiceStub):
*, *,
timeout: Optional[float] = None, timeout: Optional[float] = None,
deadline: Optional["Deadline"] = None, deadline: Optional["Deadline"] = None,
metadata: Optional["MetadataLike"] = None metadata: Optional["MetadataLike"] = None,
) -> "LoginResponse": ) -> "LoginResponse":
return await self._unary_unary( return await self._unary_unary(
"/braiins.bos.v1.AuthenticationService/Login", "/braiins.bos.v1.AuthenticationService/Login",
@@ -1861,7 +1861,7 @@ class AuthenticationServiceStub(betterproto.ServiceStub):
*, *,
timeout: Optional[float] = None, timeout: Optional[float] = None,
deadline: Optional["Deadline"] = None, deadline: Optional["Deadline"] = None,
metadata: Optional["MetadataLike"] = None metadata: Optional["MetadataLike"] = None,
) -> "SetPasswordResponse": ) -> "SetPasswordResponse":
return await self._unary_unary( return await self._unary_unary(
"/braiins.bos.v1.AuthenticationService/SetPassword", "/braiins.bos.v1.AuthenticationService/SetPassword",
@@ -1880,7 +1880,7 @@ class CoolingServiceStub(betterproto.ServiceStub):
*, *,
timeout: Optional[float] = None, timeout: Optional[float] = None,
deadline: Optional["Deadline"] = None, deadline: Optional["Deadline"] = None,
metadata: Optional["MetadataLike"] = None metadata: Optional["MetadataLike"] = None,
) -> "GetCoolingStateResponse": ) -> "GetCoolingStateResponse":
return await self._unary_unary( return await self._unary_unary(
"/braiins.bos.v1.CoolingService/GetCoolingState", "/braiins.bos.v1.CoolingService/GetCoolingState",
@@ -1897,7 +1897,7 @@ class CoolingServiceStub(betterproto.ServiceStub):
*, *,
timeout: Optional[float] = None, timeout: Optional[float] = None,
deadline: Optional["Deadline"] = None, deadline: Optional["Deadline"] = None,
metadata: Optional["MetadataLike"] = None metadata: Optional["MetadataLike"] = None,
) -> "SetImmersionModeResponse": ) -> "SetImmersionModeResponse":
return await self._unary_unary( return await self._unary_unary(
"/braiins.bos.v1.CoolingService/SetImmersionMode", "/braiins.bos.v1.CoolingService/SetImmersionMode",
@@ -1916,7 +1916,7 @@ class PerformanceServiceStub(betterproto.ServiceStub):
*, *,
timeout: Optional[float] = None, timeout: Optional[float] = None,
deadline: Optional["Deadline"] = None, deadline: Optional["Deadline"] = None,
metadata: Optional["MetadataLike"] = None metadata: Optional["MetadataLike"] = None,
) -> "GetTunerStateResponse": ) -> "GetTunerStateResponse":
return await self._unary_unary( return await self._unary_unary(
"/braiins.bos.v1.PerformanceService/GetTunerState", "/braiins.bos.v1.PerformanceService/GetTunerState",
@@ -1933,7 +1933,7 @@ class PerformanceServiceStub(betterproto.ServiceStub):
*, *,
timeout: Optional[float] = None, timeout: Optional[float] = None,
deadline: Optional["Deadline"] = None, deadline: Optional["Deadline"] = None,
metadata: Optional["MetadataLike"] = None metadata: Optional["MetadataLike"] = None,
) -> "ListTargetProfilesResponse": ) -> "ListTargetProfilesResponse":
return await self._unary_unary( return await self._unary_unary(
"/braiins.bos.v1.PerformanceService/ListTargetProfiles", "/braiins.bos.v1.PerformanceService/ListTargetProfiles",
@@ -1950,7 +1950,7 @@ class PerformanceServiceStub(betterproto.ServiceStub):
*, *,
timeout: Optional[float] = None, timeout: Optional[float] = None,
deadline: Optional["Deadline"] = None, deadline: Optional["Deadline"] = None,
metadata: Optional["MetadataLike"] = None metadata: Optional["MetadataLike"] = None,
) -> "SetPowerTargetResponse": ) -> "SetPowerTargetResponse":
return await self._unary_unary( return await self._unary_unary(
"/braiins.bos.v1.PerformanceService/SetDefaultPowerTarget", "/braiins.bos.v1.PerformanceService/SetDefaultPowerTarget",
@@ -1967,7 +1967,7 @@ class PerformanceServiceStub(betterproto.ServiceStub):
*, *,
timeout: Optional[float] = None, timeout: Optional[float] = None,
deadline: Optional["Deadline"] = None, deadline: Optional["Deadline"] = None,
metadata: Optional["MetadataLike"] = None metadata: Optional["MetadataLike"] = None,
) -> "SetPowerTargetResponse": ) -> "SetPowerTargetResponse":
return await self._unary_unary( return await self._unary_unary(
"/braiins.bos.v1.PerformanceService/SetPowerTarget", "/braiins.bos.v1.PerformanceService/SetPowerTarget",
@@ -1984,7 +1984,7 @@ class PerformanceServiceStub(betterproto.ServiceStub):
*, *,
timeout: Optional[float] = None, timeout: Optional[float] = None,
deadline: Optional["Deadline"] = None, deadline: Optional["Deadline"] = None,
metadata: Optional["MetadataLike"] = None metadata: Optional["MetadataLike"] = None,
) -> "SetPowerTargetResponse": ) -> "SetPowerTargetResponse":
return await self._unary_unary( return await self._unary_unary(
"/braiins.bos.v1.PerformanceService/IncrementPowerTarget", "/braiins.bos.v1.PerformanceService/IncrementPowerTarget",
@@ -2001,7 +2001,7 @@ class PerformanceServiceStub(betterproto.ServiceStub):
*, *,
timeout: Optional[float] = None, timeout: Optional[float] = None,
deadline: Optional["Deadline"] = None, deadline: Optional["Deadline"] = None,
metadata: Optional["MetadataLike"] = None metadata: Optional["MetadataLike"] = None,
) -> "SetPowerTargetResponse": ) -> "SetPowerTargetResponse":
return await self._unary_unary( return await self._unary_unary(
"/braiins.bos.v1.PerformanceService/DecrementPowerTarget", "/braiins.bos.v1.PerformanceService/DecrementPowerTarget",
@@ -2018,7 +2018,7 @@ class PerformanceServiceStub(betterproto.ServiceStub):
*, *,
timeout: Optional[float] = None, timeout: Optional[float] = None,
deadline: Optional["Deadline"] = None, deadline: Optional["Deadline"] = None,
metadata: Optional["MetadataLike"] = None metadata: Optional["MetadataLike"] = None,
) -> "SetHashrateTargetResponse": ) -> "SetHashrateTargetResponse":
return await self._unary_unary( return await self._unary_unary(
"/braiins.bos.v1.PerformanceService/SetDefaultHashrateTarget", "/braiins.bos.v1.PerformanceService/SetDefaultHashrateTarget",
@@ -2035,7 +2035,7 @@ class PerformanceServiceStub(betterproto.ServiceStub):
*, *,
timeout: Optional[float] = None, timeout: Optional[float] = None,
deadline: Optional["Deadline"] = None, deadline: Optional["Deadline"] = None,
metadata: Optional["MetadataLike"] = None metadata: Optional["MetadataLike"] = None,
) -> "SetHashrateTargetResponse": ) -> "SetHashrateTargetResponse":
return await self._unary_unary( return await self._unary_unary(
"/braiins.bos.v1.PerformanceService/SetHashrateTarget", "/braiins.bos.v1.PerformanceService/SetHashrateTarget",
@@ -2052,7 +2052,7 @@ class PerformanceServiceStub(betterproto.ServiceStub):
*, *,
timeout: Optional[float] = None, timeout: Optional[float] = None,
deadline: Optional["Deadline"] = None, deadline: Optional["Deadline"] = None,
metadata: Optional["MetadataLike"] = None metadata: Optional["MetadataLike"] = None,
) -> "SetHashrateTargetResponse": ) -> "SetHashrateTargetResponse":
return await self._unary_unary( return await self._unary_unary(
"/braiins.bos.v1.PerformanceService/IncrementHashrateTarget", "/braiins.bos.v1.PerformanceService/IncrementHashrateTarget",
@@ -2069,7 +2069,7 @@ class PerformanceServiceStub(betterproto.ServiceStub):
*, *,
timeout: Optional[float] = None, timeout: Optional[float] = None,
deadline: Optional["Deadline"] = None, deadline: Optional["Deadline"] = None,
metadata: Optional["MetadataLike"] = None metadata: Optional["MetadataLike"] = None,
) -> "SetHashrateTargetResponse": ) -> "SetHashrateTargetResponse":
return await self._unary_unary( return await self._unary_unary(
"/braiins.bos.v1.PerformanceService/DecrementHashrateTarget", "/braiins.bos.v1.PerformanceService/DecrementHashrateTarget",
@@ -2086,7 +2086,7 @@ class PerformanceServiceStub(betterproto.ServiceStub):
*, *,
timeout: Optional[float] = None, timeout: Optional[float] = None,
deadline: Optional["Deadline"] = None, deadline: Optional["Deadline"] = None,
metadata: Optional["MetadataLike"] = None metadata: Optional["MetadataLike"] = None,
) -> "SetDpsResponse": ) -> "SetDpsResponse":
return await self._unary_unary( return await self._unary_unary(
"/braiins.bos.v1.PerformanceService/SetDPS", "/braiins.bos.v1.PerformanceService/SetDPS",
@@ -2103,7 +2103,7 @@ class PerformanceServiceStub(betterproto.ServiceStub):
*, *,
timeout: Optional[float] = None, timeout: Optional[float] = None,
deadline: Optional["Deadline"] = None, deadline: Optional["Deadline"] = None,
metadata: Optional["MetadataLike"] = None metadata: Optional["MetadataLike"] = None,
) -> "PerformanceMode": ) -> "PerformanceMode":
return await self._unary_unary( return await self._unary_unary(
"/braiins.bos.v1.PerformanceService/SetPerformanceMode", "/braiins.bos.v1.PerformanceService/SetPerformanceMode",
@@ -2120,7 +2120,7 @@ class PerformanceServiceStub(betterproto.ServiceStub):
*, *,
timeout: Optional[float] = None, timeout: Optional[float] = None,
deadline: Optional["Deadline"] = None, deadline: Optional["Deadline"] = None,
metadata: Optional["MetadataLike"] = None metadata: Optional["MetadataLike"] = None,
) -> "PerformanceMode": ) -> "PerformanceMode":
return await self._unary_unary( return await self._unary_unary(
"/braiins.bos.v1.PerformanceService/GetActivePerformanceMode", "/braiins.bos.v1.PerformanceService/GetActivePerformanceMode",
@@ -2137,7 +2137,7 @@ class PerformanceServiceStub(betterproto.ServiceStub):
*, *,
timeout: Optional[float] = None, timeout: Optional[float] = None,
deadline: Optional["Deadline"] = None, deadline: Optional["Deadline"] = None,
metadata: Optional["MetadataLike"] = None metadata: Optional["MetadataLike"] = None,
) -> "RemoveTunedProfilesResponse": ) -> "RemoveTunedProfilesResponse":
return await self._unary_unary( return await self._unary_unary(
"/braiins.bos.v1.PerformanceService/RemoveTunedProfiles", "/braiins.bos.v1.PerformanceService/RemoveTunedProfiles",
@@ -2156,7 +2156,7 @@ class PoolServiceStub(betterproto.ServiceStub):
*, *,
timeout: Optional[float] = None, timeout: Optional[float] = None,
deadline: Optional["Deadline"] = None, deadline: Optional["Deadline"] = None,
metadata: Optional["MetadataLike"] = None metadata: Optional["MetadataLike"] = None,
) -> "GetPoolGroupsResponse": ) -> "GetPoolGroupsResponse":
return await self._unary_unary( return await self._unary_unary(
"/braiins.bos.v1.PoolService/GetPoolGroups", "/braiins.bos.v1.PoolService/GetPoolGroups",
@@ -2173,7 +2173,7 @@ class PoolServiceStub(betterproto.ServiceStub):
*, *,
timeout: Optional[float] = None, timeout: Optional[float] = None,
deadline: Optional["Deadline"] = None, deadline: Optional["Deadline"] = None,
metadata: Optional["MetadataLike"] = None metadata: Optional["MetadataLike"] = None,
) -> "CreatePoolGroupResponse": ) -> "CreatePoolGroupResponse":
return await self._unary_unary( return await self._unary_unary(
"/braiins.bos.v1.PoolService/CreatePoolGroup", "/braiins.bos.v1.PoolService/CreatePoolGroup",
@@ -2190,7 +2190,7 @@ class PoolServiceStub(betterproto.ServiceStub):
*, *,
timeout: Optional[float] = None, timeout: Optional[float] = None,
deadline: Optional["Deadline"] = None, deadline: Optional["Deadline"] = None,
metadata: Optional["MetadataLike"] = None metadata: Optional["MetadataLike"] = None,
) -> "UpdatePoolGroupResponse": ) -> "UpdatePoolGroupResponse":
return await self._unary_unary( return await self._unary_unary(
"/braiins.bos.v1.PoolService/UpdatePoolGroup", "/braiins.bos.v1.PoolService/UpdatePoolGroup",
@@ -2207,7 +2207,7 @@ class PoolServiceStub(betterproto.ServiceStub):
*, *,
timeout: Optional[float] = None, timeout: Optional[float] = None,
deadline: Optional["Deadline"] = None, deadline: Optional["Deadline"] = None,
metadata: Optional["MetadataLike"] = None metadata: Optional["MetadataLike"] = None,
) -> "RemovePoolGroupResponse": ) -> "RemovePoolGroupResponse":
return await self._unary_unary( return await self._unary_unary(
"/braiins.bos.v1.PoolService/RemovePoolGroup", "/braiins.bos.v1.PoolService/RemovePoolGroup",
@@ -2224,7 +2224,7 @@ class PoolServiceStub(betterproto.ServiceStub):
*, *,
timeout: Optional[float] = None, timeout: Optional[float] = None,
deadline: Optional["Deadline"] = None, deadline: Optional["Deadline"] = None,
metadata: Optional["MetadataLike"] = None metadata: Optional["MetadataLike"] = None,
) -> "SetPoolGroupsResponse": ) -> "SetPoolGroupsResponse":
return await self._unary_unary( return await self._unary_unary(
"/braiins.bos.v1.PoolService/SetPoolGroups", "/braiins.bos.v1.PoolService/SetPoolGroups",
@@ -2243,7 +2243,7 @@ class ConfigurationServiceStub(betterproto.ServiceStub):
*, *,
timeout: Optional[float] = None, timeout: Optional[float] = None,
deadline: Optional["Deadline"] = None, deadline: Optional["Deadline"] = None,
metadata: Optional["MetadataLike"] = None metadata: Optional["MetadataLike"] = None,
) -> "GetMinerConfigurationResponse": ) -> "GetMinerConfigurationResponse":
return await self._unary_unary( return await self._unary_unary(
"/braiins.bos.v1.ConfigurationService/GetMinerConfiguration", "/braiins.bos.v1.ConfigurationService/GetMinerConfiguration",
@@ -2260,7 +2260,7 @@ class ConfigurationServiceStub(betterproto.ServiceStub):
*, *,
timeout: Optional[float] = None, timeout: Optional[float] = None,
deadline: Optional["Deadline"] = None, deadline: Optional["Deadline"] = None,
metadata: Optional["MetadataLike"] = None metadata: Optional["MetadataLike"] = None,
) -> "GetConstraintsResponse": ) -> "GetConstraintsResponse":
return await self._unary_unary( return await self._unary_unary(
"/braiins.bos.v1.ConfigurationService/GetConstraints", "/braiins.bos.v1.ConfigurationService/GetConstraints",
@@ -2279,7 +2279,7 @@ class LicenseServiceStub(betterproto.ServiceStub):
*, *,
timeout: Optional[float] = None, timeout: Optional[float] = None,
deadline: Optional["Deadline"] = None, deadline: Optional["Deadline"] = None,
metadata: Optional["MetadataLike"] = None metadata: Optional["MetadataLike"] = None,
) -> "GetLicenseStateResponse": ) -> "GetLicenseStateResponse":
return await self._unary_unary( return await self._unary_unary(
"/braiins.bos.v1.LicenseService/GetLicenseState", "/braiins.bos.v1.LicenseService/GetLicenseState",
@@ -2298,7 +2298,7 @@ class MinerServiceStub(betterproto.ServiceStub):
*, *,
timeout: Optional[float] = None, timeout: Optional[float] = None,
deadline: Optional["Deadline"] = None, deadline: Optional["Deadline"] = None,
metadata: Optional["MetadataLike"] = None metadata: Optional["MetadataLike"] = None,
) -> AsyncIterator[GetMinerStatusResponse]: ) -> AsyncIterator[GetMinerStatusResponse]:
async for response in self._unary_stream( async for response in self._unary_stream(
"/braiins.bos.v1.MinerService/GetMinerStatus", "/braiins.bos.v1.MinerService/GetMinerStatus",
@@ -2316,7 +2316,7 @@ class MinerServiceStub(betterproto.ServiceStub):
*, *,
timeout: Optional[float] = None, timeout: Optional[float] = None,
deadline: Optional["Deadline"] = None, deadline: Optional["Deadline"] = None,
metadata: Optional["MetadataLike"] = None metadata: Optional["MetadataLike"] = None,
) -> "GetMinerDetailsResponse": ) -> "GetMinerDetailsResponse":
return await self._unary_unary( return await self._unary_unary(
"/braiins.bos.v1.MinerService/GetMinerDetails", "/braiins.bos.v1.MinerService/GetMinerDetails",
@@ -2333,7 +2333,7 @@ class MinerServiceStub(betterproto.ServiceStub):
*, *,
timeout: Optional[float] = None, timeout: Optional[float] = None,
deadline: Optional["Deadline"] = None, deadline: Optional["Deadline"] = None,
metadata: Optional["MetadataLike"] = None metadata: Optional["MetadataLike"] = None,
) -> "GetMinerStatsResponse": ) -> "GetMinerStatsResponse":
return await self._unary_unary( return await self._unary_unary(
"/braiins.bos.v1.MinerService/GetMinerStats", "/braiins.bos.v1.MinerService/GetMinerStats",
@@ -2350,7 +2350,7 @@ class MinerServiceStub(betterproto.ServiceStub):
*, *,
timeout: Optional[float] = None, timeout: Optional[float] = None,
deadline: Optional["Deadline"] = None, deadline: Optional["Deadline"] = None,
metadata: Optional["MetadataLike"] = None metadata: Optional["MetadataLike"] = None,
) -> "GetErrorsResponse": ) -> "GetErrorsResponse":
return await self._unary_unary( return await self._unary_unary(
"/braiins.bos.v1.MinerService/GetErrors", "/braiins.bos.v1.MinerService/GetErrors",
@@ -2367,7 +2367,7 @@ class MinerServiceStub(betterproto.ServiceStub):
*, *,
timeout: Optional[float] = None, timeout: Optional[float] = None,
deadline: Optional["Deadline"] = None, deadline: Optional["Deadline"] = None,
metadata: Optional["MetadataLike"] = None metadata: Optional["MetadataLike"] = None,
) -> "GetHashboardsResponse": ) -> "GetHashboardsResponse":
return await self._unary_unary( return await self._unary_unary(
"/braiins.bos.v1.MinerService/GetHashboards", "/braiins.bos.v1.MinerService/GetHashboards",
@@ -2384,7 +2384,7 @@ class MinerServiceStub(betterproto.ServiceStub):
*, *,
timeout: Optional[float] = None, timeout: Optional[float] = None,
deadline: Optional["Deadline"] = None, deadline: Optional["Deadline"] = None,
metadata: Optional["MetadataLike"] = None metadata: Optional["MetadataLike"] = None,
) -> AsyncIterator[GetSupportArchiveResponse]: ) -> AsyncIterator[GetSupportArchiveResponse]:
async for response in self._unary_stream( async for response in self._unary_stream(
"/braiins.bos.v1.MinerService/GetSupportArchive", "/braiins.bos.v1.MinerService/GetSupportArchive",
@@ -2402,7 +2402,7 @@ class MinerServiceStub(betterproto.ServiceStub):
*, *,
timeout: Optional[float] = None, timeout: Optional[float] = None,
deadline: Optional["Deadline"] = None, deadline: Optional["Deadline"] = None,
metadata: Optional["MetadataLike"] = None metadata: Optional["MetadataLike"] = None,
) -> "EnableHashboardsResponse": ) -> "EnableHashboardsResponse":
return await self._unary_unary( return await self._unary_unary(
"/braiins.bos.v1.MinerService/EnableHashboards", "/braiins.bos.v1.MinerService/EnableHashboards",
@@ -2419,7 +2419,7 @@ class MinerServiceStub(betterproto.ServiceStub):
*, *,
timeout: Optional[float] = None, timeout: Optional[float] = None,
deadline: Optional["Deadline"] = None, deadline: Optional["Deadline"] = None,
metadata: Optional["MetadataLike"] = None metadata: Optional["MetadataLike"] = None,
) -> "DisableHashboardsResponse": ) -> "DisableHashboardsResponse":
return await self._unary_unary( return await self._unary_unary(
"/braiins.bos.v1.MinerService/DisableHashboards", "/braiins.bos.v1.MinerService/DisableHashboards",
@@ -2438,7 +2438,7 @@ class NetworkServiceStub(betterproto.ServiceStub):
*, *,
timeout: Optional[float] = None, timeout: Optional[float] = None,
deadline: Optional["Deadline"] = None, deadline: Optional["Deadline"] = None,
metadata: Optional["MetadataLike"] = None metadata: Optional["MetadataLike"] = None,
) -> "GetNetworkConfigurationResponse": ) -> "GetNetworkConfigurationResponse":
return await self._unary_unary( return await self._unary_unary(
"/braiins.bos.v1.NetworkService/GetNetworkConfiguration", "/braiins.bos.v1.NetworkService/GetNetworkConfiguration",
@@ -2455,7 +2455,7 @@ class NetworkServiceStub(betterproto.ServiceStub):
*, *,
timeout: Optional[float] = None, timeout: Optional[float] = None,
deadline: Optional["Deadline"] = None, deadline: Optional["Deadline"] = None,
metadata: Optional["MetadataLike"] = None metadata: Optional["MetadataLike"] = None,
) -> "SetNetworkConfigurationResponse": ) -> "SetNetworkConfigurationResponse":
return await self._unary_unary( return await self._unary_unary(
"/braiins.bos.v1.NetworkService/SetNetworkConfiguration", "/braiins.bos.v1.NetworkService/SetNetworkConfiguration",
@@ -2472,7 +2472,7 @@ class NetworkServiceStub(betterproto.ServiceStub):
*, *,
timeout: Optional[float] = None, timeout: Optional[float] = None,
deadline: Optional["Deadline"] = None, deadline: Optional["Deadline"] = None,
metadata: Optional["MetadataLike"] = None metadata: Optional["MetadataLike"] = None,
) -> "GetNetworkInfoResponse": ) -> "GetNetworkInfoResponse":
return await self._unary_unary( return await self._unary_unary(
"/braiins.bos.v1.NetworkService/GetNetworkInfo", "/braiins.bos.v1.NetworkService/GetNetworkInfo",

View File

@@ -10,7 +10,7 @@ from pyasic import APIError, settings
from pyasic.web.base import BaseWebAPI from pyasic.web.base import BaseWebAPI
class BitAxeWebAPI(BaseWebAPI): class ESPMinerWebAPI(BaseWebAPI):
async def send_command( async def send_command(
self, self,
command: str | bytes, command: str | bytes,

7
pyasic/web/luckyminer.py Normal file
View File

@@ -0,0 +1,7 @@
from __future__ import annotations
from .bitaxe import ESPMinerWebAPI
class LuckyMinerWebAPI(ESPMinerWebAPI):
pass

View File

@@ -1,23 +1,58 @@
[tool.poetry] [project]
name = "pyasic" name = "pyasic"
version = "0.69.2" version = "0.70.6"
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"
[tool.poetry.dependencies] description = "A simplified and standardized interface for Bitcoin ASICs."
python = "^3.9" authors = [{name = "UpstreamData", email = "brett@upstreamdata.ca"}]
httpx = ">=0.26.0" repository = "https://github.com/UpstreamData/pyasic"
asyncssh = ">=2.17.0"
passlib = ">=1.7.4" homepage = "https://docs.pyasic.org"
pyaml = ">=23.12.0" source = "https://github.com/UpstreamData/pyasic"
tomli = { version = ">=2.0.1", python = "<3.11" } documentation = "https://docs.pyasic.org"
tomli-w = "^1.0.0" issues = "https://github.com/UpstreamData/pyasic/issues"
aiofiles = ">=23.2.1" readme = {file = "README.md", content-type = "text/markdown"}
betterproto = "2.0.0b7" license = "Apache 2.0"
pydantic = "^2.9.2" 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] [tool.poetry.group.dev]
optional = true optional = true
@@ -36,7 +71,7 @@ mkdocs-material = "^9.5.39"
[build-system] [build-system]
requires = ["poetry-core>=1.0.0"] requires = ["poetry-core>=2.0.0"]
build-backend = "poetry.core.masonry.api" build-backend = "poetry.core.masonry.api"
[tool.isort] [tool.isort]