Compare commits

...

21 Commits

Author SHA1 Message Date
UpstreamData
e9f54eec0a version: bump version number. 2022-11-30 10:01:27 -07:00
UpstreamData
fbbbc9f215 bug: Add VH60 to miner factory as it was missing. 2022-11-30 10:01:01 -07:00
UpstreamData
69e4f575c0 bug: fix a bug wth bosminer where it will sometimes not get data from graphql 2022-11-30 09:59:12 -07:00
UpstreamData
e95659d2e0 version: bump version number 2022-11-29 09:36:41 -07:00
UpstreamData
35f34310ec bug: fix an issue with incorrect type hinting. 2022-11-29 09:36:24 -07:00
UpstreamData
acc18e20fd Merge remote-tracking branch 'origin/master'
# Conflicts:
#	pyproject.toml
2022-11-24 11:04:19 -07:00
UpstreamData
72460eac08 version: bump version number 2022-11-24 11:03:54 -07:00
UpstreamData
3e5f9d4eca version: bump version number 2022-11-24 11:01:30 -07:00
UpstreamData
e873fa252c feature: add support for setting wattage on whatsminers with the new 2.0.5 API 2022-11-24 09:56:25 -07:00
UpstreamData
ff2c083a19 feature: add new whatsminer commands for version 2.0.5 2022-11-24 09:51:40 -07:00
UpstreamData
a30a84c34b version: bump version number 2022-11-22 18:28:02 -07:00
UpstreamData
97d2023298 feature: add support for whatsminer M31S V70 2022-11-22 18:27:35 -07:00
UpstreamData
1ce8430a14 version: bump version number 2022-11-21 11:28:29 -07:00
UpstreamData
1c0b638818 feature: add S19a Pro 2022-11-21 11:27:52 -07:00
UpstreamData
e852588eeb version: bump version number 2022-11-18 11:15:07 -07:00
UpstreamData
08b9bfd854 bug: fix error with getting miner failing to find a description key. 2022-11-18 11:14:35 -07:00
UpstreamData
7ee2f3a29a version: bump version number 2022-11-17 15:27:24 -07:00
UpstreamData
5ee6a38f39 bug: fix a bug with identifying some older version of BOSMiner. 2022-11-17 15:27:06 -07:00
UpstreamData
8f0bfd5f83 version: bump version number. 2022-11-16 14:30:52 -07:00
UpstreamData
c54f39fc77 bug: fix int and str addition in graphQL. 2022-11-16 14:30:29 -07:00
UpstreamData
eb40769ccf format: improve formatting 2022-11-15 11:28:35 -07:00
68 changed files with 338 additions and 143 deletions

View File

@@ -38,7 +38,6 @@ There are 2 main ways to get a miner (and the functions attached to it), via sca
#### Scanning for miners
```python
import asyncio
import sys
from pyasic.network import MinerNetwork
@@ -72,9 +71,8 @@ if __name__ == "__main__":
#### Getting a miner if you know the IP
```python
import asyncio
import sys
from pyasic.miners import get_miner
from pyasic import get_miner
# define asynchronous function to get miner and data
@@ -98,9 +96,8 @@ If needed, this library exposes a wrapper for the miner API that can be used for
#### List available API commands
```python
import asyncio
import sys
from pyasic.miners import get_miner
from pyasic import get_miner
async def get_api_commands(miner_ip: str):
@@ -121,9 +118,8 @@ The miner API commands will raise an `APIError` if they fail with a bad status c
```python
import asyncio
import sys
from pyasic.miners import get_miner
from pyasic import get_miner
async def get_api_commands(miner_ip: str):

View File

