Compare commits

..

9 Commits

Author SHA1 Message Date
UpstreamData
dcf37481bd version: bump version number. 2022-12-05 09:35:44 -07:00
UpstreamData
1a9cca84d5 bug: fix pool split not being found correctly with braiinsOS. 2022-12-05 09:34:43 -07:00
UpstreamData
c5272d67de version: bump version number 2022-12-03 14:20:57 -07:00
UpstreamData
3bcfb14177 feature: add support for Whatsminer M31SV20, and fix a bug with miner factory not identifying the miners properly by removing a V prefix. 2022-12-03 14:20:37 -07:00
UpstreamData
566280f280 docs: fix some missing data in the docs. 2022-12-02 16:10:30 -07:00
UpstreamData
a814f7eefb Update README.md 2022-12-02 16:06:22 -07:00
UpstreamData
097b8ed534 version: bump version number. 2022-12-02 15:57:52 -07:00
UpstreamData
da47d72749 feature: add wattage limit in get_config when getting config from whatsminers. 2022-12-02 15:57:31 -07:00
UpstreamData
abd4d18a01 feature: add whatsminer M31SV10 and V60. 2022-12-02 15:51:27 -07:00
12 changed files with 106 additions and 12 deletions

View File

@@ -46,7 +46,7 @@ from pyasic.network import MinerNetwork
async def scan_and_get_data():
# Define network range to be used for scanning
# This can take a list of IPs, a constructor string, or an IP and subnet mask
# The standard mask is /24, and you can pass any IP address in the subnet
# The standard mask is /24 (x.x.x.0-255), and you can pass any IP address in the subnet
net = MinerNetwork("192.168.1.69", mask=24)
# Scan the network for miners
# This function returns a list of miners of the correct type as a class
@@ -93,6 +93,10 @@ if __name__ == "__main__":
If needed, this library exposes a wrapper for the miner API that can be used for advanced data gathering.
You can see more information on basic usage of the APIs past this example in the docs [here](https://pyasic.readthedocs.io/en/latest/API/api/).
Please see the appropriate API documentation page (pyasic docs -> Advanced -> Miner APIs -> your API type) for a link to that specific miner's API documentation page and more information.
#### List available API commands
```python
import asyncio
@@ -105,7 +109,8 @@ async def get_api_commands(miner_ip: str):
miner = await get_miner(miner_ip)
# List all available commands
print(miner.api.get_commands())
# Can also be called explicitly with the function miner.api.get_commands()
print(miner.api.commands)
if __name__ == "__main__":

View File

@@ -90,6 +90,9 @@ details {
</details>
<details>
<summary><a href="../whatsminer/M3X/#m31s">M31S</a></summary>
<summary><a href="../whatsminer/M3X/#m31sv10">M31SV10</a></summary>
<summary><a href="../whatsminer/M3X/#m31sv20">M31SV20</a></summary>
<summary><a href="../whatsminer/M3X/#m31sv60">M31SV60</a></summary>
<summary><a href="../whatsminer/M3X/#m31sv70">M31SV70</a></summary>
</details>
<details>

View File

@@ -114,9 +114,33 @@
show_root_heading: false
heading_level: 4
## M31SV10
::: pyasic.miners.whatsminer.btminer.M3X.M31S.BTMinerM31SV10
handler: python
options:
show_root_heading: false
heading_level: 4
## M31SV20
::: pyasic.miners.whatsminer.btminer.M3X.M31S.BTMinerM31SV20
handler: python
options:
show_root_heading: false
heading_level: 4
## M31SV60
::: pyasic.miners.whatsminer.btminer.M3X.M31S.BTMinerM31SV60
handler: python
options:
show_root_heading: false
heading_level: 4
## M31SV70
::: pyasic.miners.whatsminer.btminer.M3X.M31S.BTMinerM31S
::: pyasic.miners.whatsminer.btminer.M3X.M31S.BTMinerM31SV70
handler: python
options:
show_root_heading: false

View File

@@ -28,7 +28,7 @@ from pyasic.errors import APIError
from pyasic.miners.base import BaseMiner
from pyasic.settings import PyasicSettings
#TODO: Fix quota splitting in get data
class BOSMiner(BaseMiner):
def __init__(self, ip: str) -> None:
super().__init__(ip)
@@ -471,6 +471,12 @@ class BOSMiner(BaseMiner):
data.pool_2_user = pool_2_user
if quota:
if not quota == "0":
cfg = await self.get_config()
if cfg:
if len(cfg.pool_groups) > 1:
quota = str(cfg.pool_groups[0].quota) + "/" + str(cfg.pool_groups[1].quota)
data.pool_split = str(quota)
if tunerstatus:
@@ -662,7 +668,7 @@ class BOSMiner(BaseMiner):
except (TypeError, KeyError, ValueError, IndexError):
pass
if groups[0]["strategy"].get("quota"):
data.quota = str(groups[0]["strategy"]["quota"]) + "/" + str(groups[1]["strategy"]["quota"])
data.pool_split = str(groups[0]["strategy"]["quota"]) + "/" + str(groups[1]["strategy"]["quota"])
data.fault_light = await self.check_light()

View File

@@ -238,16 +238,24 @@ class BTMiner(BaseMiner):
async def get_config(self) -> MinerConfig:
pools = None
summary = None
cfg = MinerConfig()
try:
pools = await self.api.pools()
data = await self.api.multicommand("pools", "summary")
pools = data["pools"][0]
summary = data["summary"][0]
except APIError as e:
logging.warning(e)
if pools:
if "POOLS" in pools.keys():
if "POOLS" in pools:
cfg = cfg.from_api(pools["POOLS"])
if summary:
if "SUMMARY" in summary:
if wattage := summary["SUMMARY"][0].get("Power Limit"):
cfg.autotuning_wattage = wattage
return cfg
async def get_data(self, allow_warning: bool = True) -> MinerData:

View File

@@ -24,6 +24,31 @@ class M31S(BaseMiner): # noqa - ignore ABC method implementation
self.fan_count = 2
class M31SV10(BaseMiner): # noqa - ignore ABC method implementation
def __init__(self, ip: str):
super().__init__()
self.ip = ip
self.model = "M31S V10"
self.nominal_chips = 105
self.fan_count = 2
class M31SV20(BaseMiner): # noqa - ignore ABC method implementation
def __init__(self, ip: str):
super().__init__()
self.ip = ip
self.model = "M31S V20"
self.nominal_chips = 111
self.fan_count = 2
class M31SV60(BaseMiner): # noqa - ignore ABC method implementation
def __init__(self, ip: str):
super().__init__()
self.ip = ip
self.model = "M31S V60"
self.nominal_chips = 105
self.fan_count = 2
class M31SV70(BaseMiner): # noqa - ignore ABC method implementation
def __init__(self, ip: str):
super().__init__()

View File

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

View File

@@ -218,6 +218,9 @@ class BaseMiner(ABC):
async def set_power_limit(self, wattage: int) -> bool:
"""Set the power limit to be used by the miner.
Parameters:
wattage: The power limit to set on the miner.
Returns:
A boolean value of the success of setting the power limit.
"""

View File

@@ -195,7 +195,10 @@ MINER_CLASSES = {
"M31S": {
"Default": BTMinerM31S,
"BTMiner": BTMinerM31S,
"V70": BTMinerM31SV70,
"10": BTMinerM31SV10,
"20": BTMinerM31SV20,
"60": BTMinerM31SV60,
"70": BTMinerM31SV70,
},
"M31S+": {
"Default": BTMinerM31SPlus,

View File

@@ -13,7 +13,7 @@
# limitations under the License.
from pyasic.miners._backends import BTMiner # noqa - Ignore access to _module
from pyasic.miners._types import M31S, M31SV70 # noqa - Ignore access to _module
from pyasic.miners._types import M31S, M31SV10, M31SV20, M31SV60, M31SV70 # noqa - Ignore access to _module
class BTMinerM31S(BTMiner, M31S):
@@ -21,6 +21,23 @@ class BTMinerM31S(BTMiner, M31S):
super().__init__(ip)
self.ip = ip
class BTMinerM31SV20(BTMiner, M31SV20):
def __init__(self, ip: str) -> None:
super().__init__(ip)
self.ip = ip
class BTMinerM31SV10(BTMiner, M31SV10):
def __init__(self, ip: str) -> None:
super().__init__(ip)
self.ip = ip
class BTMinerM31SV60(BTMiner, M31SV60):
def __init__(self, ip: str) -> None:
super().__init__(ip)
self.ip = ip
class BTMinerM31SV70(BTMiner, M31SV70):
def __init__(self, ip: str) -> None:

View File

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

View File

@@ -1,6 +1,6 @@
[tool.poetry]
name = "pyasic"
version = "0.23.3"
version = "0.24.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"