updated so that throughputs will update link color/width based on threshold

This commit is contained in:
Blake Harnden 2019-12-27 00:32:10 -08:00
parent 5dd08c283a
commit 2be0713ed1
7 changed files with 75 additions and 167 deletions

View file

@ -212,9 +212,7 @@ class CoreClient:
)
return
logging.info("handling throughputs event: %s", event)
self.app.canvas.throughput_draw.process_grpc_throughput_event(
event.interface_throughputs
)
self.app.canvas.set_throughputs(event)
def handle_exception_event(self, event):
logging.info("exception event: %s", event)
@ -511,6 +509,7 @@ class CoreClient:
start = time.perf_counter()
try:
response = self.client.stop_session(session_id)
self.app.canvas.stopped_session()
logging.debug(
"stopped session(%s), result: %s", session_id, response.result
)

View file

@ -8,6 +8,8 @@ from core.gui.graph import tags
from core.gui.nodeutils import NodeUtils
TEXT_DISTANCE = 0.30
EDGE_WIDTH = 3
EDGE_COLOR = "#ff0000"
class CanvasWirelessEdge:
@ -29,8 +31,6 @@ class CanvasEdge:
Canvas edge class
"""
width = 3
def __init__(self, x1, y1, x2, y2, src, canvas):
"""
Create an instance of canvas edge object
@ -47,10 +47,11 @@ class CanvasEdge:
self.dst_interface = None
self.canvas = canvas
self.id = self.canvas.create_line(
x1, y1, x2, y2, tags=tags.EDGE, width=self.width, fill="#ff0000"
x1, y1, x2, y2, tags=tags.EDGE, width=EDGE_WIDTH, fill=EDGE_COLOR
)
self.text_src = None
self.text_dst = None
self.text_middle = None
self.token = None
self.font = Font(size=8)
self.link = None
@ -77,6 +78,12 @@ class CanvasEdge:
y2 = y2 - uy
return x1, y1, x2, y2
def get_midpoint(self):
x1, y1, x2, y2 = self.canvas.coords(self.id)
x = (x1 + x2) / 2
y = (y1 + y2) / 2
return x, y
def draw_labels(self):
x1, y1, x2, y2 = self.get_coordinates()
label_one = None
@ -117,6 +124,28 @@ class CanvasEdge:
x1, y1, x2, y2 = self.get_coordinates()
self.canvas.coords(self.text_src, x1, y1)
self.canvas.coords(self.text_dst, x2, y2)
if self.text_middle is not None:
x, y = self.get_midpoint()
self.canvas.coords(self.text_middle, x, y)
def set_throughput(self, throughput):
throughput = 0.001 * throughput
value = f"{throughput:.3f} kbps"
if self.text_middle is None:
x, y = self.get_midpoint()
self.text_middle = self.canvas.create_text(
x, y, tags=tags.THROUGHPUT, font=self.font, text=value
)
else:
self.canvas.itemconfig(self.text_middle, text=value)
if throughput > self.canvas.throughput_threshold:
color = self.canvas.throughput_color
width = self.canvas.throughput_width
else:
color = EDGE_COLOR
width = EDGE_WIDTH
self.canvas.itemconfig(self.id, fill=color, width=width)
def complete(self, dst):
self.dst = dst
@ -128,14 +157,17 @@ class CanvasEdge:
self.canvas.tag_raise(self.src)
self.canvas.tag_raise(self.dst)
def check_wireless(self):
def is_wireless(self):
src_node = self.canvas.nodes[self.src]
dst_node = self.canvas.nodes[self.dst]
src_node_type = src_node.core_node.type
dst_node_type = dst_node.core_node.type
is_src_wireless = NodeUtils.is_wireless_node(src_node_type)
is_dst_wireless = NodeUtils.is_wireless_node(dst_node_type)
if is_src_wireless or is_dst_wireless:
return is_src_wireless or is_dst_wireless
def check_wireless(self):
if self.is_wireless():
self.canvas.itemconfig(self.id, state=tk.HIDDEN)
self._check_antenna()
@ -160,6 +192,12 @@ class CanvasEdge:
if self.link:
self.canvas.delete(self.text_src)
self.canvas.delete(self.text_dst)
self.canvas.delete(self.text_middle)
def reset(self):
self.canvas.delete(self.text_middle)
self.text_middle = None
self.canvas.itemconfig(self.id, fill=EDGE_COLOR, width=EDGE_WIDTH)
def create_context(self, event):
logging.debug("create link context")

