feature: optimize the way multicommand is handled on BTMiner.

This commit is contained in:
UpstreamData
2023-07-24 09:44:23 -06:00
parent ddc8c53eb9
commit 2653db90e3
3 changed files with 47 additions and 47 deletions

View File

@@ -20,7 +20,7 @@ import json
import logging import logging
import re import re
import warnings import warnings
from typing import Union from typing import Tuple, Union
from pyasic.errors import APIError, APIWarning from pyasic.errors import APIError, APIWarning
@@ -128,6 +128,18 @@ class BaseMinerAPI:
data["multicommand"] = True data["multicommand"] = True
return data return data
async def _handle_multicommand(self, command: str, allow_warning: bool = True):
try:
data = await self.send_command(command, allow_warning=allow_warning)
if not "+" in command:
return {command: [data]}
return data
except APIError:
if "+" in command:
return {command: [{}] for command in command.split("+")}
return {command: [{}]}
@property @property
def commands(self) -> list: def commands(self) -> list:
return self.get_commands() return self.get_commands()
@@ -171,7 +183,11 @@ If you are sure you want to use this command please use API.send_command("{comma
) )
return return_commands return return_commands
async def _send_bytes(self, data: bytes, timeout: int = 100) -> bytes: async def _send_bytes(
self,
data: bytes,
timeout: int = 100,
) -> bytes:
logging.debug(f"{self} - ([Hidden] Send Bytes) - Sending") logging.debug(f"{self} - ([Hidden] Send Bytes) - Sending")
try: try:
# get reader and writer streams # get reader and writer streams

View File

@@ -203,27 +203,35 @@ class BTMinerAPI(BaseMinerAPI):
# make sure we can actually run each command, otherwise they will fail # make sure we can actually run each command, otherwise they will fail
commands = self._check_commands(*commands) commands = self._check_commands(*commands)
# standard multicommand format is "command1+command2" # standard multicommand format is "command1+command2"
# commands starting with "get_" aren't supported, but we can fake that # commands starting with "get_" and the "status" command aren't supported, but we can fake that
get_commands_data = {}
tasks = []
for command in list(commands): for command in list(commands):
if command.startswith("get_"): if command.startswith("get_") or command == "status":
commands.remove(command) commands.remove(command)
# send seperately and append later # send seperately and append later
try: tasks.append(
get_commands_data[command] = [ asyncio.create_task(
await self.send_command(command, allow_warning=allow_warning) self._handle_multicommand(command, allow_warning=allow_warning)
] )
except APIError: )
get_commands_data[command] = [{}]
command = "+".join(commands) command = "+".join(commands)
try: tasks.append(
main_data = await self.send_command(command, allow_warning=allow_warning) asyncio.create_task(
except APIError: self._handle_multicommand(command, allow_warning=allow_warning)
main_data = {command: [{}] for command in commands} )
)
all_data = await asyncio.gather(*tasks)
logging.debug(f"{self} - (Multicommand) - Received data") logging.debug(f"{self} - (Multicommand) - Received data")
data = dict(**main_data, **get_commands_data) data = {}
for item in all_data:
data.update(item)
data["multicommand"] = True data["multicommand"] = True
return data return data

View File

@@ -413,46 +413,22 @@ class BaseMiner(ABC):
async def _get_data(self, allow_warning: bool, data_to_get: list = None) -> dict: async def _get_data(self, allow_warning: bool, data_to_get: list = None) -> dict:
if not data_to_get: if not data_to_get:
# everything # everything
data_to_get = [ data_to_get = list(self.data_locations.keys())
"mac",
"model", api_multicommand = set()
"api_ver", web_multicommand = set()
"fw_ver",
"hostname",
"hashrate",
"nominal_hashrate",
"hashboards",
"env_temp",
"wattage",
"wattage_limit",
"fans",
"fan_psu",
"errors",
"fault_light",
"pools",
"is_mining",
"uptime",
]
api_multicommand = []
web_multicommand = []
for data_name in data_to_get: for data_name in data_to_get:
try: try:
fn_args = self.data_locations[data_name]["kwargs"] fn_args = self.data_locations[data_name]["kwargs"]
for arg_name in fn_args: for arg_name in fn_args:
if fn_args[arg_name].get("api"): if fn_args[arg_name].get("api"):
api_multicommand.append(fn_args[arg_name]["api"]) api_multicommand.add(fn_args[arg_name]["api"])
if fn_args[arg_name].get("web"): if fn_args[arg_name].get("web"):
web_multicommand.append(fn_args[arg_name]["web"]) web_multicommand.add(fn_args[arg_name]["web"])
except KeyError as e: except KeyError as e:
logger.error(e, data_name) logger.error(e, data_name)
continue continue
api_multicommand = list(set(api_multicommand))
_web_multicommand = web_multicommand
for item in web_multicommand:
if item not in _web_multicommand:
_web_multicommand.append(item)
web_multicommand = _web_multicommand
if len(api_multicommand) > 0: if len(api_multicommand) > 0:
api_command_data = await self.api.multicommand( api_command_data = await self.api.multicommand(
*api_multicommand, allow_warning=allow_warning *api_multicommand, allow_warning=allow_warning
@@ -492,7 +468,7 @@ class BaseMiner(ABC):
args_to_send[arg_name] = web_command_data args_to_send[arg_name] = web_command_data
except LookupError: except LookupError:
args_to_send[arg_name] = None args_to_send[arg_name] = None
except LookupError as e: except LookupError:
continue continue
function = getattr(self, self.data_locations[data_name]["cmd"]) function = getattr(self, self.data_locations[data_name]["cmd"])