Compare commits

...

16 Commits

Author SHA1 Message Date
Brett Rowan
0be9e9d519 feature: add fault_light to influx 2025-03-17 14:17:37 -06:00
Upstream Data
4694c0f774 bug: fix error code handling in list 2025-03-06 11:45:38 -07:00
Brett Rowan
11012b310b bug: fix delimiter handling 2025-03-04 21:27:28 -07:00
Brett Rowan
8852fab3ee feature: allow the user to pass a delimiter to as_influx 2025-03-04 20:14:55 -07:00
Brett Rowan
ec1b2ca162 bug: fix bad " " handling in influx 2025-03-04 19:58:44 -07:00
Upstream Data
1f9d4c8c10 bug: swap to lower case booleans 2025-03-04 19:51:48 -07:00
Upstream Data
5bb04b2af4 refactor: round hashrate to 2 decimals for influx 2025-03-04 19:51:48 -07:00
Upstream Data
2e192a1536 feature: update support for influxdb line protocol 2025-03-04 19:51:48 -07:00
Brett Rowan
4da8044bc7 bug: fix bad type hint 2025-03-04 19:51:37 -07:00
Brett Rowan
76078e4d0e bug: fix wattage limit parsing on luxos 2025-03-04 19:51:13 -07:00
Upstream Data
276a476fab bug: fix json decode error possibility with avalon nanos 2025-03-03 15:04:22 -07:00
pre-commit-ci[bot]
e0abed4f93 [pre-commit.ci] pre-commit autoupdate (#307)
updates:
- [github.com/pycqa/isort: 6.0.0 → 6.0.1](https://github.com/pycqa/isort/compare/6.0.0...6.0.1)

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2025-03-03 14:56:47 -07:00
Ganey
4a67bd5d99 feat: add powerlimit to avalon nano (#302)
* feat: add powerlimit to avalon nano

add power limit to avalon nano

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

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

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2025-02-26 15:23:18 -07:00
pre-commit-ci[bot]
eb48d04939 [pre-commit.ci] pre-commit autoupdate
updates:
- [github.com/python-poetry/poetry: 2.0.1 → 2.1.1](https://github.com/python-poetry/poetry/compare/2.0.1...2.1.1)
2025-02-18 08:44:43 -07:00
Upstream Data
c4697728e4 version: bump version number 2025-02-13 15:38:53 -07:00
Upstream Data
de64172073 feature: add support for Hiveon S19kPro 2025-02-13 15:38:28 -07:00
20 changed files with 503 additions and 218 deletions

View File

@@ -5,7 +5,7 @@ ci:
- generate-docs
repos:
- repo: https://github.com/python-poetry/poetry
rev: 2.0.1
rev: 2.1.1
hooks:
- id: poetry-check
- id: poetry-lock
@@ -27,7 +27,7 @@ repos:
hooks:
- id: black
- repo: https://github.com/pycqa/isort
rev: 6.0.0
rev: 6.0.1
hooks:
- id: isort
name: isort (python)

View File

@@ -703,6 +703,19 @@
show_root_heading: false
heading_level: 0
## S19K Pro (Hive)
- [ ] Shutdowns
- [ ] Power Modes
- [ ] Setpoints
- [ ] Presets
::: pyasic.miners.antminer.hiveon.X19.S19.HiveonS19kPro
handler: python
options:
show_root_heading: false
heading_level: 0
## S19 No PIC (Hive)
- [ ] Shutdowns

View File

@@ -769,6 +769,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#s19k-pro-hive">S19K Pro (Hive)</a></li>
<li><a href="../antminer/X19#s19-no-pic-hive">S19 No PIC (Hive)</a></li>
</ul>
</details>

187
poetry.lock generated
View File

@@ -1,4 +1,4 @@
# This file is automatically @generated by Poetry 2.0.1 and should not be changed by hand.
# This file is automatically @generated by Poetry 2.1.1 and should not be changed by hand.
[[package]]
name = "aiofiles"
@@ -44,19 +44,19 @@ typing_extensions = {version = ">=4.5", markers = "python_version < \"3.13\""}
[package.extras]
doc = ["Sphinx (>=7.4,<8.0)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx_rtd_theme"]
test = ["anyio[trio]", "coverage[toml] (>=7)", "exceptiongroup (>=1.2.0)", "hypothesis (>=4.0)", "psutil (>=5.9)", "pytest (>=7.0)", "trustme", "truststore (>=0.9.1)", "uvloop (>=0.21)"]
test = ["anyio[trio]", "coverage[toml] (>=7)", "exceptiongroup (>=1.2.0)", "hypothesis (>=4.0)", "psutil (>=5.9)", "pytest (>=7.0)", "trustme", "truststore (>=0.9.1) ; python_version >= \"3.10\"", "uvloop (>=0.21) ; platform_python_implementation == \"CPython\" and platform_system != \"Windows\" and python_version < \"3.14\""]
trio = ["trio (>=0.26.1)"]
[[package]]
name = "asyncssh"
version = "2.19.0"
version = "2.20.0"
description = "AsyncSSH: Asynchronous SSHv2 client and server library"
optional = false
python-versions = ">=3.6"
groups = ["main"]
files = [
{file = "asyncssh-2.19.0-py3-none-any.whl", hash = "sha256:bb82ac30ff0cb4393fbaf1114e606ad7a4f13d6c4bdaed423c033ee26b455228"},
{file = "asyncssh-2.19.0.tar.gz", hash = "sha256:723dead4d068b558708dc66a4ca7e7a93a813aa9416036eccb9af4c03ae2cf30"},
{file = "asyncssh-2.20.0-py3-none-any.whl", hash = "sha256:af6888d937c07a4bf31293335a6166b4d87608cdb5957b49547da6ad87ecf174"},
{file = "asyncssh-2.20.0.tar.gz", hash = "sha256:020b6e384b2328ef8683908ad8e73de9ec2b9b62fd964571ea957bba98412983"},
]
[package.dependencies]
@@ -85,7 +85,26 @@ files = [
]
[package.extras]
dev = ["backports.zoneinfo", "freezegun (>=1.0,<2.0)", "jinja2 (>=3.0)", "pytest (>=6.0)", "pytest-cov", "pytz", "setuptools", "tzdata"]
dev = ["backports.zoneinfo ; python_version < \"3.9\"", "freezegun (>=1.0,<2.0)", "jinja2 (>=3.0)", "pytest (>=6.0)", "pytest-cov", "pytz", "setuptools", "tzdata ; sys_platform == \"win32\""]
[[package]]
name = "backrefs"
version = "5.8"
description = "A wrapper around re and regex that adds additional back references."
optional = false
python-versions = ">=3.9"
groups = ["docs"]
files = [
{file = "backrefs-5.8-py310-none-any.whl", hash = "sha256:c67f6638a34a5b8730812f5101376f9d41dc38c43f1fdc35cb54700f6ed4465d"},
{file = "backrefs-5.8-py311-none-any.whl", hash = "sha256:2e1c15e4af0e12e45c8701bd5da0902d326b2e200cafcd25e49d9f06d44bb61b"},
{file = "backrefs-5.8-py312-none-any.whl", hash = "sha256:bbef7169a33811080d67cdf1538c8289f76f0942ff971222a16034da88a73486"},
{file = "backrefs-5.8-py313-none-any.whl", hash = "sha256:e3a63b073867dbefd0536425f43db618578528e3896fb77be7141328642a1585"},
{file = "backrefs-5.8-py39-none-any.whl", hash = "sha256:a66851e4533fb5b371aa0628e1fee1af05135616b86140c9d787a2ffdf4b8fdc"},
{file = "backrefs-5.8.tar.gz", hash = "sha256:2cab642a205ce966af3dd4b38ee36009b31fa9502a35fd61d59ccc116e40a6bd"},
]
[package.extras]
extras = ["regex"]
[[package]]
name = "betterproto"
@@ -435,7 +454,7 @@ files = [
[package.extras]
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)"]
typing = ["typing-extensions (>=4.12.2) ; python_version < \"3.11\""]
[[package]]
name = "ghp-import"
@@ -457,14 +476,14 @@ dev = ["flake8", "markdown", "twine", "wheel"]
[[package]]
name = "griffe"
version = "1.5.6"
version = "1.6.0"
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.6-py3-none-any.whl", hash = "sha256:b2a3afe497c6c1f952e54a23095ecc09435016293e77af8478ed65df1022a394"},
{file = "griffe-1.5.6.tar.gz", hash = "sha256:181f6666d5aceb6cd6e2da5a2b646cfb431e47a0da1fda283845734b67e10944"},
{file = "griffe-1.6.0-py3-none-any.whl", hash = "sha256:9f1dfe035d4715a244ed2050dfbceb05b1f470809ed4f6bb10ece5a7302f8dd1"},
{file = "griffe-1.6.0.tar.gz", hash = "sha256:eb5758088b9c73ad61c7ac014f3cdfb4c57b5c2fcbfca69996584b702aefa354"},
]
[package.dependencies]
@@ -569,7 +588,7 @@ httpcore = "==1.*"
idna = "*"
[package.extras]
brotli = ["brotli", "brotlicffi"]
brotli = ["brotli ; platform_python_implementation == \"CPython\"", "brotlicffi ; platform_python_implementation != \"CPython\""]
cli = ["click (==8.*)", "pygments (==2.*)", "rich (>=10,<14)"]
http2 = ["h2 (>=3,<5)"]
socks = ["socksio (==1.*)"]
@@ -589,14 +608,14 @@ files = [
[[package]]
name = "identify"
version = "2.6.6"
version = "2.6.8"
description = "File identification library for Python"
optional = false
python-versions = ">=3.9"
groups = ["dev"]
files = [
{file = "identify-2.6.6-py2.py3-none-any.whl", hash = "sha256:cbd1810bce79f8b671ecb20f53ee0ae8e86ae84b557de31d89709dc2a48ba881"},
{file = "identify-2.6.6.tar.gz", hash = "sha256:7bec12768ed44ea4761efb47806f0a41f86e7c0a5fdf5950d4648c90eca7e251"},
{file = "identify-2.6.8-py2.py3-none-any.whl", hash = "sha256:83657f0f766a3c8d0eaea16d4ef42494b39b34629a4b3192a9d020d349b3e255"},
{file = "identify-2.6.8.tar.gz", hash = "sha256:61491417ea2c0c5c670484fd8abbb34de34cdae1e5f39a73ee65e48e4bb663fc"},
]
[package.extras]
@@ -634,12 +653,12 @@ files = [
zipp = ">=3.20"
[package.extras]
check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1)"]
check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1) ; sys_platform != \"cygwin\""]
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) ; python_version < \"3.9\"", "jaraco.test (>=5.4)", "packaging", "pyfakefs", "pytest (>=6,!=8.1.*)", "pytest-perf (>=0.9.2)"]
type = ["pytest-mypy"]
[[package]]
@@ -807,18 +826,18 @@ watchdog = ">=2.0"
[package.extras]
i18n = ["babel (>=2.9.0)"]
min-versions = ["babel (==2.9.0)", "click (==7.0)", "colorama (==0.4)", "ghp-import (==1.0)", "importlib-metadata (==4.4)", "jinja2 (==2.11.1)", "markdown (==3.3.6)", "markupsafe (==2.0.1)", "mergedeep (==1.3.4)", "mkdocs-get-deps (==0.2.0)", "packaging (==20.5)", "pathspec (==0.11.1)", "pyyaml (==5.1)", "pyyaml-env-tag (==0.1)", "watchdog (==2.0)"]
min-versions = ["babel (==2.9.0)", "click (==7.0)", "colorama (==0.4) ; platform_system == \"Windows\"", "ghp-import (==1.0)", "importlib-metadata (==4.4) ; python_version < \"3.10\"", "jinja2 (==2.11.1)", "markdown (==3.3.6)", "markupsafe (==2.0.1)", "mergedeep (==1.3.4)", "mkdocs-get-deps (==0.2.0)", "packaging (==20.5)", "pathspec (==0.11.1)", "pyyaml (==5.1)", "pyyaml-env-tag (==0.1)", "watchdog (==2.0)"]
[[package]]
name = "mkdocs-autorefs"
version = "1.3.0"
version = "1.4.0"
description = "Automatically link across pages in MkDocs."
optional = false
python-versions = ">=3.9"
groups = ["docs"]
files = [
{file = "mkdocs_autorefs-1.3.0-py3-none-any.whl", hash = "sha256:d180f9778a04e78b7134e31418f238bba56f56d6a8af97873946ff661befffb3"},
{file = "mkdocs_autorefs-1.3.0.tar.gz", hash = "sha256:6867764c099ace9025d6ac24fd07b85a98335fbd30107ef01053697c8f46db61"},
{file = "mkdocs_autorefs-1.4.0-py3-none-any.whl", hash = "sha256:bad19f69655878d20194acd0162e29a89c3f7e6365ffe54e72aa3fd1072f240d"},
{file = "mkdocs_autorefs-1.4.0.tar.gz", hash = "sha256:a9c0aa9c90edbce302c09d050a3c4cb7c76f8b7b2c98f84a7a05f53d00392156"},
]
[package.dependencies]
@@ -846,18 +865,19 @@ pyyaml = ">=5.1"
[[package]]
name = "mkdocs-material"
version = "9.6.2"
version = "9.6.7"
description = "Documentation that simply works"
optional = false
python-versions = ">=3.8"
groups = ["docs"]
files = [
{file = "mkdocs_material-9.6.2-py3-none-any.whl", hash = "sha256:71d90dbd63b393ad11a4d90151dfe3dcbfcd802c0f29ce80bebd9bbac6abc753"},
{file = "mkdocs_material-9.6.2.tar.gz", hash = "sha256:a3de1c5d4c745f10afa78b1a02f917b9dce0808fb206adc0f5bb48b58c1ca21f"},
{file = "mkdocs_material-9.6.7-py3-none-any.whl", hash = "sha256:8a159e45e80fcaadd9fbeef62cbf928569b93df954d4dc5ba76d46820caf7b47"},
{file = "mkdocs_material-9.6.7.tar.gz", hash = "sha256:3e2c1fceb9410056c2d91f334a00cdea3215c28750e00c691c1e46b2a33309b4"},
]
[package.dependencies]
babel = ">=2.10,<3.0"
backrefs = ">=5.7.post1,<6.0"
colorama = ">=0.4,<1.0"
jinja2 = ">=3.0,<4.0"
markdown = ">=3.2,<4.0"
@@ -866,7 +886,6 @@ mkdocs-material-extensions = ">=1.3,<2.0"
paginate = ">=0.5,<1.0"
pygments = ">=2.16,<3.0"
pymdown-extensions = ">=10.2,<11.0"
regex = ">=2022.4"
requests = ">=2.26,<3.0"
[package.extras]
@@ -1194,7 +1213,7 @@ typing-extensions = ">=4.12.2"
[package.extras]
email = ["email-validator (>=2.0.0)"]
timezone = ["tzdata"]
timezone = ["tzdata ; python_version >= \"3.9\" and platform_system == \"Windows\""]
[[package]]
name = "pydantic-core"
@@ -1436,110 +1455,6 @@ files = [
[package.dependencies]
pyyaml = "*"
[[package]]
name = "regex"
version = "2024.11.6"
description = "Alternative regular expression module, to replace re."
optional = false
python-versions = ">=3.8"
groups = ["docs"]
files = [
{file = "regex-2024.11.6-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:ff590880083d60acc0433f9c3f713c51f7ac6ebb9adf889c79a261ecf541aa91"},
{file = "regex-2024.11.6-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:658f90550f38270639e83ce492f27d2c8d2cd63805c65a13a14d36ca126753f0"},
{file = "regex-2024.11.6-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:164d8b7b3b4bcb2068b97428060b2a53be050085ef94eca7f240e7947f1b080e"},
{file = "regex-2024.11.6-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d3660c82f209655a06b587d55e723f0b813d3a7db2e32e5e7dc64ac2a9e86fde"},
{file = "regex-2024.11.6-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d22326fcdef5e08c154280b71163ced384b428343ae16a5ab2b3354aed12436e"},
{file = "regex-2024.11.6-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f1ac758ef6aebfc8943560194e9fd0fa18bcb34d89fd8bd2af18183afd8da3a2"},
{file = "regex-2024.11.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:997d6a487ff00807ba810e0f8332c18b4eb8d29463cfb7c820dc4b6e7562d0cf"},
{file = "regex-2024.11.6-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:02a02d2bb04fec86ad61f3ea7f49c015a0681bf76abb9857f945d26159d2968c"},
{file = "regex-2024.11.6-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f02f93b92358ee3f78660e43b4b0091229260c5d5c408d17d60bf26b6c900e86"},
{file = "regex-2024.11.6-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:06eb1be98df10e81ebaded73fcd51989dcf534e3c753466e4b60c4697a003b67"},
{file = "regex-2024.11.6-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:040df6fe1a5504eb0f04f048e6d09cd7c7110fef851d7c567a6b6e09942feb7d"},
{file = "regex-2024.11.6-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:fdabbfc59f2c6edba2a6622c647b716e34e8e3867e0ab975412c5c2f79b82da2"},
{file = "regex-2024.11.6-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:8447d2d39b5abe381419319f942de20b7ecd60ce86f16a23b0698f22e1b70008"},
{file = "regex-2024.11.6-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:da8f5fc57d1933de22a9e23eec290a0d8a5927a5370d24bda9a6abe50683fe62"},
{file = "regex-2024.11.6-cp310-cp310-win32.whl", hash = "sha256:b489578720afb782f6ccf2840920f3a32e31ba28a4b162e13900c3e6bd3f930e"},
{file = "regex-2024.11.6-cp310-cp310-win_amd64.whl", hash = "sha256:5071b2093e793357c9d8b2929dfc13ac5f0a6c650559503bb81189d0a3814519"},
{file = "regex-2024.11.6-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:5478c6962ad548b54a591778e93cd7c456a7a29f8eca9c49e4f9a806dcc5d638"},
{file = "regex-2024.11.6-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2c89a8cc122b25ce6945f0423dc1352cb9593c68abd19223eebbd4e56612c5b7"},
{file = "regex-2024.11.6-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:94d87b689cdd831934fa3ce16cc15cd65748e6d689f5d2b8f4f4df2065c9fa20"},
{file = "regex-2024.11.6-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1062b39a0a2b75a9c694f7a08e7183a80c63c0d62b301418ffd9c35f55aaa114"},
{file = "regex-2024.11.6-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:167ed4852351d8a750da48712c3930b031f6efdaa0f22fa1933716bfcd6bf4a3"},
{file = "regex-2024.11.6-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2d548dafee61f06ebdb584080621f3e0c23fff312f0de1afc776e2a2ba99a74f"},
{file = "regex-2024.11.6-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f2a19f302cd1ce5dd01a9099aaa19cae6173306d1302a43b627f62e21cf18ac0"},
{file = "regex-2024.11.6-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bec9931dfb61ddd8ef2ebc05646293812cb6b16b60cf7c9511a832b6f1854b55"},
{file = "regex-2024.11.6-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:9714398225f299aa85267fd222f7142fcb5c769e73d7733344efc46f2ef5cf89"},
{file = "regex-2024.11.6-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:202eb32e89f60fc147a41e55cb086db2a3f8cb82f9a9a88440dcfc5d37faae8d"},
{file = "regex-2024.11.6-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:4181b814e56078e9b00427ca358ec44333765f5ca1b45597ec7446d3a1ef6e34"},
{file = "regex-2024.11.6-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:068376da5a7e4da51968ce4c122a7cd31afaaec4fccc7856c92f63876e57b51d"},
{file = "regex-2024.11.6-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ac10f2c4184420d881a3475fb2c6f4d95d53a8d50209a2500723d831036f7c45"},
{file = "regex-2024.11.6-cp311-cp311-win32.whl", hash = "sha256:c36f9b6f5f8649bb251a5f3f66564438977b7ef8386a52460ae77e6070d309d9"},
{file = "regex-2024.11.6-cp311-cp311-win_amd64.whl", hash = "sha256:02e28184be537f0e75c1f9b2f8847dc51e08e6e171c6bde130b2687e0c33cf60"},
{file = "regex-2024.11.6-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:52fb28f528778f184f870b7cf8f225f5eef0a8f6e3778529bdd40c7b3920796a"},
{file = "regex-2024.11.6-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:fdd6028445d2460f33136c55eeb1f601ab06d74cb3347132e1c24250187500d9"},
{file = "regex-2024.11.6-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:805e6b60c54bf766b251e94526ebad60b7de0c70f70a4e6210ee2891acb70bf2"},
{file = "regex-2024.11.6-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b85c2530be953a890eaffde05485238f07029600e8f098cdf1848d414a8b45e4"},
{file = "regex-2024.11.6-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bb26437975da7dc36b7efad18aa9dd4ea569d2357ae6b783bf1118dabd9ea577"},
{file = "regex-2024.11.6-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:abfa5080c374a76a251ba60683242bc17eeb2c9818d0d30117b4486be10c59d3"},
{file = "regex-2024.11.6-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70b7fa6606c2881c1db9479b0eaa11ed5dfa11c8d60a474ff0e095099f39d98e"},
{file = "regex-2024.11.6-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0c32f75920cf99fe6b6c539c399a4a128452eaf1af27f39bce8909c9a3fd8cbe"},
{file = "regex-2024.11.6-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:982e6d21414e78e1f51cf595d7f321dcd14de1f2881c5dc6a6e23bbbbd68435e"},
{file = "regex-2024.11.6-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:a7c2155f790e2fb448faed6dd241386719802296ec588a8b9051c1f5c481bc29"},
{file = "regex-2024.11.6-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:149f5008d286636e48cd0b1dd65018548944e495b0265b45e1bffecce1ef7f39"},
{file = "regex-2024.11.6-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:e5364a4502efca094731680e80009632ad6624084aff9a23ce8c8c6820de3e51"},
{file = "regex-2024.11.6-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:0a86e7eeca091c09e021db8eb72d54751e527fa47b8d5787caf96d9831bd02ad"},
{file = "regex-2024.11.6-cp312-cp312-win32.whl", hash = "sha256:32f9a4c643baad4efa81d549c2aadefaeba12249b2adc5af541759237eee1c54"},
{file = "regex-2024.11.6-cp312-cp312-win_amd64.whl", hash = "sha256:a93c194e2df18f7d264092dc8539b8ffb86b45b899ab976aa15d48214138e81b"},
{file = "regex-2024.11.6-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:a6ba92c0bcdf96cbf43a12c717eae4bc98325ca3730f6b130ffa2e3c3c723d84"},
{file = "regex-2024.11.6-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:525eab0b789891ac3be914d36893bdf972d483fe66551f79d3e27146191a37d4"},
{file = "regex-2024.11.6-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:086a27a0b4ca227941700e0b31425e7a28ef1ae8e5e05a33826e17e47fbfdba0"},
{file = "regex-2024.11.6-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bde01f35767c4a7899b7eb6e823b125a64de314a8ee9791367c9a34d56af18d0"},
{file = "regex-2024.11.6-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b583904576650166b3d920d2bcce13971f6f9e9a396c673187f49811b2769dc7"},
{file = "regex-2024.11.6-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1c4de13f06a0d54fa0d5ab1b7138bfa0d883220965a29616e3ea61b35d5f5fc7"},
{file = "regex-2024.11.6-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3cde6e9f2580eb1665965ce9bf17ff4952f34f5b126beb509fee8f4e994f143c"},
{file = "regex-2024.11.6-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0d7f453dca13f40a02b79636a339c5b62b670141e63efd511d3f8f73fba162b3"},
{file = "regex-2024.11.6-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:59dfe1ed21aea057a65c6b586afd2a945de04fc7db3de0a6e3ed5397ad491b07"},
{file = "regex-2024.11.6-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:b97c1e0bd37c5cd7902e65f410779d39eeda155800b65fc4d04cc432efa9bc6e"},
{file = "regex-2024.11.6-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:f9d1e379028e0fc2ae3654bac3cbbef81bf3fd571272a42d56c24007979bafb6"},
{file = "regex-2024.11.6-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:13291b39131e2d002a7940fb176e120bec5145f3aeb7621be6534e46251912c4"},
{file = "regex-2024.11.6-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4f51f88c126370dcec4908576c5a627220da6c09d0bff31cfa89f2523843316d"},
{file = "regex-2024.11.6-cp313-cp313-win32.whl", hash = "sha256:63b13cfd72e9601125027202cad74995ab26921d8cd935c25f09c630436348ff"},
{file = "regex-2024.11.6-cp313-cp313-win_amd64.whl", hash = "sha256:2b3361af3198667e99927da8b84c1b010752fa4b1115ee30beaa332cabc3ef1a"},
{file = "regex-2024.11.6-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:3a51ccc315653ba012774efca4f23d1d2a8a8f278a6072e29c7147eee7da446b"},
{file = "regex-2024.11.6-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ad182d02e40de7459b73155deb8996bbd8e96852267879396fb274e8700190e3"},
{file = "regex-2024.11.6-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:ba9b72e5643641b7d41fa1f6d5abda2c9a263ae835b917348fc3c928182ad467"},
{file = "regex-2024.11.6-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40291b1b89ca6ad8d3f2b82782cc33807f1406cf68c8d440861da6304d8ffbbd"},
{file = "regex-2024.11.6-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cdf58d0e516ee426a48f7b2c03a332a4114420716d55769ff7108c37a09951bf"},
{file = "regex-2024.11.6-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a36fdf2af13c2b14738f6e973aba563623cb77d753bbbd8d414d18bfaa3105dd"},
{file = "regex-2024.11.6-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d1cee317bfc014c2419a76bcc87f071405e3966da434e03e13beb45f8aced1a6"},
{file = "regex-2024.11.6-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:50153825ee016b91549962f970d6a4442fa106832e14c918acd1c8e479916c4f"},
{file = "regex-2024.11.6-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:ea1bfda2f7162605f6e8178223576856b3d791109f15ea99a9f95c16a7636fb5"},
{file = "regex-2024.11.6-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:df951c5f4a1b1910f1a99ff42c473ff60f8225baa1cdd3539fe2819d9543e9df"},
{file = "regex-2024.11.6-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:072623554418a9911446278f16ecb398fb3b540147a7828c06e2011fa531e773"},
{file = "regex-2024.11.6-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:f654882311409afb1d780b940234208a252322c24a93b442ca714d119e68086c"},
{file = "regex-2024.11.6-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:89d75e7293d2b3e674db7d4d9b1bee7f8f3d1609428e293771d1a962617150cc"},
{file = "regex-2024.11.6-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:f65557897fc977a44ab205ea871b690adaef6b9da6afda4790a2484b04293a5f"},
{file = "regex-2024.11.6-cp38-cp38-win32.whl", hash = "sha256:6f44ec28b1f858c98d3036ad5d7d0bfc568bdd7a74f9c24e25f41ef1ebfd81a4"},
{file = "regex-2024.11.6-cp38-cp38-win_amd64.whl", hash = "sha256:bb8f74f2f10dbf13a0be8de623ba4f9491faf58c24064f32b65679b021ed0001"},
{file = "regex-2024.11.6-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:5704e174f8ccab2026bd2f1ab6c510345ae8eac818b613d7d73e785f1310f839"},
{file = "regex-2024.11.6-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:220902c3c5cc6af55d4fe19ead504de80eb91f786dc102fbd74894b1551f095e"},
{file = "regex-2024.11.6-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:5e7e351589da0850c125f1600a4c4ba3c722efefe16b297de54300f08d734fbf"},
{file = "regex-2024.11.6-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5056b185ca113c88e18223183aa1a50e66507769c9640a6ff75859619d73957b"},
{file = "regex-2024.11.6-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2e34b51b650b23ed3354b5a07aab37034d9f923db2a40519139af34f485f77d0"},
{file = "regex-2024.11.6-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5670bce7b200273eee1840ef307bfa07cda90b38ae56e9a6ebcc9f50da9c469b"},
{file = "regex-2024.11.6-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:08986dce1339bc932923e7d1232ce9881499a0e02925f7402fb7c982515419ef"},
{file = "regex-2024.11.6-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:93c0b12d3d3bc25af4ebbf38f9ee780a487e8bf6954c115b9f015822d3bb8e48"},
{file = "regex-2024.11.6-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:764e71f22ab3b305e7f4c21f1a97e1526a25ebdd22513e251cf376760213da13"},
{file = "regex-2024.11.6-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:f056bf21105c2515c32372bbc057f43eb02aae2fda61052e2f7622c801f0b4e2"},
{file = "regex-2024.11.6-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:69ab78f848845569401469da20df3e081e6b5a11cb086de3eed1d48f5ed57c95"},
{file = "regex-2024.11.6-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:86fddba590aad9208e2fa8b43b4c098bb0ec74f15718bb6a704e3c63e2cef3e9"},
{file = "regex-2024.11.6-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:684d7a212682996d21ca12ef3c17353c021fe9de6049e19ac8481ec35574a70f"},
{file = "regex-2024.11.6-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:a03e02f48cd1abbd9f3b7e3586d97c8f7a9721c436f51a5245b3b9483044480b"},
{file = "regex-2024.11.6-cp39-cp39-win32.whl", hash = "sha256:41758407fc32d5c3c5de163888068cfee69cb4c2be844e7ac517a52770f9af57"},
{file = "regex-2024.11.6-cp39-cp39-win_amd64.whl", hash = "sha256:b2837718570f95dd41675328e111345f9b7095d821bac435aac173ac80b19983"},
{file = "regex-2024.11.6.tar.gz", hash = "sha256:7ab159b063c52a0333c884e4679f8d7a85112ee3078fe3d9004b2dd875585519"},
]
[[package]]
name = "requests"
version = "2.32.3"
@@ -1667,21 +1582,21 @@ files = [
]
[package.extras]
brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"]
brotli = ["brotli (>=1.0.9) ; platform_python_implementation == \"CPython\"", "brotlicffi (>=0.8.0) ; platform_python_implementation != \"CPython\""]
h2 = ["h2 (>=4,<5)"]
socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"]
zstd = ["zstandard (>=0.18.0)"]
[[package]]
name = "virtualenv"
version = "20.29.1"
version = "20.29.2"
description = "Virtual Python Environment builder"
optional = false
python-versions = ">=3.8"
groups = ["dev"]
files = [
{file = "virtualenv-20.29.1-py3-none-any.whl", hash = "sha256:4e4cb403c0b0da39e13b46b1b2476e505cb0046b25f242bee80f62bf990b2779"},
{file = "virtualenv-20.29.1.tar.gz", hash = "sha256:b8b8970138d32fb606192cb97f6cd4bb644fa486be9308fb9b63f81091b5dc35"},
{file = "virtualenv-20.29.2-py3-none-any.whl", hash = "sha256:febddfc3d1ea571bdb1dc0f98d7b45d24def7428214d4fb73cc486c9568cce6a"},
{file = "virtualenv-20.29.2.tar.gz", hash = "sha256:fdaabebf6d03b5ba83ae0a02cfe96f48a716f4fae556461d180825866f75b728"},
]
[package.dependencies]
@@ -1691,7 +1606,7 @@ platformdirs = ">=3.9.1,<5"
[package.extras]
docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.2,!=7.3)", "sphinx-argparse (>=0.4)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=23.6)"]
test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=23.1)", "pytest (>=7.4)", "pytest-env (>=0.8.2)", "pytest-freezer (>=0.4.8)", "pytest-mock (>=3.11.1)", "pytest-randomly (>=3.12)", "pytest-timeout (>=2.1)", "setuptools (>=68)", "time-machine (>=2.10)"]
test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=23.1)", "pytest (>=7.4)", "pytest-env (>=0.8.2)", "pytest-freezer (>=0.4.8) ; platform_python_implementation == \"PyPy\" or platform_python_implementation == \"CPython\" and sys_platform == \"win32\" and python_version >= \"3.13\"", "pytest-mock (>=3.11.1)", "pytest-randomly (>=3.12)", "pytest-timeout (>=2.1)", "setuptools (>=68)", "time-machine (>=2.10) ; platform_python_implementation == \"CPython\""]
[[package]]
name = "watchdog"
@@ -1750,11 +1665,11 @@ files = [
]
[package.extras]
check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1)"]
check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1) ; sys_platform != \"cygwin\""]
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)"]
test = ["big-O", "importlib-resources", "jaraco.functools", "jaraco.itertools", "jaraco.test", "more-itertools", "pytest (>=6,!=8.1.*)", "pytest-ignore-flaky"]
test = ["big-O", "importlib-resources ; python_version < \"3.9\"", "jaraco.functools", "jaraco.itertools", "jaraco.test", "more-itertools", "pytest (>=6,!=8.1.*)", "pytest-ignore-flaky"]
type = ["pytest-mypy"]
[metadata]