View file

@ -9,7 +9,6 @@ from core.gui.dialogs.shapemod import ShapeDialog
from core.gui.graph import tags
from core.gui.graph.edges import CanvasEdge, CanvasWirelessEdge
from core.gui.graph.enums import GraphMode, ScaleOption
from core.gui.graph.linkinfo import Throughput
from core.gui.graph.node import CanvasNode
from core.gui.graph.shape import Shape
from core.gui.graph.shapeutils import ShapeType, is_draw_shape, is_marker
@ -38,7 +37,6 @@ class CanvasGraph(tk.Canvas):
self.wireless_edges = {}
self.drawing_edge = None
self.grid = None
self.throughput_draw = Throughput(self, core)
self.shape_drawing = False
self.default_dimensions = (width, height)
self.current_dimensions = self.default_dimensions
@ -158,6 +156,21 @@ class CanvasGraph(tk.Canvas):
valid_bottomright = self.inside_canvas(x2, y2)
return valid_topleft and valid_bottomright
def set_throughputs(self, throughputs_event):
for interface_throughput in throughputs_event.interface_throughputs:
node_id = interface_throughput.node_id
interface_id = interface_throughput.interface_id
throughput = interface_throughput.throughput
interface_to_edge_id = (node_id, interface_id)
token = self.core.interface_to_edge.get(interface_to_edge_id)
if not token:
continue
edge = self.edges.get(token)
if edge:
edge.set_throughput(throughput)
else:
del self.core.interface_to_edge[interface_to_edge_id]
def draw_grid(self):
"""
Create grid.
@ -269,6 +282,20 @@ class CanvasGraph(tk.Canvas):
# raise the nodes so they on top of the links
self.tag_raise(tags.NODE)
def stopped_session(self):
# clear wireless edges
for edge in self.wireless_edges.values():
edge.delete()
src_node = self.nodes[edge.src]
src_node.wireless_edges.remove(edge)
dst_node = self.nodes[edge.dst]
dst_node.wireless_edges.remove(edge)
self.wireless_edges.clear()
# clear all middle edge labels
for edge in self.edges.values():
edge.reset()
def canvas_xy(self, event):
"""
Convert window coordinate to canvas coordinate
@ -446,9 +473,7 @@ class CanvasGraph(tk.Canvas):
if edge in edges:
continue
edges.add(edge)
self.throughput_draw.delete(edge)
self.edges.pop(edge.token, None)
# del self.edges[edge.token]
edge.delete()
# update node connected to edge being deleted

View file

