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

View File

@@ -703,6 +703,19 @@
show_root_heading: false show_root_heading: false
heading_level: 0 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) ## S19 No PIC (Hive)
- [ ] Shutdowns - [ ] Shutdowns

View File

@@ -769,6 +769,7 @@ details {
<ul> <ul>
<li><a href="../antminer/X19#s19j-pro-hive">S19j Pro (Hive)</a></li> <li><a href="../antminer/X19#s19j-pro-hive">S19j Pro (Hive)</a></li>
<li><a href="../antminer/X19#s19-hive">S19 (Hive)</a></li> <li><a href="../antminer/X19#s19-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> <li><a href="../antminer/X19#s19-no-pic-hive">S19 No PIC (Hive)</a></li>
</ul> </ul>
</details> </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]] [[package]]
name = "aiofiles" name = "aiofiles"
@@ -44,19 +44,19 @@ typing_extensions = {version = ">=4.5", markers = "python_version < \"3.13\""}
[package.extras] [package.extras]
doc = ["Sphinx (>=7.4,<8.0)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx_rtd_theme"] doc = ["Sphinx (>=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)"] trio = ["trio (>=0.26.1)"]
[[package]] [[package]]
name = "asyncssh" name = "asyncssh"
version = "2.19.0" version = "2.20.0"
description = "AsyncSSH: Asynchronous SSHv2 client and server library" description = "AsyncSSH: Asynchronous SSHv2 client and server library"
optional = false optional = false
python-versions = ">=3.6" python-versions = ">=3.6"
groups = ["main"] groups = ["main"]
files = [ files = [
{file = "asyncssh-2.19.0-py3-none-any.whl", hash = "sha256:bb82ac30ff0cb4393fbaf1114e606ad7a4f13d6c4bdaed423c033ee26b455228"}, {file = "asyncssh-2.20.0-py3-none-any.whl", hash = "sha256:af6888d937c07a4bf31293335a6166b4d87608cdb5957b49547da6ad87ecf174"},
{file = "asyncssh-2.19.0.tar.gz", hash = "sha256:723dead4d068b558708dc66a4ca7e7a93a813aa9416036eccb9af4c03ae2cf30"}, {file = "asyncssh-2.20.0.tar.gz", hash = "sha256:020b6e384b2328ef8683908ad8e73de9ec2b9b62fd964571ea957bba98412983"},
] ]
[package.dependencies] [package.dependencies]
@@ -85,7 +85,26 @@ files = [
] ]
[package.extras] [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]] [[package]]
name = "betterproto" name = "betterproto"
@@ -435,7 +454,7 @@ files = [
[package.extras] [package.extras]
docs = ["furo (>=2024.8.6)", "sphinx (>=8.1.3)", "sphinx-autodoc-typehints (>=3)"] 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)"] 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]] [[package]]
name = "ghp-import" name = "ghp-import"
@@ -457,14 +476,14 @@ dev = ["flake8", "markdown", "twine", "wheel"]
[[package]] [[package]]
name = "griffe" 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." 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.6-py3-none-any.whl", hash = "sha256:b2a3afe497c6c1f952e54a23095ecc09435016293e77af8478ed65df1022a394"}, {file = "griffe-1.6.0-py3-none-any.whl", hash = "sha256:9f1dfe035d4715a244ed2050dfbceb05b1f470809ed4f6bb10ece5a7302f8dd1"},
{file = "griffe-1.5.6.tar.gz", hash = "sha256:181f6666d5aceb6cd6e2da5a2b646cfb431e47a0da1fda283845734b67e10944"}, {file = "griffe-1.6.0.tar.gz", hash = "sha256:eb5758088b9c73ad61c7ac014f3cdfb4c57b5c2fcbfca69996584b702aefa354"},
] ]
[package.dependencies] [package.dependencies]
@@ -569,7 +588,7 @@ httpcore = "==1.*"
idna = "*" idna = "*"
[package.extras] [package.extras]
brotli = ["brotli", "brotlicffi"] brotli = ["brotli ; platform_python_implementation == \"CPython\"", "brotlicffi ; platform_python_implementation != \"CPython\""]
cli = ["click (==8.*)", "pygments (==2.*)", "rich (>=10,<14)"] cli = ["click (==8.*)", "pygments (==2.*)", "rich (>=10,<14)"]
http2 = ["h2 (>=3,<5)"] http2 = ["h2 (>=3,<5)"]
socks = ["socksio (==1.*)"] socks = ["socksio (==1.*)"]
@@ -589,14 +608,14 @@ files = [
[[package]] [[package]]
name = "identify" name = "identify"
version = "2.6.6" version = "2.6.8"
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.6-py2.py3-none-any.whl", hash = "sha256:cbd1810bce79f8b671ecb20f53ee0ae8e86ae84b557de31d89709dc2a48ba881"}, {file = "identify-2.6.8-py2.py3-none-any.whl", hash = "sha256:83657f0f766a3c8d0eaea16d4ef42494b39b34629a4b3192a9d020d349b3e255"},
{file = "identify-2.6.6.tar.gz", hash = "sha256:7bec12768ed44ea4761efb47806f0a41f86e7c0a5fdf5950d4648c90eca7e251"}, {file = "identify-2.6.8.tar.gz", hash = "sha256:61491417ea2c0c5c670484fd8abbb34de34cdae1e5f39a73ee65e48e4bb663fc"},
] ]
[package.extras] [package.extras]
@@ -634,12 +653,12 @@ files = [
zipp = ">=3.20" zipp = ">=3.20"
[package.extras] [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"] 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) ; python_version < \"3.9\"", "jaraco.test (>=5.4)", "packaging", "pyfakefs", "pytest (>=6,!=8.1.*)", "pytest-perf (>=0.9.2)"]
type = ["pytest-mypy"] type = ["pytest-mypy"]
[[package]] [[package]]
@@ -807,18 +826,18 @@ watchdog = ">=2.0"
[package.extras] [package.extras]
i18n = ["babel (>=2.9.0)"] 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]] [[package]]
name = "mkdocs-autorefs" name = "mkdocs-autorefs"
version = "1.3.0" version = "1.4.0"
description = "Automatically link across pages in MkDocs." description = "Automatically link across pages in MkDocs."
optional = false optional = false
python-versions = ">=3.9" python-versions = ">=3.9"
groups = ["docs"] groups = ["docs"]
files = [ files = [
{file = "mkdocs_autorefs-1.3.0-py3-none-any.whl", hash = "sha256:d180f9778a04e78b7134e31418f238bba56f56d6a8af97873946ff661befffb3"}, {file = "mkdocs_autorefs-1.4.0-py3-none-any.whl", hash = "sha256:bad19f69655878d20194acd0162e29a89c3f7e6365ffe54e72aa3fd1072f240d"},
{file = "mkdocs_autorefs-1.3.0.tar.gz", hash = "sha256:6867764c099ace9025d6ac24fd07b85a98335fbd30107ef01053697c8f46db61"}, {file = "mkdocs_autorefs-1.4.0.tar.gz", hash = "sha256:a9c0aa9c90edbce302c09d050a3c4cb7c76f8b7b2c98f84a7a05f53d00392156"},
] ]
[package.dependencies] [package.dependencies]
@@ -846,18 +865,19 @@ pyyaml = ">=5.1"
[[package]] [[package]]
name = "mkdocs-material" name = "mkdocs-material"
version = "9.6.2" version = "9.6.7"
description = "Documentation that simply works" description = "Documentation that simply works"
optional = false optional = false
python-versions = ">=3.8" python-versions = ">=3.8"
groups = ["docs"] groups = ["docs"]
files = [ files = [
{file = "mkdocs_material-9.6.2-py3-none-any.whl", hash = "sha256:71d90dbd63b393ad11a4d90151dfe3dcbfcd802c0f29ce80bebd9bbac6abc753"}, {file = "mkdocs_material-9.6.7-py3-none-any.whl", hash = "sha256:8a159e45e80fcaadd9fbeef62cbf928569b93df954d4dc5ba76d46820caf7b47"},
{file = "mkdocs_material-9.6.2.tar.gz", hash = "sha256:a3de1c5d4c745f10afa78b1a02f917b9dce0808fb206adc0f5bb48b58c1ca21f"}, {file = "mkdocs_material-9.6.7.tar.gz", hash = "sha256:3e2c1fceb9410056c2d91f334a00cdea3215c28750e00c691c1e46b2a33309b4"},
] ]
[package.dependencies] [package.dependencies]
babel = ">=2.10,<3.0" babel = ">=2.10,<3.0"
backrefs = ">=5.7.post1,<6.0"
colorama = ">=0.4,<1.0" colorama = ">=0.4,<1.0"
jinja2 = ">=3.0,<4.0" jinja2 = ">=3.0,<4.0"
markdown = ">=3.2,<4.0" markdown = ">=3.2,<4.0"
@@ -866,7 +886,6 @@ mkdocs-material-extensions = ">=1.3,<2.0"
paginate = ">=0.5,<1.0" paginate = ">=0.5,<1.0"
pygments = ">=2.16,<3.0" pygments = ">=2.16,<3.0"
pymdown-extensions = ">=10.2,<11.0" pymdown-extensions = ">=10.2,<11.0"
regex = ">=2022.4"
requests = ">=2.26,<3.0" requests = ">=2.26,<3.0"
[package.extras] [package.extras]
@@ -1194,7 +1213,7 @@ typing-extensions = ">=4.12.2"
[package.extras] [package.extras]
email = ["email-validator (>=2.0.0)"] email = ["email-validator (>=2.0.0)"]
timezone = ["tzdata"] timezone = ["tzdata ; python_version >= \"3.9\" and platform_system == \"Windows\""]
[[package]] [[package]]
name = "pydantic-core" name = "pydantic-core"
@@ -1436,110 +1455,6 @@ files = [
[package.dependencies] [package.dependencies]
pyyaml = "*" 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]] [[package]]
name = "requests" name = "requests"
version = "2.32.3" version = "2.32.3"
@@ -1667,21 +1582,21 @@ files = [
] ]
[package.extras] [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)"] h2 = ["h2 (>=4,<5)"]
socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"]
zstd = ["zstandard (>=0.18.0)"] zstd = ["zstandard (>=0.18.0)"]
[[package]] [[package]]
name = "virtualenv" name = "virtualenv"
version = "20.29.1" version = "20.29.2"
description = "Virtual Python Environment builder" description = "Virtual Python Environment builder"
optional = false optional = false
python-versions = ">=3.8" python-versions = ">=3.8"
groups = ["dev"] groups = ["dev"]
files = [ files = [
{file = "virtualenv-20.29.1-py3-none-any.whl", hash = "sha256:4e4cb403c0b0da39e13b46b1b2476e505cb0046b25f242bee80f62bf990b2779"}, {file = "virtualenv-20.29.2-py3-none-any.whl", hash = "sha256:febddfc3d1ea571bdb1dc0f98d7b45d24def7428214d4fb73cc486c9568cce6a"},
{file = "virtualenv-20.29.1.tar.gz", hash = "sha256:b8b8970138d32fb606192cb97f6cd4bb644fa486be9308fb9b63f81091b5dc35"}, {file = "virtualenv-20.29.2.tar.gz", hash = "sha256:fdaabebf6d03b5ba83ae0a02cfe96f48a716f4fae556461d180825866f75b728"},
] ]
[package.dependencies] [package.dependencies]
@@ -1691,7 +1606,7 @@ platformdirs = ">=3.9.1,<5"
[package.extras] [package.extras]
docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.2,!=7.3)", "sphinx-argparse (>=0.4)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=23.6)"] docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.2,!=7.3)", "sphinx-argparse (>=0.4)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=23.6)"]
test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=23.1)", "pytest (>=7.4)", "pytest-env (>=0.8.2)", "pytest-freezer (>=0.4.8)", "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]] [[package]]
name = "watchdog" name = "watchdog"
@@ -1750,11 +1665,11 @@ files = [
] ]
[package.extras] [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"] 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)"]
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"] type = ["pytest-mypy"]
[metadata] [metadata]

