improved api.__init__ formatting and readability
This commit is contained in:
@@ -18,14 +18,19 @@ class APIError(Exception):
|
|||||||
|
|
||||||
|
|
||||||
class BaseMinerAPI:
|
class BaseMinerAPI:
|
||||||
def __init__(self, ip: str, port: int) -> None:
|
def __init__(self, ip: str, port: int = 4028) -> None:
|
||||||
|
# api port, should be 4028
|
||||||
self.port = port
|
self.port = port
|
||||||
|
# ip address of the miner
|
||||||
self.ip = ipaddress.ip_address(ip)
|
self.ip = ipaddress.ip_address(ip)
|
||||||
|
|
||||||
def get_commands(self) -> list:
|
def get_commands(self) -> list:
|
||||||
return [func for func in
|
return [func for func in
|
||||||
|
# each function in self
|
||||||
dir(self) if callable(getattr(self, func)) and
|
dir(self) if callable(getattr(self, func)) and
|
||||||
|
# no __ methods
|
||||||
not func.startswith("__") and
|
not func.startswith("__") and
|
||||||
|
# remove all functions that are in this base class
|
||||||
func not in
|
func not in
|
||||||
[func for func in
|
[func for func in
|
||||||
dir(BaseMinerAPI) if callable(getattr(BaseMinerAPI, func))
|
dir(BaseMinerAPI) if callable(getattr(BaseMinerAPI, func))
|
||||||
@@ -33,11 +38,18 @@ class BaseMinerAPI:
|
|||||||
]
|
]
|
||||||
|
|
||||||
async def multicommand(self, *commands: str) -> dict:
|
async def multicommand(self, *commands: str) -> dict:
|
||||||
|
# split the commands into a proper list
|
||||||
commands = [*commands]
|
commands = [*commands]
|
||||||
|
|
||||||
for item in commands:
|
for item in commands:
|
||||||
|
# make sure we can actually run the command, otherwise it will fail
|
||||||
if item not in self.get_commands():
|
if item not in self.get_commands():
|
||||||
print(f"Removing command: {item}")
|
# if the command isnt allowed, remove it
|
||||||
|
print(f"Removing incorrect command: {item}")
|
||||||
commands.remove(item)
|
commands.remove(item)
|
||||||
|
|
||||||
|
# standard multicommand format is "command1+command2"
|
||||||
|
# doesnt work for S19 which is dealt with in the send command function
|
||||||
command = "+".join(commands)
|
command = "+".join(commands)
|
||||||
return await self.send_command(command)
|
return await self.send_command(command)
|
||||||
|
|
||||||
@@ -45,6 +57,7 @@ class BaseMinerAPI:
|
|||||||
try:
|
try:
|
||||||
# get reader and writer streams
|
# get reader and writer streams
|
||||||
reader, writer = await asyncio.open_connection(str(self.ip), self.port)
|
reader, writer = await asyncio.open_connection(str(self.ip), self.port)
|
||||||
|
# handle OSError 121
|
||||||
except OSError as e:
|
except OSError as e:
|
||||||
if e.winerror == "121":
|
if e.winerror == "121":
|
||||||
print("Semaphore Timeout has Expired.")
|
print("Semaphore Timeout has Expired.")
|
||||||
@@ -72,21 +85,18 @@ class BaseMinerAPI:
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(e)
|
print(e)
|
||||||
|
|
||||||
try:
|
data = self.load_api_data(data)
|
||||||
if data.endswith(b"\x00"):
|
|
||||||
data = json.loads(data.decode('utf-8')[:-1])
|
|
||||||
else:
|
|
||||||
data = json.loads(data.decode('utf-8'))
|
|
||||||
except json.decoder.JSONDecodeError:
|
|
||||||
raise APIError(f"Decode Error: {data}")
|
|
||||||
|
|
||||||
# close the connection
|
# close the connection
|
||||||
writer.close()
|
writer.close()
|
||||||
await writer.wait_closed()
|
await writer.wait_closed()
|
||||||
|
|
||||||
|
# validate the command suceeded
|
||||||
|
# also handle for S19 not liking "command1+command2" format
|
||||||
if not self.validate_command_output(data):
|
if not self.validate_command_output(data):
|
||||||
try:
|
try:
|
||||||
data = {}
|
data = {}
|
||||||
|
# S19 handler, try again
|
||||||
for cmd in command.split("+"):
|
for cmd in command.split("+"):
|
||||||
data[cmd] = []
|
data[cmd] = []
|
||||||
data[cmd].append(await self.send_command(cmd))
|
data[cmd].append(await self.send_command(cmd))
|
||||||
@@ -99,7 +109,8 @@ class BaseMinerAPI:
|
|||||||
|
|
||||||
return data
|
return data
|
||||||
|
|
||||||
def validate_command_output(self, data):
|
@staticmethod
|
||||||
|
def validate_command_output(data):
|
||||||
# check if the data returned is correct or an error
|
# check if the data returned is correct or an error
|
||||||
# if status isn't a key, it is a multicommand
|
# if status isn't a key, it is a multicommand
|
||||||
if "STATUS" not in data.keys():
|
if "STATUS" not in data.keys():
|
||||||
@@ -118,3 +129,17 @@ class BaseMinerAPI:
|
|||||||
if data["STATUS"][0]["STATUS"] not in ("S", "I"):
|
if data["STATUS"][0]["STATUS"] not in ("S", "I"):
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def load_api_data(data):
|
||||||
|
try:
|
||||||
|
# some json from the API returns with a null byte (\x00) on the end
|
||||||
|
if data.endswith(b"\x00"):
|
||||||
|
# handle the null byte
|
||||||
|
data = json.loads(data.decode('utf-8')[:-1])
|
||||||
|
else:
|
||||||
|
# no null byte
|
||||||
|
data = json.loads(data.decode('utf-8'))
|
||||||
|
# handle bad json
|
||||||
|
except json.decoder.JSONDecodeError:
|
||||||
|
raise APIError(f"Decode Error: {data}")
|
||||||
|
|||||||
Reference in New Issue
Block a user