@ -1,152 +0,0 @@
"""
Link information, such as IPv4, IPv6 and throughput drawn in the canvas
"""
from core.api.grpc import core_pb2
class Throughput:
def __init__(self, canvas, core):
self.canvas = canvas
self.core = core
# edge canvas id mapped to throughput value
self.tracker = {}
# map an edge canvas id to a throughput canvas id
self.map = {}
# map edge canvas id to token
self.edge_id_to_token = {}
def load_throughput_info(self, interface_throughputs):
"""
load all interface throughouts from an event
:param repeated core_bp2.InterfaceThroughputinterface_throughputs: interface
throughputs
:return: nothing
"""
for throughput in interface_throughputs:
nid = throughput.node_id
iid = throughput.interface_id
tp = throughput.throughput
token = self.core.interface_to_edge.get((nid, iid))
if token:
edge = self.canvas.edges.get(token)
if edge:
edge_id = edge.id
self.edge_id_to_token[edge_id] = token
if edge_id not in self.tracker:
self.tracker[edge_id] = tp
else:
temp = self.tracker[edge_id]
self.tracker[edge_id] = (temp + tp) / 2
else:
self.core.interface_to_edge.pop((nid, iid), None)
def edge_is_wired(self, token):
"""
determine whether link is a WIRED link
:param token:
:return:
"""
canvas_edge = self.canvas.edges[token]
canvas_src_id = canvas_edge.src
canvas_dst_id = canvas_edge.dst
src = self.canvas.nodes[canvas_src_id].core_node
dst = self.canvas.nodes[canvas_dst_id].core_node
return not (
src.type == core_pb2.NodeType.WIRELESS_LAN
and dst.model == "mdr"
or src.model == "mdr"
and dst.type == core_pb2.NodeType.WIRELESS_LAN
)
def draw_wired_throughput(self, edge_id):
x0, y0, x1, y1 = self.canvas.coords(edge_id)
x = (x0 + x1) / 2
y = (y0 + y1) / 2
if edge_id not in self.map:
tpid = self.canvas.create_text(
x,
y,
tags="throughput",
font=("Arial", 8),
text="{0:.3f} kbps".format(0.001 * self.tracker[edge_id]),
)
self.map[edge_id] = tpid
else:
tpid = self.map[edge_id]
self.canvas.coords(tpid, x, y)
self.canvas.itemconfig(
tpid, text="{0:.3f} kbps".format(0.001 * self.tracker[edge_id])
)
def draw_wireless_throughput(self, edge_id):
token = self.edge_id_to_token[edge_id]
canvas_edge = self.canvas.edges[token]
canvas_src_id = canvas_edge.src
canvas_dst_id = canvas_edge.dst
src_node = self.canvas.nodes[canvas_src_id]
dst_node = self.canvas.nodes[canvas_dst_id]
not_wlan = (
dst_node
if src_node.core_node.type == core_pb2.NodeType.WIRELESS_LAN
else src_node
)
x, y = self.canvas.coords(not_wlan.id)
if edge_id not in self.map:
tp_id = self.canvas.create_text(
x + 50,
y + 25,
font=("Arial", 8),
tags="throughput",
text="{0:.3f} kbps".format(0.001 * self.tracker[edge_id]),
)
self.map[edge_id] = tp_id
# redraw throughput
else:
self.canvas.itemconfig(
self.map[edge_id],
text="{0:.3f} kbps".format(0.001 * self.tracker[edge_id]),
)
def draw_throughputs(self):
for edge_id in self.tracker:
if self.edge_is_wired(self.edge_id_to_token[edge_id]):
self.draw_wired_throughput(edge_id)
else:
self.draw_wireless_throughput(edge_id)
def process_grpc_throughput_event(self, interface_throughputs):
self.load_throughput_info(interface_throughputs)
self.draw_throughputs()
def move(self, edge):
tpid = self.map.get(edge.id)
if tpid:
if self.edge_is_wired(edge.token):
x0, y0, x1, y1 = self.canvas.coords(edge.id)
self.canvas.coords(tpid, (x0 + x1) / 2, (y0 + y1) / 2)
else:
if (
self.canvas.nodes[edge.src].core_node.type
== core_pb2.NodeType.WIRELESS_LAN
):
x, y = self.canvas.coords(edge.dst)
self.canvas.coords(tpid, x + 50, y + 20)
else:
x, y = self.canvas.coords(edge.src)
self.canvas.coords(tpid, x + 50, y + 25)
def delete(self, edge):
tpid = self.map.get(edge.id)
if tpid:
eid = edge.id
self.canvas.delete(tpid)
self.tracker.pop(eid)
self.map.pop(eid)
self.edge_id_to_token.pop(eid)

View file

@ -128,7 +128,6 @@ class CanvasNode:
self.canvas.coords(edge.id, x, y, x2, y2)
else:
self.canvas.coords(edge.id, x1, y1, x, y)
self.canvas.throughput_draw.move(edge)
edge.update_labels()
for edge in self.wireless_edges:

View file

@ -9,6 +9,7 @@ NODE_NAME = "nodename"
NODE = "node"
WALLPAPER = "wallpaper"
SELECTION = "selectednodes"
THROUGHPUT = "throughput"
ABOVE_WALLPAPER_TAGS = [
GRIDLINE,
SHAPE,

View file

@ -7,7 +7,6 @@ from tkinter.font import Font
from core.gui.dialogs.customnodes import CustomNodesDialog
from core.gui.dialogs.marker import MarkerDialog
from core.gui.graph import tags
from core.gui.graph.enums import GraphMode
from core.gui.graph.shapeutils import ShapeType, is_marker
from core.gui.images import ImageEnum, Images
@ -404,7 +403,6 @@ class Toolbar(ttk.Frame):
self.app.statusbar.progress_bar.start(5)
thread = threading.Thread(target=self.app.core.stop_session)
thread.start()
self.app.canvas.delete(tags.WIRELESS_EDGE)
self.design_frame.tkraise()
self.click_selection()