Compare commits

..

21 Commits

Author SHA1 Message Date
Brett Rowan
4b7a1a0495 bug: fix lockfile failing release 2024-11-01 16:05:59 -06:00
Brett Rowan
cc4e7da4e5 version: bump version number 2024-11-01 16:02:35 -06:00
Brett Rowan
a3d2d7d35e feature: add web parsing for luxOS type 2024-11-01 16:02:15 -06:00
Brett Rowan
d67de98bd0 version: bump version number 2024-11-01 10:52:04 -06:00
Brett Rowan
fd1a3e459b bug: reset betterproto version so that it can be built for pypi 2024-11-01 10:51:49 -06:00
Brett Rowan
adcab694b5 version: bump version number. 2024-11-01 10:46:59 -06:00
Brett Rowan
2bb097272f fix: use git version of better proto for compatibility with home assistant 2024-11-01 10:46:45 -06:00
Upstream Data
896968dded version: bump version number 2024-10-30 14:48:41 -06:00
Upstream Data
56b8f7c5b3 feature: parse iceriver config 2024-10-30 14:48:15 -06:00
Upstream Data
0ed7559aef version: bump version number 2024-10-30 14:37:47 -06:00
Upstream Data
275d87e4fe bug: fix AntminerOld board parsing 2024-10-30 14:37:19 -06:00
Upstream Data
c3ab814d77 version: bump version number 2024-10-30 14:08:38 -06:00
Upstream Data
05a8569205 bug: fix some calcuation errors with pool info 2024-10-30 14:08:22 -06:00
Upstream Data
b098cb8136 version: bump version number 2024-10-30 13:40:44 -06:00
Upstream Data
75fe7857e4 feature: add iceriver pool metrics 2024-10-30 13:39:22 -06:00
Upstream Data
66797aced1 ci: remove deprecated stages arg from pre-commit 2024-10-30 13:20:41 -06:00
Upstream Data
4a71e38078 ci: fix test framework name 2024-10-30 13:19:46 -06:00
Upstream Data
9fb07e4fa3 ci: skip pre-commit CI running pytest 2024-10-30 13:19:12 -06:00
Upstream Data
74792771ec version: bump version number 2024-10-30 13:16:22 -06:00
Upstream Data
fa6e8a976d bug: fix iceriver userpanel parsing 2024-10-30 13:16:07 -06:00
James Hilliard
f20531cff5 Run pre-commit formatting on all files 2024-10-30 13:07:57 -06:00
27 changed files with 215 additions and 132 deletions

View File

@@ -1,3 +1,6 @@
ci:
skip:
- unittest
repos: repos:
- repo: https://github.com/pre-commit/pre-commit-hooks - repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.5.0 rev: v4.5.0
@@ -24,4 +27,3 @@ repos:
'types': [python] 'types': [python]
args: ["-p '*test.py'"] # Probably this option is absolutely not needed. args: ["-p '*test.py'"] # Probably this option is absolutely not needed.
pass_filenames: false pass_filenames: false
stages: [commit]

64
poetry.lock generated
View File