View File

@@ -56,6 +56,16 @@ class MinerConfig(BaseModel):
**self.temperature.as_am_modern(),
}
def as_hiveon_modern(self, user_suffix: str | None = None) -> dict:
"""Generates the configuration in the format suitable for modern Hiveon."""
return {
**self.fan_mode.as_hiveon_modern(),
"freq-level": "100",
**self.mining_mode.as_hiveon_modern(),
**self.pools.as_hiveon_modern(user_suffix=user_suffix),
**self.temperature.as_hiveon_modern(),
}
def as_elphapex(self, user_suffix: str | None = None) -> dict:
"""Generates the configuration in the format suitable for modern Elphapex."""
return {
@@ -209,6 +219,15 @@ class MinerConfig(BaseModel):
fan_mode=FanModeConfig.from_am_modern(web_conf),
)
@classmethod
def from_hiveon_modern(cls, web_conf: dict) -> "MinerConfig":
"""Constructs a MinerConfig object from web configuration for Hiveon."""
return cls(
pools=PoolConfig.from_hiveon_modern(web_conf),
mining_mode=MiningModeConfig.from_hiveon_modern(web_conf),
fan_mode=FanModeConfig.from_hiveon_modern(web_conf),
)
@classmethod
def from_elphapex(cls, web_conf: dict) -> "MinerConfig":
"""Constructs a MinerConfig object from web configuration for modern Antminers."""
@@ -327,7 +346,3 @@ class MinerConfig(BaseModel):
@classmethod
def from_hammer(cls, *args, **kwargs) -> "MinerConfig":
return cls.from_am_modern(*args, **kwargs)
@classmethod
def from_hiveon_modern(cls, web_conf: dict) -> "MinerConfig":
return cls.from_am_modern(web_conf)

