Compare commits
25 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8b1cbed9ce | ||
|
|
0194e13427 | ||
|
|
82d71abf54 | ||
|
|
e71cfadf6e | ||
|
|
18931c4e98 | ||
|
|
8622c080aa | ||
|
|
cb71b2a593 | ||
|
|
ff5956da41 | ||
|
|
acdafc2efd | ||
|
|
b8874092ad | ||
|
|
ad28ba0b3e | ||
|
|
0d90b60eef | ||
|
|
7c18c9f69c | ||
|
|
975560f46f | ||
|
|
bfe9cbf7d9 | ||
|
|
ccb5eb73db | ||
|
|
d143667bd6 | ||
|
|
87d809abc0 | ||
|
|
4dc5b1a541 | ||
|
|
ddd3e867f9 | ||
|
|
77480d3d69 | ||
|
|
0767c93002 | ||
|
|
e690e6dd3b | ||
|
|
d4665ed768 | ||
|
|
b90a92c0df |
@@ -29,6 +29,13 @@
|
||||
show_root_heading: false
|
||||
heading_level: 4
|
||||
|
||||
## T21 (BOS+)
|
||||
::: pyasic.miners.antminer.bosminer.X21.T21.BOSMinerT21
|
||||
handler: python
|
||||
options:
|
||||
show_root_heading: false
|
||||
heading_level: 4
|
||||
|
||||
## S21 (VNish)
|
||||
::: pyasic.miners.antminer.vnish.X21.S21.VNishS21
|
||||
handler: python
|
||||
|
||||
@@ -22,6 +22,20 @@
|
||||
show_root_heading: false
|
||||
heading_level: 4
|
||||
|
||||
## KA3 (Stock)
|
||||
::: pyasic.miners.antminer.bmminer.X3.KA3.BMMinerKA3
|
||||
handler: python
|
||||
options:
|
||||
show_root_heading: false
|
||||
heading_level: 4
|
||||
|
||||
## KS3 (Stock)
|
||||
::: pyasic.miners.antminer.bmminer.X3.KS3.BMMinerKS3
|
||||
handler: python
|
||||
options:
|
||||
show_root_heading: false
|
||||
heading_level: 4
|
||||
|
||||
## L3+ (VNish)
|
||||
::: pyasic.miners.antminer.vnish.X3.L3.VnishL3Plus
|
||||
handler: python
|
||||
|
||||
@@ -8,3 +8,10 @@
|
||||
show_root_heading: false
|
||||
heading_level: 4
|
||||
|
||||
## KS5 (Stock)
|
||||
::: pyasic.miners.antminer.bmminer.X5.KS5.BMMinerKS5
|
||||
handler: python
|
||||
options:
|
||||
show_root_heading: false
|
||||
heading_level: 4
|
||||
|
||||
|
||||
@@ -1,6 +1,20 @@
|
||||
# pyasic
|
||||
## KSX Models
|
||||
|
||||
## KS0 (Stock)
|
||||
::: pyasic.miners.iceriver.iceminer.KSX.KS0.IceRiverKS0
|
||||
handler: python
|
||||
options:
|
||||
show_root_heading: false
|
||||
heading_level: 4
|
||||
|
||||
## KS1 (Stock)
|
||||
::: pyasic.miners.iceriver.iceminer.KSX.KS1.IceRiverKS1
|
||||
handler: python
|
||||
options:
|
||||
show_root_heading: false
|
||||
heading_level: 4
|
||||
|
||||
## KS2 (Stock)
|
||||
::: pyasic.miners.iceriver.iceminer.KSX.KS2.IceRiverKS2
|
||||
handler: python
|
||||
@@ -8,3 +22,24 @@
|
||||
show_root_heading: false
|
||||
heading_level: 4
|
||||
|
||||
## KS3 (Stock)
|
||||
::: pyasic.miners.iceriver.iceminer.KSX.KS3.IceRiverKS3
|
||||
handler: python
|
||||
options:
|
||||
show_root_heading: false
|
||||
heading_level: 4
|
||||
|
||||
## KS3L (Stock)
|
||||
::: pyasic.miners.iceriver.iceminer.KSX.KS3.IceRiverKS3L
|
||||
handler: python
|
||||
options:
|
||||
show_root_heading: false
|
||||
heading_level: 4
|
||||
|
||||
## KS3M (Stock)
|
||||
::: pyasic.miners.iceriver.iceminer.KSX.KS3.IceRiverKS3M
|
||||
handler: python
|
||||
options:
|
||||
show_root_heading: false
|
||||
heading_level: 4
|
||||
|
||||
|
||||
@@ -21,12 +21,15 @@ details {
|
||||
<li><a href="../antminer/X3#d3-stock">D3 (Stock)</a></li>
|
||||
<li><a href="../antminer/X3#hs3-stock">HS3 (Stock)</a></li>
|
||||
<li><a href="../antminer/X3#l3_1-stock">L3+ (Stock)</a></li>
|
||||
<li><a href="../antminer/X3#ka3-stock">KA3 (Stock)</a></li>
|
||||
<li><a href="../antminer/X3#ks3-stock">KS3 (Stock)</a></li>
|
||||
</ul>
|
||||
</details>
|
||||
<details>
|
||||
<summary>X5 Series:</summary>
|
||||
<ul>
|
||||
<li><a href="../antminer/X5#dr5-stock">DR5 (Stock)</a></li>
|
||||
<li><a href="../antminer/X5#ks5-stock">KS5 (Stock)</a></li>
|
||||
</ul>
|
||||
</details>
|
||||
<details>
|
||||
@@ -378,6 +381,12 @@ details {
|
||||
<li><a href="../avalonminer/A12X#avalon-1246-stock">Avalon 1246 (Stock)</a></li>
|
||||
</ul>
|
||||
</details>
|
||||
<details>
|
||||
<summary>nano Series:</summary>
|
||||
<ul>
|
||||
<li><a href="../avalonminer/nano#avalon-nano-3-stock">Avalon Nano 3 (Stock)</a></li>
|
||||
</ul>
|
||||
</details>
|
||||
</ul>
|
||||
</details>
|
||||
<details>
|
||||
@@ -395,6 +404,12 @@ details {
|
||||
<li><a href="../innosilicon/A10X#a10x-stock">A10X (Stock)</a></li>
|
||||
</ul>
|
||||
</details>
|
||||
<details>
|
||||
<summary>A11X Series:</summary>
|
||||
<ul>
|
||||
<li><a href="../innosilicon/A11X#a11mx-stock">A11MX (Stock)</a></li>
|
||||
</ul>
|
||||
</details>
|
||||
</ul>
|
||||
</details>
|
||||
<details>
|
||||
@@ -470,6 +485,7 @@ details {
|
||||
<summary>X21 Series:</summary>
|
||||
<ul>
|
||||
<li><a href="../antminer/X21#s21-bos_1">S21 (BOS+)</a></li>
|
||||
<li><a href="../antminer/X21#t21-bos_1">T21 (BOS+)</a></li>
|
||||
</ul>
|
||||
</details>
|
||||
</ul>
|
||||
@@ -661,7 +677,12 @@ details {
|
||||
<details>
|
||||
<summary>KSX Series:</summary>
|
||||
<ul>
|
||||
<li><a href="../iceriver/KSX#ks0-stock">KS0 (Stock)</a></li>
|
||||
<li><a href="../iceriver/KSX#ks1-stock">KS1 (Stock)</a></li>
|
||||
<li><a href="../iceriver/KSX#ks2-stock">KS2 (Stock)</a></li>
|
||||
<li><a href="../iceriver/KSX#ks3-stock">KS3 (Stock)</a></li>
|
||||
<li><a href="../iceriver/KSX#ks3l-stock">KS3L (Stock)</a></li>
|
||||
<li><a href="../iceriver/KSX#ks3m-stock">KS3M (Stock)</a></li>
|
||||
</ul>
|
||||
</details>
|
||||
</ul>
|
||||
|
||||
14
poetry.lock
generated
14
poetry.lock
generated
@@ -59,21 +59,23 @@ pywin32 = ["pywin32 (>=227)"]
|
||||
|
||||
[[package]]
|
||||
name = "betterproto"
|
||||
version = "2.0.0b6"
|
||||
version = "2.0.0b7"
|
||||
description = "A better Protobuf / gRPC generator & library"
|
||||
optional = false
|
||||
python-versions = ">=3.7,<4.0"
|
||||
python-versions = "<4.0,>=3.7"
|
||||
files = [
|
||||
{file = "betterproto-2.0.0b6-py3-none-any.whl", hash = "sha256:a0839ec165d110a69d0d116f4d0e2bec8d186af4db826257931f0831dab73fcf"},
|
||||
{file = "betterproto-2.0.0b6.tar.gz", hash = "sha256:720ae92697000f6fcf049c69267d957f0871654c8b0d7458906607685daee784"},
|
||||
{file = "betterproto-2.0.0b7-py3-none-any.whl", hash = "sha256:401ab8055e2f814e77b9c88a74d0e1ae3d1e8a969cced6aeb1b59f71ad63fbd2"},
|
||||
{file = "betterproto-2.0.0b7.tar.gz", hash = "sha256:1b1458ca5278d519bcd62556a4c236f998a91d503f0f71c67b0b954747052af2"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
grpclib = ">=0.4.1,<0.5.0"
|
||||
python-dateutil = ">=2.8,<3.0"
|
||||
typing-extensions = ">=4.7.1,<5.0.0"
|
||||
|
||||
[package.extras]
|
||||
compiler = ["black (>=19.3b0)", "isort (>=5.11.5,<6.0.0)", "jinja2 (>=3.0.3)"]
|
||||
compiler = ["black (>=23.1.0)", "isort (>=5.11.5,<6.0.0)", "jinja2 (>=3.0.3)"]
|
||||
rust-codec = ["betterproto-rust-codec (==0.1.1)"]
|
||||
|
||||
[[package]]
|
||||
name = "certifi"
|
||||
@@ -1181,4 +1183,4 @@ type = ["pytest-mypy"]
|
||||
[metadata]
|
||||
lock-version = "2.0"
|
||||
python-versions = "^3.9"
|
||||
content-hash = "fdcee9d1f9de23d7c35ab73ca06127e70638929f5db176f6b789cbd7b76bf6b5"
|
||||
content-hash = "d611b5e8b0c5611d6ee916cedfb7f07f20dfc90a675ebaed04188e8b3c96aabe"
|
||||
|
||||
@@ -198,7 +198,7 @@ class MiningModePowerTune(MinerConfigValue):
|
||||
def as_boser(self) -> dict:
|
||||
cfg = {
|
||||
"set_performance_mode": SetPerformanceModeRequest(
|
||||
save_action=SaveAction.SAVE_ACTION_SAVE_AND_APPLY,
|
||||
save_action=SaveAction.SAVE_AND_APPLY,
|
||||
mode=PerformanceMode(
|
||||
tuner_mode=TunerPerformanceMode(
|
||||
power_target=PowerTargetMode(
|
||||
@@ -275,7 +275,7 @@ class MiningModeHashrateTune(MinerConfigValue):
|
||||
def as_boser(self) -> dict:
|
||||
cfg = {
|
||||
"set_performance_mode": SetPerformanceModeRequest(
|
||||
save_action=SaveAction.SAVE_ACTION_SAVE_AND_APPLY,
|
||||
save_action=SaveAction.SAVE_AND_APPLY,
|
||||
mode=PerformanceMode(
|
||||
tuner_mode=TunerPerformanceMode(
|
||||
hashrate_target=HashrateTargetMode(
|
||||
|
||||
@@ -467,7 +467,7 @@ class PoolConfig(MinerConfigValue):
|
||||
def as_boser(self, user_suffix: str = None) -> dict:
|
||||
return {
|
||||
"set_pool_groups": SetPoolGroupsRequest(
|
||||
save_action=SaveAction.SAVE_ACTION_SAVE_AND_APPLY,
|
||||
save_action=SaveAction.SAVE_AND_APPLY,
|
||||
pool_groups=[g.as_boser(user_suffix=user_suffix) for g in self.groups],
|
||||
)
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ from urllib.parse import urlparse
|
||||
class Scheme(Enum):
|
||||
STRATUM_V1 = "stratum+tcp"
|
||||
STRATUM_V2 = "stratum2+tcp"
|
||||
STRATUM_V1_SSL = "stratum+ssl"
|
||||
|
||||
|
||||
@dataclass
|
||||
|
||||
@@ -26,6 +26,7 @@ class MinerMake(str, Enum):
|
||||
AURADINE = "Auradine"
|
||||
EPIC = "ePIC"
|
||||
BITAXE = "BitAxe"
|
||||
ICERIVER = "IceRiver"
|
||||
|
||||
def __str__(self):
|
||||
return self.value
|
||||
|
||||
@@ -6,7 +6,9 @@ class AntminerModels(str, Enum):
|
||||
HS3 = "HS3"
|
||||
L3Plus = "L3+"
|
||||
KA3 = "KA3"
|
||||
KS3 = "KS3"
|
||||
DR5 = "DR5"
|
||||
KS5 = "KS5"
|
||||
L7 = "L7"
|
||||
E9Pro = "E9Pro"
|
||||
S9 = "S9"
|
||||
@@ -343,7 +345,12 @@ class BitAxeModels(str, Enum):
|
||||
|
||||
|
||||
class IceRiverModels(str, Enum):
|
||||
KS0 = "KS0"
|
||||
KS1 = "KS1"
|
||||
KS2 = "KS2"
|
||||
KS3 = "KS3"
|
||||
KS3L = "KS3L"
|
||||
KS3M = "KS3M"
|
||||
|
||||
def __str__(self):
|
||||
return self.value
|
||||
|
||||
22
pyasic/miners/antminer/bmminer/X3/KS3.py
Normal file
22
pyasic/miners/antminer/bmminer/X3/KS3.py
Normal file
@@ -0,0 +1,22 @@
|
||||
# ------------------------------------------------------------------------------
|
||||
# Copyright 2022 Upstream Data Inc -
|
||||
# -
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); -
|
||||
# you may not use this file except in compliance with the License. -
|
||||
# You may obtain a copy of the License at -
|
||||
# -
|
||||
# http://www.apache.org/licenses/LICENSE-2.0 -
|
||||
# -
|
||||
# Unless required by applicable law or agreed to in writing, software -
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, -
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -
|
||||
# See the License for the specific language governing permissions and -
|
||||
# limitations under the License. -
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
from pyasic.miners.backends import AntminerModern
|
||||
from pyasic.miners.device.models.antminer import KS3
|
||||
|
||||
|
||||
class BMMinerKS3(AntminerModern, KS3):
|
||||
pass
|
||||
@@ -15,4 +15,5 @@
|
||||
# ------------------------------------------------------------------------------
|
||||
from .HS3 import BMMinerHS3
|
||||
from .KA3 import BMMinerKA3
|
||||
from .KS3 import BMMinerKS3
|
||||
from .L3 import BMMinerL3Plus
|
||||
|
||||
21
pyasic/miners/antminer/bmminer/X5/KS5.py
Normal file
21
pyasic/miners/antminer/bmminer/X5/KS5.py
Normal file
@@ -0,0 +1,21 @@
|
||||
# ------------------------------------------------------------------------------
|
||||
# Copyright 2022 Upstream Data Inc -
|
||||
# -
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); -
|
||||
# you may not use this file except in compliance with the License. -
|
||||
# You may obtain a copy of the License at -
|
||||
# -
|
||||
# http://www.apache.org/licenses/LICENSE-2.0 -
|
||||
# -
|
||||
# Unless required by applicable law or agreed to in writing, software -
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, -
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -
|
||||
# See the License for the specific language governing permissions and -
|
||||
# limitations under the License. -
|
||||
# ------------------------------------------------------------------------------
|
||||
from pyasic.miners.backends import AntminerModern
|
||||
from pyasic.miners.device.models import KS5
|
||||
|
||||
|
||||
class BMMinerKS5(AntminerModern, KS5):
|
||||
supports_shutdown = False
|
||||
16
pyasic/miners/antminer/bmminer/X5/__init__.py
Normal file
16
pyasic/miners/antminer/bmminer/X5/__init__.py
Normal file
@@ -0,0 +1,16 @@
|
||||
# ------------------------------------------------------------------------------
|
||||
# Copyright 2022 Upstream Data Inc -
|
||||
# -
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); -
|
||||
# you may not use this file except in compliance with the License. -
|
||||
# You may obtain a copy of the License at -
|
||||
# -
|
||||
# http://www.apache.org/licenses/LICENSE-2.0 -
|
||||
# -
|
||||
# Unless required by applicable law or agreed to in writing, software -
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, -
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -
|
||||
# See the License for the specific language governing permissions and -
|
||||
# limitations under the License. -
|
||||
# ------------------------------------------------------------------------------
|
||||
from .KS5 import BMMinerKS5
|
||||
@@ -14,6 +14,7 @@
|
||||
# limitations under the License. -
|
||||
# ------------------------------------------------------------------------------
|
||||
from .X3 import *
|
||||
from .X5 import *
|
||||
from .X7 import *
|
||||
from .X9 import *
|
||||
from .X17 import *
|
||||
|
||||
@@ -798,7 +798,7 @@ class BOSer(BraiinsOSFirmware):
|
||||
async def set_power_limit(self, wattage: int) -> bool:
|
||||
try:
|
||||
result = await self.web.set_power_target(
|
||||
wattage, save_action=SaveAction.SAVE_ACTION_SAVE_AND_FORCE_APPLY
|
||||
wattage, save_action=SaveAction.SAVE_AND_FORCE_APPLY
|
||||
)
|
||||
except APIError:
|
||||
return False
|
||||
|
||||
@@ -165,13 +165,13 @@ class IceRiver(StockFirmware):
|
||||
if web_userpanel is not None:
|
||||
try:
|
||||
for board in web_userpanel["boards"]:
|
||||
idx = board["no"] - 1
|
||||
idx = int(board["no"] - 1)
|
||||
hb_list[idx].chip_temp = round(board["outtmp"])
|
||||
hb_list[idx].temp = round(board["intmp"])
|
||||
hb_list[idx].hashrate = AlgoHashRate.SHA256(
|
||||
float(board["rtpow"].replace("G", "")), HashUnit.SHA256.GH
|
||||
).into(self.algo.unit.default)
|
||||
hb_list[idx].chips = board["chipnum"]
|
||||
hb_list[idx].chips = int(board["chipnum"])
|
||||
hb_list[idx].missing = False
|
||||
except LookupError:
|
||||
pass
|
||||
|
||||
@@ -19,6 +19,7 @@ from pyasic.config import MinerConfig
|
||||
from pyasic.data import AlgoHashRate, Fan, HashBoard, HashUnit
|
||||
from pyasic.data.error_codes import MinerErrorData
|
||||
from pyasic.data.error_codes.innosilicon import InnosiliconError
|
||||
from pyasic.data.pools import PoolMetrics, PoolUrl
|
||||
from pyasic.errors import APIError
|
||||
from pyasic.miners.backends import CGMiner
|
||||
from pyasic.miners.data import (
|
||||
@@ -29,7 +30,6 @@ from pyasic.miners.data import (
|
||||
WebAPICommand,
|
||||
)
|
||||
from pyasic.web.innosilicon import InnosiliconWebAPI
|
||||
from pyasic.data.pools import PoolMetrics, PoolUrl
|
||||
|
||||
INNOSILICON_DATA_LOC = DataLocations(
|
||||
**{
|
||||
@@ -92,9 +92,8 @@ INNOSILICON_DATA_LOC = DataLocations(
|
||||
[RPCAPICommand("rpc_stats", "stats")],
|
||||
),
|
||||
str(DataOptions.POOLS): DataFunction(
|
||||
"_get_pools",
|
||||
[RPCAPICommand("rpc_pools", "pools")]
|
||||
)
|
||||
"_get_pools", [RPCAPICommand("rpc_pools", "pools")]
|
||||
),
|
||||
}
|
||||
)
|
||||
|
||||
@@ -116,7 +115,7 @@ class Innosilicon(CGMiner):
|
||||
except APIError:
|
||||
return self.config
|
||||
|
||||
self.config = MinerConfig.from_inno([pools])
|
||||
self.config = MinerConfig.from_inno(pools["pools"])
|
||||
return self.config
|
||||
|
||||
async def reboot(self) -> bool:
|
||||
|
||||
@@ -51,4 +51,4 @@ class BitAxeMake(BaseMiner):
|
||||
|
||||
|
||||
class IceRiverMake(BaseMiner):
|
||||
make = MinerMake.BITAXE
|
||||
make = MinerMake.ICERIVER
|
||||
|
||||
24
pyasic/miners/device/models/antminer/X3/KS3.py
Normal file
24
pyasic/miners/device/models/antminer/X3/KS3.py
Normal file
@@ -0,0 +1,24 @@
|
||||
# ------------------------------------------------------------------------------
|
||||
# Copyright 2022 Upstream Data Inc -
|
||||
# -
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); -
|
||||
# you may not use this file except in compliance with the License. -
|
||||
# You may obtain a copy of the License at -
|
||||
# -
|
||||
# http://www.apache.org/licenses/LICENSE-2.0 -
|
||||
# -
|
||||
# Unless required by applicable law or agreed to in writing, software -
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, -
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -
|
||||
# See the License for the specific language governing permissions and -
|
||||
# limitations under the License. -
|
||||
# ------------------------------------------------------------------------------
|
||||
from pyasic.device.models import MinerModel
|
||||
from pyasic.miners.device.makes import AntMinerMake
|
||||
|
||||
|
||||
class KS3(AntMinerMake):
|
||||
raw_model = MinerModel.ANTMINER.KS3
|
||||
|
||||
expected_chips = 92
|
||||
expected_fans = 2
|
||||
@@ -16,4 +16,5 @@
|
||||
from .D3 import D3
|
||||
from .HS3 import HS3
|
||||
from .KA3 import KA3
|
||||
from .KS3 import KS3
|
||||
from .L3 import L3Plus
|
||||
|
||||
23
pyasic/miners/device/models/antminer/X5/KS5.py
Normal file
23
pyasic/miners/device/models/antminer/X5/KS5.py
Normal file
@@ -0,0 +1,23 @@
|
||||
# ------------------------------------------------------------------------------
|
||||
# Copyright 2022 Upstream Data Inc -
|
||||
# -
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); -
|
||||
# you may not use this file except in compliance with the License. -
|
||||
# You may obtain a copy of the License at -
|
||||
# -
|
||||
# http://www.apache.org/licenses/LICENSE-2.0 -
|
||||
# -
|
||||
# Unless required by applicable law or agreed to in writing, software -
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, -
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -
|
||||
# See the License for the specific language governing permissions and -
|
||||
# limitations under the License. -
|
||||
# ------------------------------------------------------------------------------
|
||||
from pyasic.device.models import MinerModel
|
||||
from pyasic.miners.device.makes import AntMinerMake
|
||||
|
||||
|
||||
class KS5(AntMinerMake):
|
||||
raw_model = MinerModel.ANTMINER.KS5
|
||||
|
||||
expected_chips = 92
|
||||
@@ -14,3 +14,4 @@
|
||||
# limitations under the License. -
|
||||
# ------------------------------------------------------------------------------
|
||||
from .DR5 import DR5
|
||||
from .KS5 import KS5
|
||||
|
||||
23
pyasic/miners/device/models/iceriver/KSX/KS0.py
Normal file
23
pyasic/miners/device/models/iceriver/KSX/KS0.py
Normal file
@@ -0,0 +1,23 @@
|
||||
# ------------------------------------------------------------------------------
|
||||
# Copyright 2024 Upstream Data Inc -
|
||||
# -
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); -
|
||||
# you may not use this file except in compliance with the License. -
|
||||
# You may obtain a copy of the License at -
|
||||
# -
|
||||
# http://www.apache.org/licenses/LICENSE-2.0 -
|
||||
# -
|
||||
# Unless required by applicable law or agreed to in writing, software -
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, -
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -
|
||||
# See the License for the specific language governing permissions and -
|
||||
# limitations under the License. -
|
||||
# ------------------------------------------------------------------------------
|
||||
from pyasic.device.models import MinerModel
|
||||
from pyasic.miners.device.makes import IceRiverMake
|
||||
|
||||
|
||||
class KS0(IceRiverMake):
|
||||
raw_model = MinerModel.ICERIVER.KS0
|
||||
|
||||
expected_fans = 0
|
||||
23
pyasic/miners/device/models/iceriver/KSX/KS1.py
Normal file
23
pyasic/miners/device/models/iceriver/KSX/KS1.py
Normal file
@@ -0,0 +1,23 @@
|
||||
# ------------------------------------------------------------------------------
|
||||
# Copyright 2024 Upstream Data Inc -
|
||||
# -
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); -
|
||||
# you may not use this file except in compliance with the License. -
|
||||
# You may obtain a copy of the License at -
|
||||
# -
|
||||
# http://www.apache.org/licenses/LICENSE-2.0 -
|
||||
# -
|
||||
# Unless required by applicable law or agreed to in writing, software -
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, -
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -
|
||||
# See the License for the specific language governing permissions and -
|
||||
# limitations under the License. -
|
||||
# ------------------------------------------------------------------------------
|
||||
from pyasic.device.models import MinerModel
|
||||
from pyasic.miners.device.makes import IceRiverMake
|
||||
|
||||
|
||||
class KS1(IceRiverMake):
|
||||
raw_model = MinerModel.ICERIVER.KS1
|
||||
|
||||
expected_fans = 4
|
||||
@@ -21,3 +21,4 @@ class KS2(IceRiverMake):
|
||||
raw_model = MinerModel.ICERIVER.KS2
|
||||
|
||||
expected_fans = 4
|
||||
expected_chips = 18
|
||||
|
||||
36
pyasic/miners/device/models/iceriver/KSX/KS3.py
Normal file
36
pyasic/miners/device/models/iceriver/KSX/KS3.py
Normal file
@@ -0,0 +1,36 @@
|
||||
# ------------------------------------------------------------------------------
|
||||
# Copyright 2024 Upstream Data Inc -
|
||||
# -
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); -
|
||||
# you may not use this file except in compliance with the License. -
|
||||
# You may obtain a copy of the License at -
|
||||
# -
|
||||
# http://www.apache.org/licenses/LICENSE-2.0 -
|
||||
# -
|
||||
# Unless required by applicable law or agreed to in writing, software -
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, -
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -
|
||||
# See the License for the specific language governing permissions and -
|
||||
# limitations under the License. -
|
||||
# ------------------------------------------------------------------------------
|
||||
from pyasic.device.models import MinerModel
|
||||
from pyasic.miners.device.makes import IceRiverMake
|
||||
|
||||
|
||||
class KS3(IceRiverMake):
|
||||
raw_model = MinerModel.ICERIVER.KS3
|
||||
|
||||
expected_fans = 4
|
||||
|
||||
|
||||
class KS3L(IceRiverMake):
|
||||
raw_model = MinerModel.ICERIVER.KS3L
|
||||
|
||||
expected_fans = 4
|
||||
|
||||
|
||||
class KS3M(IceRiverMake):
|
||||
raw_model = MinerModel.ICERIVER.KS3M
|
||||
|
||||
expected_fans = 4
|
||||
expected_chips = 18
|
||||
@@ -1 +1,4 @@
|
||||
from .KS0 import KS0
|
||||
from .KS1 import KS1
|
||||
from .KS2 import KS2
|
||||
from .KS3 import KS3, KS3L, KS3M
|
||||
|
||||
@@ -19,3 +19,6 @@ from pyasic.miners.device.makes import InnosiliconMake
|
||||
|
||||
class A11MX(InnosiliconMake):
|
||||
raw_model = MinerModel.INNOSILICON.A11MX
|
||||
|
||||
expected_hashboards = 4
|
||||
expected_chips = 8
|
||||
|
||||
@@ -24,6 +24,8 @@ class M60VK10(WhatsMinerMake):
|
||||
class M60VK20(WhatsMinerMake):
|
||||
raw_model = MinerModel.WHATSMINER.M60VK20
|
||||
|
||||
expected_chips = 172
|
||||
|
||||
|
||||
class M60VK30(WhatsMinerMake):
|
||||
raw_model = MinerModel.WHATSMINER.M60VK30
|
||||
|
||||
@@ -20,6 +20,7 @@ import enum
|
||||
import ipaddress
|
||||
import json
|
||||
import re
|
||||
import warnings
|
||||
from typing import Any, AsyncGenerator, Callable
|
||||
|
||||
import anyio
|
||||
@@ -67,7 +68,9 @@ MINER_CLASSES = {
|
||||
"ANTMINER HS3": BMMinerHS3,
|
||||
"ANTMINER L3+": BMMinerL3Plus,
|
||||
"ANTMINER KA3": BMMinerKA3,
|
||||
"ANTMINER KS3": BMMinerKS3,
|
||||
"ANTMINER DR5": CGMinerDR5,
|
||||
"ANTMINER KS5": BMMinerKS5,
|
||||
"ANTMINER L7": BMMinerL7,
|
||||
"ANTMINER E9 PRO": BMMinerE9Pro,
|
||||
"ANTMINER S9": BMMinerS9,
|
||||
@@ -459,7 +462,12 @@ MINER_CLASSES = {
|
||||
},
|
||||
MinerTypes.ICERIVER: {
|
||||
None: type("IceRiverUnknown", (IceRiver, IceRiverMake), {}),
|
||||
"KS0": IceRiverKS0,
|
||||
"KS1": IceRiverKS1,
|
||||
"KS2": IceRiverKS2,
|
||||
"KS3": IceRiverKS3,
|
||||
"KS3L": IceRiverKS3L,
|
||||
"KS3M": IceRiverKS3M,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -538,6 +546,7 @@ class MinerFactory:
|
||||
MinerTypes.AURADINE: self.get_miner_model_auradine,
|
||||
MinerTypes.MARATHON: self.get_miner_model_marathon,
|
||||
MinerTypes.BITAXE: self.get_miner_model_bitaxe,
|
||||
MinerTypes.ICERIVER: self.get_miner_model_iceriver,
|
||||
}
|
||||
fn = miner_model_fns.get(miner_type)
|
||||
|
||||
@@ -619,6 +628,8 @@ class MinerFactory:
|
||||
return MinerTypes.WHATSMINER
|
||||
if "Braiins OS" in web_text:
|
||||
return MinerTypes.BRAIINS_OS
|
||||
if "<TITLE>用户界面</TITLE>" in web_text:
|
||||
return MinerTypes.ICERIVER
|
||||
if "AxeOS" in web_text:
|
||||
return MinerTypes.BITAXE
|
||||
if "cloud-box" in web_text:
|
||||
@@ -633,8 +644,6 @@ class MinerFactory:
|
||||
return MinerTypes.INNOSILICON
|
||||
if "Miner UI" in web_text:
|
||||
return MinerTypes.AURADINE
|
||||
if "<TITLE>用户界面</TITLE>" in web_text:
|
||||
return MinerTypes.ICERIVER
|
||||
|
||||
async def _get_miner_socket(self, ip: str) -> MinerTypes | None:
|
||||
commands = ["version", "devdetails"]
|
||||
@@ -839,6 +848,10 @@ class MinerFactory:
|
||||
return MINER_CLASSES[miner_type][str(miner_model).upper()](ip)
|
||||
except LookupError:
|
||||
if miner_type in MINER_CLASSES:
|
||||
warnings.warn(
|
||||
f"Partially supported miner found: {miner_model}, please open an issue with miner data "
|
||||
f"and this model on GitHub (https://github.com/UpstreamData/pyasic/issues)."
|
||||
)
|
||||
return MINER_CLASSES[miner_type][None](ip)
|
||||
return UnknownMiner(str(ip))
|
||||
|
||||
@@ -929,10 +942,19 @@ class MinerFactory:
|
||||
async with httpx.AsyncClient(transport=settings.transport()) as session:
|
||||
auth_req = await session.post(
|
||||
f"http://{ip}/api/auth",
|
||||
data={"username": "admin", "password": "admin"},
|
||||
data={
|
||||
"username": "admin",
|
||||
"password": settings.get(
|
||||
"default_innosilicon_web_password", "admin"
|
||||
),
|
||||
},
|
||||
)
|
||||
auth = auth_req.json()["jwt"]
|
||||
except (httpx.HTTPError, LookupError):
|
||||
return
|
||||
|
||||
try:
|
||||
async with httpx.AsyncClient(transport=settings.transport()) as session:
|
||||
web_data = (
|
||||
await session.post(
|
||||
f"http://{ip}/api/type",
|
||||
@@ -943,6 +965,18 @@ class MinerFactory:
|
||||
return web_data["type"]
|
||||
except (httpx.HTTPError, LookupError):
|
||||
pass
|
||||
try:
|
||||
async with httpx.AsyncClient(transport=settings.transport()) as session:
|
||||
web_data = (
|
||||
await session.post(
|
||||
f"http://{ip}/overview",
|
||||
headers={"Authorization": "Bearer " + auth},
|
||||
data={},
|
||||
)
|
||||
).json()
|
||||
return web_data["type"]
|
||||
except (httpx.HTTPError, LookupError):
|
||||
pass
|
||||
|
||||
async def get_miner_model_braiins_os(self, ip: str) -> str | None:
|
||||
sock_json_data = await self.send_api_command(ip, "devdetails")
|
||||
@@ -1056,6 +1090,39 @@ class MinerFactory:
|
||||
except (TypeError, LookupError):
|
||||
pass
|
||||
|
||||
async def get_miner_model_iceriver(self, ip: str) -> str | None:
|
||||
async with httpx.AsyncClient(transport=settings.transport()) as client:
|
||||
try:
|
||||
# auth
|
||||
await client.post(
|
||||
f"http://{ip}/user/loginpost",
|
||||
params={
|
||||
"post": "6",
|
||||
"user": "admin",
|
||||
"pwd": settings.get(
|
||||
"default_iceriver_web_password", "12345678"
|
||||
),
|
||||
},
|
||||
)
|
||||
except httpx.HTTPError:
|
||||
return None
|
||||
try:
|
||||
resp = await client.post(
|
||||
f"http://{ip}:/user/userpanel", params={"post": "4"}
|
||||
)
|
||||
if not resp.status_code == 200:
|
||||
return
|
||||
result = resp.json()
|
||||
software_ver = result["data"]["softver1"]
|
||||
split_ver = software_ver.split("_")
|
||||
if split_ver[-1] == "miner":
|
||||
miner_ver = split_ver[-2]
|
||||
else:
|
||||
miner_ver = split_ver[-1].replace("miner", "")
|
||||
return miner_ver.upper()
|
||||
except httpx.HTTPError:
|
||||
pass
|
||||
|
||||
|
||||
miner_factory = MinerFactory()
|
||||
|
||||
|
||||
6
pyasic/miners/iceriver/iceminer/KSX/KS0.py
Normal file
6
pyasic/miners/iceriver/iceminer/KSX/KS0.py
Normal file
@@ -0,0 +1,6 @@
|
||||
from pyasic.miners.backends.iceriver import IceRiver
|
||||
from pyasic.miners.device.models import KS0
|
||||
|
||||
|
||||
class IceRiverKS0(IceRiver, KS0):
|
||||
pass
|
||||
6
pyasic/miners/iceriver/iceminer/KSX/KS1.py
Normal file
6
pyasic/miners/iceriver/iceminer/KSX/KS1.py
Normal file
@@ -0,0 +1,6 @@
|
||||
from pyasic.miners.backends.iceriver import IceRiver
|
||||
from pyasic.miners.device.models import KS1
|
||||
|
||||
|
||||
class IceRiverKS1(IceRiver, KS1):
|
||||
pass
|
||||
14
pyasic/miners/iceriver/iceminer/KSX/KS3.py
Normal file
14
pyasic/miners/iceriver/iceminer/KSX/KS3.py
Normal file
@@ -0,0 +1,14 @@
|
||||
from pyasic.miners.backends.iceriver import IceRiver
|
||||
from pyasic.miners.device.models.iceriver import KS3, KS3L, KS3M
|
||||
|
||||
|
||||
class IceRiverKS3(IceRiver, KS3):
|
||||
pass
|
||||
|
||||
|
||||
class IceRiverKS3L(IceRiver, KS3L):
|
||||
pass
|
||||
|
||||
|
||||
class IceRiverKS3M(IceRiver, KS3M):
|
||||
pass
|
||||
@@ -1 +1,4 @@
|
||||
from .KS0 import IceRiverKS0
|
||||
from .KS1 import IceRiverKS1
|
||||
from .KS2 import IceRiverKS2
|
||||
from .KS3 import IceRiverKS3, IceRiverKS3L, IceRiverKS3M
|
||||
|
||||
93
pyasic/web/braiins_os/better_monkey.py
Normal file
93
pyasic/web/braiins_os/better_monkey.py
Normal file
@@ -0,0 +1,93 @@
|
||||
from datetime import datetime, timedelta
|
||||
from typing import Any, Dict
|
||||
|
||||
from betterproto import DATETIME_ZERO, TYPE_MAP, TYPE_MESSAGE, Casing, Message
|
||||
|
||||
|
||||
# https://github.com/danielgtaylor/python-betterproto/pull/609
|
||||
def to_pydict(
|
||||
self, casing: Casing = Casing.CAMEL, include_default_values: bool = False
|
||||
) -> Dict[str, Any]:
|
||||
"""
|
||||
Returns a python dict representation of this object.
|
||||
|
||||
Parameters
|
||||
-----------
|
||||
casing: :class:`Casing`
|
||||
The casing to use for key values. Default is :attr:`Casing.CAMEL` for
|
||||
compatibility purposes.
|
||||
include_default_values: :class:`bool`
|
||||
If ``True`` will include the default values of fields. Default is ``False``.
|
||||
E.g. an ``int32`` field will be included with a value of ``0`` if this is
|
||||
set to ``True``, otherwise this would be ignored.
|
||||
|
||||
Returns
|
||||
--------
|
||||
Dict[:class:`str`, Any]
|
||||
The python dict representation of this object.
|
||||
"""
|
||||
output: Dict[str, Any] = {}
|
||||
defaults = self._betterproto.default_gen
|
||||
for field_name, meta in self._betterproto.meta_by_field_name.items():
|
||||
field_is_repeated = defaults[field_name] is list
|
||||
try:
|
||||
value = getattr(self, field_name)
|
||||
except AttributeError:
|
||||
value = self._get_field_default(field_name)
|
||||
cased_name = casing(field_name).rstrip("_") # type: ignore
|
||||
if meta.proto_type == TYPE_MESSAGE:
|
||||
if isinstance(value, datetime):
|
||||
if (
|
||||
value != DATETIME_ZERO
|
||||
or include_default_values
|
||||
or self._include_default_value_for_oneof(
|
||||
field_name=field_name, meta=meta
|
||||
)
|
||||
):
|
||||
output[cased_name] = value
|
||||
elif isinstance(value, timedelta):
|
||||
if (
|
||||
value != timedelta(0)
|
||||
or include_default_values
|
||||
or self._include_default_value_for_oneof(
|
||||
field_name=field_name, meta=meta
|
||||
)
|
||||
):
|
||||
output[cased_name] = value
|
||||
elif meta.wraps:
|
||||
if value is not None or include_default_values:
|
||||
output[cased_name] = value
|
||||
elif field_is_repeated:
|
||||
# Convert each item.
|
||||
value = [i.to_pydict(casing, include_default_values) for i in value]
|
||||
if value or include_default_values:
|
||||
output[cased_name] = value
|
||||
elif value is None:
|
||||
if include_default_values:
|
||||
output[cased_name] = None
|
||||
elif (
|
||||
value._serialized_on_wire
|
||||
or include_default_values
|
||||
or self._include_default_value_for_oneof(
|
||||
field_name=field_name, meta=meta
|
||||
)
|
||||
):
|
||||
output[cased_name] = value.to_pydict(casing, include_default_values)
|
||||
elif meta.proto_type == TYPE_MAP:
|
||||
for k in value:
|
||||
if hasattr(value[k], "to_pydict"):
|
||||
value[k] = value[k].to_pydict(casing, include_default_values)
|
||||
|
||||
if value or include_default_values:
|
||||
output[cased_name] = value
|
||||
elif (
|
||||
value != self._get_field_default(field_name)
|
||||
or include_default_values
|
||||
or self._include_default_value_for_oneof(field_name=field_name, meta=meta)
|
||||
):
|
||||
output[cased_name] = value
|
||||
return output
|
||||
|
||||
|
||||
def patch():
|
||||
Message.to_pydict = to_pydict
|
||||
@@ -26,6 +26,9 @@ from grpclib.client import Channel
|
||||
from pyasic import settings
|
||||
from pyasic.errors import APIError
|
||||
from pyasic.web.base import BaseWebAPI
|
||||
from pyasic.web.braiins_os.better_monkey import patch
|
||||
|
||||
patch()
|
||||
|
||||
from .proto.braiins.bos import *
|
||||
from .proto.braiins.bos.v1 import *
|
||||
@@ -206,7 +209,7 @@ class BOSerWebAPI(BaseWebAPI):
|
||||
async def set_immersion_mode(
|
||||
self,
|
||||
enable: bool,
|
||||
save_action: SaveAction = SaveAction.SAVE_ACTION_SAVE_AND_APPLY,
|
||||
save_action: SaveAction = SaveAction.SAVE_AND_APPLY,
|
||||
) -> dict:
|
||||
return await self.send_command(
|
||||
"set_immersion_mode",
|
||||
@@ -227,7 +230,7 @@ class BOSerWebAPI(BaseWebAPI):
|
||||
)
|
||||
|
||||
async def set_default_power_target(
|
||||
self, save_action: SaveAction = SaveAction.SAVE_ACTION_SAVE_AND_APPLY
|
||||
self, save_action: SaveAction = SaveAction.SAVE_AND_APPLY
|
||||
) -> dict:
|
||||
return await self.send_command(
|
||||
"set_default_power_target",
|
||||
@@ -238,7 +241,7 @@ class BOSerWebAPI(BaseWebAPI):
|
||||
async def set_power_target(
|
||||
self,
|
||||
power_target: int,
|
||||
save_action: SaveAction = SaveAction.SAVE_ACTION_SAVE_AND_APPLY,
|
||||
save_action: SaveAction = SaveAction.SAVE_AND_APPLY,
|
||||
) -> dict:
|
||||
return await self.send_command(
|
||||
"set_power_target",
|
||||
@@ -251,7 +254,7 @@ class BOSerWebAPI(BaseWebAPI):
|
||||
async def increment_power_target(
|
||||
self,
|
||||
power_target_increment: int,
|
||||
save_action: SaveAction = SaveAction.SAVE_ACTION_SAVE_AND_APPLY,
|
||||
save_action: SaveAction = SaveAction.SAVE_AND_APPLY,
|
||||
) -> dict:
|
||||
return await self.send_command(
|
||||
"increment_power_target",
|
||||
@@ -265,7 +268,7 @@ class BOSerWebAPI(BaseWebAPI):
|
||||
async def decrement_power_target(
|
||||
self,
|
||||
power_target_decrement: int,
|
||||
save_action: SaveAction = SaveAction.SAVE_ACTION_SAVE_AND_APPLY,
|
||||
save_action: SaveAction = SaveAction.SAVE_AND_APPLY,
|
||||
) -> dict:
|
||||
return await self.send_command(
|
||||
"decrement_power_target",
|
||||
@@ -277,7 +280,7 @@ class BOSerWebAPI(BaseWebAPI):
|
||||
)
|
||||
|
||||
async def set_default_hashrate_target(
|
||||
self, save_action: SaveAction = SaveAction.SAVE_ACTION_SAVE_AND_APPLY
|
||||
self, save_action: SaveAction = SaveAction.SAVE_AND_APPLY
|
||||
) -> dict:
|
||||
return await self.send_command(
|
||||
"set_default_hashrate_target",
|
||||
@@ -288,7 +291,7 @@ class BOSerWebAPI(BaseWebAPI):
|
||||
async def set_hashrate_target(
|
||||
self,
|
||||
hashrate_target: float,
|
||||
save_action: SaveAction = SaveAction.SAVE_ACTION_SAVE_AND_APPLY,
|
||||
save_action: SaveAction = SaveAction.SAVE_AND_APPLY,
|
||||
) -> dict:
|
||||
return await self.send_command(
|
||||
"set_hashrate_target",
|
||||
@@ -302,7 +305,7 @@ class BOSerWebAPI(BaseWebAPI):
|
||||
async def increment_hashrate_target(
|
||||
self,
|
||||
hashrate_target_increment: int,
|
||||
save_action: SaveAction = SaveAction.SAVE_ACTION_SAVE_AND_APPLY,
|
||||
save_action: SaveAction = SaveAction.SAVE_AND_APPLY,
|
||||
) -> dict:
|
||||
return await self.send_command(
|
||||
"increment_hashrate_target",
|
||||
@@ -318,7 +321,7 @@ class BOSerWebAPI(BaseWebAPI):
|
||||
async def decrement_hashrate_target(
|
||||
self,
|
||||
hashrate_target_decrement: int,
|
||||
save_action: SaveAction = SaveAction.SAVE_ACTION_SAVE_AND_APPLY,
|
||||
save_action: SaveAction = SaveAction.SAVE_AND_APPLY,
|
||||
) -> dict:
|
||||
return await self.send_command(
|
||||
"decrement_hashrate_target",
|
||||
@@ -359,7 +362,7 @@ class BOSerWebAPI(BaseWebAPI):
|
||||
self,
|
||||
wattage_target: int = None,
|
||||
hashrate_target: int = None,
|
||||
save_action: SaveAction = SaveAction.SAVE_ACTION_SAVE_AND_APPLY,
|
||||
save_action: SaveAction = SaveAction.SAVE_AND_APPLY,
|
||||
) -> dict:
|
||||
if wattage_target is not None and hashrate_target is not None:
|
||||
logging.error(
|
||||
@@ -459,7 +462,7 @@ class BOSerWebAPI(BaseWebAPI):
|
||||
async def enable_hashboards(
|
||||
self,
|
||||
hashboard_ids: List[str],
|
||||
save_action: SaveAction = SaveAction.SAVE_ACTION_SAVE_AND_APPLY,
|
||||
save_action: SaveAction = SaveAction.SAVE_AND_APPLY,
|
||||
) -> dict:
|
||||
return await self.send_command(
|
||||
"enable_hashboards",
|
||||
@@ -472,7 +475,7 @@ class BOSerWebAPI(BaseWebAPI):
|
||||
async def disable_hashboards(
|
||||
self,
|
||||
hashboard_ids: List[str],
|
||||
save_action: SaveAction = SaveAction.SAVE_ACTION_SAVE_AND_APPLY,
|
||||
save_action: SaveAction = SaveAction.SAVE_AND_APPLY,
|
||||
) -> dict:
|
||||
return await self.send_command(
|
||||
"disable_hashboards",
|
||||
@@ -485,7 +488,7 @@ class BOSerWebAPI(BaseWebAPI):
|
||||
async def set_pool_groups(
|
||||
self,
|
||||
pool_groups: List[PoolGroupConfiguration],
|
||||
save_action: SaveAction = SaveAction.SAVE_ACTION_SAVE_AND_APPLY,
|
||||
save_action: SaveAction = SaveAction.SAVE_AND_APPLY,
|
||||
) -> dict:
|
||||
return await self.send_command(
|
||||
"set_pool_groups",
|
||||
|
||||
@@ -4,12 +4,17 @@
|
||||
# This file has been @generated
|
||||
|
||||
from dataclasses import dataclass
|
||||
from typing import TYPE_CHECKING, Dict, Optional
|
||||
from typing import (
|
||||
TYPE_CHECKING,
|
||||
Dict,
|
||||
Optional,
|
||||
)
|
||||
|
||||
import betterproto
|
||||
import grpclib
|
||||
from betterproto.grpc.grpclib_server import ServiceBase
|
||||
|
||||
|
||||
if TYPE_CHECKING:
|
||||
import grpclib.server
|
||||
from betterproto.grpc.grpclib_client import MetadataLike
|
||||
@@ -18,7 +23,7 @@ if TYPE_CHECKING:
|
||||
|
||||
@dataclass(eq=False, repr=False)
|
||||
class ApiVersion(betterproto.Message):
|
||||
"""LATEST_API_VERSION=1.2.0"""
|
||||
"""LATEST_API_VERSION=1.3.0"""
|
||||
|
||||
major: int = betterproto.uint64_field(1)
|
||||
minor: int = betterproto.uint64_field(2)
|
||||
|
||||
@@ -5,12 +5,19 @@
|
||||
import warnings
|
||||
from dataclasses import dataclass
|
||||
from datetime import datetime
|
||||
from typing import TYPE_CHECKING, AsyncIterator, Dict, List, Optional
|
||||
from typing import (
|
||||
TYPE_CHECKING,
|
||||
AsyncIterator,
|
||||
Dict,
|
||||
List,
|
||||
Optional,
|
||||
)
|
||||
|
||||
import betterproto
|
||||
import grpclib
|
||||
from betterproto.grpc.grpclib_server import ServiceBase
|
||||
|
||||
|
||||
if TYPE_CHECKING:
|
||||
import grpclib.server
|
||||
from betterproto.grpc.grpclib_client import MetadataLike
|
||||
@@ -20,125 +27,129 @@ if TYPE_CHECKING:
|
||||
class SaveAction(betterproto.Enum):
|
||||
"""Save action for different operations"""
|
||||
|
||||
SAVE_ACTION_UNSPECIFIED = 0
|
||||
SAVE_ACTION_SAVE = 1
|
||||
SAVE_ACTION_SAVE_AND_APPLY = 2
|
||||
SAVE_ACTION_SAVE_AND_FORCE_APPLY = 3
|
||||
UNSPECIFIED = 0
|
||||
SAVE = 1
|
||||
SAVE_AND_APPLY = 2
|
||||
SAVE_AND_FORCE_APPLY = 3
|
||||
|
||||
|
||||
class CoolingMode(betterproto.Enum):
|
||||
COOLING_MODE_UNSPECIFIED = 0
|
||||
COOLING_MODE_AUTO = 1
|
||||
COOLING_MODE_MANUAL = 2
|
||||
COOLING_MODE_DISABLED = 3
|
||||
UNSPECIFIED = 0
|
||||
AUTO = 1
|
||||
MANUAL = 2
|
||||
DISABLED = 3
|
||||
|
||||
|
||||
class SensorLocation(betterproto.Enum):
|
||||
SENSOR_LOCATION_UNSPECIFIED = 0
|
||||
SENSOR_LOCATION_CHIP = 1
|
||||
SENSOR_LOCATION_PCB = 2
|
||||
UNSPECIFIED = 0
|
||||
CHIP = 1
|
||||
PCB = 2
|
||||
|
||||
|
||||
class TunerMode(betterproto.Enum):
|
||||
TUNER_MODE_UNSPECIFIED = 0
|
||||
TUNER_MODE_POWER_TARGET = 1
|
||||
TUNER_MODE_HASHRATE_TARGET = 2
|
||||
UNSPECIFIED = 0
|
||||
POWER_TARGET = 1
|
||||
HASHRATE_TARGET = 2
|
||||
|
||||
|
||||
class TunerState(betterproto.Enum):
|
||||
TUNER_STATE_UNSPECIFIED = 0
|
||||
TUNER_STATE_DISABLED = 1
|
||||
TUNER_STATE_STABLE = 2
|
||||
TUNER_STATE_TUNING = 3
|
||||
TUNER_STATE_ERROR = 4
|
||||
UNSPECIFIED = 0
|
||||
DISABLED = 1
|
||||
STABLE = 2
|
||||
TUNING = 3
|
||||
ERROR = 4
|
||||
|
||||
|
||||
class LicenseType(betterproto.Enum):
|
||||
LICENSE_TYPE_UNSPECIFIED = 0
|
||||
LICENSE_TYPE_STANDARD = 1
|
||||
LICENSE_TYPE_CUSTOM = 2
|
||||
UNSPECIFIED = 0
|
||||
STANDARD = 1
|
||||
CUSTOM = 2
|
||||
|
||||
|
||||
class Platform(betterproto.Enum):
|
||||
"""Supported platforms"""
|
||||
|
||||
PLATFORM_UNSPECIFIED = 0
|
||||
PLATFORM_AM1_S9 = 1
|
||||
PLATFORM_AM2_S17 = 2
|
||||
PLATFORM_AM3_BBB = 3
|
||||
PLATFORM_AM3_AML = 4
|
||||
PLATFORM_STM32MP157C_II1_AM2 = 5
|
||||
PLATFORM_CVITEK_BM1_AM2 = 6
|
||||
PLATFORM_ZYNQ_BM3_AM2 = 7
|
||||
UNSPECIFIED = 0
|
||||
AM1_S9 = 1
|
||||
AM2_S17 = 2
|
||||
AM3_BBB = 3
|
||||
AM3_AML = 4
|
||||
STM32MP157C_II1_AM2 = 5
|
||||
CVITEK_BM1_AM2 = 6
|
||||
ZYNQ_BM3_AM2 = 7
|
||||
STM32MP157C_II2_BMM1 = 8
|
||||
|
||||
|
||||
class BosMode(betterproto.Enum):
|
||||
"""BOS modes enumeration"""
|
||||
|
||||
BOS_MODE_UNSPECIFIED = 0
|
||||
BOS_MODE_UPGRADE = 1
|
||||
BOS_MODE_RECOVERY = 2
|
||||
BOS_MODE_SD = 3
|
||||
BOS_MODE_NAND = 4
|
||||
BOS_MODE_EMMC = 5
|
||||
UNSPECIFIED = 0
|
||||
UPGRADE = 1
|
||||
RECOVERY = 2
|
||||
SD = 3
|
||||
NAND = 4
|
||||
EMMC = 5
|
||||
|
||||
|
||||
class MinerBrand(betterproto.Enum):
|
||||
MINER_BRAND_UNSPECIFIED = 0
|
||||
MINER_BRAND_ANTMINER = 1
|
||||
MINER_BRAND_WHATSMINER = 2
|
||||
UNSPECIFIED = 0
|
||||
ANTMINER = 1
|
||||
WHATSMINER = 2
|
||||
|
||||
|
||||
class MinerModel(betterproto.Enum):
|
||||
"""Deprecated: This enumeration is not longer maintained"""
|
||||
|
||||
MINER_MODEL_UNSPECIFIED = 0
|
||||
MINER_MODEL_ANTMINER_S9 = 1
|
||||
MINER_MODEL_ANTMINER_X17 = 2
|
||||
MINER_MODEL_ANTMINER_S17 = 3
|
||||
MINER_MODEL_ANTMINER_S17_PLUS = 4
|
||||
MINER_MODEL_ANTMINER_S17_PRO = 5
|
||||
MINER_MODEL_ANTMINER_S17E = 6
|
||||
MINER_MODEL_ANTMINER_T17 = 7
|
||||
MINER_MODEL_ANTMINER_T17E = 8
|
||||
MINER_MODEL_ANTMINER_T17_PLUS = 9
|
||||
MINER_MODEL_ANTMINER_X19 = 10
|
||||
MINER_MODEL_ANTMINER_S19 = 11
|
||||
MINER_MODEL_ANTMINER_S19_PRO = 12
|
||||
MINER_MODEL_ANTMINER_S19_PLUS = 13
|
||||
MINER_MODEL_ANTMINER_S19J = 14
|
||||
MINER_MODEL_ANTMINER_S19J_PRO = 15
|
||||
MINER_MODEL_ANTMINER_S19A = 16
|
||||
MINER_MODEL_ANTMINER_S19A_PRO = 17
|
||||
MINER_MODEL_ANTMINER_S19XP = 18
|
||||
MINER_MODEL_ANTMINER_T19 = 19
|
||||
MINER_MODEL_ANTMINER_S19J_PRO_PLUS = 20
|
||||
UNSPECIFIED = 0
|
||||
ANTMINER_S9 = 1
|
||||
ANTMINER_X17 = 2
|
||||
ANTMINER_S17 = 3
|
||||
ANTMINER_S17_PLUS = 4
|
||||
ANTMINER_S17_PRO = 5
|
||||
ANTMINER_S17E = 6
|
||||
ANTMINER_T17 = 7
|
||||
ANTMINER_T17E = 8
|
||||
ANTMINER_T17_PLUS = 9
|
||||
ANTMINER_X19 = 10
|
||||
ANTMINER_S19 = 11
|
||||
ANTMINER_S19_PRO = 12
|
||||
ANTMINER_S19_PLUS = 13
|
||||
ANTMINER_S19J = 14
|
||||
ANTMINER_S19J_PRO = 15
|
||||
ANTMINER_S19A = 16
|
||||
ANTMINER_S19A_PRO = 17
|
||||
ANTMINER_S19XP = 18
|
||||
ANTMINER_T19 = 19
|
||||
ANTMINER_S19J_PRO_PLUS = 20
|
||||
|
||||
|
||||
class MinerStatus(betterproto.Enum):
|
||||
MINER_STATUS_UNSPECIFIED = 0
|
||||
MINER_STATUS_NOT_STARTED = 1
|
||||
MINER_STATUS_NORMAL = 2
|
||||
MINER_STATUS_PAUSED = 3
|
||||
MINER_STATUS_SUSPENDED = 4
|
||||
MINER_STATUS_RESTRICTED = 5
|
||||
UNSPECIFIED = 0
|
||||
NOT_STARTED = 1
|
||||
NORMAL = 2
|
||||
PAUSED = 3
|
||||
SUSPENDED = 4
|
||||
RESTRICTED = 5
|
||||
|
||||
|
||||
class SupportArchiveFormat(betterproto.Enum):
|
||||
"""Enumeration for support archive format"""
|
||||
|
||||
SUPPORT_ARCHIVE_FORMAT_UNSPECIFIED = 0
|
||||
SUPPORT_ARCHIVE_FORMAT_ZIP = 1
|
||||
UNSPECIFIED = 0
|
||||
ZIP = 1
|
||||
"""Compressed zip format"""
|
||||
|
||||
SUPPORT_ARCHIVE_FORMAT_BOS = 2
|
||||
BOS = 2
|
||||
"""BOS custom format"""
|
||||
|
||||
ZIP_ENCRYPTED = 3
|
||||
"""Compressed encrypted zip format"""
|
||||
|
||||
|
||||
class NetworkProtocol(betterproto.Enum):
|
||||
NETWORK_PROTOCOL_UNSPECIFIED = 0
|
||||
NETWORK_PROTOCOL_DHCP = 1
|
||||
NETWORK_PROTOCOL_STATIC = 2
|
||||
UNSPECIFIED = 0
|
||||
DHCP = 1
|
||||
STATIC = 2
|
||||
|
||||
|
||||
@dataclass(eq=False, repr=False)
|
||||
@@ -268,8 +279,8 @@ class LoginResponse(betterproto.Message):
|
||||
|
||||
timeout_s: int = betterproto.uint32_field(2)
|
||||
"""
|
||||
Authentication token validity/timeout in seconds. Token validity refreshed
|
||||
to this value with each request.
|
||||
Authentication token validity/timeout in seconds.
|
||||
Token validity refreshed to this value with each request.
|
||||
"""
|
||||
|
||||
|
||||
@@ -277,9 +288,7 @@ class LoginResponse(betterproto.Message):
|
||||
class SetPasswordRequest(betterproto.Message):
|
||||
"""Request for set password action."""
|
||||
|
||||
password: Optional[str] = betterproto.string_field(
|
||||
1, optional=True, group="_password"
|
||||
)
|
||||
password: Optional[str] = betterproto.string_field(1, optional=True)
|
||||
|
||||
|
||||
@dataclass(eq=False, repr=False)
|
||||
@@ -335,8 +344,8 @@ class BasesPoints(betterproto.Message):
|
||||
|
||||
bsp: int = betterproto.uint32_field(1)
|
||||
"""
|
||||
A basis point is one hundredth of 1 percentage point. For example: 1bps =
|
||||
0.01%, 250bps = 2.5%
|
||||
A basis point is one hundredth of 1 percentage point.
|
||||
For example: 1bps = 0.01%, 250bps = 2.5%
|
||||
"""
|
||||
|
||||
|
||||
@@ -409,9 +418,9 @@ class VoltageConstraints(betterproto.Message):
|
||||
@dataclass(eq=False, repr=False)
|
||||
class CoolingAutoMode(betterproto.Message):
|
||||
"""
|
||||
The temperature control modes. Miner software tries to regulate the fan
|
||||
speed so that miner temperature is approximately at the target temperature.
|
||||
The allowed temperature range is 0-200 degree Celsius.
|
||||
The temperature control modes.
|
||||
Miner software tries to regulate the fan speed so that miner temperature is approximately at the target temperature.
|
||||
The allowed temperature range is 0-200 degree Celsius.
|
||||
"""
|
||||
|
||||
target_temperature: "Temperature" = betterproto.message_field(1)
|
||||
@@ -422,8 +431,7 @@ class CoolingAutoMode(betterproto.Message):
|
||||
|
||||
dangerous_temperature: "Temperature" = betterproto.message_field(3)
|
||||
"""
|
||||
Temperature threshold at which BOSMiner shuts down in order to prevent
|
||||
overheating and damaging the miner.
|
||||
Temperature threshold at which BOSMiner shuts down in order to prevent overheating and damaging the miner.
|
||||
"""
|
||||
|
||||
|
||||
@@ -433,12 +441,11 @@ class CoolingManualMode(betterproto.Message):
|
||||
Fans are kept at a fixed, user-defined speed, no matter the temperature.
|
||||
"""
|
||||
|
||||
fan_speed_ratio: Optional[float] = betterproto.double_field(
|
||||
1, optional=True, group="_fan_speed_ratio"
|
||||
)
|
||||
fan_speed_ratio: Optional[float] = betterproto.double_field(1, optional=True)
|
||||
"""
|
||||
User defined fan speed expressed as a ratio between 0.0 and 1.0 where 0.0
|
||||
means completely turned off and 1.0 means running at full speed possible
|
||||
User defined fan speed expressed as a ratio between 0.0 and 1.0
|
||||
where 0.0 means completely turned off and
|
||||
1.0 means running at full speed possible
|
||||
"""
|
||||
|
||||
hot_temperature: "Temperature" = betterproto.message_field(2)
|
||||
@@ -446,8 +453,7 @@ class CoolingManualMode(betterproto.Message):
|
||||
|
||||
dangerous_temperature: "Temperature" = betterproto.message_field(3)
|
||||
"""
|
||||
Temperature threshold at which BOSMiner shuts down in order to prevent
|
||||
overheating and damaging the miner.
|
||||
Temperature threshold at which BOSMiner shuts down in order to prevent overheating and damaging the miner.
|
||||
"""
|
||||
|
||||
|
||||
@@ -455,20 +461,17 @@ class CoolingManualMode(betterproto.Message):
|
||||
class CoolingDisabledMode(betterproto.Message):
|
||||
"""Disable temperature control. May be dangerous."""
|
||||
|
||||
fan_speed_ratio: Optional[float] = betterproto.double_field(
|
||||
1, optional=True, group="_fan_speed_ratio"
|
||||
)
|
||||
fan_speed_ratio: Optional[float] = betterproto.double_field(1, optional=True)
|
||||
"""
|
||||
User defined fan speed expressed as a ratio between 0.0 and 1.0 where 0.0
|
||||
means completely turned off and 1.0 means running at full speed possible
|
||||
User defined fan speed expressed as a ratio between 0.0 and 1.0
|
||||
where 0.0 means completely turned off and
|
||||
1.0 means running at full speed possible
|
||||
"""
|
||||
|
||||
|
||||
@dataclass(eq=False, repr=False)
|
||||
class CoolingConfiguration(betterproto.Message):
|
||||
minimum_required_fans: Optional[int] = betterproto.uint32_field(
|
||||
1, optional=True, group="_minimum_required_fans"
|
||||
)
|
||||
minimum_required_fans: Optional[int] = betterproto.uint32_field(1, optional=True)
|
||||
auto: "CoolingAutoMode" = betterproto.message_field(2, group="mode")
|
||||
manual: "CoolingManualMode" = betterproto.message_field(3, group="mode")
|
||||
disabled: "CoolingDisabledMode" = betterproto.message_field(4, group="mode")
|
||||
@@ -488,23 +491,19 @@ class CoolingConstraints(betterproto.Message):
|
||||
class FanState(betterproto.Message):
|
||||
"""Structure which contain info about one specific miner fan."""
|
||||
|
||||
position: Optional[int] = betterproto.uint32_field(
|
||||
1, optional=True, group="_position"
|
||||
)
|
||||
position: Optional[int] = betterproto.uint32_field(1, optional=True)
|
||||
"""Fan positions/ID"""
|
||||
|
||||
rpm: int = betterproto.uint32_field(2)
|
||||
"""Actual fan RPM (Revolutions/Rotation Per Minute)"""
|
||||
|
||||
target_speed_ratio: Optional[float] = betterproto.double_field(
|
||||
3, optional=True, group="_target_speed_ratio"
|
||||
)
|
||||
target_speed_ratio: Optional[float] = betterproto.double_field(3, optional=True)
|
||||
"""Actual fan speed ratio(PWM) in range 0.0 - 1.0"""
|
||||
|
||||
|
||||
@dataclass(eq=False, repr=False)
|
||||
class TemperatureSensor(betterproto.Message):
|
||||
id: Optional[int] = betterproto.uint32_field(1, optional=True, group="_id")
|
||||
id: Optional[int] = betterproto.uint32_field(1, optional=True)
|
||||
"""Sensor id"""
|
||||
|
||||
location: "SensorLocation" = betterproto.enum_field(2)
|
||||
@@ -523,7 +522,10 @@ class GetCoolingStateRequest(betterproto.Message):
|
||||
|
||||
@dataclass(eq=False, repr=False)
|
||||
class GetCoolingStateResponse(betterproto.Message):
|
||||
"""Response to get current fan states and temperature measurements"""
|
||||
"""
|
||||
Response to get current fan states and
|
||||
temperature measurements
|
||||
"""
|
||||
|
||||
fans: List["FanState"] = betterproto.message_field(1)
|
||||
"""All Fans state"""
|
||||
@@ -551,12 +553,10 @@ class SetImmersionModeResponse(betterproto.Message):
|
||||
|
||||
@dataclass(eq=False, repr=False)
|
||||
class TunerConfiguration(betterproto.Message):
|
||||
enabled: Optional[bool] = betterproto.bool_field(1, optional=True, group="_enabled")
|
||||
enabled: Optional[bool] = betterproto.bool_field(1, optional=True)
|
||||
"""Flag if tuner is enabled"""
|
||||
|
||||
tuner_mode: Optional["TunerMode"] = betterproto.enum_field(
|
||||
2, optional=True, group="_tuner_mode"
|
||||
)
|
||||
tuner_mode: Optional["TunerMode"] = betterproto.enum_field(2, optional=True)
|
||||
"""Tuner mode"""
|
||||
|
||||
power_target: "Power" = betterproto.message_field(3)
|
||||
@@ -583,7 +583,7 @@ class TunerConstraints(betterproto.Message):
|
||||
|
||||
@dataclass(eq=False, repr=False)
|
||||
class DpsConfiguration(betterproto.Message):
|
||||
enabled: Optional[bool] = betterproto.bool_field(1, optional=True, group="_enabled")
|
||||
enabled: Optional[bool] = betterproto.bool_field(1, optional=True)
|
||||
"""Flag if Dynamic Performance Scaling is enabled"""
|
||||
|
||||
power_step: "Power" = betterproto.message_field(2)
|
||||
@@ -598,9 +598,7 @@ class DpsConfiguration(betterproto.Message):
|
||||
min_hashrate_target: "TeraHashrate" = betterproto.message_field(5)
|
||||
"""Dynamic Performance Scaling minimal hashrate target"""
|
||||
|
||||
shutdown_enabled: Optional[bool] = betterproto.bool_field(
|
||||
6, optional=True, group="_shutdown_enabled"
|
||||
)
|
||||
shutdown_enabled: Optional[bool] = betterproto.bool_field(6, optional=True)
|
||||
"""Flag if shutdown for Dynamic Performance Scaling is enabled"""
|
||||
|
||||
shutdown_duration: "Hours" = betterproto.message_field(7)
|
||||
@@ -879,17 +877,13 @@ class SetDpsRequest(betterproto.Message):
|
||||
save_action: "SaveAction" = betterproto.enum_field(1)
|
||||
"""Save action"""
|
||||
|
||||
enable: Optional[bool] = betterproto.bool_field(2, optional=True, group="_enable")
|
||||
enable: Optional[bool] = betterproto.bool_field(2, optional=True)
|
||||
"""Flag if Dynamic Performance Scaling should be enabled"""
|
||||
|
||||
enable_shutdown: Optional[bool] = betterproto.bool_field(
|
||||
3, optional=True, group="_enable_shutdown"
|
||||
)
|
||||
enable_shutdown: Optional[bool] = betterproto.bool_field(3, optional=True)
|
||||
"""Flag if shutdown for Dynamic Performance Scaling should be enabled"""
|
||||
|
||||
shutdown_duration: Optional["Hours"] = betterproto.message_field(
|
||||
4, optional=True, group="_shutdown_duration"
|
||||
)
|
||||
shutdown_duration: Optional["Hours"] = betterproto.message_field(4, optional=True)
|
||||
"""Dynamic Performance Scaling shutdown duration"""
|
||||
|
||||
target: "DpsTarget" = betterproto.message_field(5)
|
||||
@@ -898,17 +892,13 @@ class SetDpsRequest(betterproto.Message):
|
||||
|
||||
@dataclass(eq=False, repr=False)
|
||||
class SetDpsResponse(betterproto.Message):
|
||||
enabled: Optional[bool] = betterproto.bool_field(1, optional=True, group="_enabled")
|
||||
enabled: Optional[bool] = betterproto.bool_field(1, optional=True)
|
||||
"""Flag if Dynamic Performance Scaling is enabled"""
|
||||
|
||||
shutdown_enabled: Optional[bool] = betterproto.bool_field(
|
||||
2, optional=True, group="_shutdown_enabled"
|
||||
)
|
||||
shutdown_enabled: Optional[bool] = betterproto.bool_field(2, optional=True)
|
||||
"""Flag if shutdown for Dynamic Performance Scaling should be enabled"""
|
||||
|
||||
shutdown_duration: Optional["Hours"] = betterproto.message_field(
|
||||
3, optional=True, group="_shutdown_duration"
|
||||
)
|
||||
shutdown_duration: Optional["Hours"] = betterproto.message_field(3, optional=True)
|
||||
"""Dynamic Performance Scaling shutdown duration"""
|
||||
|
||||
power_target: "DpsPowerTarget" = betterproto.message_field(4)
|
||||
@@ -935,7 +925,7 @@ class HashboardConfig(betterproto.Message):
|
||||
id: str = betterproto.string_field(1)
|
||||
"""Hashboard id"""
|
||||
|
||||
enabled: Optional[bool] = betterproto.bool_field(2, optional=True, group="_enabled")
|
||||
enabled: Optional[bool] = betterproto.bool_field(2, optional=True)
|
||||
"""Flag if HB si enabled"""
|
||||
|
||||
frequency: "Frequency" = betterproto.message_field(3)
|
||||
@@ -1019,9 +1009,9 @@ class Quota(betterproto.Message):
|
||||
@dataclass(eq=False, repr=False)
|
||||
class FixedShareRatio(betterproto.Message):
|
||||
"""
|
||||
Structure for fixed share ratio load balance strategy Fixed share ratio is
|
||||
value between 0.0 to 1.0 where 1.0 represents that all work is generated
|
||||
from the group
|
||||
Structure for fixed share ratio load balance strategy
|
||||
Fixed share ratio is value between 0.0 to 1.0 where 1.0 represents that all work is
|
||||
generated from the group
|
||||
"""
|
||||
|
||||
value: float = betterproto.double_field(1)
|
||||
@@ -1058,12 +1048,10 @@ class PoolConfiguration(betterproto.Message):
|
||||
user: str = betterproto.string_field(3)
|
||||
"""Pool connection user"""
|
||||
|
||||
password: Optional[str] = betterproto.string_field(
|
||||
4, optional=True, group="_password"
|
||||
)
|
||||
password: Optional[str] = betterproto.string_field(4, optional=True)
|
||||
"""Pool connection password if set"""
|
||||
|
||||
enabled: Optional[bool] = betterproto.bool_field(5, optional=True, group="_enabled")
|
||||
enabled: Optional[bool] = betterproto.bool_field(5, optional=True)
|
||||
"""Flag if pool connection is enabled"""
|
||||
|
||||
|
||||
@@ -1130,9 +1118,7 @@ class PoolStats(betterproto.Message):
|
||||
generated_work: int = betterproto.uint64_field(6)
|
||||
"""Generated work"""
|
||||
|
||||
last_share_time: Optional[datetime] = betterproto.message_field(
|
||||
7, optional=True, group="_last_share_time"
|
||||
)
|
||||
last_share_time: Optional[datetime] = betterproto.message_field(7, optional=True)
|
||||
"""Last share time"""
|
||||
|
||||
|
||||
@@ -1154,9 +1140,9 @@ class GetPoolGroupsResponse(betterproto.Message):
|
||||
@dataclass(eq=False, repr=False)
|
||||
class CreatePoolGroupRequest(betterproto.Message):
|
||||
"""
|
||||
Request for pool group create action group.uid must not be specified (it
|
||||
will be generated) group.pools[].uid must not be specified (it will be
|
||||
generated)
|
||||
Request for pool group create action
|
||||
group.uid must not be specified (it will be generated)
|
||||
group.pools[].uid must not be specified (it will be generated)
|
||||
"""
|
||||
|
||||
save_action: "SaveAction" = betterproto.enum_field(1)
|
||||
@@ -1177,9 +1163,9 @@ class CreatePoolGroupResponse(betterproto.Message):
|
||||
@dataclass(eq=False, repr=False)
|
||||
class UpdatePoolGroupRequest(betterproto.Message):
|
||||
"""
|
||||
Request for pool group update action group.uid must be specified and
|
||||
represents unique id of group which will be updated group.pools[].uid must
|
||||
not be specified (it will be generated)
|
||||
Request for pool group update action
|
||||
group.uid must be specified and represents unique id of group which will be updated
|
||||
group.pools[].uid must not be specified (it will be generated)
|
||||
"""
|
||||
|
||||
save_action: "SaveAction" = betterproto.enum_field(1)
|
||||
@@ -1221,16 +1207,15 @@ class SetPoolGroupsRequest(betterproto.Message):
|
||||
|
||||
save_action: "SaveAction" = betterproto.enum_field(1)
|
||||
"""
|
||||
Save action SAVE just update config but changes will not be applied
|
||||
SAVE_AND_APPLY and SAVE_AND_FORCE_APPLY are equal for this method. Pools
|
||||
config will be updated and changes will be applied that will trigger
|
||||
restart.
|
||||
Save action
|
||||
SAVE just update config but changes will not be applied
|
||||
SAVE_AND_APPLY and SAVE_AND_FORCE_APPLY are equal for this method. Pools config will be updated and changes will be applied that will trigger restart.
|
||||
"""
|
||||
|
||||
pool_groups: List["PoolGroupConfiguration"] = betterproto.message_field(2)
|
||||
"""
|
||||
Pool groups configuration `uid` must not be specified (it will be
|
||||
generated)
|
||||
Pool groups configuration
|
||||
`uid` must not be specified (it will be generated)
|
||||
"""
|
||||
|
||||
|
||||
@@ -1292,9 +1277,8 @@ class NoneLicense(betterproto.Message):
|
||||
time_to_restricted: int = betterproto.uint32_field(1)
|
||||
"""
|
||||
BOS Initialization timeout - number of seconds elapsed since bosminer start
|
||||
i.e., number of seconds BOS will start mining in restricted mode burning 5%
|
||||
of hashrate For more, see Section 3.10 of
|
||||
https://braiins.com/os/plus/license
|
||||
i.e., number of seconds BOS will start mining in restricted mode burning 5% of hashrate
|
||||
For more, see Section 3.10 of https://braiins.com/os/plus/license
|
||||
"""
|
||||
|
||||
|
||||
@@ -1313,9 +1297,8 @@ class ValidLicense(betterproto.Message):
|
||||
|
||||
time_to_restricted: int = betterproto.uint32_field(3)
|
||||
"""
|
||||
Current license expiration - number of seconds since the moment the license
|
||||
was received i.e., number of seconds BOS will start mining in restricted
|
||||
mode burning 15% of hashrate
|
||||
Current license expiration - number of seconds since the moment the license was received
|
||||
i.e., number of seconds BOS will start mining in restricted mode burning 15% of hashrate
|
||||
"""
|
||||
|
||||
dev_fee: "BasesPoints" = betterproto.message_field(4)
|
||||
@@ -1388,7 +1371,8 @@ class MinerIdentity(betterproto.Message):
|
||||
brand: "MinerBrand" = betterproto.enum_field(1)
|
||||
model: "MinerModel" = betterproto.enum_field(2)
|
||||
"""
|
||||
Deprecated: Use miner_model instead. This field is no longer supported.
|
||||
Deprecated: Use miner_model instead.
|
||||
This field is no longer supported.
|
||||
"""
|
||||
|
||||
name: str = betterproto.string_field(3)
|
||||
@@ -1564,7 +1548,7 @@ class Hashboard(betterproto.Message):
|
||||
stats: "WorkSolverStats" = betterproto.message_field(8)
|
||||
"""Hashboard stats"""
|
||||
|
||||
model: Optional[str] = betterproto.string_field(9, optional=True, group="_model")
|
||||
model: Optional[str] = betterproto.string_field(9, optional=True)
|
||||
"""Hashboard model"""
|
||||
|
||||
|
||||
@@ -1644,9 +1628,7 @@ class GetNetworkConfigurationResponse(betterproto.Message):
|
||||
class SetNetworkConfigurationRequest(betterproto.Message):
|
||||
dhcp: "Dhcp" = betterproto.message_field(1, group="protocol")
|
||||
static: "Static" = betterproto.message_field(2, group="protocol")
|
||||
hostname: Optional[str] = betterproto.string_field(
|
||||
3, optional=True, group="_hostname"
|
||||
)
|
||||
hostname: Optional[str] = betterproto.string_field(3, optional=True)
|
||||
"""Hostname. Existing value will be preserved if this field is not set."""
|
||||
|
||||
|
||||
@@ -1691,27 +1673,21 @@ class GetNetworkInfoRequest(betterproto.Message):
|
||||
@dataclass(eq=False, repr=False)
|
||||
class GetNetworkInfoResponse(betterproto.Message):
|
||||
"""
|
||||
Response message for GetCurrentNetworkConfiguration Represents the current
|
||||
network configuration for the default network interface. Only IPv4 is
|
||||
supported.
|
||||
Response message for GetCurrentNetworkConfiguration
|
||||
Represents the current network configuration for the default network interface.
|
||||
Only IPv4 is supported.
|
||||
"""
|
||||
|
||||
name: str = betterproto.string_field(1)
|
||||
"""Name of the network interface"""
|
||||
|
||||
mac_address: Optional[str] = betterproto.string_field(
|
||||
2, optional=True, group="_mac_address"
|
||||
)
|
||||
mac_address: Optional[str] = betterproto.string_field(2, optional=True)
|
||||
"""MAC address of the network interface"""
|
||||
|
||||
hostname: Optional[str] = betterproto.string_field(
|
||||
3, optional=True, group="_hostname"
|
||||
)
|
||||
hostname: Optional[str] = betterproto.string_field(3, optional=True)
|
||||
"""Miner hostname"""
|
||||
|
||||
protocol: Optional["NetworkProtocol"] = betterproto.enum_field(
|
||||
4, optional=True, group="_protocol"
|
||||
)
|
||||
protocol: Optional["NetworkProtocol"] = betterproto.enum_field(4, optional=True)
|
||||
"""Network protocol"""
|
||||
|
||||
dns_servers: List[str] = betterproto.string_field(5)
|
||||
@@ -1720,9 +1696,7 @@ class GetNetworkInfoResponse(betterproto.Message):
|
||||
networks: List["IpNetwork"] = betterproto.message_field(6)
|
||||
"""List of assigned IP addresses"""
|
||||
|
||||
default_gateway: Optional[str] = betterproto.string_field(
|
||||
7, optional=True, group="_default_gateway"
|
||||
)
|
||||
default_gateway: Optional[str] = betterproto.string_field(7, optional=True)
|
||||
"""Default gateway/route for the interface"""
|
||||
|
||||
|
||||
@@ -2332,7 +2306,7 @@ class MinerServiceStub(betterproto.ServiceStub):
|
||||
timeout: Optional[float] = None,
|
||||
deadline: Optional["Deadline"] = None,
|
||||
metadata: Optional["MetadataLike"] = None
|
||||
) -> AsyncIterator["GetMinerStatusResponse"]:
|
||||
) -> AsyncIterator[GetMinerStatusResponse]:
|
||||
async for response in self._unary_stream(
|
||||
"/braiins.bos.v1.MinerService/GetMinerStatus",
|
||||
get_miner_status_request,
|
||||
@@ -2418,7 +2392,7 @@ class MinerServiceStub(betterproto.ServiceStub):
|
||||
timeout: Optional[float] = None,
|
||||
deadline: Optional["Deadline"] = None,
|
||||
metadata: Optional["MetadataLike"] = None
|
||||
) -> AsyncIterator["GetSupportArchiveResponse"]:
|
||||
) -> AsyncIterator[GetSupportArchiveResponse]:
|
||||
async for response in self._unary_stream(
|
||||
"/braiins.bos.v1.MinerService/GetSupportArchive",
|
||||
get_support_archive_request,
|
||||
@@ -3195,7 +3169,7 @@ class MinerServiceBase(ServiceBase):
|
||||
|
||||
async def get_miner_status(
|
||||
self, get_miner_status_request: "GetMinerStatusRequest"
|
||||
) -> AsyncIterator["GetMinerStatusResponse"]:
|
||||
) -> AsyncIterator[GetMinerStatusResponse]:
|
||||
raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)
|
||||
yield GetMinerStatusResponse()
|
||||
|
||||
@@ -3221,7 +3195,7 @@ class MinerServiceBase(ServiceBase):
|
||||
|
||||
async def get_support_archive(
|
||||
self, get_support_archive_request: "GetSupportArchiveRequest"
|
||||
) -> AsyncIterator["GetSupportArchiveResponse"]:
|
||||
) -> AsyncIterator[GetSupportArchiveResponse]:
|
||||
raise grpclib.GRPCError(grpclib.const.Status.UNIMPLEMENTED)
|
||||
yield GetSupportArchiveResponse()
|
||||
|
||||
|
||||
@@ -127,6 +127,9 @@ class InnosiliconWebAPI(BaseWebAPI):
|
||||
async def get_all(self) -> dict:
|
||||
return await self.send_command("getAll")
|
||||
|
||||
async def summary(self) -> dict:
|
||||
return await self.send_command("summary")
|
||||
|
||||
async def get_error_detail(self) -> dict:
|
||||
return await self.send_command("getErrorDetail")
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[tool.poetry]
|
||||
name = "pyasic"
|
||||
version = "0.61.1"
|
||||
version = "0.61.8"
|
||||
description = "A simplified and standardized interface for Bitcoin ASICs."
|
||||
authors = ["UpstreamData <brett@upstreamdata.ca>"]
|
||||
repository = "https://github.com/UpstreamData/pyasic"
|
||||
@@ -15,7 +15,7 @@ passlib = ">=1.7.4"
|
||||
pyaml = ">=23.12.0"
|
||||
tomli = { version = ">=2.0.1", python = "<3.11" }
|
||||
tomli-w = "^1.0.0"
|
||||
betterproto = "2.0.0b6"
|
||||
betterproto = "2.0.0b7"
|
||||
aiofiles = ">=23.2.1"
|
||||
|
||||
[tool.poetry.group.dev]
|
||||
|
||||
Reference in New Issue
Block a user