@@ -1,4 +1,4 @@
# This file is automatically @generated by Poetry 1.8.4 and should not be changed by hand. # This file is automatically @generated by Poetry 1.6.1 and should not be changed by hand.
[[package]] [[package]]
name = "aiofiles" name = "aiofiles"
@@ -1121,41 +1121,41 @@ test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess
[[package]] [[package]]
name = "watchdog" name = "watchdog"
version = "5.0.3" version = "6.0.0"
description = "Filesystem events monitoring" description = "Filesystem events monitoring"
optional = false optional = false
python-versions = ">=3.9" python-versions = ">=3.9"
files = [ files = [
{file = "watchdog-5.0.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:85527b882f3facda0579bce9d743ff7f10c3e1e0db0a0d0e28170a7d0e5ce2ea"}, {file = "watchdog-6.0.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d1cdb490583ebd691c012b3d6dae011000fe42edb7a82ece80965b42abd61f26"},
{file = "watchdog-5.0.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:53adf73dcdc0ef04f7735066b4a57a4cd3e49ef135daae41d77395f0b5b692cb"}, {file = "watchdog-6.0.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bc64ab3bdb6a04d69d4023b29422170b74681784ffb9463ed4870cf2f3e66112"},
{file = "watchdog-5.0.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e25adddab85f674acac303cf1f5835951345a56c5f7f582987d266679979c75b"}, {file = "watchdog-6.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c897ac1b55c5a1461e16dae288d22bb2e412ba9807df8397a635d88f671d36c3"},
{file = "watchdog-5.0.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:f01f4a3565a387080dc49bdd1fefe4ecc77f894991b88ef927edbfa45eb10818"}, {file = "watchdog-6.0.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:6eb11feb5a0d452ee41f824e271ca311a09e250441c262ca2fd7ebcf2461a06c"},
{file = "watchdog-5.0.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:91b522adc25614cdeaf91f7897800b82c13b4b8ac68a42ca959f992f6990c490"}, {file = "watchdog-6.0.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ef810fbf7b781a5a593894e4f439773830bdecb885e6880d957d5b9382a960d2"},
{file = "watchdog-5.0.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d52db5beb5e476e6853da2e2d24dbbbed6797b449c8bf7ea118a4ee0d2c9040e"}, {file = "watchdog-6.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:afd0fe1b2270917c5e23c2a65ce50c2a4abb63daafb0d419fde368e272a76b7c"},
{file = "watchdog-5.0.3-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:94d11b07c64f63f49876e0ab8042ae034674c8653bfcdaa8c4b32e71cfff87e8"}, {file = "watchdog-6.0.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:bdd4e6f14b8b18c334febb9c4425a878a2ac20efd1e0b231978e7b150f92a948"},
{file = "watchdog-5.0.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:349c9488e1d85d0a58e8cb14222d2c51cbc801ce11ac3936ab4c3af986536926"}, {file = "watchdog-6.0.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:c7c15dda13c4eb00d6fb6fc508b3c0ed88b9d5d374056b239c4ad1611125c860"},
{file = "watchdog-5.0.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:53a3f10b62c2d569e260f96e8d966463dec1a50fa4f1b22aec69e3f91025060e"}, {file = "watchdog-6.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6f10cb2d5902447c7d0da897e2c6768bca89174d0c6e1e30abec5421af97a5b0"},
{file = "watchdog-5.0.3-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:950f531ec6e03696a2414b6308f5c6ff9dab7821a768c9d5788b1314e9a46ca7"}, {file = "watchdog-6.0.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:490ab2ef84f11129844c23fb14ecf30ef3d8a6abafd3754a6f75ca1e6654136c"},
{file = "watchdog-5.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ae6deb336cba5d71476caa029ceb6e88047fc1dc74b62b7c4012639c0b563906"}, {file = "watchdog-6.0.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:76aae96b00ae814b181bb25b1b98076d5fc84e8a53cd8885a318b42b6d3a5134"},
{file = "watchdog-5.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:1021223c08ba8d2d38d71ec1704496471ffd7be42cfb26b87cd5059323a389a1"}, {file = "watchdog-6.0.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a175f755fc2279e0b7312c0035d52e27211a5bc39719dd529625b1930917345b"},
{file = "watchdog-5.0.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:752fb40efc7cc8d88ebc332b8f4bcbe2b5cc7e881bccfeb8e25054c00c994ee3"}, {file = "watchdog-6.0.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:e6f0e77c9417e7cd62af82529b10563db3423625c5fce018430b249bf977f9e8"},
{file = "watchdog-5.0.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a2e8f3f955d68471fa37b0e3add18500790d129cc7efe89971b8a4cc6fdeb0b2"}, {file = "watchdog-6.0.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:90c8e78f3b94014f7aaae121e6b909674df5b46ec24d6bebc45c44c56729af2a"},
{file = "watchdog-5.0.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b8ca4d854adcf480bdfd80f46fdd6fb49f91dd020ae11c89b3a79e19454ec627"}, {file = "watchdog-6.0.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e7631a77ffb1f7d2eefa4445ebbee491c720a5661ddf6df3498ebecae5ed375c"},
{file = "watchdog-5.0.3-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:90a67d7857adb1d985aca232cc9905dd5bc4803ed85cfcdcfcf707e52049eda7"}, {file = "watchdog-6.0.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:c7ac31a19f4545dd92fc25d200694098f42c9a8e391bc00bdd362c5736dbf881"},
{file = "watchdog-5.0.3-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:720ef9d3a4f9ca575a780af283c8fd3a0674b307651c1976714745090da5a9e8"}, {file = "watchdog-6.0.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:9513f27a1a582d9808cf21a07dae516f0fab1cf2d7683a742c498b93eedabb11"},
{file = "watchdog-5.0.3-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:223160bb359281bb8e31c8f1068bf71a6b16a8ad3d9524ca6f523ac666bb6a1e"}, {file = "watchdog-6.0.0-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:7a0e56874cfbc4b9b05c60c8a1926fedf56324bb08cfbc188969777940aef3aa"},
{file = "watchdog-5.0.3-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:560135542c91eaa74247a2e8430cf83c4342b29e8ad4f520ae14f0c8a19cfb5b"}, {file = "watchdog-6.0.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:e6439e374fc012255b4ec786ae3c4bc838cd7309a540e5fe0952d03687d8804e"},
{file = "watchdog-5.0.3-py3-none-manylinux2014_aarch64.whl", hash = "sha256:dd021efa85970bd4824acacbb922066159d0f9e546389a4743d56919b6758b91"}, {file = "watchdog-6.0.0-py3-none-manylinux2014_aarch64.whl", hash = "sha256:7607498efa04a3542ae3e05e64da8202e58159aa1fa4acddf7678d34a35d4f13"},
{file = "watchdog-5.0.3-py3-none-manylinux2014_armv7l.whl", hash = "sha256:78864cc8f23dbee55be34cc1494632a7ba30263951b5b2e8fc8286b95845f82c"}, {file = "watchdog-6.0.0-py3-none-manylinux2014_armv7l.whl", hash = "sha256:9041567ee8953024c83343288ccc458fd0a2d811d6a0fd68c4c22609e3490379"},
{file = "watchdog-5.0.3-py3-none-manylinux2014_i686.whl", hash = "sha256:1e9679245e3ea6498494b3028b90c7b25dbb2abe65c7d07423ecfc2d6218ff7c"}, {file = "watchdog-6.0.0-py3-none-manylinux2014_i686.whl", hash = "sha256:82dc3e3143c7e38ec49d61af98d6558288c415eac98486a5c581726e0737c00e"},
{file = "watchdog-5.0.3-py3-none-manylinux2014_ppc64.whl", hash = "sha256:9413384f26b5d050b6978e6fcd0c1e7f0539be7a4f1a885061473c5deaa57221"}, {file = "watchdog-6.0.0-py3-none-manylinux2014_ppc64.whl", hash = "sha256:212ac9b8bf1161dc91bd09c048048a95ca3a4c4f5e5d4a7d1b1a7d5752a7f96f"},
{file = "watchdog-5.0.3-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:294b7a598974b8e2c6123d19ef15de9abcd282b0fbbdbc4d23dfa812959a9e05"}, {file = "watchdog-6.0.0-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:e3df4cbb9a450c6d49318f6d14f4bbc80d763fa587ba46ec86f99f9e6876bb26"},
{file = "watchdog-5.0.3-py3-none-manylinux2014_s390x.whl", hash = "sha256:26dd201857d702bdf9d78c273cafcab5871dd29343748524695cecffa44a8d97"}, {file = "watchdog-6.0.0-py3-none-manylinux2014_s390x.whl", hash = "sha256:2cce7cfc2008eb51feb6aab51251fd79b85d9894e98ba847408f662b3395ca3c"},
{file = "watchdog-5.0.3-py3-none-manylinux2014_x86_64.whl", hash = "sha256:0f9332243355643d567697c3e3fa07330a1d1abf981611654a1f2bf2175612b7"}, {file = "watchdog-6.0.0-py3-none-manylinux2014_x86_64.whl", hash = "sha256:20ffe5b202af80ab4266dcd3e91aae72bf2da48c0d33bdb15c66658e685e94e2"},
{file = "watchdog-5.0.3-py3-none-win32.whl", hash = "sha256:c66f80ee5b602a9c7ab66e3c9f36026590a0902db3aea414d59a2f55188c1f49"}, {file = "watchdog-6.0.0-py3-none-win32.whl", hash = "sha256:07df1fdd701c5d4c8e55ef6cf55b8f0120fe1aef7ef39a1c6fc6bc2e606d517a"},
{file = "watchdog-5.0.3-py3-none-win_amd64.whl", hash = "sha256:f00b4cf737f568be9665563347a910f8bdc76f88c2970121c86243c8cfdf90e9"}, {file = "watchdog-6.0.0-py3-none-win_amd64.whl", hash = "sha256:cbafb470cf848d93b5d013e2ecb245d4aa1c8fd0504e863ccefa32445359d680"},
{file = "watchdog-5.0.3-py3-none-win_ia64.whl", hash = "sha256:49f4d36cb315c25ea0d946e018c01bb028048023b9e103d3d3943f58e109dd45"}, {file = "watchdog-6.0.0-py3-none-win_ia64.whl", hash = "sha256:a1914259fa9e1454315171103c6a30961236f508b9b623eae470268bbcc6a22f"},
{file = "watchdog-5.0.3.tar.gz", hash = "sha256:108f42a7f0345042a854d4d0ad0834b741d421330d5f575b81cb27b883500176"}, {file = "watchdog-6.0.0.tar.gz", hash = "sha256:9ddf7c82fda3ae8e24decda1338ede66e1c99883db93711d8fb941eaa2d8c282"},
] ]
[package.extras] [package.extras]