View File

@@ -28,6 +28,9 @@ class MinerConfigOption(Enum):
def as_am_modern(self) -> dict:
return self.value.as_am_modern()
def as_hiveon_modern(self) -> dict:
return self.value.as_hiveon_modern()
def as_am_old(self) -> dict:
return self.value.as_am_old()
@@ -95,6 +98,9 @@ class MinerConfigValue(BaseModel):
def as_am_modern(self) -> dict:
return {}
def as_hiveon_modern(self) -> dict:
return {}
def as_am_old(self) -> dict:
return {}

View File

@@ -55,6 +55,9 @@ class FanModeNormal(MinerConfigValue):
def as_am_modern(self) -> dict:
return {"bitmain-fan-ctrl": False, "bitmain-fan-pwn": "100"}
def as_hiveon_modern(self) -> dict:
return {"bitmain-fan-ctrl": False, "bitmain-fan-pwn": "100"}
def as_elphapex(self) -> dict:
return {"fc-fan-ctrl": False, "fc-fan-pwn": "100"}
@@ -138,6 +141,9 @@ class FanModeManual(MinerConfigValue):
def as_am_modern(self) -> dict:
return {"bitmain-fan-ctrl": True, "bitmain-fan-pwm": str(self.speed)}
def as_hiveon_modern(self) -> dict:
return {"bitmain-fan-ctrl": True, "bitmain-fan-pwm": str(self.speed)}
def as_elphapex(self) -> dict:
return {"fc-fan-ctrl": True, "fc-fan-pwm": str(self.speed)}
@@ -191,6 +197,9 @@ class FanModeImmersion(MinerConfigValue):
def as_am_modern(self) -> dict:
return {"bitmain-fan-ctrl": True, "bitmain-fan-pwm": "0"}
def as_hiveon_modern(self) -> dict:
return {"bitmain-fan-ctrl": True, "bitmain-fan-pwm": "0"}
def as_elphapex(self) -> dict:
return {"fc-fan-ctrl": True, "fc-fan-pwm": "0"}
@@ -248,6 +257,20 @@ class FanModeConfig(MinerConfigOption):
else:
return cls.default()
@classmethod
def from_hiveon_modern(cls, web_conf: dict):
if web_conf.get("bitmain-fan-ctrl") is not None:
fan_manual = web_conf["bitmain-fan-ctrl"]
if fan_manual:
speed = int(web_conf["bitmain-fan-pwm"])
if speed == 0:
return cls.immersion()
return cls.manual(speed=speed)
else:
return cls.normal()
else:
return cls.default()
@classmethod
def from_elphapex(cls, web_conf: dict):
if web_conf.get("fc-fan-ctrl") is not None:

