Compare commits

...

5 Commits

Author SHA1 Message Date
UpstreamData
49a77f1b79 version: bump version number. 2024-01-29 12:47:54 -07:00
UpstreamData
3838c4f2f9 bug: fix missing validation import for BTMiner. 2024-01-29 12:47:30 -07:00
UpstreamData
80d89c95b5 version: bump version number. 2024-01-29 12:33:07 -07:00
UpstreamData
30cd8b5cfe bug: fix some issues with rpc renaming. 2024-01-29 12:32:54 -07:00
b-rowan
c443170f78 refactor: improve epic web send_command implementation. 2024-01-27 09:42:35 -07:00
10 changed files with 55 additions and 57 deletions

View File

@@ -68,7 +68,7 @@ class BFGMiner(BaseMiner):
except APIError:
return self.config
self.config = MinerConfig.from_rpc(pools)
self.config = MinerConfig.from_api(pools)
return self.config
##################################################
@@ -84,11 +84,11 @@ class BFGMiner(BaseMiner):
if rpc_version is not None:
try:
self.rpc_ver = rpc_version["VERSION"][0]["API"]
self.api_ver = rpc_version["VERSION"][0]["API"]
except LookupError:
pass
return self.rpc_ver
return self.api_ver
async def _get_fw_ver(self, rpc_version: dict = None) -> Optional[str]:
if rpc_version is None:

View File

@@ -72,7 +72,7 @@ class BMMiner(BaseMiner):
except APIError:
return self.config
self.config = MinerConfig.from_rpc(pools)
self.config = MinerConfig.from_api(pools)
return self.config
##################################################
@@ -88,11 +88,11 @@ class BMMiner(BaseMiner):
if rpc_version is not None:
try:
self.rpc_ver = rpc_version["VERSION"][0]["API"]
self.api_ver = rpc_version["VERSION"][0]["API"]
except LookupError:
pass
return self.rpc_ver
return self.api_ver
async def _get_fw_ver(self, rpc_version: dict = None) -> Optional[str]:
if rpc_version is None:

View File

@@ -305,10 +305,10 @@ class BOSMiner(BaseMiner):
rpc_ver = rpc_version["VERSION"][0]["API"]
except LookupError:
rpc_ver = None
self.rpc_ver = rpc_ver
self.rpc.rpc_ver = self.rpc_ver
self.api_ver = rpc_ver
self.rpc.rpc_ver = self.api_ver
return self.rpc_ver
return self.api_ver
async def _get_fw_ver(self, web_bos_info: dict = None) -> Optional[str]:
if web_bos_info is None:
@@ -731,10 +731,10 @@ class BOSer(BaseMiner):
rpc_ver = rpc_version["VERSION"][0]["API"]
except LookupError:
rpc_ver = None
self.rpc_ver = rpc_ver
self.rpc.rpc_ver = self.rpc_ver
self.api_ver = rpc_ver
self.rpc.rpc_ver = self.api_ver
return self.rpc_ver
return self.api_ver
async def _get_fw_ver(self, grpc_miner_details: dict = None) -> Optional[str]:
if grpc_miner_details is None:

View File

