feature: refactor BOS web class into multiple classes.
This commit is contained in:
@@ -18,14 +18,27 @@ from typing import Union
|
|||||||
|
|
||||||
import httpx
|
import httpx
|
||||||
|
|
||||||
from pyasic import APIError, settings
|
from pyasic import APIError
|
||||||
|
from pyasic.settings import PyasicSettings
|
||||||
from pyasic.web import BaseWebAPI
|
from pyasic.web import BaseWebAPI
|
||||||
|
|
||||||
|
|
||||||
class BOSMinerWebAPI(BaseWebAPI):
|
class BOSMinerWebAPI(BaseWebAPI):
|
||||||
def __init__(self, ip: str) -> None:
|
def __init__(self, ip: str) -> None:
|
||||||
|
self.gql = BOSMinerGQLAPI(ip, PyasicSettings().global_bosminer_password)
|
||||||
|
self.luci = BOSMinerLuCIAPI(ip, PyasicSettings().global_bosminer_password)
|
||||||
|
self._pwd = PyasicSettings().global_bosminer_password
|
||||||
super().__init__(ip)
|
super().__init__(ip)
|
||||||
self.pwd = settings.get("default_bosminer_password", "root")
|
|
||||||
|
@property
|
||||||
|
def pwd(self):
|
||||||
|
return self._pwd
|
||||||
|
|
||||||
|
@pwd.setter
|
||||||
|
def pwd(self, other: str):
|
||||||
|
self._pwd = other
|
||||||
|
self.luci.pwd = other
|
||||||
|
self.gql.pwd = other
|
||||||
|
|
||||||
async def send_command(
|
async def send_command(
|
||||||
self,
|
self,
|
||||||
@@ -34,44 +47,10 @@ class BOSMinerWebAPI(BaseWebAPI):
|
|||||||
allow_warning: bool = True,
|
allow_warning: bool = True,
|
||||||
**parameters: Union[str, int, bool],
|
**parameters: Union[str, int, bool],
|
||||||
) -> dict:
|
) -> dict:
|
||||||
if isinstance(command, str):
|
if command.startswith("/cgi-bin/luci"):
|
||||||
return await self.send_luci_command(command)
|
return await self.luci.send_command(command)
|
||||||
else:
|
else:
|
||||||
return await self.send_gql_command(command)
|
return await self.gql.send_command(command)
|
||||||
|
|
||||||
def parse_command(self, graphql_command: Union[dict, set]) -> str:
|
|
||||||
if isinstance(graphql_command, dict):
|
|
||||||
data = []
|
|
||||||
for key in graphql_command:
|
|
||||||
if graphql_command[key] is not None:
|
|
||||||
parsed = self.parse_command(graphql_command[key])
|
|
||||||
data.append(key + parsed)
|
|
||||||
else:
|
|
||||||
data.append(key)
|
|
||||||
else:
|
|
||||||
data = graphql_command
|
|
||||||
return "{" + ",".join(data) + "}"
|
|
||||||
|
|
||||||
async def send_gql_command(
|
|
||||||
self,
|
|
||||||
command: dict,
|
|
||||||
) -> dict:
|
|
||||||
url = f"http://{self.ip}/graphql"
|
|
||||||
query = command
|
|
||||||
if command.get("query") is None:
|
|
||||||
query = {"query": self.parse_command(command)}
|
|
||||||
try:
|
|
||||||
async with httpx.AsyncClient() as client:
|
|
||||||
await self.auth(client)
|
|
||||||
data = await client.post(url, json=query)
|
|
||||||
except httpx.HTTPError:
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
if data.status_code == 200:
|
|
||||||
try:
|
|
||||||
return data.json()
|
|
||||||
except json.decoder.JSONDecodeError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
async def multicommand(
|
async def multicommand(
|
||||||
self, *commands: Union[dict, str], allow_warning: bool = True
|
self, *commands: Union[dict, str], allow_warning: bool = True
|
||||||
@@ -79,13 +58,13 @@ class BOSMinerWebAPI(BaseWebAPI):
|
|||||||
luci_commands = []
|
luci_commands = []
|
||||||
gql_commands = []
|
gql_commands = []
|
||||||
for cmd in commands:
|
for cmd in commands:
|
||||||
|
if cmd.startswith("/cgi-bin/luci"):
|
||||||
|
luci_commands.append(cmd)
|
||||||
if isinstance(cmd, dict):
|
if isinstance(cmd, dict):
|
||||||
gql_commands.append(cmd)
|
gql_commands.append(cmd)
|
||||||
if isinstance(cmd, str):
|
|
||||||
luci_commands.append(cmd)
|
|
||||||
|
|
||||||
luci_data = await self.luci_multicommand(*luci_commands)
|
luci_data = await self.luci.multicommand(*luci_commands)
|
||||||
gql_data = await self.gql_multicommand(*gql_commands)
|
gql_data = await self.gql.multicommand(*gql_commands)
|
||||||
|
|
||||||
if gql_data is None:
|
if gql_data is None:
|
||||||
gql_data = {}
|
gql_data = {}
|
||||||
@@ -95,13 +74,14 @@ class BOSMinerWebAPI(BaseWebAPI):
|
|||||||
data = dict(**luci_data, **gql_data)
|
data = dict(**luci_data, **gql_data)
|
||||||
return data
|
return data
|
||||||
|
|
||||||
async def luci_multicommand(self, *commands: str) -> dict:
|
|
||||||
data = {}
|
|
||||||
for command in commands:
|
|
||||||
data[command] = await self.send_luci_command(command, ignore_errors=True)
|
|
||||||
return data
|
|
||||||
|
|
||||||
async def gql_multicommand(self, *commands: dict) -> dict:
|
class BOSMinerGQLAPI:
|
||||||
|
def __init__(self, ip: str, pwd: str):
|
||||||
|
self.ip = ip
|
||||||
|
self.username = "root"
|
||||||
|
self.pwd = pwd
|
||||||
|
|
||||||
|
async def multicommand(self, *commands: dict) -> dict:
|
||||||
def merge(*d: dict):
|
def merge(*d: dict):
|
||||||
ret = {}
|
ret = {}
|
||||||
for i in d:
|
for i in d:
|
||||||
@@ -122,7 +102,7 @@ class BOSMinerWebAPI(BaseWebAPI):
|
|||||||
# noinspection PyTypeChecker
|
# noinspection PyTypeChecker
|
||||||
commands.remove({"bos": {"faultLight": None}})
|
commands.remove({"bos": {"faultLight": None}})
|
||||||
command = merge(*commands)
|
command = merge(*commands)
|
||||||
data = await self.send_gql_command(command)
|
data = await self.send_command(command)
|
||||||
except (LookupError, ValueError):
|
except (LookupError, ValueError):
|
||||||
pass
|
pass
|
||||||
if not data:
|
if not data:
|
||||||
@@ -130,6 +110,40 @@ class BOSMinerWebAPI(BaseWebAPI):
|
|||||||
data["multicommand"] = False
|
data["multicommand"] = False
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
async def send_command(
|
||||||
|
self,
|
||||||
|
command: dict,
|
||||||
|
) -> dict:
|
||||||
|
url = f"http://{self.ip}/graphql"
|
||||||
|
query = command
|
||||||
|
if command.get("query") is None:
|
||||||
|
query = {"query": self.parse_command(command)}
|
||||||
|
try:
|
||||||
|
async with httpx.AsyncClient() as client:
|
||||||
|
await self.auth(client)
|
||||||
|
data = await client.post(url, json=query)
|
||||||
|
except httpx.HTTPError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
if data.status_code == 200:
|
||||||
|
try:
|
||||||
|
return data.json()
|
||||||
|
except json.decoder.JSONDecodeError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def parse_command(self, graphql_command: Union[dict, set]) -> str:
|
||||||
|
if isinstance(graphql_command, dict):
|
||||||
|
data = []
|
||||||
|
for key in graphql_command:
|
||||||
|
if graphql_command[key] is not None:
|
||||||
|
parsed = self.parse_command(graphql_command[key])
|
||||||
|
data.append(key + parsed)
|
||||||
|
else:
|
||||||
|
data.append(key)
|
||||||
|
else:
|
||||||
|
data = graphql_command
|
||||||
|
return "{" + ",".join(data) + "}"
|
||||||
|
|
||||||
async def auth(self, client: httpx.AsyncClient) -> None:
|
async def auth(self, client: httpx.AsyncClient) -> None:
|
||||||
url = f"http://{self.ip}/graphql"
|
url = f"http://{self.ip}/graphql"
|
||||||
await client.post(
|
await client.post(
|
||||||
@@ -143,10 +157,23 @@ class BOSMinerWebAPI(BaseWebAPI):
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
async def send_luci_command(self, path: str, ignore_errors: bool = False) -> dict:
|
|
||||||
|
class BOSMinerLuCIAPI:
|
||||||
|
def __init__(self, ip: str, pwd: str):
|
||||||
|
self.ip = ip
|
||||||
|
self.username = "root"
|
||||||
|
self.pwd = pwd
|
||||||
|
|
||||||
|
async def multicommand(self, *commands: str) -> dict:
|
||||||
|
data = {}
|
||||||
|
for command in commands:
|
||||||
|
data[command] = await self.send_command(command, ignore_errors=True)
|
||||||
|
return data
|
||||||
|
|
||||||
|
async def send_command(self, path: str, ignore_errors: bool = False) -> dict:
|
||||||
try:
|
try:
|
||||||
async with httpx.AsyncClient() as client:
|
async with httpx.AsyncClient() as client:
|
||||||
await self.luci_auth(client)
|
await self.auth(client)
|
||||||
data = await client.get(
|
data = await client.get(
|
||||||
f"http://{self.ip}{path}", headers={"User-Agent": "BTC Tools v0.1"}
|
f"http://{self.ip}{path}", headers={"User-Agent": "BTC Tools v0.1"}
|
||||||
)
|
)
|
||||||
@@ -162,7 +189,7 @@ class BOSMinerWebAPI(BaseWebAPI):
|
|||||||
return {}
|
return {}
|
||||||
raise APIError(f"Web command failed: path={path}")
|
raise APIError(f"Web command failed: path={path}")
|
||||||
|
|
||||||
async def luci_auth(self, session: httpx.AsyncClient):
|
async def auth(self, session: httpx.AsyncClient):
|
||||||
login = {"luci_username": self.username, "luci_password": self.pwd}
|
login = {"luci_username": self.username, "luci_password": self.pwd}
|
||||||
url = f"http://{self.ip}/cgi-bin/luci"
|
url = f"http://{self.ip}/cgi-bin/luci"
|
||||||
headers = {
|
headers = {
|
||||||
@@ -172,23 +199,21 @@ class BOSMinerWebAPI(BaseWebAPI):
|
|||||||
await session.post(url, headers=headers, data=login)
|
await session.post(url, headers=headers, data=login)
|
||||||
|
|
||||||
async def get_net_conf(self):
|
async def get_net_conf(self):
|
||||||
return await self.send_luci_command(
|
return await self.send_command("/cgi-bin/luci/admin/network/iface_status/lan")
|
||||||
"/cgi-bin/luci/admin/network/iface_status/lan"
|
|
||||||
)
|
|
||||||
|
|
||||||
async def get_cfg_metadata(self):
|
async def get_cfg_metadata(self):
|
||||||
return await self.send_luci_command("/cgi-bin/luci/admin/miner/cfg_metadata")
|
return await self.send_command("/cgi-bin/luci/admin/miner/cfg_metadata")
|
||||||
|
|
||||||
async def get_cfg_data(self):
|
async def get_cfg_data(self):
|
||||||
return await self.send_luci_command("/cgi-bin/luci/admin/miner/cfg_data")
|
return await self.send_command("/cgi-bin/luci/admin/miner/cfg_data")
|
||||||
|
|
||||||
async def get_bos_info(self):
|
async def get_bos_info(self):
|
||||||
return await self.send_luci_command("/cgi-bin/luci/bos/info")
|
return await self.send_command("/cgi-bin/luci/bos/info")
|
||||||
|
|
||||||
async def get_overview(self):
|
async def get_overview(self):
|
||||||
return await self.send_luci_command(
|
return await self.send_command(
|
||||||
"/cgi-bin/luci/admin/status/overview?status=1"
|
"/cgi-bin/luci/admin/status/overview?status=1"
|
||||||
) # needs status=1 or it fails
|
) # needs status=1 or it fails
|
||||||
|
|
||||||
async def get_api_status(self):
|
async def get_api_status(self):
|
||||||
return await self.send_luci_command("/cgi-bin/luci/admin/miner/api_status")
|
return await self.send_command("/cgi-bin/luci/admin/miner/api_status")
|
||||||
|
|||||||
Reference in New Issue
Block a user