@@ -90,6 +90,7 @@ details {
</details>
<details>
<summary><a href="../whatsminer/M3X/#m31s">M31S</a></summary>
<summary><a href="../whatsminer/M3X/#m31sv70">M31SV70</a></summary>
</details>
<details>
<summary><a href="../whatsminer/M3X/#m31s_1">M31S+</a></summary>

View File

@@ -108,6 +108,14 @@
## M31S
::: pyasic.miners.whatsminer.btminer.M3X.M31S.BTMinerM31S
handler: python
options:
show_root_heading: false
heading_level: 4
## M31SV70
::: pyasic.miners.whatsminer.btminer.M3X.M31S.BTMinerM31S
handler: python
options:

View File

@@ -198,7 +198,6 @@ If you are sure you want to use this command please use API.send_command("{comma
@staticmethod
def _load_api_data(data: bytes) -> dict:
str_data = None
# some json from the API returns with a null byte (\x00) on the end
if data.endswith(b"\x00"):
# handle the null byte

View File

@@ -12,7 +12,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import asyncio
import base64
import binascii
import hashlib
@@ -582,7 +581,7 @@ class BTMinerAPI(BaseMinerAPI):
return await self.send_privileged_command("set_hostname", hostname=hostname)
async def set_power_pct(self, percent: int) -> dict:
"""Set the power percentage of the miner.
"""Set the power percentage of the miner based on current power. Used for temporary adjustment.
<details>
<summary>Expand</summary>
@@ -642,6 +641,119 @@ class BTMinerAPI(BaseMinerAPI):
"pre_power_on", complete="false", msg=msg
)
### ADDED IN V2.0.5 Whatsminer API ###
async def set_temp_offset(self, temp_offset: int):
"""Set the offset of miner hash board target temperature.
<details>
<summary>Expand</summary>
Set the offset of miner hash board target temperature, only works after
changing the password of the miner using the Whatsminer tool.
Parameters:
temp_offset: Target temperature offset.
Returns:
A reply informing of the status of setting temp offset.
</details>
"""
if not -30 < temp_offset < 0:
raise APIError(
f"Temp offset is outside of the allowed "
f"range. Please set a number between -30 and "
f"0."
)
return await self.send_privileged_command("set_temp_offset", temp_offset=temp_offset)
async def adjust_power_limit(self, power_limit: int):
"""Set the upper limit of the miner's power. Cannot be higher than the ordinary power of the machine.
<details>
<summary>Expand</summary>
Set the upper limit of the miner's power, only works after
changing the password of the miner using the Whatsminer tool.
The miner will reboot after this is set.
Parameters:
power_limit: New power limit.
Returns:
A reply informing of the status of setting power limit.
</details>
"""
return await self.send_privileged_command("adjust_power_limit", power_limit=power_limit)
async def adjust_upfreq_speed(self, upfreq_speed: int):
"""Set the upfreq speed, 0 is the normal speed, 9 is the fastest speed.
<details>
<summary>Expand</summary>
Set the upfreq speed, 0 is the normal speed, 9 is the fastest speed, only works after
changing the password of the miner using the Whatsminer tool.
The faster the speed, the greater the final hash rate and power deviation, and the stability
may be impacted. Fast boot mode cannot be used at the same time.
Parameters:
upfreq_speed: New upfreq speed.
Returns:
A reply informing of the status of setting upfreq speed.
</details>
"""
if not 0 < upfreq_speed < 9:
raise APIError(
f"Upfreq speed is outside of the allowed "
f"range. Please set a number between 0 (Normal) and "
f"9 (Fastest)."
)
return await self.send_privileged_command("adjust_upfreq_speed", upfreq_speed=upfreq_speed)
async def set_poweroff_cool(self, poweroff_cool: bool):
"""Set whether to cool the machine when mining is stopped.
<details>
<summary>Expand</summary>
Set whether to cool the machine when mining is stopped, only works after
changing the password of the miner using the Whatsminer tool.
Parameters:
poweroff_cool: Whether to cool the miner during power off mode.
Returns:
A reply informing of the status of setting power off cooling mode.
</details>
"""
return await self.send_privileged_command("set_poweroff_cool", poweroff_cool=int(poweroff_cool))
async def set_fan_zero_speed(self, fan_zero_speed: bool):
"""Sets whether the fan speed supports the lowest 0 speed.
<details>
<summary>Expand</summary>
Sets whether the fan speed supports the lowest 0 speed, only works after
changing the password of the miner using the Whatsminer tool.
Parameters:
fan_zero_speed: Whether the fan is allowed to support 0 speed.
Returns:
A reply informing of the status of setting fan minimum speed.
</details>
"""
return await self.send_privileged_command("set_fan_zero_speed", fan_zero_speed=int(fan_zero_speed))
#### END privileged COMMANDS ####
async def summary(self) -> dict:

View File

@@ -17,7 +17,7 @@ import random
import string
import time
from dataclasses import asdict, dataclass, fields
from typing import List, Literal
from typing import List, Literal, Dict
import toml
import yaml
@@ -193,7 +193,7 @@ class _PoolGroup:
return pools
def as_wm(self, user_suffix: str = None) -> List[dict]:
"""Convert the data in this class to a list usable by an Whatsminer device.
"""Convert the data in this class to a list usable by a Whatsminer device.
Parameters:
user_suffix: The suffix to append to username.
@@ -399,13 +399,13 @@ class MinerConfig:
"""
return self.from_dict(yaml.load(data, Loader=yaml.SafeLoader))
def as_wm(self, user_suffix: str = None) -> List[dict]:
"""Convert the data in this class to a config usable by an Whatsminer device.
def as_wm(self, user_suffix: str = None) -> Dict[str, int]:
"""Convert the data in this class to a config usable by a Whatsminer device.
Parameters:
user_suffix: The suffix to append to username.
"""
return self.pool_groups[0].as_wm(user_suffix=user_suffix)
return {"pools": self.pool_groups[0].as_wm(user_suffix=user_suffix), "wattage": self.autotuning_wattage}
def as_inno(self, user_suffix: str = None) -> dict:
"""Convert the data in this class to a config usable by an Innosilicon device.

View File

@@ -17,7 +17,6 @@ import json
import time
from dataclasses import asdict, dataclass, field, fields
from datetime import datetime, timezone
from functools import reduce
from typing import List, Union
from .error_codes import BraiinsOSError, InnosiliconError, WhatsminerError, X19Error

View File

@@ -356,9 +356,6 @@ class BOSMiner(BaseMiner):
],
)
board_offset = -1
fan_offset = -1
model = await self.get_model()
hostname = await self.get_hostname()
mac = await self.get_mac()
@@ -551,6 +548,8 @@ class BOSMiner(BaseMiner):
if not query_data:
return None
query_data = query_data["data"]
if not query_data:
return None
data.mac = await self.get_mac()
data.model = await self.get_model()
@@ -663,7 +662,7 @@ class BOSMiner(BaseMiner):
except (TypeError, KeyError, ValueError, IndexError):
pass
if groups[0]["strategy"].get("quota"):
data.quota = groups[0]["strategy"]["quota"] + "/" + groups[1]["strategy"]["quota"]
data.quota = str(groups[0]["strategy"]["quota"]) + "/" + str(groups[1]["strategy"]["quota"])
data.fault_light = await self.check_light()

View File

@@ -104,5 +104,5 @@ class BOSMinerOld(BaseMiner):
async def send_config(self, config: MinerConfig, user_suffix: str = None) -> None:
return None
async def get_data(self) -> MinerData:
async def get_data(self, **kwargs) -> MinerData:
return MinerData(ip=str(self.ip))

View File

@@ -211,18 +211,24 @@ class BTMiner(BaseMiner):
async def send_config(self, config: MinerConfig, user_suffix: str = None) -> None:
conf = config.as_wm(user_suffix=user_suffix)
pools_conf = conf["pools"]
await self.api.update_pools(
conf[0]["url"],
conf[0]["user"],
conf[0]["pass"],
conf[1]["url"],
conf[1]["user"],
conf[1]["pass"],
conf[2]["url"],
conf[2]["user"],
conf[2]["pass"],
pools_conf[0]["url"],
pools_conf[0]["user"],
pools_conf[0]["pass"],
pools_conf[1]["url"],
pools_conf[1]["user"],
pools_conf[1]["pass"],
pools_conf[2]["url"],
pools_conf[2]["user"],
pools_conf[2]["pass"],
)
try:
await self.api.adjust_power_limit(conf["wattage"])
except APIError:
# cannot set wattage
pass
async def get_config(self) -> MinerConfig:
pools = None

View File

@@ -15,7 +15,7 @@
from pyasic.miners.base import BaseMiner
class S17(BaseMiner):
class S17(BaseMiner): # noqa - ignore ABC method implementation
def __init__(self, ip: str):
super().__init__()
self.ip = ip

View File

@@ -15,7 +15,7 @@
from pyasic.miners.base import BaseMiner
class S17Plus(BaseMiner):
class S17Plus(BaseMiner): # noqa - ignore ABC method implementation
def __init__(self, ip: str):
super().__init__()
self.ip = ip

View File

@@ -15,7 +15,7 @@
from pyasic.miners.base import BaseMiner
class S17Pro(BaseMiner):
class S17Pro(BaseMiner): # noqa - ignore ABC method implementation
def __init__(self, ip: str):
super().__init__()
self.ip = ip

View File

@@ -15,7 +15,7 @@
from pyasic.miners.base import BaseMiner
class S17e(BaseMiner):
class S17e(BaseMiner): # noqa - ignore ABC method implementation
def __init__(self, ip: str):
super().__init__()
self.ip = ip

View File

@@ -15,7 +15,7 @@
from pyasic.miners.base import BaseMiner
class T17(BaseMiner):
class T17(BaseMiner): # noqa - ignore ABC method implementation
def __init__(self, ip: str):
super().__init__()
self.ip = ip

View File

@@ -15,7 +15,7 @@
from pyasic.miners.base import BaseMiner
class T17Plus(BaseMiner):
class T17Plus(BaseMiner): # noqa - ignore ABC method implementation
def __init__(self, ip: str):
super().__init__()
self.ip = ip

View File

@@ -15,7 +15,7 @@
from pyasic.miners.base import BaseMiner
class T17e(BaseMiner):
class T17e(BaseMiner): # noqa - ignore ABC method implementation
def __init__(self, ip: str):
super().__init__()
self.ip = ip

View File

@@ -15,7 +15,7 @@
from pyasic.miners.base import BaseMiner
class S19(BaseMiner):
class S19(BaseMiner): # noqa - ignore ABC method implementation
def __init__(self, ip: str):
super().__init__()
self.ip = ip

View File

@@ -15,7 +15,7 @@
from pyasic.miners.base import BaseMiner
class S19Pro(BaseMiner):
class S19Pro(BaseMiner): # noqa - ignore ABC method implementation
def __init__(self, ip: str):
super().__init__()
self.ip = ip

View File

@@ -15,7 +15,7 @@
from pyasic.miners.base import BaseMiner
class S19XP(BaseMiner):
class S19XP(BaseMiner): # noqa - ignore ABC method implementation
def __init__(self, ip: str):
super().__init__()
self.ip = ip

View File

@@ -15,7 +15,7 @@
from pyasic.miners.base import BaseMiner
class S19a(BaseMiner):
class S19a(BaseMiner): # noqa - ignore ABC method implementation
def __init__(self, ip: str):
super().__init__()
self.ip = ip

View 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.miners.base import BaseMiner
class S19aPro(BaseMiner): # noqa - ignore ABC method implementation
def __init__(self, ip: str):
super().__init__()
self.ip = ip
self.model = "S19a Pro"
self.nominal_chips = 100
self.fan_count = 4

View File

@@ -15,7 +15,7 @@
from pyasic.miners.base import BaseMiner
class S19j(BaseMiner):
class S19j(BaseMiner): # noqa - ignore ABC method implementation
def __init__(self, ip: str):
super().__init__()
self.ip = ip

View File

@@ -15,7 +15,7 @@
from pyasic.miners.base import BaseMiner
class S19jPro(BaseMiner):
class S19jPro(BaseMiner): # noqa - ignore ABC method implementation
def __init__(self, ip: str):
super().__init__()
self.ip = ip

View File

@@ -15,7 +15,7 @@
from pyasic.miners.base import BaseMiner
class T19(BaseMiner):
class T19(BaseMiner): # noqa - ignore ABC method implementation
def __init__(self, ip: str):
super().__init__()
self.ip = ip

View File

@@ -16,6 +16,7 @@ from .S19 import S19
from .S19_Pro import S19Pro
from .S19_XP import S19XP
from .S19a import S19a
from .S19a_Pro import S19aPro
from .S19j import S19j
from .S19j_Pro import S19jPro
from .T19 import T19

View File

@@ -15,7 +15,7 @@
from pyasic.miners.base import BaseMiner
class S9(BaseMiner):
class S9(BaseMiner): # noqa - ignore ABC method implementation
def __init__(self, ip: str):
super().__init__()
self.ip = ip

View File

@@ -15,7 +15,7 @@
from pyasic.miners.base import BaseMiner
class S9i(BaseMiner):
class S9i(BaseMiner): # noqa - ignore ABC method implementation
def __init__(self, ip: str):
super().__init__()
self.ip = ip

View File

@@ -15,7 +15,7 @@
from pyasic.miners.base import BaseMiner
class T9(BaseMiner):
class T9(BaseMiner): # noqa - ignore ABC method implementation
def __init__(self, ip: str):
super().__init__()
self.ip = ip

View File

@@ -15,7 +15,7 @@
from pyasic.miners.base import BaseMiner
class Avalon1026(BaseMiner):
class Avalon1026(BaseMiner): # noqa - ignore ABC method implementation
def __init__(self, ip: str):
super().__init__()
self.ip = ip

View File

@@ -15,7 +15,7 @@
from pyasic.miners.base import BaseMiner
class Avalon1047(BaseMiner):
class Avalon1047(BaseMiner): # noqa - ignore ABC method implementation
def __init__(self, ip: str):
super().__init__()
self.ip = ip

View File

@@ -15,7 +15,7 @@
from pyasic.miners.base import BaseMiner
class Avalon1066(BaseMiner):
class Avalon1066(BaseMiner): # noqa - ignore ABC method implementation
def __init__(self, ip: str):
super().__init__()
self.ip = ip

View File

@@ -15,10 +15,11 @@
from pyasic.miners.base import BaseMiner
class Avalon721(BaseMiner):
class Avalon721(BaseMiner): # noqa - ignore ABC method implementation
def __init__(self, ip: str):
super().__init__()
self.ip = ip
self.model = "Avalon 721"
self.chip_count = 18 # This miner has 4 boards totaling 72
self.fan_count = 1 # also only 1 fan
self.ideal_hashboards = 4
self.chip_count = 18
self.fan_count = 1

View File

@@ -15,10 +15,11 @@
from pyasic.miners.base import BaseMiner
class Avalon741(BaseMiner):
class Avalon741(BaseMiner): # noqa - ignore ABC method implementation
def __init__(self, ip: str):
super().__init__()
self.ip = ip
self.model = "Avalon 741"
self.chip_count = 22 # This miner has 4 boards totaling 88
self.fan_count = 1 # also only 1 fan
self.ideal_hashboards = 4
self.chip_count = 22
self.fan_count = 1

View File

@@ -15,10 +15,11 @@
from pyasic.miners.base import BaseMiner
class Avalon761(BaseMiner):
class Avalon761(BaseMiner): # noqa - ignore ABC method implementation
def __init__(self, ip: str):
super().__init__()
self.ip = ip
self.model = "Avalon 761"
self.chip_count = 18 # This miner has 4 boards totaling 72
self.fan_count = 1 # also only 1 fan
self.ideal_hashboards = 4
self.chip_count = 18
self.fan_count = 1

View File

@@ -15,10 +15,11 @@
from pyasic.miners.base import BaseMiner
class Avalon821(BaseMiner):
class Avalon821(BaseMiner): # noqa - ignore ABC method implementation
def __init__(self, ip: str):
super().__init__()
self.ip = ip
self.model = "Avalon 821"
self.chip_count = 26 # This miner has 4 boards totaling 104
self.fan_count = 1 # also only 1 fan
self.ideal_hashboards = 4
self.chip_count = 26
self.fan_count = 1

View File

@@ -15,10 +15,11 @@
from pyasic.miners.base import BaseMiner
class Avalon841(BaseMiner):
class Avalon841(BaseMiner): # noqa - ignore ABC method implementation
def __init__(self, ip: str):
super().__init__()
self.ip = ip
self.model = "Avalon 841"
self.chip_count = 26 # This miner has 4 boards totaling 104
self.fan_count = 1 # also only 1 fan
self.ideal_hashboards = 4
self.chip_count = 26
self.fan_count = 1

View File

@@ -15,10 +15,11 @@
from pyasic.miners.base import BaseMiner
class Avalon851(BaseMiner):
class Avalon851(BaseMiner): # noqa - ignore ABC method implementation
def __init__(self, ip: str):
super().__init__()
self.ip = ip
self.model = "Avalon 851"
self.chip_count = 26 # This miner has 4 boards totaling 104
self.fan_count = 1 # also only 1 fan
self.ideal_hashboards = 4
self.chip_count = 26
self.fan_count = 1

View File

@@ -15,10 +15,11 @@
from pyasic.miners.base import BaseMiner
class Avalon921(BaseMiner):
class Avalon921(BaseMiner): # noqa - ignore ABC method implementation
def __init__(self, ip: str):
super().__init__()
self.ip = ip
self.model = "Avalon 921"
self.chip_count = 26 # This miner has 4 boards totaling 104
self.fan_count = 1 # also only 1 fan
self.ideal_hashboards = 4
self.chip_count = 26
self.fan_count = 1

View File

@@ -15,7 +15,7 @@
from pyasic.miners.base import BaseMiner
class InnosiliconT3HPlus(BaseMiner):
class InnosiliconT3HPlus(BaseMiner): # noqa - ignore ABC method implementation
def __init__(self, ip: str) -> None:
super().__init__()
self.ip = ip

View File

@@ -15,7 +15,7 @@
from pyasic.miners.base import BaseMiner
class M20(BaseMiner):
class M20(BaseMiner): # noqa - ignore ABC method implementation
def __init__(self, ip: str):
super().__init__()
self.ip = ip
@@ -24,7 +24,7 @@ class M20(BaseMiner):
self.fan_count = 2
class M20V10(BaseMiner):
class M20V10(BaseMiner): # noqa - ignore ABC method implementation
def __init__(self, ip: str):
super().__init__()
self.ip = ip

View File

@@ -15,7 +15,7 @@
from pyasic.miners.base import BaseMiner
class M20S(BaseMiner):
class M20S(BaseMiner): # noqa - ignore ABC method implementation
def __init__(self, ip: str):
super().__init__()
self.ip = ip
@@ -24,7 +24,7 @@ class M20S(BaseMiner):
self.fan_count = 2
class M20SV10(BaseMiner):
class M20SV10(BaseMiner): # noqa - ignore ABC method implementation
def __init__(self, ip: str):
super().__init__()
self.ip = ip
@@ -33,7 +33,7 @@ class M20SV10(BaseMiner):
self.fan_count = 2
class M20SV20(BaseMiner):
class M20SV20(BaseMiner): # noqa - ignore ABC method implementation
def __init__(self, ip: str):
super().__init__()
self.ip = ip

View File

@@ -15,7 +15,7 @@
from pyasic.miners.base import BaseMiner
class M20SPlus(BaseMiner):
class M20SPlus(BaseMiner): # noqa - ignore ABC method implementation
def __init__(self, ip: str):
super().__init__()
self.ip = ip

View File

@@ -15,7 +15,7 @@
from pyasic.miners.base import BaseMiner
class M21(BaseMiner):
class M21(BaseMiner): # noqa - ignore ABC method implementation
def __init__(self, ip: str):
super().__init__()
self.ip = ip

View File

@@ -15,7 +15,7 @@
from pyasic.miners.base import BaseMiner
class M21S(BaseMiner):
class M21S(BaseMiner): # noqa - ignore ABC method implementation
def __init__(self, ip: str):
super().__init__()
self.ip = ip
@@ -24,7 +24,7 @@ class M21S(BaseMiner):
self.fan_count = 2
class M21SV60(BaseMiner):
class M21SV60(BaseMiner): # noqa - ignore ABC method implementation
def __init__(self, ip: str):
super().__init__()
self.ip = ip
@@ -33,7 +33,7 @@ class M21SV60(BaseMiner):
self.fan_count = 2
class M21SV20(BaseMiner):
class M21SV20(BaseMiner): # noqa - ignore ABC method implementation
def __init__(self, ip: str):
super().__init__()
self.ip = ip

View File

@@ -15,7 +15,7 @@
from pyasic.miners.base import BaseMiner
class M21SPlus(BaseMiner):
class M21SPlus(BaseMiner): # noqa - ignore ABC method implementation
def __init__(self, ip: str):
super().__init__()
self.ip = ip

View File

@@ -15,7 +15,7 @@
from pyasic.miners.base import BaseMiner
class M30S(BaseMiner):
class M30S(BaseMiner): # noqa - ignore ABC method implementation
def __init__(self, ip: str):
super().__init__()
self.ip = ip
@@ -24,7 +24,7 @@ class M30S(BaseMiner):
self.fan_count = 2
class M30SV50(BaseMiner):
class M30SV50(BaseMiner): # noqa - ignore ABC method implementation
def __init__(self, ip: str):
super().__init__()
self.ip = ip
@@ -33,7 +33,7 @@ class M30SV50(BaseMiner):
self.fan_count = 2
class M30SVG20(BaseMiner):
class M30SVG20(BaseMiner): # noqa - ignore ABC method implementation
def __init__(self, ip: str):
super().__init__()
self.ip = ip
@@ -42,7 +42,7 @@ class M30SVG20(BaseMiner):
self.fan_count = 2
class M30SVE20(BaseMiner):
class M30SVE20(BaseMiner): # noqa - ignore ABC method implementation
def __init__(self, ip: str):
super().__init__()
self.ip = ip
@@ -51,7 +51,7 @@ class M30SVE20(BaseMiner):
self.fan_count = 2
class M30SVE10(BaseMiner):
class M30SVE10(BaseMiner): # noqa - ignore ABC method implementation
def __init__(self, ip: str):
super().__init__()
self.ip = ip

View File

@@ -15,7 +15,7 @@
from pyasic.miners.base import BaseMiner
class M30SPlus(BaseMiner):
class M30SPlus(BaseMiner): # noqa - ignore ABC method implementation
def __init__(self, ip: str):
super().__init__()
self.ip = ip
@@ -24,7 +24,7 @@ class M30SPlus(BaseMiner):
self.fan_count = 2
class M30SPlusVG60(BaseMiner):
class M30SPlusVG60(BaseMiner): # noqa - ignore ABC method implementation
def __init__(self, ip: str):
super().__init__()
self.ip = ip
@@ -33,7 +33,7 @@ class M30SPlusVG60(BaseMiner):
self.fan_count = 2
class M30SPlusVE40(BaseMiner):
class M30SPlusVE40(BaseMiner): # noqa - ignore ABC method implementation
def __init__(self, ip: str):
super().__init__()
self.ip = ip
@@ -42,7 +42,7 @@ class M30SPlusVE40(BaseMiner):
self.fan_count = 2
class M30SPlusVF20(BaseMiner):
class M30SPlusVF20(BaseMiner): # noqa - ignore ABC method implementation
def __init__(self, ip: str):
super().__init__()
self.ip = ip

View File

@@ -15,7 +15,7 @@
from pyasic.miners.base import BaseMiner
class M30SPlusPlus(BaseMiner):
class M30SPlusPlus(BaseMiner): # noqa - ignore ABC method implementation
def __init__(self, ip: str):
super().__init__()
self.ip = ip
@@ -24,7 +24,7 @@ class M30SPlusPlus(BaseMiner):
self.fan_count = 2
class M30SPlusPlusVG30(BaseMiner):
class M30SPlusPlusVG30(BaseMiner): # noqa - ignore ABC method implementation
def __init__(self, ip: str):
super().__init__()
self.ip = ip
@@ -33,7 +33,7 @@ class M30SPlusPlusVG30(BaseMiner):
self.fan_count = 2
class M30SPlusPlusVG40(BaseMiner):
class M30SPlusPlusVG40(BaseMiner): # noqa - ignore ABC method implementation
def __init__(self, ip: str):
super().__init__()
self.ip = ip
@@ -42,7 +42,7 @@ class M30SPlusPlusVG40(BaseMiner):
self.fan_count = 2
class M30SPlusPlusVH60(BaseMiner):
class M30SPlusPlusVH60(BaseMiner): # noqa - ignore ABC method implementation
def __init__(self, ip: str):
super().__init__()
self.ip = ip

View File

@@ -15,10 +15,19 @@
from pyasic.miners.base import BaseMiner
class M31S(BaseMiner):
class M31S(BaseMiner): # noqa - ignore ABC method implementation
def __init__(self, ip: str):
super().__init__()
self.ip = ip
self.model = "M31S"
# TODO: Add chip count for this miner (per board) - self.nominal_chips
self.nominal_chips = 111
self.fan_count = 2
class M31SV70(BaseMiner): # noqa - ignore ABC method implementation
def __init__(self, ip: str):
super().__init__()
self.ip = ip
self.model = "M31S V70"
self.nominal_chips = 111
self.fan_count = 2

View File

@@ -15,7 +15,7 @@
from pyasic.miners.base import BaseMiner
class M31SPlus(BaseMiner):
class M31SPlus(BaseMiner): # noqa - ignore ABC method implementation
def __init__(self, ip: str):
super().__init__()
self.ip = ip
@@ -24,7 +24,7 @@ class M31SPlus(BaseMiner):
self.fan_count = 2
class M31SPlusVE20(BaseMiner):
class M31SPlusVE20(BaseMiner): # noqa - ignore ABC method implementation
def __init__(self, ip: str):
super().__init__()
self.ip = ip
@@ -33,7 +33,7 @@ class M31SPlusVE20(BaseMiner):
self.fan_count = 2
class M31SPlusV30(BaseMiner):
class M31SPlusV30(BaseMiner): # noqa - ignore ABC method implementation
def __init__(self, ip: str):
super().__init__()
self.ip = ip
@@ -42,7 +42,7 @@ class M31SPlusV30(BaseMiner):
self.fan_count = 2
class M31SPlusV40(BaseMiner):
class M31SPlusV40(BaseMiner): # noqa - ignore ABC method implementation
def __init__(self, ip: str):
super().__init__()
self.ip = ip
@@ -51,7 +51,7 @@ class M31SPlusV40(BaseMiner):
self.fan_count = 2
class M31SPlusV60(BaseMiner):
class M31SPlusV60(BaseMiner): # noqa - ignore ABC method implementation
def __init__(self, ip: str):
super().__init__()
self.ip = ip
@@ -60,7 +60,7 @@ class M31SPlusV60(BaseMiner):
self.fan_count = 2
class M31SPlusV80(BaseMiner):
class M31SPlusV80(BaseMiner): # noqa - ignore ABC method implementation
def __init__(self, ip: str):
super().__init__()
self.ip = ip
@@ -69,7 +69,7 @@ class M31SPlusV80(BaseMiner):
self.fan_count = 2
class M31SPlusV90(BaseMiner):
class M31SPlusV90(BaseMiner): # noqa - ignore ABC method implementation
def __init__(self, ip: str):
super().__init__()
self.ip = ip

View File

@@ -15,7 +15,7 @@
from pyasic.miners.base import BaseMiner
class M32(BaseMiner):
class M32(BaseMiner): # noqa - ignore ABC method implementation
def __init__(self, ip: str):
super().__init__()
self.ip = ip
@@ -24,7 +24,7 @@ class M32(BaseMiner):
self.fan_count = 2
class M32V20(BaseMiner):
class M32V20(BaseMiner): # noqa - ignore ABC method implementation
def __init__(self, ip: str):
super().__init__()
self.ip = ip

View File

@@ -15,7 +15,7 @@
from pyasic.miners.base import BaseMiner
class M32S(BaseMiner):
class M32S(BaseMiner): # noqa - ignore ABC method implementation
def __init__(self, ip: str):
super().__init__()
self.ip = ip

View File

@@ -15,7 +15,7 @@
from pyasic.miners.base import BaseMiner
class M34SPlus(BaseMiner):
class M34SPlus(BaseMiner): # noqa - ignore ABC method implementation
def __init__(self, ip: str):
super().__init__()
self.ip = ip
@@ -25,7 +25,7 @@ class M34SPlus(BaseMiner):
self.fan_count = 0
class M34SPlusVE10(BaseMiner):
class M34SPlusVE10(BaseMiner): # noqa - ignore ABC method implementation
def __init__(self, ip: str):
super().__init__()
self.ip = ip

View File

@@ -20,7 +20,7 @@ from .M30S_Plus_Plus import (
M30SPlusPlusVG40,
M30SPlusPlusVH60,
)
from .M31S import M31S
from .M31S import M31S, M31SV70
from .M31S_Plus import (
M31SPlus,
M31SPlusV30,

View File

@@ -15,7 +15,7 @@
from pyasic.miners.base import BaseMiner
class M50(BaseMiner):
class M50(BaseMiner): # noqa - ignore ABC method implementation
def __init__(self, ip: str):
super().__init__()
self.ip = ip
@@ -24,7 +24,7 @@ class M50(BaseMiner):
self.fan_count = 2
class M50VH50(BaseMiner):
class M50VH50(BaseMiner): # noqa - ignore ABC method implementation
def __init__(self, ip: str):
super().__init__()
self.ip = ip

View 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.miners._types import S19aPro # noqa - Ignore access to _module
from .X19 import BMMinerX19
class BMMinerS19aPro(BMMinerX19, S19aPro):
def __init__(self, ip: str) -> None:
super().__init__(ip)
self.ip = ip

View File

@@ -62,7 +62,7 @@ class BMMinerX19(BMMiner):
try:
async with httpx.AsyncClient() as client:
await client.post(url, data=conf, auth=auth)
await client.post(url, data=conf, auth=auth) # noqa - ignore conf being a str
except httpx.ReadTimeout:
pass
for i in range(7):
@@ -102,7 +102,7 @@ class BMMinerX19(BMMiner):
auth = httpx.DigestAuth(self.uname, self.pwd)
data = json.dumps({"blink": "true"})
async with httpx.AsyncClient() as client:
data = await client.post(url, data=data, auth=auth)
data = await client.post(url, data=data, auth=auth) # noqa - ignore conf being a str
if data.status_code == 200:
data = data.json()
if data.get("code") == "B000":
@@ -115,7 +115,7 @@ class BMMinerX19(BMMiner):
auth = httpx.DigestAuth(self.uname, self.pwd)
data = json.dumps({"blink": "false"})
async with httpx.AsyncClient() as client:
data = await client.post(url, data=data, auth=auth)
data = await client.post(url, data=data, auth=auth) # noqa - ignore conf being a str
if data.status_code == 200:
data = data.json()
if data.get("code") == "B100":
@@ -139,7 +139,10 @@ class BMMinerX19(BMMiner):
async with httpx.AsyncClient() as client:
data = await client.get(url, auth=auth)
if data:
data = data.json()
try:
data = data.json()
except json.decoder.JSONDecodeError:
return []
if "SUMMARY" in data.keys():
if "status" in data["SUMMARY"][0].keys():
for item in data["SUMMARY"][0]["status"]:

View File

@@ -16,6 +16,7 @@ from .S19 import BMMinerS19
from .S19_Pro import BMMinerS19Pro
from .S19_XP import BMMinerS19XP
from .S19a import BMMinerS19a
from .S19a_Pro import BMMinerS19aPro
from .S19j import BMMinerS19j
from .S19j_Pro import BMMinerS19jPro
from .T19 import BMMinerT19

View File

@@ -44,7 +44,6 @@ class HiveonT9(Hiveon, T9):
ideal_hashboards=self.ideal_hashboards,
)
board_offset = -1
fan_offset = -1
model = await self.get_model()

View File

@@ -15,18 +15,14 @@
import ipaddress
import logging
from abc import ABC, abstractmethod
from typing import List, TypeVar, Union
from typing import List, TypeVar
import asyncssh
from pyasic.config import MinerConfig
from pyasic.data import MinerData
from pyasic.data.error_codes import (
BraiinsOSError,
InnosiliconError,
MinerErrorData,
WhatsminerError,
X19Error,
)

View File

@@ -169,9 +169,6 @@ class CGMinerInnosiliconT3HPlus(CGMiner, InnosiliconT3HPlus):
],
)
board_offset = -1
fan_offset = -1
model = await self.get_model()
hostname = await self.get_hostname()

View File

@@ -131,6 +131,10 @@ MINER_CLASSES = {
"Default": BMMinerS19a,
"BMMiner": BMMinerS19a,
},
"ANTMINER S19A PRO": {
"Default": BMMinerS19aPro,
"BMMiner": BMMinerS19aPro,
},
"ANTMINER T19": {
"Default": BMMinerT19,
"BOSMiner+": BOSMinerT19,
@@ -186,10 +190,12 @@ MINER_CLASSES = {
"BTMiner": BTMinerM30SPlusPlus,
"G40": BTMinerM30SPlusPlusVG40,
"G30": BTMinerM30SPlusPlusVG30,
"H60": BTMinerM30SPlusPlusVH60,
},
"M31S": {
"Default": BTMinerM31S,
"BTMiner": BTMinerM31S,
"V70": BTMinerM31SV70,
},
"M31S+": {
"Default": BTMinerM31SPlus,
@@ -448,16 +454,21 @@ class MinerFactory(metaclass=Singleton):
api = "BOSMiner+"
except (KeyError, TypeError, ValueError, IndexError):
pass
if not model:
# braiins OS bug check just in case
if "s9" in devdetails["STATUS"][0]["Description"]:
model = "ANTMINER S9"
if "s17" in version["STATUS"][0]["Description"]:
model = "ANTMINER S17"
if not api:
if "boser" in version["STATUS"][0]["Description"]:
api = "BOSMiner+"
try:
if not model:
# braiins OS bug check just in case
if "s9" in devdetails["STATUS"][0]["Description"]:
model = "ANTMINER S9"
if "s17" in version["STATUS"][0]["Description"]:
model = "ANTMINER S17"
except (KeyError, TypeError, ValueError, IndexError):
pass
try:
if not api:
if "boser" in version["STATUS"][0]["Description"]:
api = "BOSMiner+"
except (KeyError, TypeError, ValueError, IndexError):
pass
else:
try:
_model = await self.__get_model_from_graphql(ip)
@@ -572,7 +583,7 @@ class MinerFactory(metaclass=Singleton):
try:
if data["version"][0]["STATUS"][0]["Msg"] == "Disconnected":
return data["devdetails"], data["version"]
except KeyError:
except (KeyError, TypeError):
pass
raise APIError(validation[1])
# copy each part of the main command to devdetails and version

View File

@@ -13,10 +13,16 @@
# limitations under the License.
from pyasic.miners._backends import BTMiner # noqa - Ignore access to _module
from pyasic.miners._types import M31S # noqa - Ignore access to _module
from pyasic.miners._types import M31S, M31SV70 # noqa - Ignore access to _module
class BTMinerM31S(BTMiner, M31S):
def __init__(self, ip: str) -> None:
super().__init__(ip)
self.ip = ip
class BTMinerM31SV70(BTMiner, M31SV70):
def __init__(self, ip: str) -> None:
super().__init__(ip)
self.ip = ip

View File

@@ -31,7 +31,7 @@ from .M30S_Plus_Plus import (
BTMinerM30SPlusPlusVG40,
BTMinerM30SPlusPlusVH60,
)
from .M31S import BTMinerM31S
from .M31S import BTMinerM31S, BTMinerM31SV70
from .M31S_Plus import (
BTMinerM31SPlus,
BTMinerM31SPlusV30,

View File

@@ -1,6 +1,6 @@
[tool.poetry]
name = "pyasic"
version = "0.21.12"
version = "0.22.2"
description = "A set of modules for interfacing with many common types of ASIC bitcoin miners, using both their API and SSH."
authors = ["UpstreamData <brett@upstreamdata.ca>"]
repository = "https://github.com/UpstreamData/pyasic"

View File

@@ -16,10 +16,9 @@ import inspect
import sys
import unittest
from pyasic.miners._backends import CGMiner
from pyasic.miners._backends import CGMiner # noqa
from pyasic.miners.base import BaseMiner
from pyasic.miners.miner_factory import MINER_CLASSES, MinerFactory
from pyasic.miners.miner_listener import MinerListener
class MinersTest(unittest.TestCase):

View File

@@ -16,7 +16,6 @@ import ipaddress
import unittest
from pyasic.network import MinerNetwork
from pyasic.network.net_range import MinerNetworkRange
class NetworkTest(unittest.TestCase):