added table manager, to manage tables and handle the treeview
This commit is contained in:
@@ -42,17 +42,19 @@ from settings import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class MinerFactory:
|
class Singleton(type):
|
||||||
_instance = None
|
_instances = {}
|
||||||
|
|
||||||
|
def __call__(cls, *args, **kwargs):
|
||||||
|
if cls not in cls._instances:
|
||||||
|
cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)
|
||||||
|
return cls._instances[cls]
|
||||||
|
|
||||||
|
|
||||||
|
class MinerFactory(metaclass=Singleton):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.miners = {}
|
self.miners = {}
|
||||||
|
|
||||||
def __new__(cls):
|
|
||||||
if not cls._instance:
|
|
||||||
cls._instance = super(MinerFactory, cls).__new__(cls)
|
|
||||||
return cls._instance
|
|
||||||
|
|
||||||
async def get_miner_generator(self, ips: list):
|
async def get_miner_generator(self, ips: list):
|
||||||
"""
|
"""
|
||||||
Get Miner objects from ip addresses using an async generator.
|
Get Miner objects from ip addresses using an async generator.
|
||||||
|
|||||||
@@ -1,12 +1,9 @@
|
|||||||
import PySimpleGUI as sg
|
import PySimpleGUI as sg
|
||||||
import asyncio
|
import asyncio
|
||||||
import sys
|
import sys
|
||||||
import base64
|
|
||||||
from io import BytesIO
|
|
||||||
from PIL import ImageTk, Image
|
|
||||||
from tools.cfg_util.cfg_util_qt.imgs import FAULT_LIGHT, TkImages
|
from tools.cfg_util.cfg_util_qt.imgs import FAULT_LIGHT, TkImages
|
||||||
from tools.cfg_util.cfg_util_qt.tables import clear_tables, _update_tree_by_ip
|
|
||||||
from tools.cfg_util.cfg_util_qt.scan import btn_scan
|
from tools.cfg_util.cfg_util_qt.scan import btn_scan
|
||||||
|
from tools.cfg_util.cfg_util_qt.commands import btn_light
|
||||||
from tools.cfg_util.cfg_util_qt.layout import window
|
from tools.cfg_util.cfg_util_qt.layout import window
|
||||||
from tools.cfg_util.cfg_util_qt.general import btn_all
|
from tools.cfg_util.cfg_util_qt.general import btn_all
|
||||||
import tkinter as tk
|
import tkinter as tk
|
||||||
@@ -46,6 +43,10 @@ async def main():
|
|||||||
if event == "cmd_all":
|
if event == "cmd_all":
|
||||||
_table = "cmd_table"
|
_table = "cmd_table"
|
||||||
btn_all(_table, value[_table])
|
btn_all(_table, value[_table])
|
||||||
|
if event == "cmd_light":
|
||||||
|
_table = "cmd_table"
|
||||||
|
_ips = value[_table]
|
||||||
|
await btn_light(_ips)
|
||||||
|
|
||||||
if event == "__TIMEOUT__":
|
if event == "__TIMEOUT__":
|
||||||
await asyncio.sleep(0)
|
await asyncio.sleep(0)
|
||||||
|
|||||||
20
tools/cfg_util/cfg_util_qt/commands/__init__.py
Normal file
20
tools/cfg_util/cfg_util_qt/commands/__init__.py
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
from tools.cfg_util.cfg_util_qt.layout import window
|
||||||
|
from tools.cfg_util.cfg_util_qt.tables import update_tree
|
||||||
|
from tools.cfg_util.cfg_util_qt.imgs import TkImages
|
||||||
|
|
||||||
|
|
||||||
|
async def btn_light(ips: list):
|
||||||
|
_table = window["cmd_table"].Widget
|
||||||
|
data = []
|
||||||
|
iids = _table.get_children()
|
||||||
|
for idx in ips:
|
||||||
|
item = _table.item(iids[idx])
|
||||||
|
data.append(
|
||||||
|
{
|
||||||
|
"IP": item["values"][0],
|
||||||
|
"Model": item["values"][1],
|
||||||
|
"Command Output": item["values"][2],
|
||||||
|
"Light": True,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
await update_tree(data)
|
||||||
@@ -8,9 +8,16 @@ FAULT_LIGHT = b"iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAAXNSR0IArs4c6QAA
|
|||||||
LIGHT = b"iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAACkSURBVChThZDhDcIgEIWBLuAe8N90kAa2MDWdw8YtIEzgBF0AdJviey0aNWn9kiv3Li8vvZOiYq3tpJQ92nadiFhKiSGESLEYnXMXPCeUov5gRl2992dZkzwGv6YXM5KdgqmD2DIRenoaaPxHu5f0BY3T2u4SFX50RMPttuAysck5340xBwyOqPddK8t5cMuxoUop3bTWD2xHqfkBE5IGmoQQ4gmmsjUl2gChkgAAAABJRU5ErkJggg=="
|
LIGHT = b"iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAACkSURBVChThZDhDcIgEIWBLuAe8N90kAa2MDWdw8YtIEzgBF0AdJviey0aNWn9kiv3Li8vvZOiYq3tpJQ92nadiFhKiSGESLEYnXMXPCeUov5gRl2992dZkzwGv6YXM5KdgqmD2DIRenoaaPxHu5f0BY3T2u4SFX50RMPttuAysck5340xBwyOqPddK8t5cMuxoUop3bTWD2xHqfkBE5IGmoQQ4gmmsjUl2gChkgAAAABJRU5ErkJggg=="
|
||||||
|
|
||||||
|
|
||||||
class TkImages:
|
class Singleton(type):
|
||||||
_instance = None
|
_instances = {}
|
||||||
|
|
||||||
|
def __call__(cls, *args, **kwargs):
|
||||||
|
if cls not in cls._instances:
|
||||||
|
cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)
|
||||||
|
return cls._instances[cls]
|
||||||
|
|
||||||
|
|
||||||
|
class TkImages(metaclass=Singleton):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.fault_light = ImageTk.PhotoImage(
|
self.fault_light = ImageTk.PhotoImage(
|
||||||
Image.open(BytesIO(base64.b64decode(FAULT_LIGHT)))
|
Image.open(BytesIO(base64.b64decode(FAULT_LIGHT)))
|
||||||
@@ -18,8 +25,3 @@ class TkImages:
|
|||||||
self.light = ImageTk.PhotoImage(
|
self.light = ImageTk.PhotoImage(
|
||||||
Image.open(BytesIO(base64.b64decode(FAULT_LIGHT)))
|
Image.open(BytesIO(base64.b64decode(FAULT_LIGHT)))
|
||||||
)
|
)
|
||||||
|
|
||||||
def __new__(cls):
|
|
||||||
if not cls._instance:
|
|
||||||
cls._instance = super(TkImages, cls).__new__(cls)
|
|
||||||
return cls._instance
|
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ TABLE_HEADERS = {
|
|||||||
"CMD": ["IP", "Model", "Command Output"],
|
"CMD": ["IP", "Model", "Command Output"],
|
||||||
"POOLS": [
|
"POOLS": [
|
||||||
"IP",
|
"IP",
|
||||||
# "Model",
|
|
||||||
"Split",
|
"Split",
|
||||||
"Pool 1",
|
"Pool 1",
|
||||||
"Pool 1 User",
|
"Pool 1 User",
|
||||||
@@ -134,8 +133,6 @@ def get_scan_layout():
|
|||||||
|
|
||||||
def get_command_layout():
|
def get_command_layout():
|
||||||
data = sg.TreeData()
|
data = sg.TreeData()
|
||||||
data.insert("", 0, "", ["", "", ""], icon=FAULT_LIGHT)
|
|
||||||
data.insert("", 1, "", ["192.168.1.13", "", ""], icon=LIGHT)
|
|
||||||
col_widths = [
|
col_widths = [
|
||||||
IP_COL_WIDTH,
|
IP_COL_WIDTH,
|
||||||
MODEL_COL_WIDTH,
|
MODEL_COL_WIDTH,
|
||||||
|
|||||||
@@ -11,6 +11,20 @@ import logging
|
|||||||
|
|
||||||
progress_bar_len = 0
|
progress_bar_len = 0
|
||||||
|
|
||||||
|
DEFAULT_DATA = [
|
||||||
|
"Model",
|
||||||
|
"Hostname",
|
||||||
|
"Hashrate",
|
||||||
|
"Temperature",
|
||||||
|
"Pool User",
|
||||||
|
"Pool 1",
|
||||||
|
"Pool 1 User",
|
||||||
|
"Pool 2",
|
||||||
|
"Pool 2 User",
|
||||||
|
"Wattage",
|
||||||
|
"Split",
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
async def btn_all():
|
async def btn_all():
|
||||||
table = "scan_table"
|
table = "scan_table"
|
||||||
@@ -53,7 +67,15 @@ async def _scan_miners(network: MinerNetwork):
|
|||||||
async for found_miner in get_miner_genenerator:
|
async for found_miner in get_miner_genenerator:
|
||||||
resolved_miners.append(found_miner)
|
resolved_miners.append(found_miner)
|
||||||
resolved_miners.sort(key=lambda x: x.ip)
|
resolved_miners.sort(key=lambda x: x.ip)
|
||||||
update_tables([{"IP": str(miner.ip)} for miner in resolved_miners])
|
resolved_miners_data = []
|
||||||
|
for miner in resolved_miners:
|
||||||
|
_data = {}
|
||||||
|
for key in DEFAULT_DATA:
|
||||||
|
_data[key] = ""
|
||||||
|
_data["IP"] = str(miner.ip)
|
||||||
|
_data["Light"] = False
|
||||||
|
resolved_miners_data.append(_data)
|
||||||
|
update_tables(resolved_miners_data)
|
||||||
progress_bar_len += 1
|
progress_bar_len += 1
|
||||||
await update_prog_bar(progress_bar_len)
|
await update_prog_bar(progress_bar_len)
|
||||||
progress_bar_len += network_size - len(resolved_miners)
|
progress_bar_len += network_size - len(resolved_miners)
|
||||||
@@ -68,7 +90,6 @@ async def _get_miners_data(miners: list):
|
|||||||
for all_data in data_generator:
|
for all_data in data_generator:
|
||||||
data = await all_data
|
data = await all_data
|
||||||
for idx, item in enumerate(miner_data):
|
for idx, item in enumerate(miner_data):
|
||||||
# print(item["IP"], data["IP"])
|
|
||||||
if item["IP"] == data["IP"]:
|
if item["IP"] == data["IP"]:
|
||||||
miner_data[idx] = data
|
miner_data[idx] = data
|
||||||
update_tables(miner_data)
|
update_tables(miner_data)
|
||||||
|
|||||||
@@ -21,69 +21,105 @@ def update_miner_count(count):
|
|||||||
window[button].update(f"Miners: {count}")
|
window[button].update(f"Miners: {count}")
|
||||||
|
|
||||||
|
|
||||||
def update_tables(data: list):
|
def update_tables(data: list or None = None):
|
||||||
tables = {
|
table_manager = TableManager()
|
||||||
"SCAN": [["" for _ in TABLE_HEADERS["SCAN"]] for _ in data],
|
table_manager.update_tables(data)
|
||||||
"CMD": [["" for _ in TABLE_HEADERS["CMD"]] for _ in data],
|
|
||||||
"POOLS": [["" for _ in TABLE_HEADERS["POOLS"]] for _ in data],
|
|
||||||
"CONFIG": [["" for _ in TABLE_HEADERS["CONFIG"]] for _ in data],
|
|
||||||
}
|
|
||||||
for data_idx, item in enumerate(data):
|
|
||||||
keys = item.keys()
|
|
||||||
if "Hashrate" in keys:
|
|
||||||
if not isinstance(item["Hashrate"], str):
|
|
||||||
item[
|
|
||||||
"Hashrate"
|
|
||||||
] = f"{format(float(item['Hashrate']), '.2f').rjust(6, ' ')} TH/s"
|
|
||||||
for key in keys:
|
|
||||||
for table in TABLE_HEADERS.keys():
|
|
||||||
for idx, header in enumerate(TABLE_HEADERS[table]):
|
|
||||||
if key == header:
|
|
||||||
tables[table][data_idx][idx] = item[key]
|
|
||||||
|
|
||||||
window["scan_table"].update(tables["SCAN"])
|
|
||||||
window["pools_table"].update(tables["POOLS"])
|
|
||||||
window["cfg_table"].update(tables["CONFIG"])
|
|
||||||
|
|
||||||
treedata = sg.TreeData()
|
|
||||||
for idx, item in enumerate(tables["CMD"]):
|
|
||||||
treedata.insert("", idx, "", item, icon=LIGHT)
|
|
||||||
|
|
||||||
window["cmd_table"].update(treedata)
|
|
||||||
|
|
||||||
update_miner_count(len(data))
|
|
||||||
|
|
||||||
|
|
||||||
async def _update_tree_by_ip(ip: str, data: dict):
|
async def update_tree(data: list):
|
||||||
keys = data.keys()
|
for item in data:
|
||||||
img = None
|
if not item.get("IP"):
|
||||||
if "IP" not in keys or "Model" not in keys:
|
continue
|
||||||
return
|
table_manager = TableManager()
|
||||||
_tree = window["cmd_table"].Widget
|
table_manager.update_tree_by_key(item, "IP")
|
||||||
for iid in _tree.get_children():
|
|
||||||
values = _tree.item(iid)["values"]
|
|
||||||
if data.get("Light"):
|
class Singleton(type):
|
||||||
if data["Light"]:
|
_instances = {}
|
||||||
img = TkImages().fault_light
|
|
||||||
if not data["Light"]:
|
def __call__(cls, *args, **kwargs):
|
||||||
img = TkImages().light
|
if cls not in cls._instances:
|
||||||
if values[0] == ip:
|
cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)
|
||||||
if img:
|
return cls._instances[cls]
|
||||||
_tree.item(
|
|
||||||
iid,
|
|
||||||
image=img,
|
class TableManager(metaclass=Singleton):
|
||||||
values=[
|
_instance = None
|
||||||
data["IP"],
|
|
||||||
data["Model"] if "Model" in keys else "",
|
def __init__(self):
|
||||||
data["Command Output"] if "Command Output" in keys else "",
|
self.images = TkImages()
|
||||||
],
|
self.data = []
|
||||||
)
|
|
||||||
else:
|
def update_tables(self, data: list or None = None):
|
||||||
_tree.item(
|
if not data or data == []:
|
||||||
iid,
|
data = self.data
|
||||||
values=[
|
self.data = data
|
||||||
data["IP"],
|
tables = {
|
||||||
data["Model"] if "Model" in keys else "",
|
"SCAN": [["" for _ in TABLE_HEADERS["SCAN"]] for _ in data],
|
||||||
data["Command Output"] if "Command Output" in keys else "",
|
"CMD": [["" for _ in TABLE_HEADERS["CMD"]] for _ in data],
|
||||||
],
|
"POOLS": [["" for _ in TABLE_HEADERS["POOLS"]] for _ in data],
|
||||||
)
|
"CONFIG": [["" for _ in TABLE_HEADERS["CONFIG"]] for _ in data],
|
||||||
|
}
|
||||||
|
for data_idx, item in enumerate(data):
|
||||||
|
keys = item.keys()
|
||||||
|
if "Hashrate" in keys:
|
||||||
|
if not isinstance(item["Hashrate"], str):
|
||||||
|
item[
|
||||||
|
"Hashrate"
|
||||||
|
] = f"{format(float(item['Hashrate']), '.2f').rjust(6, ' ')} TH/s"
|
||||||
|
for key in keys:
|
||||||
|
for table in TABLE_HEADERS.keys():
|
||||||
|
for idx, header in enumerate(TABLE_HEADERS[table]):
|
||||||
|
if key == header:
|
||||||
|
tables[table][data_idx][idx] = item[key]
|
||||||
|
|
||||||
|
window["scan_table"].update(tables["SCAN"])
|
||||||
|
window["pools_table"].update(tables["POOLS"])
|
||||||
|
window["cfg_table"].update(tables["CONFIG"])
|
||||||
|
|
||||||
|
treedata = sg.TreeData()
|
||||||
|
for idx, item in enumerate(tables["CMD"]):
|
||||||
|
treedata.insert("", idx, "", item, icon=LIGHT)
|
||||||
|
|
||||||
|
window["cmd_table"].update(treedata)
|
||||||
|
|
||||||
|
update_miner_count(len(data))
|
||||||
|
|
||||||
|
def update_tree_by_key(self, data: dict, key: str = "IP"):
|
||||||
|
for idx, item in enumerate(self.data):
|
||||||
|
if key in item.keys():
|
||||||
|
if data[key] == item[key]:
|
||||||
|
self.data[idx] = data
|
||||||
|
|
||||||
|
keys = data.keys()
|
||||||
|
img = None
|
||||||
|
if key not in keys:
|
||||||
|
return
|
||||||
|
_tree = window["cmd_table"].Widget
|
||||||
|
for iid in _tree.get_children():
|
||||||
|
values = _tree.item(iid)["values"]
|
||||||
|
if data.get("Light"):
|
||||||
|
if data["Light"]:
|
||||||
|
img = self.images.fault_light
|
||||||
|
if not data["Light"]:
|
||||||
|
img = self.images.light
|
||||||
|
if values[0] == data["IP"]:
|
||||||
|
if img:
|
||||||
|
_tree.item(
|
||||||
|
iid,
|
||||||
|
image=img,
|
||||||
|
values=[
|
||||||
|
data["IP"],
|
||||||
|
data["Model"] if "Model" in keys else "",
|
||||||
|
data["Command Output"] if "Command Output" in keys else "",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
_tree.item(
|
||||||
|
iid,
|
||||||
|
values=[
|
||||||
|
data["IP"],
|
||||||
|
data["Model"] if "Model" in keys else "",
|
||||||
|
data["Command Output"] if "Command Output" in keys else "",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user