View File

@@ -250,3 +250,9 @@ class MinerConfig:
pools=PoolConfig.from_bitaxe(web_system_info), pools=PoolConfig.from_bitaxe(web_system_info),
fan_mode=FanModeConfig.from_bitaxe(web_system_info), fan_mode=FanModeConfig.from_bitaxe(web_system_info),
) )
@classmethod
def from_iceriver(cls, web_userpanel: dict) -> "MinerConfig":
return cls(
pools=PoolConfig.from_iceriver(web_userpanel),
)

View File

@@ -222,6 +222,14 @@ class Pool(MinerConfigValue):
password=web_system_info.get("stratumPassword", ""), password=web_system_info.get("stratumPassword", ""),
) )
@classmethod
def from_iceriver(cls, web_pool: dict) -> "Pool":
return cls(
url=web_pool["addr"],
user=web_pool["user"],
password=web_pool["pass"],
)
@dataclass @dataclass
class PoolGroup(MinerConfigValue): class PoolGroup(MinerConfigValue):
@@ -402,6 +410,15 @@ class PoolGroup(MinerConfigValue):
def from_bitaxe(cls, web_system_info: dict) -> "PoolGroup": def from_bitaxe(cls, web_system_info: dict) -> "PoolGroup":
return cls(pools=[Pool.from_bitaxe(web_system_info)]) return cls(pools=[Pool.from_bitaxe(web_system_info)])
@classmethod
def from_iceriver(cls, web_userpanel: dict) -> "PoolGroup":
return cls(
pools=[
Pool.from_iceriver(web_pool)
for web_pool in web_userpanel["data"]["pools"]
]
)
@dataclass @dataclass
class PoolConfig(MinerConfigValue): class PoolConfig(MinerConfigValue):
@@ -568,3 +585,7 @@ class PoolConfig(MinerConfigValue):
@classmethod @classmethod
def from_bitaxe(cls, web_system_info: dict) -> "PoolConfig": def from_bitaxe(cls, web_system_info: dict) -> "PoolConfig":
return cls(groups=[PoolGroup.from_bitaxe(web_system_info)]) return cls(groups=[PoolGroup.from_bitaxe(web_system_info)])
@classmethod
def from_iceriver(cls, web_userpanel: dict) -> "PoolConfig":
return cls(groups=[PoolGroup.from_iceriver(web_userpanel)])