View File

@@ -56,6 +56,16 @@ class MinerConfig(BaseModel):
**self.temperature.as_am_modern(), **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: def as_elphapex(self, user_suffix: str | None = None) -> dict:
"""Generates the configuration in the format suitable for modern Elphapex.""" """Generates the configuration in the format suitable for modern Elphapex."""
return { return {
@@ -209,6 +219,15 @@ class MinerConfig(BaseModel):
fan_mode=FanModeConfig.from_am_modern(web_conf), 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 @classmethod
def from_elphapex(cls, web_conf: dict) -> "MinerConfig": def from_elphapex(cls, web_conf: dict) -> "MinerConfig":
"""Constructs a MinerConfig object from web configuration for modern Antminers.""" """Constructs a MinerConfig object from web configuration for modern Antminers."""
@@ -327,7 +346,3 @@ class MinerConfig(BaseModel):
@classmethod @classmethod
def from_hammer(cls, *args, **kwargs) -> "MinerConfig": def from_hammer(cls, *args, **kwargs) -> "MinerConfig":
return cls.from_am_modern(*args, **kwargs) return cls.from_am_modern(*args, **kwargs)
@classmethod
def from_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: def as_am_modern(self) -> dict:
return self.value.as_am_modern() return self.value.as_am_modern()
def as_hiveon_modern(self) -> dict:
return self.value.as_hiveon_modern()
def as_am_old(self) -> dict: def as_am_old(self) -> dict:
return self.value.as_am_old() return self.value.as_am_old()
@@ -95,6 +98,9 @@ class MinerConfigValue(BaseModel):
def as_am_modern(self) -> dict: def as_am_modern(self) -> dict:
return {} return {}
def as_hiveon_modern(self) -> dict:
return {}
def as_am_old(self) -> dict: def as_am_old(self) -> dict:
return {} return {}

View File

@@ -55,6 +55,9 @@ class FanModeNormal(MinerConfigValue):
def as_am_modern(self) -> dict: def as_am_modern(self) -> dict:
return {"bitmain-fan-ctrl": False, "bitmain-fan-pwn": "100"} 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: def as_elphapex(self) -> dict:
return {"fc-fan-ctrl": False, "fc-fan-pwn": "100"} return {"fc-fan-ctrl": False, "fc-fan-pwn": "100"}
@@ -138,6 +141,9 @@ class FanModeManual(MinerConfigValue):
def as_am_modern(self) -> dict: def as_am_modern(self) -> dict:
return {"bitmain-fan-ctrl": True, "bitmain-fan-pwm": str(self.speed)} 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: def as_elphapex(self) -> dict:
return {"fc-fan-ctrl": True, "fc-fan-pwm": str(self.speed)} return {"fc-fan-ctrl": True, "fc-fan-pwm": str(self.speed)}
@@ -191,6 +197,9 @@ class FanModeImmersion(MinerConfigValue):
def as_am_modern(self) -> dict: def as_am_modern(self) -> dict:
return {"bitmain-fan-ctrl": True, "bitmain-fan-pwm": "0"} 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: def as_elphapex(self) -> dict:
return {"fc-fan-ctrl": True, "fc-fan-pwm": "0"} return {"fc-fan-ctrl": True, "fc-fan-pwm": "0"}
@@ -248,6 +257,20 @@ class FanModeConfig(MinerConfigOption):
else: else:
return cls.default() 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 @classmethod
def from_elphapex(cls, web_conf: dict): def from_elphapex(cls, web_conf: dict):
if web_conf.get("fc-fan-ctrl") is not None: 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"}
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: def as_elphapex(self) -> dict:
return {"miner-mode": 0} return {"miner-mode": 0}
@@ -90,6 +95,11 @@ class MiningModeSleep(MinerConfigValue):
return {"miner-mode": "1"} return {"miner-mode": "1"}
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: def as_elphapex(self) -> dict:
return {"miner-mode": 1} return {"miner-mode": 1}
@@ -125,6 +135,11 @@ class MiningModeLPM(MinerConfigValue):
return {"miner-mode": "3"} return {"miner-mode": "3"}
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: def as_elphapex(self) -> dict:
return {"miner-mode": 3} return {"miner-mode": 3}
@@ -150,6 +165,11 @@ class MiningModeHPM(MinerConfigValue):
return {"miner-mode": "0"} return {"miner-mode": "0"}
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: def as_elphapex(self) -> dict:
return {"miner-mode": 0} return {"miner-mode": 0}
@@ -186,6 +206,11 @@ class MiningModePowerTune(MinerConfigValue):
return {"miner-mode": "0"} return {"miner-mode": "0"}
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: def as_elphapex(self) -> dict:
return {"miner-mode": 0} return {"miner-mode": 0}
@@ -288,6 +313,11 @@ class MiningModeHashrateTune(MinerConfigValue):
return {"miner-mode": "0"} return {"miner-mode": "0"}
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: def as_elphapex(self) -> dict:
return {"miner-mode": 0} return {"miner-mode": 0}
@@ -386,12 +416,10 @@ class MiningModePreset(MinerConfigValue):
) )
@classmethod @classmethod
def from_luxos( def from_luxos(cls, rpc_config: dict, rpc_profiles: dict) -> "MiningModePreset":
cls, rpc_config: dict, rpc_profiles: list[dict]
) -> "MiningModePreset":
active_preset = cls.get_active_preset_from_luxos(rpc_config, rpc_profiles) active_preset = cls.get_active_preset_from_luxos(rpc_config, rpc_profiles)
return cls( return cls(
active_preset=MiningPreset.from_luxos(active_preset), active_preset=active_preset,
available_presets=[ available_presets=[
MiningPreset.from_luxos(p) for p in rpc_profiles["PROFILES"] MiningPreset.from_luxos(p) for p in rpc_profiles["PROFILES"]
], ],
@@ -399,14 +427,14 @@ class MiningModePreset(MinerConfigValue):
@classmethod @classmethod
def get_active_preset_from_luxos( def get_active_preset_from_luxos(
cls, rpc_config: dict, rpc_profiles: list[dict] cls, rpc_config: dict, rpc_profiles: dict
) -> dict: ) -> MiningPreset:
active_preset = None active_preset = None
active_profile = rpc_config["CONFIG"][0]["Profile"] active_profile = rpc_config["CONFIG"][0]["Profile"]
for profile in rpc_profiles["PROFILES"]: for profile in rpc_profiles["PROFILES"]:
if profile["Profile Name"] == active_profile: if profile["Profile Name"] == active_profile:
active_preset = profile active_preset = profile
return active_preset return MiningPreset.from_luxos(active_preset)
class ManualBoardSettings(MinerConfigValue): class ManualBoardSettings(MinerConfigValue):
@@ -422,6 +450,11 @@ class ManualBoardSettings(MinerConfigValue):
return {"miner-mode": "0"} return {"miner-mode": "0"}
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: def as_elphapex(self) -> dict:
return {"miner-mode": 0} return {"miner-mode": 0}
@@ -549,6 +582,20 @@ class MiningModeConfig(MinerConfigOption):
return cls.low() return cls.low()
return cls.default() 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 @classmethod
def from_elphapex(cls, web_conf: dict): def from_elphapex(cls, web_conf: dict):
if web_conf.get("fc-work-mode") is not None: if web_conf.get("fc-work-mode") is not None:

View File

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

View File

@@ -16,7 +16,7 @@
import copy import copy
import time import time
from datetime import datetime, timezone from datetime import datetime, timezone
from typing import Any, List, Union from typing import Any
from pydantic import BaseModel, Field, computed_field from pydantic import BaseModel, Field, computed_field
@@ -28,6 +28,7 @@ from pyasic.device.algorithm.hashrate import AlgoHashRateType
from .boards import HashBoard from .boards import HashBoard
from .device import DeviceInfo from .device import DeviceInfo
from .error_codes import BraiinsOSError, InnosiliconError, WhatsminerError, X19Error from .error_codes import BraiinsOSError, InnosiliconError, WhatsminerError, X19Error
from .error_codes.base import BaseMinerError
from .fans import Fan from .fans import Fan
@@ -107,25 +108,18 @@ class MinerData(BaseModel):
raw_wattage_limit: int | None = Field(exclude=True, default=None, repr=False) raw_wattage_limit: int | None = Field(exclude=True, default=None, repr=False)
# fans # fans
fans: List[Fan] = Field(default_factory=list) fans: list[Fan] = Field(default_factory=list)
fan_psu: int | None = None fan_psu: int | None = None
# boards # boards
hashboards: List[HashBoard] = Field(default_factory=list) hashboards: list[HashBoard] = Field(default_factory=list)
# config # config
config: MinerConfig | None = None config: MinerConfig | None = None
fault_light: bool | None = None fault_light: bool | None = None
# errors # errors
errors: List[ errors: list[BaseMinerError] = Field(default_factory=list)
Union[
WhatsminerError,
BraiinsOSError,
X19Error,
InnosiliconError,
]
] = Field(default_factory=list)
# mining state # mining state
is_mining: bool = True is_mining: bool = True
@@ -135,8 +129,10 @@ class MinerData(BaseModel):
pools: list[PoolMetrics] = Field(default_factory=list) pools: list[PoolMetrics] = Field(default_factory=list)
@classmethod @classmethod
def fields(cls): def fields(cls) -> set:
return list(cls.model_fields.keys()) 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): def get(self, __key: str, default: Any = None):
try: try:
@@ -307,25 +303,25 @@ class MinerData(BaseModel):
@computed_field # type: ignore[misc] @computed_field # type: ignore[misc]
@property @property
def make(self) -> str: def make(self) -> str | None:
if self.device_info.make is not None: if self.device_info.make is not None:
return str(self.device_info.make) return str(self.device_info.make)
@computed_field # type: ignore[misc] @computed_field # type: ignore[misc]
@property @property
def model(self) -> str: def model(self) -> str | None:
if self.device_info.model is not None: if self.device_info.model is not None:
return str(self.device_info.model) return str(self.device_info.model)
@computed_field # type: ignore[misc] @computed_field # type: ignore[misc]
@property @property
def firmware(self) -> str: def firmware(self) -> str | None:
if self.device_info.firmware is not None: if self.device_info.firmware is not None:
return str(self.device_info.firmware) return str(self.device_info.firmware)
@computed_field # type: ignore[misc] @computed_field # type: ignore[misc]
@property @property
def algo(self) -> str: def algo(self) -> str | None:
if self.device_info.algo is not None: if self.device_info.algo is not None:
return str(self.device_info.algo) return str(self.device_info.algo)
@@ -365,7 +361,9 @@ class MinerData(BaseModel):
data_list = [str(data[item]) for item in data] data_list = [str(data[item]) for item in data]
return ",".join(data_list) 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/). """Get this dataclass as [influxdb line protocol](https://docs.influxdata.com/influxdb/v2.4/reference/syntax/line-protocol/).
Parameters: Parameters:
@@ -374,54 +372,127 @@ class MinerData(BaseModel):
Returns: Returns:
A influxdb line protocol version of this class. 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 = [] field_data = []
tags = ["ip", "mac", "model", "hostname"] for field in include:
for attribute in self.fields(): field_val = getattr(self, field)
if attribute in tags: serialization_func = serialization_map.get(
escaped_data = self.get(attribute, "Unknown").replace(" ", "\\ ") type(field_val), lambda _k, _v: None
tag_data.append(f"{attribute}={escaped_data}") )
serialized = serialization_func(field, field_val)
if serialized is not None:
field_data.append(serialized)
continue continue
elif str(attribute).startswith("_"): for datatype in serialization_map_instance:
continue if serialized is None:
elif isinstance(self[attribute], str): if isinstance(field_val, datatype):
field_data.append(f'{attribute}="{self[attribute]}"') serialized = serialization_map_instance[datatype](
continue field, field_val
elif isinstance(self[attribute], bool): )
field_data.append(f"{attribute}={str(self[attribute]).lower()}") if serialized is not None:
continue field_data.append(serialized)
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}")
tags_str = ",".join(tag_data) tags_str = ",".join(tag_data).replace(" ", "\\ ")
field_str = ",".join(field_data) field_str = ",".join(field_data).replace(" ", "\\ ")
timestamp = str(self.timestamp * 1e9) timestamp = str(self.timestamp * 10**9)
return " ".join([tags_str, field_str, timestamp]) return " ".join([tags_str, field_str, timestamp])

View File

@@ -51,6 +51,12 @@ class HashBoard(BaseModel):
active: bool | None = None active: bool | None = None
voltage: float | 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): def get(self, __key: str, default: Any = None):
try: try:
val = self.__getitem__(__key) val = self.__getitem__(__key)
@@ -65,3 +71,63 @@ class HashBoard(BaseModel):
return getattr(self, item) return getattr(self, item)
except AttributeError: except AttributeError:
raise KeyError(f"{item}") 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. A dictionary version of this class.
""" """
return self.asdict() 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: if total == 0:
return 0 return 0
return (value / total) * 100 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 pass
class HiveonS19KPro(HiveonModern, S19KPro): class HiveonS19kPro(HiveonModern, S19KPro):
pass pass

View File

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

View File

@@ -104,6 +104,23 @@ class AvalonMiner(CGMiner):
return True return True
return False 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: async def reboot(self) -> bool:
try: try:
data = await self.rpc.restart() data = await self.rpc.restart()

View File

@@ -152,7 +152,7 @@ class LUXMiner(LuxOSFirmware):
rpc_profiles=data.get("profiles", [{}])[0], 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. Upgrade the firmware on a LuxOS miner by calling the 'updaterun' API command.
Returns: Returns:

View File

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

View File

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

View File

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