diff --git a/cfg_util/func.py b/cfg_util/func/__init__.py similarity index 93% rename from cfg_util/func.py rename to cfg_util/func/__init__.py index 74f8d84e..9732eb89 100644 --- a/cfg_util/func.py +++ b/cfg_util/func/__init__.py @@ -10,6 +10,7 @@ import toml from cfg_util.miner_factory import miner_factory 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 @@ -131,23 +132,26 @@ async def get_formatted_data(ip: ipaddress.ip_address): data = await miner.api.multicommand("summary", "pools", "tunerstatus") host = await miner.get_hostname() 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: wattage = 0 if "summary" in data.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(): 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: th5s = 0 else: th5s = 0 else: th5s = 0 - if not data['pools'][0]['POOLS'] == []: - user = data['pools'][0]['POOLS'][0]['User'] + if "pools" not in data.keys(): + user = "?" + elif not data['pools'][0]['POOLS'] == []: + user = await safe_parse_api_data(data, 'pools', 0, 'POOLS', 0, 'User') else: user = "Blank" return {'TH/s': th5s, 'IP': str(miner.ip), 'host': host, 'user': user, 'wattage': wattage} diff --git a/cfg_util/func/data.py b/cfg_util/func/data.py new file mode 100644 index 00000000..6814c655 --- /dev/null +++ b/cfg_util/func/data.py @@ -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 diff --git a/main.py b/main.py index 3d808d8d..0b6a26db 100644 --- a/main.py +++ b/main.py @@ -4,6 +4,7 @@ import asyncio from API.bosminer import BOSMinerAPI from API.cgminer import CGMinerAPI 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: @@ -42,8 +43,12 @@ async def braiins_update(): async def test_command(): miner_network = MinerNetwork('192.168.1.1') miners = await miner_network.scan_network_for_miners() - tasks = miners[0].api.multicommand("summary", "pools", "tunerstatus") - data = await asyncio.gather(tasks) + tasks = [miner.api.summary() for miner in miners] + 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) async def get_commands_from_miner_api(): @@ -54,4 +59,4 @@ async def get_commands_from_miner_api(): if __name__ == '__main__': - asyncio.new_event_loop().run_until_complete(get_commands_from_miner_api()) + asyncio.new_event_loop().run_until_complete(test_command())