View File

@@ -23,13 +23,13 @@ from typing import Any, List, Union
from pyasic.config import MinerConfig from pyasic.config import MinerConfig
from pyasic.config.mining import MiningModePowerTune from pyasic.config.mining import MiningModePowerTune
from pyasic.data.pools import PoolMetrics
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 .fans import Fan from .fans import Fan
from .hashrate import AlgoHashRate, HashUnit from .hashrate import AlgoHashRate, HashUnit
from pyasic.data.pools import PoolMetrics
@dataclass @dataclass

View File

@@ -89,6 +89,8 @@ class PoolMetrics:
@staticmethod @staticmethod
def _calculate_percentage(value: int, total: int) -> float: def _calculate_percentage(value: int, total: int) -> float:
"""Calculate the percentage.""" """Calculate the percentage."""
if value is None or total is None:
return 0
if total == 0: if total == 0:
return 0 return 0
return (value / total) * 100 return (value / total) * 100

View File

@@ -23,6 +23,7 @@ from .S19 import (
BMMinerS19j, BMMinerS19j,
BMMinerS19jNoPIC, BMMinerS19jNoPIC,
BMMinerS19jPro, BMMinerS19jPro,
BMMinerS19KPro,
BMMinerS19L, BMMinerS19L,
BMMinerS19Plus, BMMinerS19Plus,
BMMinerS19Pro, BMMinerS19Pro,
@@ -30,6 +31,5 @@ from .S19 import (
BMMinerS19ProPlus, BMMinerS19ProPlus,
BMMinerS19ProPlusHydro, BMMinerS19ProPlusHydro,
BMMinerS19XP, BMMinerS19XP,
BMMinerS19KPro,
) )
from .T19 import BMMinerT19 from .T19 import BMMinerT19

View File

@@ -15,7 +15,4 @@
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
from .S21 import ePICS21, ePICS21Pro from .S21 import ePICS21, ePICS21Pro
from .T21 import ePICT21
from .T21 import (
ePICT21,
)

View File

@@ -597,49 +597,44 @@ class AntminerOld(CGMiner):
pass pass
if rpc_stats is not None: if rpc_stats is not None:
try: board_offset = -1
board_offset = -1 boards = rpc_stats["STATS"]
boards = rpc_stats["STATS"] if len(boards) > 1:
if len(boards) > 1: for board_num in range(1, 16, 5):
for board_num in range(1, 16, 5): for _b_num in range(5):
for _b_num in range(5): b = boards[1].get(f"chain_acn{board_num + _b_num}")
b = boards[1].get(f"chain_acn{board_num + _b_num}")
if b and not b == 0 and board_offset == -1: if b and not b == 0 and board_offset == -1:
board_offset = board_num board_offset = board_num
if board_offset == -1: if board_offset == -1:
board_offset = 1 board_offset = 1
for i in range( for i in range(board_offset, board_offset + self.expected_hashboards):
board_offset, board_offset + self.expected_hashboards hashboard = HashBoard(
): slot=i - board_offset, expected_chips=self.expected_chips
hashboard = HashBoard( )
slot=i - board_offset, expected_chips=self.expected_chips
)
chip_temp = boards[1].get(f"temp{i}") chip_temp = boards[1].get(f"temp{i}")
if chip_temp: if chip_temp:
hashboard.chip_temp = round(chip_temp) hashboard.chip_temp = round(chip_temp)
temp = boards[1].get(f"temp2_{i}") temp = boards[1].get(f"temp2_{i}")
if temp: if temp:
hashboard.temp = round(temp) hashboard.temp = round(temp)
hashrate = boards[1].get(f"chain_rate{i}") hashrate = boards[1].get(f"chain_rate{i}")
if hashrate: if hashrate:
hashboard.hashrate = AlgoHashRate.SHA256( hashboard.hashrate = AlgoHashRate.SHA256(
hashrate, HashUnit.SHA256.GH float(hashrate), HashUnit.SHA256.GH
).into(self.algo.unit.default) ).into(self.algo.unit.default)
chips = boards[1].get(f"chain_acn{i}") chips = boards[1].get(f"chain_acn{i}")
if chips: if chips:
hashboard.chips = chips hashboard.chips = chips
hashboard.missing = False hashboard.missing = False
if (not chips) or (not chips > 0): if (not chips) or (not chips > 0):
hashboard.missing = True hashboard.missing = True
hashboards.append(hashboard) hashboards.append(hashboard)
except (LookupError, ValueError, TypeError):
pass
return hashboards return hashboards

View File