View File

@@ -52,6 +52,11 @@ class MiningModeNormal(MinerConfigValue):
return {"miner-mode": "0"}
return {"miner-mode": 0}
def as_hiveon_modern(self) -> dict:
if settings.get("antminer_mining_mode_as_str", False):
return {"miner-mode": "0"}
return {"miner-mode": 0}
def as_elphapex(self) -> dict:
return {"miner-mode": 0}
@@ -90,6 +95,11 @@ class MiningModeSleep(MinerConfigValue):
return {"miner-mode": "1"}
return {"miner-mode": 1}
def as_hiveon_modern(self) -> dict:
if settings.get("antminer_mining_mode_as_str", False):
return {"miner-mode": "1"}
return {"miner-mode": 1}
def as_elphapex(self) -> dict:
return {"miner-mode": 1}
@@ -125,6 +135,11 @@ class MiningModeLPM(MinerConfigValue):
return {"miner-mode": "3"}
return {"miner-mode": 3}
def as_hiveon_modern(self) -> dict:
if settings.get("antminer_mining_mode_as_str", False):
return {"miner-mode": "3"}
return {"miner-mode": 3}
def as_elphapex(self) -> dict:
return {"miner-mode": 3}
@@ -150,6 +165,11 @@ class MiningModeHPM(MinerConfigValue):
return {"miner-mode": "0"}
return {"miner-mode": 0}
def as_hiveon_modern(self) -> dict:
if settings.get("antminer_mining_mode_as_str", False):
return {"miner-mode": "0"}
return {"miner-mode": 0}
def as_elphapex(self) -> dict:
return {"miner-mode": 0}
@@ -186,6 +206,11 @@ class MiningModePowerTune(MinerConfigValue):
return {"miner-mode": "0"}
return {"miner-mode": 0}
def as_hiveon_modern(self) -> dict:
if settings.get("antminer_mining_mode_as_str", False):
return {"miner-mode": "0"}
return {"miner-mode": 0}
def as_elphapex(self) -> dict:
return {"miner-mode": 0}
@@ -288,6 +313,11 @@ class MiningModeHashrateTune(MinerConfigValue):
return {"miner-mode": "0"}
return {"miner-mode": 0}
def as_hiveon_modern(self) -> dict:
if settings.get("antminer_mining_mode_as_str", False):
return {"miner-mode": "0"}
return {"miner-mode": 0}
def as_elphapex(self) -> dict:
return {"miner-mode": 0}
@@ -386,12 +416,10 @@ class MiningModePreset(MinerConfigValue):
)
@classmethod
def from_luxos(
cls, rpc_config: dict, rpc_profiles: list[dict]
) -> "MiningModePreset":
def from_luxos(cls, rpc_config: dict, rpc_profiles: dict) -> "MiningModePreset":
active_preset = cls.get_active_preset_from_luxos(rpc_config, rpc_profiles)
return cls(
active_preset=MiningPreset.from_luxos(active_preset),
active_preset=active_preset,
available_presets=[
MiningPreset.from_luxos(p) for p in rpc_profiles["PROFILES"]
],
@@ -399,14 +427,14 @@ class MiningModePreset(MinerConfigValue):
@classmethod
def get_active_preset_from_luxos(
cls, rpc_config: dict, rpc_profiles: list[dict]
) -> dict:
cls, rpc_config: dict, rpc_profiles: dict
) -> MiningPreset:
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
return MiningPreset.from_luxos(active_preset)
class ManualBoardSettings(MinerConfigValue):
@@ -422,6 +450,11 @@ class ManualBoardSettings(MinerConfigValue):
return {"miner-mode": "0"}
return {"miner-mode": 0}
def as_hiveon_modern(self) -> dict:
if settings.get("antminer_mining_mode_as_str", False):
return {"miner-mode": "0"}
return {"miner-mode": 0}
def as_elphapex(self) -> dict:
return {"miner-mode": 0}
@@ -549,6 +582,20 @@ class MiningModeConfig(MinerConfigOption):
return cls.low()
return cls.default()
@classmethod
def from_hiveon_modern(cls, web_conf: dict):
if web_conf.get("bitmain-work-mode") is not None:
work_mode = web_conf["bitmain-work-mode"]
if work_mode == "":
return cls.default()
if int(work_mode) == 0:
return cls.normal()
elif int(work_mode) == 1:
return cls.sleep()
elif int(work_mode) == 3:
return cls.low()
return cls.default()
@classmethod
def from_elphapex(cls, web_conf: dict):
if web_conf.get("fc-work-mode") is not None:

