refactor: re-arrange some imports.
This commit is contained in:
@@ -15,44 +15,10 @@
|
|||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
from pyasic import settings
|
from pyasic import settings
|
||||||
from pyasic.config import MinerConfig
|
from pyasic.config import MinerConfig
|
||||||
from pyasic.data import (
|
from pyasic.data import MinerData
|
||||||
BraiinsOSError,
|
|
||||||
InnosiliconError,
|
|
||||||
MinerData,
|
|
||||||
WhatsminerError,
|
|
||||||
X19Error,
|
|
||||||
)
|
|
||||||
from pyasic.errors import APIError, APIWarning
|
from pyasic.errors import APIError, APIWarning
|
||||||
from pyasic.miners import AnyMiner, DataOptions, get_miner
|
from pyasic.miners import *
|
||||||
from pyasic.miners.factory import MinerFactory, miner_factory
|
|
||||||
from pyasic.miners.listener import MinerListener
|
|
||||||
from pyasic.network import MinerNetwork
|
from pyasic.network import MinerNetwork
|
||||||
from pyasic.rpc.bmminer import BMMinerRPCAPI
|
from pyasic.rpc import *
|
||||||
from pyasic.rpc.bosminer import BOSMinerRPCAPI
|
from pyasic.ssh import *
|
||||||
from pyasic.rpc.btminer import BTMinerRPCAPI
|
from pyasic.web import *
|
||||||
from pyasic.rpc.cgminer import CGMinerRPCAPI
|
|
||||||
from pyasic.rpc.unknown import UnknownRPCAPI
|
|
||||||
|
|
||||||
__all__ = [
|
|
||||||
"BMMinerRPCAPI",
|
|
||||||
"BOSMinerRPCAPI",
|
|
||||||
"BTMinerRPCAPI",
|
|
||||||
"CGMinerRPCAPI",
|
|
||||||
"UnknownRPCAPI",
|
|
||||||
"MinerConfig",
|
|
||||||
"MinerData",
|
|
||||||
"BraiinsOSError",
|
|
||||||
"InnosiliconError",
|
|
||||||
"WhatsminerError",
|
|
||||||
"X19Error",
|
|
||||||
"APIError",
|
|
||||||
"APIWarning",
|
|
||||||
"get_miner",
|
|
||||||
"AnyMiner",
|
|
||||||
"DataOptions",
|
|
||||||
"MinerFactory",
|
|
||||||
"miner_factory",
|
|
||||||
"MinerListener",
|
|
||||||
"MinerNetwork",
|
|
||||||
"settings",
|
|
||||||
]
|
|
||||||
|
|||||||
@@ -14,14 +14,7 @@
|
|||||||
# limitations under the License. -
|
# limitations under the License. -
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
import ipaddress
|
from .base import AnyMiner
|
||||||
from typing import Union
|
from .data import DataOptions
|
||||||
|
from .factory import get_miner, miner_factory
|
||||||
from pyasic.miners.base import AnyMiner, BaseMiner
|
from .listener import MinerListener
|
||||||
from pyasic.miners.data import DataOptions
|
|
||||||
from pyasic.miners.factory import miner_factory
|
|
||||||
|
|
||||||
|
|
||||||
# abstracted version of get miner that is easier to access
|
|
||||||
async def get_miner(ip: Union[ipaddress.ip_address, str]) -> AnyMiner:
|
|
||||||
return await miner_factory.get_miner(ip)
|
|
||||||
|
|||||||
@@ -13,19 +13,20 @@
|
|||||||
# See the License for the specific language governing permissions and -
|
# See the License for the specific language governing permissions and -
|
||||||
# limitations under the License. -
|
# limitations under the License. -
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
import asyncio
|
import asyncio
|
||||||
import enum
|
import enum
|
||||||
import ipaddress
|
import ipaddress
|
||||||
import json
|
import json
|
||||||
import re
|
import re
|
||||||
from typing import AsyncGenerator, Callable, List, Optional, Tuple, Union
|
from typing import Any, AsyncGenerator, Callable
|
||||||
|
|
||||||
import anyio
|
import anyio
|
||||||
import httpx
|
import httpx
|
||||||
|
|
||||||
from pyasic import settings
|
from pyasic import settings
|
||||||
from pyasic.logger import logger
|
from pyasic.logger import logger
|
||||||
from pyasic.miners import AnyMiner
|
|
||||||
from pyasic.miners.antminer import *
|
from pyasic.miners.antminer import *
|
||||||
from pyasic.miners.auradine import *
|
from pyasic.miners.auradine import *
|
||||||
from pyasic.miners.avalonminer import *
|
from pyasic.miners.avalonminer import *
|
||||||
@@ -43,6 +44,7 @@ from pyasic.miners.backends import (
|
|||||||
ePIC,
|
ePIC,
|
||||||
)
|
)
|
||||||
from pyasic.miners.backends.unknown import UnknownMiner
|
from pyasic.miners.backends.unknown import UnknownMiner
|
||||||
|
from pyasic.miners.base import AnyMiner
|
||||||
from pyasic.miners.goldshell import *
|
from pyasic.miners.goldshell import *
|
||||||
from pyasic.miners.innosilicon import *
|
from pyasic.miners.innosilicon import *
|
||||||
from pyasic.miners.whatsminer import *
|
from pyasic.miners.whatsminer import *
|
||||||
@@ -408,7 +410,7 @@ MINER_CLASSES = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
async def concurrent_get_first_result(tasks: list, verification_func: Callable):
|
async def concurrent_get_first_result(tasks: list, verification_func: Callable) -> Any:
|
||||||
res = None
|
res = None
|
||||||
for fut in asyncio.as_completed(tasks):
|
for fut in asyncio.as_completed(tasks):
|
||||||
res = await fut
|
res = await fut
|
||||||
@@ -425,8 +427,8 @@ async def concurrent_get_first_result(tasks: list, verification_func: Callable):
|
|||||||
|
|
||||||
class MinerFactory:
|
class MinerFactory:
|
||||||
async def get_multiple_miners(
|
async def get_multiple_miners(
|
||||||
self, ips: List[str], limit: int = 200
|
self, ips: list[str], limit: int = 200
|
||||||
) -> List[AnyMiner]:
|
) -> list[AnyMiner]:
|
||||||
results = []
|
results = []
|
||||||
|
|
||||||
async for miner in self.get_miner_generator(ips, limit):
|
async for miner in self.get_miner_generator(ips, limit):
|
||||||
@@ -434,7 +436,9 @@ class MinerFactory:
|
|||||||
|
|
||||||
return results
|
return results
|
||||||
|
|
||||||
async def get_miner_generator(self, ips: list, limit: int = 200) -> AsyncGenerator:
|
async def get_miner_generator(
|
||||||
|
self, ips: list, limit: int = 200
|
||||||
|
) -> AsyncGenerator[AnyMiner]:
|
||||||
tasks = []
|
tasks = []
|
||||||
semaphore = asyncio.Semaphore(limit)
|
semaphore = asyncio.Semaphore(limit)
|
||||||
|
|
||||||
@@ -447,7 +451,7 @@ class MinerFactory:
|
|||||||
if result is not None:
|
if result is not None:
|
||||||
yield result
|
yield result
|
||||||
|
|
||||||
async def get_miner(self, ip: str):
|
async def get_miner(self, ip: str | ipaddress.ip_address) -> AnyMiner | None:
|
||||||
ip = str(ip)
|
ip = str(ip)
|
||||||
|
|
||||||
miner_type = None
|
miner_type = None
|
||||||
@@ -499,7 +503,7 @@ class MinerFactory:
|
|||||||
|
|
||||||
return miner
|
return miner
|
||||||
|
|
||||||
async def _get_miner_type(self, ip: str):
|
async def _get_miner_type(self, ip: str) -> MinerTypes | None:
|
||||||
tasks = [
|
tasks = [
|
||||||
asyncio.create_task(self._get_miner_web(ip)),
|
asyncio.create_task(self._get_miner_web(ip)),
|
||||||
asyncio.create_task(self._get_miner_socket(ip)),
|
asyncio.create_task(self._get_miner_socket(ip)),
|
||||||
@@ -507,7 +511,7 @@ class MinerFactory:
|
|||||||
|
|
||||||
return await concurrent_get_first_result(tasks, lambda x: x is not None)
|
return await concurrent_get_first_result(tasks, lambda x: x is not None)
|
||||||
|
|
||||||
async def _get_miner_web(self, ip: str):
|
async def _get_miner_web(self, ip: str) -> MinerTypes | None:
|
||||||
tasks = []
|
tasks = []
|
||||||
try:
|
try:
|
||||||
urls = [f"http://{ip}/", f"https://{ip}/"]
|
urls = [f"http://{ip}/", f"https://{ip}/"]
|
||||||
@@ -536,7 +540,7 @@ class MinerFactory:
|
|||||||
@staticmethod
|
@staticmethod
|
||||||
async def _web_ping(
|
async def _web_ping(
|
||||||
session: httpx.AsyncClient, url: str
|
session: httpx.AsyncClient, url: str
|
||||||
) -> Tuple[Optional[str], Optional[httpx.Response]]:
|
) -> tuple[str | None, httpx.Response | None]:
|
||||||
try:
|
try:
|
||||||
resp = await session.get(url, follow_redirects=True)
|
resp = await session.get(url, follow_redirects=True)
|
||||||
return resp.text, resp
|
return resp.text, resp
|
||||||
@@ -550,7 +554,7 @@ class MinerFactory:
|
|||||||
return None, None
|
return None, None
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _parse_web_type(web_text: str, web_resp: httpx.Response) -> MinerTypes:
|
def _parse_web_type(web_text: str, web_resp: httpx.Response) -> MinerTypes | None:
|
||||||
if web_resp.status_code == 401 and 'realm="antMiner' in web_resp.headers.get(
|
if web_resp.status_code == 401 and 'realm="antMiner' in web_resp.headers.get(
|
||||||
"www-authenticate", ""
|
"www-authenticate", ""
|
||||||
):
|
):
|
||||||
@@ -578,7 +582,7 @@ class MinerFactory:
|
|||||||
if "Miner UI" in web_text:
|
if "Miner UI" in web_text:
|
||||||
return MinerTypes.AURADINE
|
return MinerTypes.AURADINE
|
||||||
|
|
||||||
async def _get_miner_socket(self, ip: str):
|
async def _get_miner_socket(self, ip: str) -> MinerTypes | None:
|
||||||
tasks = []
|
tasks = []
|
||||||
try:
|
try:
|
||||||
commands = ["version", "devdetails"]
|
commands = ["version", "devdetails"]
|
||||||
@@ -602,7 +606,7 @@ class MinerFactory:
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
async def _socket_ping(ip: str, cmd: str) -> Optional[str]:
|
async def _socket_ping(ip: str, cmd: str) -> str | None:
|
||||||
data = b""
|
data = b""
|
||||||
try:
|
try:
|
||||||
reader, writer = await asyncio.wait_for(
|
reader, writer = await asyncio.wait_for(
|
||||||
@@ -648,7 +652,7 @@ class MinerFactory:
|
|||||||
return data.decode("utf-8")
|
return data.decode("utf-8")
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _parse_socket_type(data: str) -> MinerTypes:
|
def _parse_socket_type(data: str) -> MinerTypes | None:
|
||||||
upper_data = data.upper()
|
upper_data = data.upper()
|
||||||
if "BOSMINER" in upper_data or "BOSER" in upper_data:
|
if "BOSMINER" in upper_data or "BOSER" in upper_data:
|
||||||
return MinerTypes.BRAIINS_OS
|
return MinerTypes.BRAIINS_OS
|
||||||
@@ -671,14 +675,14 @@ class MinerFactory:
|
|||||||
|
|
||||||
async def send_web_command(
|
async def send_web_command(
|
||||||
self,
|
self,
|
||||||
ip: Union[ipaddress.ip_address, str],
|
ip: str,
|
||||||
location: str,
|
location: str,
|
||||||
auth: Optional[httpx.DigestAuth] = None,
|
auth: httpx.DigestAuth = None,
|
||||||
) -> Optional[dict]:
|
) -> dict | None:
|
||||||
async with httpx.AsyncClient(transport=settings.transport()) as session:
|
async with httpx.AsyncClient(transport=settings.transport()) as session:
|
||||||
try:
|
try:
|
||||||
data = await session.get(
|
data = await session.get(
|
||||||
f"http://{str(ip)}{location}",
|
f"http://{ip}{location}",
|
||||||
auth=auth,
|
auth=auth,
|
||||||
timeout=settings.get("factory_get_timeout", 3),
|
timeout=settings.get("factory_get_timeout", 3),
|
||||||
)
|
)
|
||||||
@@ -697,12 +701,10 @@ class MinerFactory:
|
|||||||
else:
|
else:
|
||||||
return json_data
|
return json_data
|
||||||
|
|
||||||
async def send_api_command(
|
async def send_api_command(self, ip: str, command: str) -> dict | None:
|
||||||
self, ip: Union[ipaddress.ip_address, str], command: str
|
|
||||||
) -> Optional[dict]:
|
|
||||||
data = b""
|
data = b""
|
||||||
try:
|
try:
|
||||||
reader, writer = await asyncio.open_connection(str(ip), 4028)
|
reader, writer = await asyncio.open_connection(ip, 4028)
|
||||||
except (ConnectionError, OSError):
|
except (ConnectionError, OSError):
|
||||||
return
|
return
|
||||||
cmd = {"command": command}
|
cmd = {"command": command}
|
||||||
@@ -740,7 +742,7 @@ class MinerFactory:
|
|||||||
return data
|
return data
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
async def _fix_api_data(data: bytes):
|
async def _fix_api_data(data: bytes) -> str:
|
||||||
if data.endswith(b"\x00"):
|
if data.endswith(b"\x00"):
|
||||||
str_data = data.decode("utf-8")[:-1]
|
str_data = data.decode("utf-8")[:-1]
|
||||||
else:
|
else:
|
||||||
@@ -777,9 +779,9 @@ class MinerFactory:
|
|||||||
@staticmethod
|
@staticmethod
|
||||||
def _select_miner_from_classes(
|
def _select_miner_from_classes(
|
||||||
ip: ipaddress.ip_address,
|
ip: ipaddress.ip_address,
|
||||||
miner_model: Union[str, None],
|
miner_model: str | None,
|
||||||
miner_type: Union[MinerTypes, None],
|
miner_type: MinerTypes | None,
|
||||||
) -> AnyMiner:
|
) -> AnyMiner | None:
|
||||||
try:
|
try:
|
||||||
return MINER_CLASSES[miner_type][str(miner_model).upper()](ip)
|
return MINER_CLASSES[miner_type][str(miner_model).upper()](ip)
|
||||||
except LookupError:
|
except LookupError:
|
||||||
@@ -787,7 +789,7 @@ class MinerFactory:
|
|||||||
return MINER_CLASSES[miner_type][None](ip)
|
return MINER_CLASSES[miner_type][None](ip)
|
||||||
return UnknownMiner(str(ip))
|
return UnknownMiner(str(ip))
|
||||||
|
|
||||||
async def get_miner_model_antminer(self, ip: str):
|
async def get_miner_model_antminer(self, ip: str) -> str | None:
|
||||||
tasks = [
|
tasks = [
|
||||||
asyncio.create_task(self._get_model_antminer_web(ip)),
|
asyncio.create_task(self._get_model_antminer_web(ip)),
|
||||||
asyncio.create_task(self._get_model_antminer_sock(ip)),
|
asyncio.create_task(self._get_model_antminer_sock(ip)),
|
||||||
@@ -795,7 +797,7 @@ class MinerFactory:
|
|||||||
|
|
||||||
return await concurrent_get_first_result(tasks, lambda x: x is not None)
|
return await concurrent_get_first_result(tasks, lambda x: x is not None)
|
||||||
|
|
||||||
async def _get_model_antminer_web(self, ip: str):
|
async def _get_model_antminer_web(self, ip: str) -> str | None:
|
||||||
# last resort, this is slow
|
# last resort, this is slow
|
||||||
auth = httpx.DigestAuth("root", "root")
|
auth = httpx.DigestAuth("root", "root")
|
||||||
web_json_data = await self.send_web_command(
|
web_json_data = await self.send_web_command(
|
||||||
@@ -809,7 +811,7 @@ class MinerFactory:
|
|||||||
except (TypeError, LookupError):
|
except (TypeError, LookupError):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
async def _get_model_antminer_sock(self, ip: str):
|
async def _get_model_antminer_sock(self, ip: str) -> str | None:
|
||||||
sock_json_data = await self.send_api_command(ip, "version")
|
sock_json_data = await self.send_api_command(ip, "version")
|
||||||
try:
|
try:
|
||||||
miner_model = sock_json_data["VERSION"][0]["Type"]
|
miner_model = sock_json_data["VERSION"][0]["Type"]
|
||||||
@@ -834,7 +836,7 @@ class MinerFactory:
|
|||||||
except (TypeError, LookupError):
|
except (TypeError, LookupError):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
async def get_miner_model_goldshell(self, ip: str):
|
async def get_miner_model_goldshell(self, ip: str) -> str | None:
|
||||||
json_data = await self.send_web_command(ip, "/mcb/status")
|
json_data = await self.send_web_command(ip, "/mcb/status")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@@ -844,7 +846,7 @@ class MinerFactory:
|
|||||||
except (TypeError, LookupError):
|
except (TypeError, LookupError):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
async def get_miner_model_whatsminer(self, ip: str):
|
async def get_miner_model_whatsminer(self, ip: str) -> str | None:
|
||||||
sock_json_data = await self.send_api_command(ip, "devdetails")
|
sock_json_data = await self.send_api_command(ip, "devdetails")
|
||||||
try:
|
try:
|
||||||
miner_model = sock_json_data["DEVDETAILS"][0]["Model"].replace("_", "")
|
miner_model = sock_json_data["DEVDETAILS"][0]["Model"].replace("_", "")
|
||||||
@@ -854,7 +856,7 @@ class MinerFactory:
|
|||||||
except (TypeError, LookupError):
|
except (TypeError, LookupError):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
async def get_miner_model_avalonminer(self, ip: str) -> Optional[str]:
|
async def get_miner_model_avalonminer(self, ip: str) -> str | None:
|
||||||
sock_json_data = await self.send_api_command(ip, "version")
|
sock_json_data = await self.send_api_command(ip, "version")
|
||||||
try:
|
try:
|
||||||
miner_model = sock_json_data["VERSION"][0]["PROD"]
|
miner_model = sock_json_data["VERSION"][0]["PROD"]
|
||||||
@@ -865,7 +867,7 @@ class MinerFactory:
|
|||||||
except (TypeError, LookupError):
|
except (TypeError, LookupError):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
async def get_miner_model_innosilicon(self, ip: str) -> Optional[str]:
|
async def get_miner_model_innosilicon(self, ip: str) -> str | None:
|
||||||
try:
|
try:
|
||||||
async with httpx.AsyncClient(transport=settings.transport()) as session:
|
async with httpx.AsyncClient(transport=settings.transport()) as session:
|
||||||
auth_req = await session.post(
|
auth_req = await session.post(
|
||||||
@@ -885,7 +887,7 @@ class MinerFactory:
|
|||||||
except (httpx.HTTPError, LookupError):
|
except (httpx.HTTPError, LookupError):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
async def get_miner_model_braiins_os(self, ip: str) -> Optional[str]:
|
async def get_miner_model_braiins_os(self, ip: str) -> str | None:
|
||||||
sock_json_data = await self.send_api_command(ip, "devdetails")
|
sock_json_data = await self.send_api_command(ip, "devdetails")
|
||||||
try:
|
try:
|
||||||
miner_model = sock_json_data["DEVDETAILS"][0]["Model"].replace(
|
miner_model = sock_json_data["DEVDETAILS"][0]["Model"].replace(
|
||||||
@@ -909,7 +911,7 @@ class MinerFactory:
|
|||||||
except (httpx.HTTPError, LookupError):
|
except (httpx.HTTPError, LookupError):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
async def get_miner_model_vnish(self, ip: str) -> Optional[str]:
|
async def get_miner_model_vnish(self, ip: str) -> str | None:
|
||||||
sock_json_data = await self.send_api_command(ip, "stats")
|
sock_json_data = await self.send_api_command(ip, "stats")
|
||||||
try:
|
try:
|
||||||
miner_model = sock_json_data["STATS"][0]["Type"]
|
miner_model = sock_json_data["STATS"][0]["Type"]
|
||||||
@@ -927,7 +929,7 @@ class MinerFactory:
|
|||||||
except (TypeError, LookupError):
|
except (TypeError, LookupError):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
async def get_miner_model_epic(self, ip: str) -> Optional[str]:
|
async def get_miner_model_epic(self, ip: str) -> str | None:
|
||||||
sock_json_data = await self.send_web_command(ip, ":4028/capabilities")
|
sock_json_data = await self.send_web_command(ip, ":4028/capabilities")
|
||||||
try:
|
try:
|
||||||
miner_model = sock_json_data["Model"]
|
miner_model = sock_json_data["Model"]
|
||||||
@@ -935,7 +937,7 @@ class MinerFactory:
|
|||||||
except (TypeError, LookupError):
|
except (TypeError, LookupError):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
async def get_miner_model_hiveon(self, ip: str) -> Optional[str]:
|
async def get_miner_model_hiveon(self, ip: str) -> str | None:
|
||||||
sock_json_data = await self.send_api_command(ip, "version")
|
sock_json_data = await self.send_api_command(ip, "version")
|
||||||
try:
|
try:
|
||||||
miner_type = sock_json_data["VERSION"][0]["Type"]
|
miner_type = sock_json_data["VERSION"][0]["Type"]
|
||||||
@@ -944,7 +946,7 @@ class MinerFactory:
|
|||||||
except (TypeError, LookupError):
|
except (TypeError, LookupError):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
async def get_miner_model_luxos(self, ip: str):
|
async def get_miner_model_luxos(self, ip: str) -> str | None:
|
||||||
sock_json_data = await self.send_api_command(ip, "version")
|
sock_json_data = await self.send_api_command(ip, "version")
|
||||||
try:
|
try:
|
||||||
miner_model = sock_json_data["VERSION"][0]["Type"]
|
miner_model = sock_json_data["VERSION"][0]["Type"]
|
||||||
@@ -956,7 +958,7 @@ class MinerFactory:
|
|||||||
except (TypeError, LookupError):
|
except (TypeError, LookupError):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
async def get_miner_model_auradine(self, ip: str):
|
async def get_miner_model_auradine(self, ip: str) -> str | None:
|
||||||
sock_json_data = await self.send_api_command(ip, "devdetails")
|
sock_json_data = await self.send_api_command(ip, "devdetails")
|
||||||
try:
|
try:
|
||||||
return sock_json_data["DEVDETAILS"][0]["Model"]
|
return sock_json_data["DEVDETAILS"][0]["Model"]
|
||||||
@@ -965,3 +967,7 @@ class MinerFactory:
|
|||||||
|
|
||||||
|
|
||||||
miner_factory = MinerFactory()
|
miner_factory = MinerFactory()
|
||||||
|
|
||||||
|
# abstracted version of get miner that is easier to access
|
||||||
|
async def get_miner(ip: ipaddress.ip_address | str) -> AnyMiner:
|
||||||
|
return await miner_factory.get_miner(ip)
|
||||||
|
|||||||
@@ -16,10 +16,8 @@
|
|||||||
|
|
||||||
import asyncio
|
import asyncio
|
||||||
|
|
||||||
from pyasic.misc import Singleton
|
|
||||||
|
|
||||||
|
class MinerListenerProtocol(asyncio.Protocol):
|
||||||
class _MinerListener:
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.responses = {}
|
self.responses = {}
|
||||||
self.transport = None
|
self.transport = None
|
||||||
@@ -44,7 +42,7 @@ class _MinerListener:
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class MinerListener(metaclass=Singleton):
|
class MinerListener:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.found_miners = []
|
self.found_miners = []
|
||||||
self.new_miner = None
|
self.new_miner = None
|
||||||
@@ -56,10 +54,10 @@ class MinerListener(metaclass=Singleton):
|
|||||||
loop = asyncio.get_running_loop()
|
loop = asyncio.get_running_loop()
|
||||||
|
|
||||||
transport_14235, _ = await loop.create_datagram_endpoint(
|
transport_14235, _ = await loop.create_datagram_endpoint(
|
||||||
_MinerListener, local_addr=("0.0.0.0", 14235)
|
MinerListenerProtocol, local_addr=("0.0.0.0", 14235)
|
||||||
)
|
)
|
||||||
transport_8888, _ = await loop.create_datagram_endpoint(
|
transport_8888, _ = await loop.create_datagram_endpoint(
|
||||||
_MinerListener, local_addr=("0.0.0.0", 8888)
|
MinerListenerProtocol, local_addr=("0.0.0.0", 8888)
|
||||||
)
|
)
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
@@ -75,21 +73,3 @@ class MinerListener(metaclass=Singleton):
|
|||||||
|
|
||||||
async def cancel(self):
|
async def cancel(self):
|
||||||
self.stop = True
|
self.stop = True
|
||||||
|
|
||||||
|
|
||||||
async def main():
|
|
||||||
await asyncio.gather(run(), cancel())
|
|
||||||
|
|
||||||
|
|
||||||
async def run():
|
|
||||||
async for miner in MinerListener().listen():
|
|
||||||
print(miner)
|
|
||||||
|
|
||||||
|
|
||||||
async def cancel():
|
|
||||||
await asyncio.sleep(60)
|
|
||||||
await MinerListener().cancel()
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
asyncio.run(main())
|
|
||||||
|
|||||||
@@ -18,15 +18,6 @@ from copy import deepcopy
|
|||||||
from pyasic.errors import APIError
|
from pyasic.errors import APIError
|
||||||
|
|
||||||
|
|
||||||
class Singleton(type):
|
|
||||||
_instances = {}
|
|
||||||
|
|
||||||
def __call__(cls, *args, **kwargs):
|
|
||||||
if cls not in cls._instances:
|
|
||||||
cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)
|
|
||||||
return cls._instances[cls]
|
|
||||||
|
|
||||||
|
|
||||||
def api_min_version(version: str):
|
def api_min_version(version: str):
|
||||||
def decorator(func):
|
def decorator(func):
|
||||||
# handle the inner function that the decorator is wrapping
|
# handle the inner function that the decorator is wrapping
|
||||||
|
|||||||
Reference in New Issue
Block a user