@@ -234,7 +234,7 @@ class BTMiner(BaseMiner):
pass
if pools is not None:
cfg = MinerConfig.from_rpc(pools)
cfg = MinerConfig.from_api(pools)
else:
cfg = MinerConfig()
@@ -325,14 +325,14 @@ class BTMiner(BaseMiner):
rpc_ver = rpc_get_version["Msg"]
if not isinstance(rpc_ver, str):
rpc_ver = rpc_ver["rpc_ver"]
self.rpc_ver = rpc_ver.replace("whatsminer v", "")
self.api_ver = rpc_ver.replace("whatsminer v", "")
except (KeyError, TypeError):
pass
else:
self.rpc.rpc_ver = self.rpc_ver
return self.rpc_ver
self.rpc.rpc_ver = self.api_ver
return self.api_ver
return self.rpc_ver
return self.api_ver
async def _get_fw_ver(
self, rpc_get_version: dict = None, rpc_summary: dict = None

View File

@@ -71,7 +71,7 @@ class CGMiner(BaseMiner):
except APIError:
return self.config
self.config = MinerConfig.from_rpc(pools)
self.config = MinerConfig.from_api(pools)
return self.config
##################################################
@@ -87,11 +87,11 @@ class CGMiner(BaseMiner):
if rpc_version is not None:
try:
self.rpc_ver = rpc_version["VERSION"][0]["API"]
self.api_ver = rpc_version["VERSION"][0]["API"]
except LookupError:
pass
return self.rpc_ver
return self.api_ver
async def _get_fw_ver(self, rpc_version: dict = None) -> Optional[str]:
if rpc_version is None:

View File

@@ -107,3 +107,4 @@ def validate_command_output(data: dict) -> tuple[bool, str | None]:
if data[key][0]["STATUS"][0]["STATUS"] not in ["S", "I"]:
# this is an error
return False, f"{key}: " + data[key][0]["STATUS"][0]["Msg"]
return True, None

View File

@@ -90,7 +90,7 @@ class BaseMinerRPCAPI:
if not validation[0]:
if not ignore_errors:
# validate the command succeeded
raise APIError(validation[1])
raise APIError(f"{command}: {validation[1]}")
if allow_warning:
logging.warning(
f"{self.ip}: API Command Error: {command}: {validation[1]}"

View File

@@ -29,7 +29,7 @@ from passlib.handlers.md5_crypt import md5_crypt
from pyasic import settings
from pyasic.errors import APIError
from pyasic.misc import api_min_version
from pyasic.misc import api_min_version, validate_command_output
from pyasic.rpc.base import BaseMinerRPCAPI
### IMPORTANT ###
@@ -272,7 +272,7 @@ class BTMinerRPCAPI(BaseMinerRPCAPI):
if not ignore_errors:
# if it fails to validate, it is likely an error
validation = self._validate_command_output(data)
validation = validate_command_output(data)
if not validation[0]:
raise APIError(validation[1])

View File

@@ -44,40 +44,37 @@ class ePICWebAPI(BaseWebAPI):
post = privileged or not parameters == {}
async with httpx.AsyncClient(transport=settings.transport()) as client:
for i in range(settings.get("get_data_retries", 1) + 1):
try:
if post:
response = await client.post(
f"http://{self.ip}:{self.port}/{command}",
timeout=5,
json={
**parameters,
"password": self.pwd,
},
try:
if post:
response = await client.post(
f"http://{self.ip}:{self.port}/{command}",
timeout=5,
json={
**parameters,
"password": self.pwd,
},
)
else:
response = await client.get(
f"http://{self.ip}:{self.port}/{command}",
timeout=5,
)
if not response.status_code == 200:
if not ignore_errors:
raise APIError(
f"Web command {command} failed with status code {response.status_code}"
)
else:
response = await client.get(
f"http://{self.ip}:{self.port}/{command}",
timeout=5,
)
if not response.status_code == 200:
continue
json_data = response.json()
if json_data:
# The API can return a fail status if the miner cannot return the requested data. Catch this and pass
if (
"result" in json_data
and json_data["result"] is False
and not post
):
if not i > settings.get("get_data_retries", 1):
continue
if not ignore_errors:
raise APIError(json_data["error"])
return json_data
return {"success": True}
except (httpx.HTTPError, json.JSONDecodeError, AttributeError):
pass
return {}
json_data = response.json()
if json_data:
# The API can return a fail status if the miner cannot return the requested data. Catch this and pass
if not json_data.get("result", True) and not post:
if not ignore_errors:
raise APIError(json_data["error"])
return json_data
return {"success": True}
except (httpx.HTTPError, json.JSONDecodeError, AttributeError):
pass
async def multicommand(
self, *commands: str, ignore_errors: bool = False, allow_warning: bool = True

View File

@@ -1,6 +1,6 @@
[tool.poetry]
name = "pyasic"
version = "0.50.2"
version = "0.50.4"
description = "A simplified and standardized interface for Bitcoin ASICs."
authors = ["UpstreamData <brett@upstreamdata.ca>"]
repository = "https://github.com/UpstreamData/pyasic"