View File

@@ -43,6 +43,13 @@ class Pool(MinerConfigValue):
"pass": self.password,
}
def as_hiveon_modern(self, user_suffix: str | None = None) -> dict:
return {
"url": self.url,
"user": f"{self.user}{user_suffix or ''}",
"pass": self.password,
}
def as_elphapex(self, user_suffix: str | None = None) -> dict:
return {
"url": self.url,
@@ -153,6 +160,12 @@ class Pool(MinerConfigValue):
url=web_pool["url"], user=web_pool["user"], password=web_pool["pass"]
)
@classmethod
def from_hiveon_modern(cls, web_pool: dict) -> "Pool":
return cls(
url=web_pool["url"], user=web_pool["user"], password=web_pool["pass"]
)
@classmethod
def from_elphapex(cls, web_pool: dict) -> "Pool":
return cls(
@@ -248,6 +261,17 @@ class PoolGroup(MinerConfigValue):
idx += 1
return pools
def as_hiveon_modern(self, user_suffix: str | None = None) -> list:
pools = []
idx = 0
while idx < 3:
if len(self.pools) > idx:
pools.append(self.pools[idx].as_hiveon_modern(user_suffix=user_suffix))
else:
pools.append(Pool(url="", user="", password="").as_hiveon_modern())
idx += 1
return pools
def as_elphapex(self, user_suffix: str | None = None) -> list:
pools = []
idx = 0
@@ -375,6 +399,13 @@ class PoolGroup(MinerConfigValue):
pools.append(Pool.from_am_modern(pool))
return cls(pools=pools)
@classmethod
def from_hiveon_modern(cls, web_pool_list: list) -> "PoolGroup":
pools = []
for pool in web_pool_list:
pools.append(Pool.from_hiveon_modern(pool))
return cls(pools=pools)
@classmethod
def from_elphapex(cls, web_pool_list: list) -> "PoolGroup":
pools = []
@@ -467,6 +498,11 @@ class PoolConfig(MinerConfigValue):
return {"pools": self.groups[0].as_am_modern(user_suffix=user_suffix)}
return {"pools": PoolGroup().as_am_modern()}
def as_hiveon_modern(self, user_suffix: str | None = None) -> dict:
if len(self.groups) > 0:
return {"pools": self.groups[0].as_hiveon_modern(user_suffix=user_suffix)}
return {"pools": PoolGroup().as_hiveon_modern()}
def as_elphapex(self, user_suffix: str | None = None) -> dict:
if len(self.groups) > 0:
return {"pools": self.groups[0].as_elphapex(user_suffix=user_suffix)}
@@ -569,10 +605,22 @@ class PoolConfig(MinerConfigValue):
@classmethod
def from_am_modern(cls, web_conf: dict) -> "PoolConfig":
pool_data = web_conf["pools"]
try:
pool_data = web_conf["pools"]
except KeyError:
return cls(groups=[])
return cls(groups=[PoolGroup.from_am_modern(pool_data)])
@classmethod
def from_hiveon_modern(cls, web_conf: dict) -> "PoolConfig":
try:
pool_data = web_conf["pools"]
except KeyError:
return cls(groups=[])
return cls(groups=[PoolGroup.from_hiveon_modern(pool_data)])
@classmethod
def from_elphapex(cls, web_conf: dict) -> "PoolConfig":
pool_data = web_conf["pools"]

View File

@@ -16,7 +16,7 @@
import copy
import time
from datetime import datetime, timezone
from typing import Any, List, Union
from typing import Any
from pydantic import BaseModel, Field, computed_field
@@ -28,6 +28,7 @@ from pyasic.device.algorithm.hashrate import AlgoHashRateType
from .boards import HashBoard
from .device import DeviceInfo
from .error_codes import BraiinsOSError, InnosiliconError, WhatsminerError, X19Error
from .error_codes.base import BaseMinerError
from .fans import Fan
@@ -107,25 +108,18 @@ class MinerData(BaseModel):
raw_wattage_limit: int | None = Field(exclude=True, default=None, repr=False)
# fans
fans: List[Fan] = Field(default_factory=list)
fans: list[Fan] = Field(default_factory=list)
fan_psu: int | None = None
# boards
hashboards: List[HashBoard] = Field(default_factory=list)
hashboards: list[HashBoard] = Field(default_factory=list)
# config
config: MinerConfig | None = None
fault_light: bool | None = None
# errors
errors: List[
Union[
WhatsminerError,
BraiinsOSError,
X19Error,
InnosiliconError,
]
] = Field(default_factory=list)
errors: list[BaseMinerError] = Field(default_factory=list)
# mining state
is_mining: bool = True
@@ -135,8 +129,10 @@ class MinerData(BaseModel):
pools: list[PoolMetrics] = Field(default_factory=list)
@classmethod
def fields(cls):
return list(cls.model_fields.keys())
def fields(cls) -> set:
all_fields = set(cls.model_fields.keys())
all_fields.update(set(cls.model_computed_fields.keys()))
return all_fields
def get(self, __key: str, default: Any = None):
try:
@@ -307,25 +303,25 @@ class MinerData(BaseModel):
@computed_field # type: ignore[misc]
@property
def make(self) -> str:
def make(self) -> str | None:
if self.device_info.make is not None:
return str(self.device_info.make)
@computed_field # type: ignore[misc]
@property
def model(self) -> str:
def model(self) -> str | None:
if self.device_info.model is not None:
return str(self.device_info.model)
@computed_field # type: ignore[misc]
@property
def firmware(self) -> str:
def firmware(self) -> str | None:
if self.device_info.firmware is not None:
return str(self.device_info.firmware)
@computed_field # type: ignore[misc]
@property
def algo(self) -> str:
def algo(self) -> str | None:
if self.device_info.algo is not None:
return str(self.device_info.algo)
@@ -365,7 +361,9 @@ class MinerData(BaseModel):
data_list = [str(data[item]) for item in data]
return ",".join(data_list)
def as_influxdb(self, measurement_name: str = "miner_data") -> str:
def as_influxdb(
self, measurement_name: str = "miner_data", level_delimiter: str = "."
) -> str:
"""Get this dataclass as [influxdb line protocol](https://docs.influxdata.com/influxdb/v2.4/reference/syntax/line-protocol/).
Parameters:
@@ -374,54 +372,127 @@ class MinerData(BaseModel):
Returns:
A influxdb line protocol version of this class.
"""
tag_data = [measurement_name]
def serialize_int(key: str, value: int) -> str:
return f"{key}={value}"
def serialize_float(key: str, value: float) -> str:
return f"{key}={value}"
def serialize_str(key: str, value: str) -> str:
return f'{key}="{value}"'
def serialize_algo_hash_rate(key: str, value: AlgoHashRateType) -> str:
return f"{key}={round(float(value), 2)}"
def serialize_list(key: str, value: list[Any]) -> str | None:
if len(value) == 0:
return None
list_field_data = []
for idx, list_field_val in enumerate(value):
item_serialization_func = serialization_map.get(
type(list_field_val), lambda _k, _v: None
)
item_serialized = item_serialization_func(
f"{key}{level_delimiter}{idx}", list_field_val
)
if item_serialized is not None:
list_field_data.append(item_serialized)
continue
for dt in serialization_map_instance:
if item_serialized is None:
if isinstance(list_field_val, dt):
item_serialized = serialization_map_instance[dt](
f"{key}{level_delimiter}{idx}", list_field_val
)
if item_serialized is not None:
list_field_data.append(item_serialized)
return ",".join(list_field_data)
def serialize_miner_error(key: str, value: BaseMinerError):
return value.as_influxdb(key, level_delimiter=level_delimiter)
def serialize_fan(key: str, value: Fan) -> str:
return f"{key}{level_delimiter}speed={value.speed}"
def serialize_hashboard(key: str, value: HashBoard) -> str:
return value.as_influxdb(key, level_delimiter=level_delimiter)
def serialize_bool(key: str, value: bool):
return f"{key}={str(value).lower()}"
def serialize_pool_metrics(key: str, value: PoolMetrics):
return value.as_influxdb(key, level_delimiter=level_delimiter)
include = [
"uptime",
"expected_hashrate",
"hashrate",
"hashboards",
"temperature_avg",
"env_temp",
"wattage",
"wattage_limit",
"voltage",
"fans",
"expected_fans",
"fan_psu",
"total_chips",
"expected_chips",
"efficiency",
"fault_light",
"is_mining",
"errors",
"pools",
]
serialization_map_instance = {
AlgoHashRateType: serialize_algo_hash_rate,
BaseMinerError: serialize_miner_error,
}
serialization_map = {
int: serialize_int,
float: serialize_float,
str: serialize_str,
bool: serialize_bool,
list: serialize_list,
Fan: serialize_fan,
HashBoard: serialize_hashboard,
PoolMetrics: serialize_pool_metrics,
}
tag_data = [
measurement_name,
f"ip={str(self.ip)}",
f"mac={str(self.mac)}",
f"make={str(self.make)}",
f"model={str(self.model)}",
f"firmware={str(self.firmware)}",
f"algo={str(self.algo)}",
]
field_data = []
tags = ["ip", "mac", "model", "hostname"]
for attribute in self.fields():
if attribute in tags:
escaped_data = self.get(attribute, "Unknown").replace(" ", "\\ ")
tag_data.append(f"{attribute}={escaped_data}")
for field in include:
field_val = getattr(self, field)
serialization_func = serialization_map.get(
type(field_val), lambda _k, _v: None
)
serialized = serialization_func(field, field_val)
if serialized is not None:
field_data.append(serialized)
continue
elif str(attribute).startswith("_"):
continue
elif isinstance(self[attribute], str):
field_data.append(f'{attribute}="{self[attribute]}"')
continue
elif isinstance(self[attribute], bool):
field_data.append(f"{attribute}={str(self[attribute]).lower()}")
continue
elif isinstance(self[attribute], int):
field_data.append(f"{attribute}={self[attribute]}")
continue
elif isinstance(self[attribute], float):
field_data.append(f"{attribute}={self[attribute]}")
continue
elif attribute == "errors":
for idx, item in enumerate(self[attribute]):
field_data.append(f'error_{idx+1}="{item.error_message}"')
elif attribute == "hashboards":
for idx, item in enumerate(self[attribute]):
field_data.append(
f"hashboard_{idx+1}_hashrate={item.get('hashrate', 0.0)}"
)
field_data.append(
f"hashboard_{idx+1}_temperature={item.get('temp', 0)}"
)
field_data.append(
f"hashboard_{idx+1}_chip_temperature={item.get('chip_temp', 0)}"
)
field_data.append(f"hashboard_{idx+1}_chips={item.get('chips', 0)}")
field_data.append(
f"hashboard_{idx+1}_expected_chips={item.get('expected_chips', 0)}"
)
elif attribute == "fans":
for idx, item in enumerate(self[attribute]):
if item.speed is not None:
field_data.append(f"fan_{idx+1}={item.speed}")
for datatype in serialization_map_instance:
if serialized is None:
if isinstance(field_val, datatype):
serialized = serialization_map_instance[datatype](
field, field_val
)
if serialized is not None:
field_data.append(serialized)
tags_str = ",".join(tag_data)
field_str = ",".join(field_data)
timestamp = str(self.timestamp * 1e9)
tags_str = ",".join(tag_data).replace(" ", "\\ ")
field_str = ",".join(field_data).replace(" ", "\\ ")
timestamp = str(self.timestamp * 10**9)
return " ".join([tags_str, field_str, timestamp])

View File

@@ -51,6 +51,12 @@ class HashBoard(BaseModel):
active: bool | None = None
voltage: float | None = None
@classmethod
def fields(cls) -> set:
all_fields = set(cls.model_fields.keys())
all_fields.update(set(cls.model_computed_fields.keys()))
return all_fields
def get(self, __key: str, default: Any = None):
try:
val = self.__getitem__(__key)
@@ -65,3 +71,63 @@ class HashBoard(BaseModel):
return getattr(self, item)
except AttributeError:
raise KeyError(f"{item}")
def as_influxdb(self, key_root: str, level_delimiter: str = ".") -> str:
def serialize_int(key: str, value: int) -> str:
return f"{key}={value}"
def serialize_float(key: str, value: float) -> str:
return f"{key}={value}"
def serialize_str(key: str, value: str) -> str:
return f'{key}="{value}"'
def serialize_algo_hash_rate(key: str, value: AlgoHashRateType) -> str:
return f"{key}={round(float(value), 2)}"
def serialize_bool(key: str, value: bool):
return f"{key}={str(value).lower()}"
serialization_map_instance = {
AlgoHashRateType: serialize_algo_hash_rate,
}
serialization_map = {
int: serialize_int,
float: serialize_float,
str: serialize_str,
bool: serialize_bool,
}
include = [
"hashrate",
"temp",
"chip_temp",
"chips",
"expected_chips",
"tuned",
"active",
"voltage",
]
field_data = []
for field in include:
field_val = getattr(self, field)
serialization_func = serialization_map.get(
type(field_val), lambda _k, _v: None
)
serialized = serialization_func(
f"{key_root}{level_delimiter}{field}", field_val
)
if serialized is not None:
field_data.append(serialized)
continue
for datatype in serialization_map_instance:
if serialized is None:
if isinstance(field_val, datatype):
serialized = serialization_map_instance[datatype](
f"{key_root}{level_delimiter}{field}", field_val
)
if serialized is not None:
field_data.append(serialized)
return ",".join(field_data)

View File

@@ -16,3 +16,17 @@ class BaseMinerError(BaseModel):
A dictionary version of this class.
"""
return self.asdict()
def as_influxdb(self, root_key: str, level_delimiter: str = ".") -> str:
field_data = []
if self.error_code is not None:
field_data.append(
f"{root_key}{level_delimiter}error_code={self.error_code}"
)
if self.error_message is not None:
field_data.append(
f'{root_key}{level_delimiter}error_message="{self.error_message}"'
)
return ",".join(field_data)

View File

@@ -92,3 +92,51 @@ class PoolMetrics(BaseModel):
if total == 0:
return 0
return (value / total) * 100
def as_influxdb(self, key_root: str, level_delimiter: str = ".") -> str:
def serialize_int(key: str, value: int) -> str:
return f"{key}={value}"
def serialize_float(key: str, value: float) -> str:
return f"{key}={value}"
def serialize_str(key: str, value: str) -> str:
return f'{key}="{value}"'
def serialize_pool_url(key: str, value: str) -> str:
return f'{key}="{str(value)}"'
def serialize_bool(key: str, value: bool):
return f"{key}={str(value).lower()}"
serialization_map = {
int: serialize_int,
float: serialize_float,
str: serialize_str,
bool: serialize_bool,
PoolUrl: serialize_pool_url,
}
include = [
"url",
"accepted",
"rejected",
"active",
"alive",
"user",
]
field_data = []
for field in include:
field_val = getattr(self, field)
serialization_func = serialization_map.get(
type(field_val), lambda _k, _v: None
)
serialized = serialization_func(
f"{key_root}{level_delimiter}{field}", field_val
)
if serialized is not None:
field_data.append(serialized)
return ",".join(field_data)

View File

@@ -100,5 +100,5 @@ class HiveonS19ProPlusHydro(HiveonModern, S19ProPlusHydro):
pass
class HiveonS19KPro(HiveonModern, S19KPro):
class HiveonS19kPro(HiveonModern, S19KPro):
pass

View File

@@ -23,7 +23,7 @@ from .S19 import (
HiveonS19j,
HiveonS19jNoPIC,
HiveonS19jPro,
HiveonS19KPro,
HiveonS19kPro,
HiveonS19L,
HiveonS19NoPIC,
HiveonS19Plus,

View File

@@ -104,6 +104,23 @@ class AvalonMiner(CGMiner):
return True
return False
async def set_power_limit(self, wattage: int) -> bool:
try:
if wattage < 3:
limit = wattage
elif wattage > 100:
limit = 2
elif wattage > 80:
limit = 1
else:
limit = 0
data = await self.rpc.ascset(0, "worklevel,set", 1)
except APIError:
return False
if data["STATUS"][0]["Msg"] == "ASC 0 set OK":
return True
return False
async def reboot(self) -> bool:
try:
data = await self.rpc.restart()

View File

@@ -152,7 +152,7 @@ class LUXMiner(LuxOSFirmware):
rpc_profiles=data.get("profiles", [{}])[0],
)
async def upgrade_firmware(self) -> bool:
async def upgrade_firmware(self, *args, **kwargs) -> bool:
"""
Upgrade the firmware on a LuxOS miner by calling the 'updaterun' API command.
Returns:

View File

@@ -600,6 +600,7 @@ MINER_CLASSES = {
"ANTMINER T9": HiveonT9,
"ANTMINER S19JPRO": HiveonS19jPro,
"ANTMINER S19": HiveonS19,
"ANTMINER S19K PRO": HiveonS19kPro,
"ANTMINER S19X88": HiveonS19NoPIC,
},
MinerTypes.MSKMINER: {

View File

@@ -64,7 +64,7 @@ class AvalonMinerWebAPI(BaseWebAPI):
resp = await client.get(url)
raw_data = resp.text.replace("minerinfoCallback(", "").replace(");", "")
return json.loads(raw_data)
except httpx.HTTPError:
except (httpx.HTTPError, json.JSONDecodeError):
pass
return {}

View File

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