@@ -193,7 +193,14 @@ class Auradine(StockFirmware):
for key in conf.keys(): for key in conf.keys():
await self.web.send_command(command=key, **conf[key]) await self.web.send_command(command=key, **conf[key])
async def upgrade_firmware(self, *, url: str = None, version: str = "latest", keep_settings: bool = False, **kwargs) -> bool: async def upgrade_firmware(
self,
*,
url: str = None,
version: str = "latest",
keep_settings: bool = False,
**kwargs,
) -> bool:
""" """
Upgrade the firmware of the Auradine device. Upgrade the firmware of the Auradine device.
@@ -209,7 +216,9 @@ class Auradine(StockFirmware):
logging.info("Starting firmware upgrade process.") logging.info("Starting firmware upgrade process.")
if not url and not version: if not url and not version:
raise ValueError("Either URL or version must be provided for firmware upgrade.") raise ValueError(
"Either URL or version must be provided for firmware upgrade."
)
if url: if url:
result = await self.web.firmware_upgrade(url=url) result = await self.web.firmware_upgrade(url=url)
@@ -220,11 +229,15 @@ class Auradine(StockFirmware):
logging.info("Firmware upgrade process completed successfully.") logging.info("Firmware upgrade process completed successfully.")
return True return True
else: else:
logging.error(f"Firmware upgrade failed: {result.get('error', 'Unknown error')}") logging.error(
f"Firmware upgrade failed: {result.get('error', 'Unknown error')}"
)
return False return False
except Exception as e: except Exception as e:
logging.error(f"An error occurred during the firmware upgrade process: {str(e)}") logging.error(
f"An error occurred during the firmware upgrade process: {str(e)}"
)
return False return False
################################################## ##################################################

View File

