Compare commits
15 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f69e07fe68 | ||
|
|
84aab38954 | ||
|
|
dcf37481bd | ||
|
|
1a9cca84d5 | ||
|
|
c5272d67de | ||
|
|
3bcfb14177 | ||
|
|
566280f280 | ||
|
|
a814f7eefb | ||
|
|
097b8ed534 | ||
|
|
da47d72749 | ||
|
|
abd4d18a01 | ||
|
|
2adbce3c21 | ||
|
|
c41324b324 | ||
|
|
151a4f6c2d | ||
|
|
d23777a83f |
@@ -46,7 +46,7 @@ from pyasic.network import MinerNetwork
|
|||||||
async def scan_and_get_data():
|
async def scan_and_get_data():
|
||||||
# Define network range to be used for scanning
|
# Define network range to be used for scanning
|
||||||
# This can take a list of IPs, a constructor string, or an IP and subnet mask
|
# 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)
|
net = MinerNetwork("192.168.1.69", mask=24)
|
||||||
# Scan the network for miners
|
# Scan the network for miners
|
||||||
# This function returns a list of miners of the correct type as a class
|
# 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.
|
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
|
#### List available API commands
|
||||||
```python
|
```python
|
||||||
import asyncio
|
import asyncio
|
||||||
@@ -105,7 +109,8 @@ async def get_api_commands(miner_ip: str):
|
|||||||
miner = await get_miner(miner_ip)
|
miner = await get_miner(miner_ip)
|
||||||
|
|
||||||
# List all available commands
|
# 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__":
|
if __name__ == "__main__":
|
||||||
|
|||||||
@@ -90,6 +90,9 @@ details {
|
|||||||
</details>
|
</details>
|
||||||
<details>
|
<details>
|
||||||
<summary><a href="../whatsminer/M3X/#m31s">M31S</a></summary>
|
<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>
|
<summary><a href="../whatsminer/M3X/#m31sv70">M31SV70</a></summary>
|
||||||
</details>
|
</details>
|
||||||
<details>
|
<details>
|
||||||
|
|||||||
@@ -114,9 +114,33 @@
|
|||||||
show_root_heading: false
|
show_root_heading: false
|
||||||
heading_level: 4
|
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
|
## M31SV70
|
||||||
|
|
||||||
::: pyasic.miners.whatsminer.btminer.M3X.M31S.BTMinerM31S
|
::: pyasic.miners.whatsminer.btminer.M3X.M31S.BTMinerM31SV70
|
||||||
handler: python
|
handler: python
|
||||||
options:
|
options:
|
||||||
show_root_heading: false
|
show_root_heading: false
|
||||||
|
|||||||
@@ -121,6 +121,7 @@ class BaseMinerAPI:
|
|||||||
for func in
|
for func in
|
||||||
# each function in self
|
# each function in self
|
||||||
dir(self)
|
dir(self)
|
||||||
|
if not func == "commands"
|
||||||
if callable(getattr(self, func)) and
|
if callable(getattr(self, func)) and
|
||||||
# no __ or _ methods
|
# no __ or _ methods
|
||||||
not func.startswith("__") and not func.startswith("_") and
|
not func.startswith("__") and not func.startswith("_") and
|
||||||
|
|||||||
@@ -198,6 +198,8 @@ class BTMinerAPI(BaseMinerAPI):
|
|||||||
enc_command = create_privileged_cmd(token_data, command)
|
enc_command = create_privileged_cmd(token_data, command)
|
||||||
|
|
||||||
data = await self._send_bytes(enc_command)
|
data = await self._send_bytes(enc_command)
|
||||||
|
if not data:
|
||||||
|
raise APIError("No data was returned from the API.")
|
||||||
data = self._load_api_data(data)
|
data = self._load_api_data(data)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|||||||
@@ -327,7 +327,7 @@ class BOSMiner(BaseMiner):
|
|||||||
if board["Status"] not in [
|
if board["Status"] not in [
|
||||||
"Stable",
|
"Stable",
|
||||||
"Testing performance profile",
|
"Testing performance profile",
|
||||||
"Tuning individual chips"
|
"Tuning individual chips",
|
||||||
]:
|
]:
|
||||||
_error = board["Status"].split(" {")[0]
|
_error = board["Status"].split(" {")[0]
|
||||||
_error = _error[0].lower() + _error[1:]
|
_error = _error[0].lower() + _error[1:]
|
||||||
@@ -471,6 +471,16 @@ class BOSMiner(BaseMiner):
|
|||||||
data.pool_2_user = pool_2_user
|
data.pool_2_user = pool_2_user
|
||||||
|
|
||||||
if quota:
|
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)
|
data.pool_split = str(quota)
|
||||||
|
|
||||||
if tunerstatus:
|
if tunerstatus:
|
||||||
@@ -558,9 +568,13 @@ class BOSMiner(BaseMiner):
|
|||||||
data.hostname = query_data["bos"]["hostname"]
|
data.hostname = query_data["bos"]["hostname"]
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if query_data["bosminer"]["info"]["workSolver"]["realHashrate"].get("mhs1M"):
|
if query_data["bosminer"]["info"]["workSolver"]["realHashrate"].get(
|
||||||
|
"mhs1M"
|
||||||
|
):
|
||||||
data.hashrate = round(
|
data.hashrate = round(
|
||||||
query_data["bosminer"]["info"]["workSolver"]["realHashrate"]["mhs1M"]
|
query_data["bosminer"]["info"]["workSolver"]["realHashrate"][
|
||||||
|
"mhs1M"
|
||||||
|
]
|
||||||
/ 1000000,
|
/ 1000000,
|
||||||
2,
|
2,
|
||||||
)
|
)
|
||||||
@@ -571,9 +585,13 @@ class BOSMiner(BaseMiner):
|
|||||||
if query_data.get("bosminer"):
|
if query_data.get("bosminer"):
|
||||||
if query_data["bosminer"].get("info"):
|
if query_data["bosminer"].get("info"):
|
||||||
if query_data["bosminer"]["info"].get("workSolver"):
|
if query_data["bosminer"]["info"].get("workSolver"):
|
||||||
boards = query_data["bosminer"]["info"]["workSolver"].get("childSolvers")
|
boards = query_data["bosminer"]["info"]["workSolver"].get(
|
||||||
|
"childSolvers"
|
||||||
|
)
|
||||||
if boards:
|
if boards:
|
||||||
offset = 6 if int(boards[0]["name"]) in [6, 7, 8] else int(boards[0]["name"])
|
offset = (
|
||||||
|
6 if int(boards[0]["name"]) in [6, 7, 8] else int(boards[0]["name"])
|
||||||
|
)
|
||||||
for hb in boards:
|
for hb in boards:
|
||||||
_id = int(hb["name"]) - offset
|
_id = int(hb["name"]) - offset
|
||||||
|
|
||||||
@@ -600,24 +618,33 @@ class BOSMiner(BaseMiner):
|
|||||||
if hb["tuner"]["statusMessages"][0] not in [
|
if hb["tuner"]["statusMessages"][0] not in [
|
||||||
"Stable",
|
"Stable",
|
||||||
"Testing performance profile",
|
"Testing performance profile",
|
||||||
"Tuning individual chips"
|
"Tuning individual chips",
|
||||||
]:
|
]:
|
||||||
data.errors.append(
|
data.errors.append(
|
||||||
BraiinsOSError(f"Slot {_id} {hb['tuner']['statusMessages'][0]}")
|
BraiinsOSError(
|
||||||
|
f"Slot {_id} {hb['tuner']['statusMessages'][0]}"
|
||||||
|
)
|
||||||
)
|
)
|
||||||
try:
|
try:
|
||||||
data.wattage = query_data["bosminer"]["info"]["workSolver"]["power"]["approxConsumptionW"]
|
data.wattage = query_data["bosminer"]["info"]["workSolver"]["power"][
|
||||||
|
"approxConsumptionW"
|
||||||
|
]
|
||||||
except (TypeError, KeyError, ValueError, IndexError):
|
except (TypeError, KeyError, ValueError, IndexError):
|
||||||
data.wattage = 0
|
data.wattage = 0
|
||||||
try:
|
try:
|
||||||
data.wattage_limit = query_data["bosminer"]["info"]["workSolver"]["power"]["limitW"]
|
data.wattage_limit = query_data["bosminer"]["info"]["workSolver"]["power"][
|
||||||
|
"limitW"
|
||||||
|
]
|
||||||
except (TypeError, KeyError, ValueError, IndexError):
|
except (TypeError, KeyError, ValueError, IndexError):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
for n in range(self.fan_count):
|
for n in range(self.fan_count):
|
||||||
try:
|
try:
|
||||||
setattr(data, f"fan_{n + 1}", query_data["bosminer"]["info"]["fans"][n]["rpm"])
|
setattr(
|
||||||
|
data,
|
||||||
|
f"fan_{n + 1}",
|
||||||
|
query_data["bosminer"]["info"]["fans"][n]["rpm"],
|
||||||
|
)
|
||||||
except (TypeError, KeyError, ValueError, IndexError):
|
except (TypeError, KeyError, ValueError, IndexError):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@@ -632,7 +659,11 @@ class BOSMiner(BaseMiner):
|
|||||||
except (TypeError, KeyError, ValueError, IndexError):
|
except (TypeError, KeyError, ValueError, IndexError):
|
||||||
pass
|
pass
|
||||||
try:
|
try:
|
||||||
data.pool_1_url = groups[0]["pools"][0]["url"]
|
data.pool_1_url = (
|
||||||
|
groups[0]["pools"][0]["url"]
|
||||||
|
.replace("stratum+tcp://", "")
|
||||||
|
.replace("stratum2+tcp://", "")
|
||||||
|
)
|
||||||
except (TypeError, KeyError, ValueError, IndexError):
|
except (TypeError, KeyError, ValueError, IndexError):
|
||||||
pass
|
pass
|
||||||
try:
|
try:
|
||||||
@@ -640,7 +671,11 @@ class BOSMiner(BaseMiner):
|
|||||||
except (TypeError, KeyError, ValueError, IndexError):
|
except (TypeError, KeyError, ValueError, IndexError):
|
||||||
pass
|
pass
|
||||||
try:
|
try:
|
||||||
data.pool_2_url = groups[0]["pools"][1]["url"]
|
data.pool_2_url = (
|
||||||
|
groups[0]["pools"][1]["url"]
|
||||||
|
.replace("stratum+tcp://", "")
|
||||||
|
.replace("stratum2+tcp://", "")
|
||||||
|
)
|
||||||
except (TypeError, KeyError, ValueError, IndexError):
|
except (TypeError, KeyError, ValueError, IndexError):
|
||||||
pass
|
pass
|
||||||
data.quota = 0
|
data.quota = 0
|
||||||
@@ -650,7 +685,11 @@ class BOSMiner(BaseMiner):
|
|||||||
except (TypeError, KeyError, ValueError, IndexError):
|
except (TypeError, KeyError, ValueError, IndexError):
|
||||||
pass
|
pass
|
||||||
try:
|
try:
|
||||||
data.pool_1_url = groups[0]["pools"][0]["url"]
|
data.pool_1_url = (
|
||||||
|
groups[0]["pools"][0]["url"]
|
||||||
|
.replace("stratum+tcp://", "")
|
||||||
|
.replace("stratum2+tcp://", "")
|
||||||
|
)
|
||||||
except (TypeError, KeyError, ValueError, IndexError):
|
except (TypeError, KeyError, ValueError, IndexError):
|
||||||
pass
|
pass
|
||||||
try:
|
try:
|
||||||
@@ -658,11 +697,19 @@ class BOSMiner(BaseMiner):
|
|||||||
except (TypeError, KeyError, ValueError, IndexError):
|
except (TypeError, KeyError, ValueError, IndexError):
|
||||||
pass
|
pass
|
||||||
try:
|
try:
|
||||||
data.pool_2_url = groups[1]["pools"][0]["url"]
|
data.pool_2_url = (
|
||||||
|
groups[1]["pools"][0]["url"]
|
||||||
|
.replace("stratum+tcp://", "")
|
||||||
|
.replace("stratum2+tcp://", "")
|
||||||
|
)
|
||||||
except (TypeError, KeyError, ValueError, IndexError):
|
except (TypeError, KeyError, ValueError, IndexError):
|
||||||
pass
|
pass
|
||||||
if groups[0]["strategy"].get("quota"):
|
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()
|
data.fault_light = await self.check_light()
|
||||||
|
|
||||||
|
|||||||
@@ -238,16 +238,24 @@ class BTMiner(BaseMiner):
|
|||||||
|
|
||||||
async def get_config(self) -> MinerConfig:
|
async def get_config(self) -> MinerConfig:
|
||||||
pools = None
|
pools = None
|
||||||
|
summary = None
|
||||||
cfg = MinerConfig()
|
cfg = MinerConfig()
|
||||||
|
|
||||||
try:
|
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:
|
except APIError as e:
|
||||||
logging.warning(e)
|
logging.warning(e)
|
||||||
|
|
||||||
if pools:
|
if pools:
|
||||||
if "POOLS" in pools.keys():
|
if "POOLS" in pools:
|
||||||
cfg = cfg.from_api(pools["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
|
return cfg
|
||||||
|
|
||||||
async def get_data(self, allow_warning: bool = True) -> MinerData:
|
async def get_data(self, allow_warning: bool = True) -> MinerData:
|
||||||
|
|||||||
@@ -24,6 +24,31 @@ class M31S(BaseMiner): # noqa - ignore ABC method implementation
|
|||||||
self.fan_count = 2
|
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
|
class M31SV70(BaseMiner): # noqa - ignore ABC method implementation
|
||||||
def __init__(self, ip: str):
|
def __init__(self, ip: str):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ from .M30S_Plus_Plus import (
|
|||||||
M30SPlusPlusVG40,
|
M30SPlusPlusVG40,
|
||||||
M30SPlusPlusVH60,
|
M30SPlusPlusVH60,
|
||||||
)
|
)
|
||||||
from .M31S import M31S, M31SV70
|
from .M31S import M31S, M31SV10, M31SV20, M31SV60, M31SV70
|
||||||
from .M31S_Plus import (
|
from .M31S_Plus import (
|
||||||
M31SPlus,
|
M31SPlus,
|
||||||
M31SPlusV30,
|
M31SPlusV30,
|
||||||
|
|||||||
@@ -218,6 +218,9 @@ class BaseMiner(ABC):
|
|||||||
async def set_power_limit(self, wattage: int) -> bool:
|
async def set_power_limit(self, wattage: int) -> bool:
|
||||||
"""Set the power limit to be used by the miner.
|
"""Set the power limit to be used by the miner.
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
wattage: The power limit to set on the miner.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
A boolean value of the success of setting the power limit.
|
A boolean value of the success of setting the power limit.
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -195,7 +195,10 @@ MINER_CLASSES = {
|
|||||||
"M31S": {
|
"M31S": {
|
||||||
"Default": BTMinerM31S,
|
"Default": BTMinerM31S,
|
||||||
"BTMiner": BTMinerM31S,
|
"BTMiner": BTMinerM31S,
|
||||||
"V70": BTMinerM31SV70,
|
"10": BTMinerM31SV10,
|
||||||
|
"20": BTMinerM31SV20,
|
||||||
|
"60": BTMinerM31SV60,
|
||||||
|
"70": BTMinerM31SV70,
|
||||||
},
|
},
|
||||||
"M31S+": {
|
"M31S+": {
|
||||||
"Default": BTMinerM31SPlus,
|
"Default": BTMinerM31SPlus,
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
from pyasic.miners._backends import BTMiner # noqa - Ignore access to _module
|
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):
|
class BTMinerM31S(BTMiner, M31S):
|
||||||
@@ -21,6 +21,23 @@ class BTMinerM31S(BTMiner, M31S):
|
|||||||
super().__init__(ip)
|
super().__init__(ip)
|
||||||
self.ip = 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):
|
class BTMinerM31SV70(BTMiner, M31SV70):
|
||||||
def __init__(self, ip: str) -> None:
|
def __init__(self, ip: str) -> None:
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ from .M30S_Plus_Plus import (
|
|||||||
BTMinerM30SPlusPlusVG40,
|
BTMinerM30SPlusPlusVG40,
|
||||||
BTMinerM30SPlusPlusVH60,
|
BTMinerM30SPlusPlusVH60,
|
||||||
)
|
)
|
||||||
from .M31S import BTMinerM31S, BTMinerM31SV70
|
from .M31S import BTMinerM31S, BTMinerM31SV10, BTMinerM31SV20, BTMinerM31SV60, BTMinerM31SV70
|
||||||
from .M31S_Plus import (
|
from .M31S_Plus import (
|
||||||
BTMinerM31SPlus,
|
BTMinerM31SPlus,
|
||||||
BTMinerM31SPlusV30,
|
BTMinerM31SPlusV30,
|
||||||
|
|||||||
@@ -110,23 +110,9 @@ class MinerNetwork:
|
|||||||
scan_tasks = []
|
scan_tasks = []
|
||||||
miners = []
|
miners = []
|
||||||
|
|
||||||
# for each IP in the network
|
|
||||||
for host in local_network.hosts():
|
|
||||||
|
|
||||||
# make sure we don't exceed the allowed async tasks
|
limit = asyncio.Semaphore(PyasicSettings().network_scan_threads)
|
||||||
if len(scan_tasks) < round(PyasicSettings().network_scan_threads):
|
miners = await asyncio.gather(*[self.ping_and_get_miner(host, limit) for host in local_network.hosts()])
|
||||||
# add the task to the list
|
|
||||||
scan_tasks.append(self.ping_and_get_miner(host))
|
|
||||||
else:
|
|
||||||
# run the scan tasks
|
|
||||||
miners_scan = await asyncio.gather(*scan_tasks)
|
|
||||||
# add scanned miners to the list of found miners
|
|
||||||
miners.extend(miners_scan)
|
|
||||||
# empty the task list
|
|
||||||
scan_tasks = []
|
|
||||||
# do a final scan to empty out the list
|
|
||||||
miners_scan = await asyncio.gather(*scan_tasks)
|
|
||||||
miners.extend(miners_scan)
|
|
||||||
|
|
||||||
# remove all None from the miner list
|
# remove all None from the miner list
|
||||||
miners = list(filter(None, miners))
|
miners = list(filter(None, miners))
|
||||||
@@ -151,29 +137,15 @@ class MinerNetwork:
|
|||||||
# create a list of scan tasks
|
# create a list of scan tasks
|
||||||
scan_tasks = []
|
scan_tasks = []
|
||||||
|
|
||||||
# for each ip on the network, loop through and scan it
|
limit = asyncio.Semaphore(PyasicSettings().network_scan_threads)
|
||||||
for host in local_network.hosts():
|
miners = asyncio.as_completed([loop.create_task(self.ping_and_get_miner(host, limit)) for host in local_network.hosts()])
|
||||||
# make sure we don't exceed the allowed async tasks
|
for miner in miners:
|
||||||
if len(scan_tasks) >= round(PyasicSettings().network_scan_threads):
|
|
||||||
# scanned is a loopable list of awaitables
|
|
||||||
scanned = asyncio.as_completed(scan_tasks)
|
|
||||||
# when we scan, empty the scan tasks
|
|
||||||
scan_tasks = []
|
|
||||||
|
|
||||||
# yield miners as they are scanned
|
|
||||||
for miner in scanned:
|
|
||||||
yield await miner
|
yield await miner
|
||||||
|
|
||||||
# add the ping to the list of tasks if we dont scan
|
|
||||||
scan_tasks.append(loop.create_task(self.ping_and_get_miner(host)))
|
|
||||||
|
|
||||||
# do one last scan at the end to close out the list
|
|
||||||
scanned = asyncio.as_completed(scan_tasks)
|
|
||||||
for miner in scanned:
|
|
||||||
yield await miner
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
async def ping_miner(ip: ipaddress.ip_address) -> Union[None, ipaddress.ip_address]:
|
async def ping_miner(ip: ipaddress.ip_address, semaphore: asyncio.Semaphore) -> Union[None, ipaddress.ip_address]:
|
||||||
|
async with semaphore:
|
||||||
try:
|
try:
|
||||||
miner = await ping_miner(ip)
|
miner = await ping_miner(ip)
|
||||||
if miner:
|
if miner:
|
||||||
@@ -190,8 +162,9 @@ class MinerNetwork:
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
async def ping_and_get_miner(
|
async def ping_and_get_miner(
|
||||||
ip: ipaddress.ip_address,
|
ip: ipaddress.ip_address, semaphore: asyncio.Semaphore
|
||||||
) -> Union[None, AnyMiner]:
|
) -> Union[None, AnyMiner]:
|
||||||
|
async with semaphore:
|
||||||
try:
|
try:
|
||||||
miner = await ping_and_get_miner(ip)
|
miner = await ping_and_get_miner(ip)
|
||||||
if miner:
|
if miner:
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[tool.poetry]
|
[tool.poetry]
|
||||||
name = "pyasic"
|
name = "pyasic"
|
||||||
version = "0.23.1"
|
version = "0.24.3"
|
||||||
description = "A set of modules for interfacing with many common types of ASIC bitcoin miners, using both their API and SSH."
|
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>"]
|
authors = ["UpstreamData <brett@upstreamdata.ca>"]
|
||||||
repository = "https://github.com/UpstreamData/pyasic"
|
repository = "https://github.com/UpstreamData/pyasic"
|
||||||
|
|||||||
Reference in New Issue
Block a user