added safe_parse_api_data, recursive function to make sure the api data is parsed safely

This commit is contained in:
UpstreamData
2021-11-26 13:40:59 -07:00
parent d93c147fa2
commit 4062af0e19
3 changed files with 62 additions and 8 deletions

View File

@@ -10,6 +10,7 @@ import toml
from cfg_util.miner_factory import miner_factory from cfg_util.miner_factory import miner_factory
from cfg_util.layout import window from cfg_util.layout import window
from cfg_util.func.data import safe_parse_api_data
from config.bos import bos_config_convert, general_config_convert_bos from config.bos import bos_config_convert, general_config_convert_bos
@@ -131,23 +132,26 @@ async def get_formatted_data(ip: ipaddress.ip_address):
data = await miner.api.multicommand("summary", "pools", "tunerstatus") data = await miner.api.multicommand("summary", "pools", "tunerstatus")
host = await miner.get_hostname() host = await miner.get_hostname()
if "tunerstatus" in data.keys(): if "tunerstatus" in data.keys():
wattage = data['tunerstatus'][0]['TUNERSTATUS'][0]['PowerLimit'] wattage = await safe_parse_api_data(data, "tunerstatus", 0, 'TUNERSTATUS', 0, "PowerLimit")
# data['tunerstatus'][0]['TUNERSTATUS'][0]['PowerLimit']
else: else:
wattage = 0 wattage = 0
if "summary" in data.keys(): if "summary" in data.keys():
if 'MHS 5s' in data['summary'][0]['SUMMARY'][0].keys(): if 'MHS 5s' in data['summary'][0]['SUMMARY'][0].keys():
th5s = round(data['summary'][0]['SUMMARY'][0]['MHS 5s'] / 1000000, 2) th5s = round(await safe_parse_api_data(data, 'summary', 0, 'SUMMARY', 0, 'MHS 5s') / 1000000, 2)
elif 'GHS 5s' in data['summary'][0]['SUMMARY'][0].keys(): elif 'GHS 5s' in data['summary'][0]['SUMMARY'][0].keys():
if not data['summary'][0]['SUMMARY'][0]['GHS 5s'] == "": if not data['summary'][0]['SUMMARY'][0]['GHS 5s'] == "":
th5s = round(float(data['summary'][0]['SUMMARY'][0]['GHS 5s']) / 1000, 2) th5s = round(float(await safe_parse_api_data(data, 'summary', 0, 'SUMMARY', 0, 'GHS 5s')) / 1000, 2)
else: else:
th5s = 0 th5s = 0
else: else:
th5s = 0 th5s = 0
else: else:
th5s = 0 th5s = 0
if not data['pools'][0]['POOLS'] == []: if "pools" not in data.keys():
user = data['pools'][0]['POOLS'][0]['User'] user = "?"
elif not data['pools'][0]['POOLS'] == []:
user = await safe_parse_api_data(data, 'pools', 0, 'POOLS', 0, 'User')
else: else:
user = "Blank" user = "Blank"
return {'TH/s': th5s, 'IP': str(miner.ip), 'host': host, 'user': user, 'wattage': wattage} return {'TH/s': th5s, 'IP': str(miner.ip), 'host': host, 'user': user, 'wattage': wattage}

45
cfg_util/func/data.py Normal file
View File

@@ -0,0 +1,45 @@
from API import APIError
async def safe_parse_api_data(data: dict or list, *path: str or int, idx: int = 0):
path = [*path]
if len(path) == idx+1:
if isinstance(path[idx], str):
if isinstance(data, dict):
if path[idx] in data.keys():
return data[path[idx]]
elif isinstance(path[idx], int):
if isinstance(data, list):
if len(data) > path[idx]:
return data[path[idx]]
else:
if isinstance(path[idx], str):
if isinstance(data, dict):
if path[idx] in data.keys():
parsed_data = await safe_parse_api_data(data[path[idx]], idx=idx+1, *path)
if not parsed_data:
raise APIError(f"Data parsing failed on path index {idx} - \nKey: {path[idx]} \nData: {data}")
return parsed_data
else:
if idx == 0:
raise APIError(f"Data parsing failed on path index {idx} - \nKey: {path[idx]} \nData: {data}")
return False
else:
if idx == 0:
raise APIError(f"Data parsing failed on path index {idx} - \nKey: {path[idx]} \nData: {data}")
return False
elif isinstance(path[idx], int):
if isinstance(data, list):
if len(data) > path[idx]:
parsed_data = await safe_parse_api_data(data[path[idx]], idx=idx+1, *path)
if not parsed_data:
raise APIError(f"Data parsing failed on path index {idx} - \nKey: {path[idx]} \nData: {data}")
return parsed_data
else:
if idx == 0:
raise APIError(f"Data parsing failed on path index {idx} - \nKey: {path[idx]} \nData: {data}")
return False
else:
if idx == 0:
raise APIError(f"Data parsing failed on path index {idx} - \nKey: {path[idx]} \nData: {data}")
return False

11
main.py
View File

@@ -4,6 +4,7 @@ import asyncio
from API.bosminer import BOSMinerAPI from API.bosminer import BOSMinerAPI
from API.cgminer import CGMinerAPI from API.cgminer import CGMinerAPI
import sys import sys
from cfg_util.func.data import safe_parse_api_data
# Fix bug with some whatsminers and asyncio because of a socket not being shut down: # Fix bug with some whatsminers and asyncio because of a socket not being shut down:
@@ -42,8 +43,12 @@ async def braiins_update():
async def test_command(): async def test_command():
miner_network = MinerNetwork('192.168.1.1') miner_network = MinerNetwork('192.168.1.1')
miners = await miner_network.scan_network_for_miners() miners = await miner_network.scan_network_for_miners()
tasks = miners[0].api.multicommand("summary", "pools", "tunerstatus") tasks = [miner.api.summary() for miner in miners]
data = await asyncio.gather(tasks) data = await asyncio.gather(*tasks)
parse_tasks = []
for item in data:
parse_tasks.append(safe_parse_api_data(item, 'SUMMARY', 0, 'MHS 5s'))
data = await asyncio.gather(*parse_tasks)
print(data) print(data)
async def get_commands_from_miner_api(): async def get_commands_from_miner_api():
@@ -54,4 +59,4 @@ async def get_commands_from_miner_api():
if __name__ == '__main__': if __name__ == '__main__':
asyncio.new_event_loop().run_until_complete(get_commands_from_miner_api()) asyncio.new_event_loop().run_until_complete(test_command())