@@ -18,11 +18,11 @@ from typing import List, Optional
from pyasic.config import MinerConfig from pyasic.config import MinerConfig
from pyasic.data import AlgoHashRate, Fan, HashBoard, HashUnit from pyasic.data import AlgoHashRate, Fan, HashBoard, HashUnit
from pyasic.data.pools import PoolMetrics, PoolUrl
from pyasic.errors import APIError from pyasic.errors import APIError
from pyasic.miners.data import DataFunction, DataLocations, DataOptions, RPCAPICommand from pyasic.miners.data import DataFunction, DataLocations, DataOptions, RPCAPICommand
from pyasic.miners.device.firmware import StockFirmware from pyasic.miners.device.firmware import StockFirmware
from pyasic.rpc.bfgminer import BFGMinerRPCAPI from pyasic.rpc.bfgminer import BFGMinerRPCAPI
from pyasic.data.pools import PoolMetrics, PoolUrl
BFGMINER_DATA_LOC = DataLocations( BFGMINER_DATA_LOC = DataLocations(
**{ **{
@@ -263,4 +263,4 @@ class BFGMiner(StockFirmware):
expected_rate, HashUnit.SHA256.from_str(rate_unit) expected_rate, HashUnit.SHA256.from_str(rate_unit)
).into(self.algo.unit.default) ).into(self.algo.unit.default)
except LookupError: except LookupError:
pass pass

View File

@@ -23,11 +23,11 @@ import aiofiles
from pyasic.config import MinerConfig, MiningModeConfig from pyasic.config import MinerConfig, MiningModeConfig
from pyasic.data import AlgoHashRate, Fan, HashBoard, HashUnit from pyasic.data import AlgoHashRate, Fan, HashBoard, HashUnit
from pyasic.data.error_codes import MinerErrorData, WhatsminerError from pyasic.data.error_codes import MinerErrorData, WhatsminerError
from pyasic.data.pools import PoolMetrics, PoolUrl
from pyasic.errors import APIError from pyasic.errors import APIError
from pyasic.miners.data import DataFunction, DataLocations, DataOptions, RPCAPICommand from pyasic.miners.data import DataFunction, DataLocations, DataOptions, RPCAPICommand
from pyasic.miners.device.firmware import StockFirmware from pyasic.miners.device.firmware import StockFirmware
from pyasic.rpc.btminer import BTMinerRPCAPI from pyasic.rpc.btminer import BTMinerRPCAPI
from pyasic.data.pools import PoolMetrics, PoolUrl
BTMINER_DATA_LOC = DataLocations( BTMINER_DATA_LOC = DataLocations(
**{ **{
@@ -113,7 +113,7 @@ BTMINER_DATA_LOC = DataLocations(
str(DataOptions.POOLS): DataFunction( str(DataOptions.POOLS): DataFunction(
"_get_pools", "_get_pools",
[RPCAPICommand("rpc_pools", "pools")], [RPCAPICommand("rpc_pools", "pools")],
) ),
} }
) )

View File

@@ -14,15 +14,15 @@
# limitations under the License. - # limitations under the License. -
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
from typing import Optional, List from typing import List, Optional
from pyasic.config import MinerConfig from pyasic.config import MinerConfig
from pyasic.data import AlgoHashRate, HashUnit from pyasic.data import AlgoHashRate, HashUnit
from pyasic.data.pools import PoolMetrics, PoolUrl
from pyasic.errors import APIError from pyasic.errors import APIError
from pyasic.miners.data import DataFunction, DataLocations, DataOptions, RPCAPICommand from pyasic.miners.data import DataFunction, DataLocations, DataOptions, RPCAPICommand
from pyasic.miners.device.firmware import StockFirmware from pyasic.miners.device.firmware import StockFirmware
from pyasic.rpc.cgminer import CGMinerRPCAPI from pyasic.rpc.cgminer import CGMinerRPCAPI
from pyasic.data.pools import PoolMetrics, PoolUrl
CGMINER_DATA_LOC = DataLocations( CGMINER_DATA_LOC = DataLocations(
**{ **{

View File

@@ -454,8 +454,9 @@ class ePIC(ePICFirmware):
except LookupError: except LookupError:
pass pass
async def upgrade_firmware(self, file: Path | str, keep_settings: bool = True) -> bool: async def upgrade_firmware(
self, file: Path | str, keep_settings: bool = True
) -> bool:
""" """
Upgrade the firmware of the ePIC miner device. Upgrade the firmware of the ePIC miner device.
@@ -466,4 +467,4 @@ class ePIC(ePICFirmware):
Returns: Returns:
bool: Whether the firmware update succeeded. bool: Whether the firmware update succeeded.
""" """
return await self.web.system_update(file=file, keep_settings=keep_settings) return await self.web.system_update(file=file, keep_settings=keep_settings)

View File

@@ -1,6 +1,8 @@
from typing import List, Optional from typing import List, Optional
from pyasic import MinerConfig
from pyasic.data import AlgoHashRate, Fan, HashBoard, HashUnit from pyasic.data import AlgoHashRate, Fan, HashBoard, HashUnit
from pyasic.data.pools import PoolMetrics, PoolUrl
from pyasic.device import MinerAlgo from pyasic.device import MinerAlgo
from pyasic.errors import APIError from pyasic.errors import APIError
from pyasic.miners.data import DataFunction, DataLocations, DataOptions, WebAPICommand from pyasic.miners.data import DataFunction, DataLocations, DataOptions, WebAPICommand
@@ -41,6 +43,10 @@ ICERIVER_DATA_LOC = DataLocations(
"_get_uptime", "_get_uptime",
[WebAPICommand("web_userpanel", "userpanel")], [WebAPICommand("web_userpanel", "userpanel")],
), ),
str(DataOptions.POOLS): DataFunction(
"_get_pools",
[WebAPICommand("web_userpanel", "userpanel")],
),
} }
) )
@@ -67,6 +73,11 @@ class IceRiver(StockFirmware):
return False return False
return True return True
async def get_config(self) -> MinerConfig:
web_userpanel = await self.web.userpanel()
return MinerConfig.from_iceriver(web_userpanel)
async def _get_fans(self, web_userpanel: dict = None) -> List[Fan]: async def _get_fans(self, web_userpanel: dict = None) -> List[Fan]:
if web_userpanel is None: if web_userpanel is None:
try: try:
@@ -76,7 +87,7 @@ class IceRiver(StockFirmware):
if web_userpanel is not None: if web_userpanel is not None:
try: try:
return [Fan(spd) for spd in web_userpanel["fans"]] return [Fan(spd) for spd in web_userpanel["userpanel"]["data"]["fans"]]
except (LookupError, ValueError, TypeError): except (LookupError, ValueError, TypeError):
pass pass
@@ -89,7 +100,9 @@ class IceRiver(StockFirmware):
if web_userpanel is not None: if web_userpanel is not None:
try: try:
return web_userpanel["mac"].upper().replace("-", ":") return (
web_userpanel["userpanel"]["data"]["mac"].upper().replace("-", ":")
)
except (LookupError, ValueError, TypeError): except (LookupError, ValueError, TypeError):
pass pass
@@ -102,7 +115,7 @@ class IceRiver(StockFirmware):
if web_userpanel is not None: if web_userpanel is not None:
try: try:
return web_userpanel["host"] return web_userpanel["userpanel"]["data"]["host"]
except (LookupError, ValueError, TypeError): except (LookupError, ValueError, TypeError):
pass pass
@@ -115,9 +128,13 @@ class IceRiver(StockFirmware):
if web_userpanel is not None: if web_userpanel is not None:
try: try:
base_unit = web_userpanel["unit"] base_unit = web_userpanel["userpanel"]["data"]["unit"]
return AlgoHashRate.SHA256( return AlgoHashRate.SHA256(
float(web_userpanel["rtpow"].replace(base_unit, "")), float(
web_userpanel["userpanel"]["data"]["rtpow"].replace(
base_unit, ""
)
),
unit=MinerAlgo.SHA256.unit.from_str(base_unit + "H"), unit=MinerAlgo.SHA256.unit.from_str(base_unit + "H"),
).into(MinerAlgo.SHA256.unit.default) ).into(MinerAlgo.SHA256.unit.default)
except (LookupError, ValueError, TypeError): except (LookupError, ValueError, TypeError):
@@ -132,7 +149,7 @@ class IceRiver(StockFirmware):
if web_userpanel is not None: if web_userpanel is not None:
try: try:
return web_userpanel["locate"] return web_userpanel["userpanel"]["data"]["locate"]
except (LookupError, ValueError, TypeError): except (LookupError, ValueError, TypeError):
pass pass
return False return False
@@ -146,7 +163,7 @@ class IceRiver(StockFirmware):
if web_userpanel is not None: if web_userpanel is not None:
try: try:
return web_userpanel["powstate"] return web_userpanel["userpanel"]["data"]["powstate"]
except (LookupError, ValueError, TypeError): except (LookupError, ValueError, TypeError):
pass pass
@@ -164,7 +181,7 @@ class IceRiver(StockFirmware):
if web_userpanel is not None: if web_userpanel is not None:
try: try:
for board in web_userpanel["boards"]: for board in web_userpanel["userpanel"]["data"]["boards"]:
idx = int(board["no"] - 1) idx = int(board["no"] - 1)
hb_list[idx].chip_temp = round(board["outtmp"]) hb_list[idx].chip_temp = round(board["outtmp"])
hb_list[idx].temp = round(board["intmp"]) hb_list[idx].temp = round(board["intmp"])
@@ -186,7 +203,7 @@ class IceRiver(StockFirmware):
if web_userpanel is not None: if web_userpanel is not None:
try: try:
runtime = web_userpanel["runtime"] runtime = web_userpanel["userpanel"]["data"]["runtime"]
days, hours, minutes, seconds = runtime.split(":") days, hours, minutes, seconds = runtime.split(":")
return ( return (
(int(days) * 24 * 60 * 60) (int(days) * 24 * 60 * 60)
@@ -196,3 +213,36 @@ class IceRiver(StockFirmware):
) )
except (LookupError, ValueError, TypeError): except (LookupError, ValueError, TypeError):
pass pass
async def _get_pools(self, web_userpanel: dict = None) -> List[PoolMetrics]:
if web_userpanel is None:
try:
web_userpanel = await self.web.userpanel()
except APIError:
pass
pools_data = []
if web_userpanel is not None:
try:
pools = web_userpanel["userpanel"]["data"]["pools"]
for pool_info in pools:
pool_num = pool_info.get("no")
if pool_num is not None:
pool_num = int(pool_num)
if pool_info["addr"] == "":
continue
url = pool_info.get("addr")
pool_url = PoolUrl.from_str(url) if url else None
pool_data = PoolMetrics(
accepted=pool_info.get("accepted"),
rejected=pool_info.get("rejected"),
active=pool_info.get("connect"),
alive=int(pool_info.get("state", 0)) == 1,
url=pool_url,
user=pool_info.get("user"),
index=pool_num,
)
pools_data.append(pool_data)
except LookupError:
pass
return pools_data

View File

@@ -13,8 +13,8 @@
# See the License for the specific language governing permissions and - # See the License for the specific language governing permissions and -
# limitations under the License. - # limitations under the License. -
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
from typing import List, Optional
import logging import logging
from typing import List, Optional
from pyasic.config import MinerConfig from pyasic.config import MinerConfig
from pyasic.data import AlgoHashRate, Fan, HashBoard, HashUnit from pyasic.data import AlgoHashRate, Fan, HashBoard, HashUnit

View File

@@ -3,13 +3,13 @@ from typing import List, Optional
from pyasic import MinerConfig from pyasic import MinerConfig
from pyasic.config import MiningModeConfig from pyasic.config import MiningModeConfig
from pyasic.data import AlgoHashRate, Fan, HashBoard, HashUnit from pyasic.data import AlgoHashRate, Fan, HashBoard, HashUnit
from pyasic.data.pools import PoolMetrics, PoolUrl
from pyasic.errors import APIError from pyasic.errors import APIError
from pyasic.miners.data import DataFunction, DataLocations, DataOptions, WebAPICommand from pyasic.miners.data import DataFunction, DataLocations, DataOptions, WebAPICommand
from pyasic.miners.device.firmware import MaraFirmware from pyasic.miners.device.firmware import MaraFirmware
from pyasic.misc import merge_dicts from pyasic.misc import merge_dicts
from pyasic.rpc.marathon import MaraRPCAPI from pyasic.rpc.marathon import MaraRPCAPI
from pyasic.web.marathon import MaraWebAPI from pyasic.web.marathon import MaraWebAPI
from pyasic.data.pools import PoolMetrics, PoolUrl
MARA_DATA_LOC = DataLocations( MARA_DATA_LOC = DataLocations(
**{ **{
@@ -319,10 +319,13 @@ class MaraMiner(MaraFirmware):
return [] return []
active_pool_index = None active_pool_index = None
highest_priority = float('inf') highest_priority = float("inf")
for pool_info in web_pools: for pool_info in web_pools:
if pool_info.get("status") == "Alive" and pool_info.get("priority", float('inf')) < highest_priority: if (
pool_info.get("status") == "Alive"
and pool_info.get("priority", float("inf")) < highest_priority
):
highest_priority = pool_info.get["priority"] highest_priority = pool_info.get["priority"]
active_pool_index = pool_info["index"] active_pool_index = pool_info["index"]

View File

@@ -560,7 +560,14 @@ class BaseMiner(MinerProtocol):
if self._ssh_cls is not None: if self._ssh_cls is not None:
self.ssh = self._ssh_cls(ip) self.ssh = self._ssh_cls(ip)
async def upgrade_firmware(self, *, file: str = None, url: str = None, version: str = None, keep_settings: bool = True) -> bool: async def upgrade_firmware(
self,
*,
file: str = None,
url: str = None,
version: str = None,
keep_settings: bool = True,
) -> bool:
"""Upgrade the firmware of the miner. """Upgrade the firmware of the miner.
Parameters: Parameters:
@@ -574,4 +581,5 @@ class BaseMiner(MinerProtocol):
""" """
return False return False
AnyMiner = TypeVar("AnyMiner", bound=BaseMiner) AnyMiner = TypeVar("AnyMiner", bound=BaseMiner)

View File

@@ -14,7 +14,4 @@
# limitations under the License. - # limitations under the License. -
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
from .blockminer import ( from .blockminer import ePICBlockMiner520i, ePICBlockMiner720i
ePICBlockMiner520i,
ePICBlockMiner720i,
)

View File

@@ -43,4 +43,4 @@ class LuxOSFirmware(BaseMiner):
class MaraFirmware(BaseMiner): class MaraFirmware(BaseMiner):
firmware = MinerFirmware.MARATHON firmware = MinerFirmware.MARATHON

View File

@@ -628,6 +628,8 @@ class MinerFactory:
return MinerTypes.WHATSMINER return MinerTypes.WHATSMINER
if "Braiins OS" in web_text: if "Braiins OS" in web_text:
return MinerTypes.BRAIINS_OS return MinerTypes.BRAIINS_OS
if "Luxor Firmware" in web_text:
return MinerTypes.LUX_OS
if "<TITLE>用户界面</TITLE>" in web_text: if "<TITLE>用户界面</TITLE>" in web_text:
return MinerTypes.ICERIVER return MinerTypes.ICERIVER
if "AxeOS" in web_text: if "AxeOS" in web_text:

View File

@@ -22,8 +22,8 @@ import hashlib
import json import json
import logging import logging
import re import re
from typing import Literal, Union
import struct import struct
from typing import Literal, Union
import httpx import httpx
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes

View File

@@ -757,4 +757,4 @@ class LUXMinerRPCAPI(BaseMinerRPCAPI):
Returns: Returns:
The response from the miner after sending the 'updaterun' command. The response from the miner after sending the 'updaterun' command.
""" """
return await self.send_command("updaterun") return await self.send_command("updaterun")

View File

@@ -17,10 +17,11 @@ from __future__ import annotations
import asyncio import asyncio
import json import json
from pathlib import Path
from typing import Any from typing import Any
import aiofiles import aiofiles
import httpx import httpx
from pathlib import Path
from pyasic import settings from pyasic import settings
from pyasic.web.base import BaseWebAPI from pyasic.web.base import BaseWebAPI
@@ -414,10 +415,7 @@ class AntminerOldWebAPI(BaseWebAPI):
parameters = { parameters = {
"file": (file.name, file_content, "application/octet-stream"), "file": (file.name, file_content, "application/octet-stream"),
"filename": file.name, "filename": file.name,
"keep_settings": keep_settings "keep_settings": keep_settings,
} }
return await self.send_command( return await self.send_command(command="upgrade", **parameters)
command="upgrade",
**parameters
)

View File

@@ -4,17 +4,12 @@
# This file has been @generated # This file has been @generated
from dataclasses import dataclass from dataclasses import dataclass
from typing import ( from typing import TYPE_CHECKING, Dict, Optional
TYPE_CHECKING,
Dict,
Optional,
)
import betterproto import betterproto
import grpclib import grpclib
from betterproto.grpc.grpclib_server import ServiceBase from betterproto.grpc.grpclib_server import ServiceBase
if TYPE_CHECKING: if TYPE_CHECKING:
import grpclib.server import grpclib.server
from betterproto.grpc.grpclib_client import MetadataLike from betterproto.grpc.grpclib_client import MetadataLike

View File

@@ -5,19 +5,12 @@
import warnings import warnings
from dataclasses import dataclass from dataclasses import dataclass
from datetime import datetime from datetime import datetime
from typing import ( from typing import TYPE_CHECKING, AsyncIterator, Dict, List, Optional
TYPE_CHECKING,
AsyncIterator,
Dict,
List,
Optional,
)
import betterproto import betterproto
import grpclib import grpclib
from betterproto.grpc.grpclib_server import ServiceBase from betterproto.grpc.grpclib_server import ServiceBase
if TYPE_CHECKING: if TYPE_CHECKING:
import grpclib.server import grpclib.server
from betterproto.grpc.grpclib_client import MetadataLike from betterproto.grpc.grpclib_client import MetadataLike

View File

@@ -1,6 +1,6 @@
[tool.poetry] [tool.poetry]
name = "pyasic" name = "pyasic"
version = "0.61.8" version = "0.61.16"
description = "A simplified and standardized interface for Bitcoin ASICs." description = "A simplified and standardized interface for Bitcoin ASICs."
authors = ["UpstreamData <brett@upstreamdata.ca>"] authors = ["UpstreamData <brett@upstreamdata.ca>"]
repository = "https://github.com/UpstreamData/pyasic" repository = "https://github.com/UpstreamData/pyasic"
@@ -15,8 +15,8 @@ passlib = ">=1.7.4"
pyaml = ">=23.12.0" pyaml = ">=23.12.0"
tomli = { version = ">=2.0.1", python = "<3.11" } tomli = { version = ">=2.0.1", python = "<3.11" }
tomli-w = "^1.0.0" tomli-w = "^1.0.0"
betterproto = "2.0.0b7"
aiofiles = ">=23.2.1" aiofiles = ">=23.2.1"
betterproto = "2.0.0b7"
[tool.poetry.group.dev] [tool.poetry.group.dev]
optional = true optional = true