change to appropriate toolbar when join session, emane config, emane model config
This commit is contained in:
parent
68da6c0c14
commit
20637da140
7 changed files with 217 additions and 110 deletions
|
@ -7,6 +7,7 @@ from tkinter import ttk
|
|||
class ConfigType(enum.Enum):
|
||||
STRING = 10
|
||||
BOOL = 11
|
||||
EMANECONFIG = 7
|
||||
|
||||
|
||||
def create_config(master, config, padx=2, pady=2):
|
||||
|
@ -52,8 +53,13 @@ def create_config(master, config, padx=2, pady=2):
|
|||
else:
|
||||
value.set("Off")
|
||||
elif config_type == ConfigType.STRING:
|
||||
value.set(option.value)
|
||||
entry = tk.Entry(frame, textvariable=value)
|
||||
entry.grid(row=index, column=1, sticky="ew", pady=pady)
|
||||
elif config_type == ConfigType.EMANECONFIG:
|
||||
value.set(option.value)
|
||||
entry = tk.Entry(frame, textvariable=value, bg="white")
|
||||
entry.grid(row=index, column=1, sticky="ew", pady=pady)
|
||||
else:
|
||||
logging.error("unhandled config option type: %s", config_type)
|
||||
values[key] = value
|
||||
|
@ -68,7 +74,6 @@ def create_config(master, config, padx=2, pady=2):
|
|||
canvas.bind(
|
||||
"<Configure>", lambda event: canvas.itemconfig(frame_id, width=event.width)
|
||||
)
|
||||
|
||||
return values
|
||||
|
||||
|
||||
|
|
|
@ -80,6 +80,7 @@ class CoreClient:
|
|||
self.core_mapping = CoreToCanvasMapping()
|
||||
self.wlanconfig_management = WlanNodeConfig()
|
||||
self.mobilityconfig_management = MobilityNodeConfig()
|
||||
self.emane_config = None
|
||||
|
||||
def handle_events(self, event):
|
||||
logging.info("event: %s", event)
|
||||
|
@ -110,11 +111,15 @@ class CoreClient:
|
|||
self.nodes.clear()
|
||||
self.edges.clear()
|
||||
self.hooks.clear()
|
||||
self.wlanconfig_management.configurations.clear()
|
||||
self.mobilityconfig_management.configurations.clear()
|
||||
self.emane_config = None
|
||||
|
||||
# get session data
|
||||
response = self.client.get_session(self.session_id)
|
||||
logging.info("joining session(%s): %s", self.session_id, response)
|
||||
session = response.session
|
||||
session_state = session.state
|
||||
self.client.events(self.session_id, self.handle_events)
|
||||
|
||||
# get hooks
|
||||
|
@ -140,6 +145,11 @@ class CoreClient:
|
|||
config = {x: node_config[x].value for x in node_config}
|
||||
self.mobilityconfig_management.configurations[node_id] = config
|
||||
|
||||
# get emane config
|
||||
response = self.client.get_emane_config(self.session_id)
|
||||
logging.info("emane config: %s", response)
|
||||
self.emane_config = response.config
|
||||
|
||||
# determine next node id and reusable nodes
|
||||
max_id = 1
|
||||
for node in session.nodes:
|
||||
|
@ -154,6 +164,14 @@ class CoreClient:
|
|||
# draw session
|
||||
self.app.canvas.canvas_reset_and_redraw(session)
|
||||
|
||||
# draw tool bar appropritate with session state
|
||||
if session_state == core_pb2.SessionState.RUNTIME:
|
||||
self.app.core_editbar.destroy_children_widgets()
|
||||
self.app.core_editbar.create_runtime_toolbar()
|
||||
else:
|
||||
self.app.core_editbar.destroy_children_widgets()
|
||||
self.app.core_editbar.create_toolbar()
|
||||
|
||||
def create_new_session(self):
|
||||
"""
|
||||
Create a new session
|
||||
|
@ -298,6 +316,7 @@ class CoreClient:
|
|||
links,
|
||||
hooks=list(self.hooks.values()),
|
||||
wlan_configs=wlan_configs,
|
||||
emane_config=emane_config,
|
||||
)
|
||||
logging.debug("Start session %s, result: %s", self.session_id, response.result)
|
||||
|
||||
|
|
|
@ -7,18 +7,6 @@ from coretk.graph import GraphMode
|
|||
from coretk.images import ImageEnum, Images
|
||||
from coretk.tooltip import CreateToolTip
|
||||
|
||||
# from enum import Enum
|
||||
|
||||
|
||||
# class SessionStateEnum(Enum):
|
||||
# NONE = "none"
|
||||
# DEFINITION = "definition"
|
||||
# CONFIGURATION = "configuration"
|
||||
# RUNTIME = "runtime"
|
||||
# DATACOLLECT = "datacollect"
|
||||
# SHUTDOWN = "shutdown"
|
||||
# INSTANTIATION = "instantiation"
|
||||
|
||||
|
||||
class CoreToolbar(object):
|
||||
"""
|
||||
|
|
|
@ -3,6 +3,8 @@ CoreToolbar help to draw on canvas, and make grpc client call
|
|||
"""
|
||||
from core.api.grpc.client import core_pb2
|
||||
|
||||
# from coretk import configutils
|
||||
|
||||
|
||||
class CoreToolbarHelp:
|
||||
def __init__(self, app):
|
||||
|
@ -85,6 +87,15 @@ class CoreToolbarHelp:
|
|||
links = self.get_link_list()
|
||||
wlan_configs = self.get_wlan_configuration_list()
|
||||
mobility_configs = self.get_mobility_configuration_list()
|
||||
|
||||
# get emane config
|
||||
pb_emane_config = self.app.core.emane_config
|
||||
emane_config = {x: pb_emane_config[x].value for x in pb_emane_config}
|
||||
|
||||
self.app.core.start_session(
|
||||
nodes, links, wlan_configs=wlan_configs, mobility_configs=mobility_configs
|
||||
nodes,
|
||||
links,
|
||||
wlan_configs=wlan_configs,
|
||||
mobility_configs=mobility_configs,
|
||||
emane_config=emane_config,
|
||||
)
|
||||
|
|
|
@ -5,11 +5,15 @@ emane configuration
|
|||
import logging
|
||||
import tkinter as tk
|
||||
import webbrowser
|
||||
from tkinter import ttk
|
||||
|
||||
from coretk import configutils
|
||||
from coretk.dialogs.dialog import Dialog
|
||||
from coretk.dialogs.mobilityconfig import MobilityConfiguration
|
||||
from coretk.images import ImageEnum, Images
|
||||
|
||||
PAD_X = 2
|
||||
PAD_Y = 2
|
||||
|
||||
|
||||
class EmaneConfiguration(Dialog):
|
||||
def __init__(self, master, app, canvas_node):
|
||||
|
@ -20,6 +24,13 @@ class EmaneConfiguration(Dialog):
|
|||
self.radiovar.set(1)
|
||||
self.columnconfigure(0, weight=1)
|
||||
|
||||
# list(string) of emane models
|
||||
self.emane_models = None
|
||||
|
||||
self.emane_dialog = Dialog(self, app, "emane configuration", modal=False)
|
||||
self.emane_model_dialog = None
|
||||
self.emane_model_combobox = None
|
||||
|
||||
# draw
|
||||
self.node_name_and_image()
|
||||
self.emane_configuration()
|
||||
|
@ -27,8 +38,10 @@ class EmaneConfiguration(Dialog):
|
|||
self.emane_options()
|
||||
self.draw_apply_and_cancel()
|
||||
|
||||
def browse_emane_wiki(self):
|
||||
webbrowser.open_new("https://github.com/adjacentlink/emane/wiki")
|
||||
self.values = None
|
||||
self.options = app.core.emane_config
|
||||
self.model_options = None
|
||||
self.model_values = None
|
||||
|
||||
def create_text_variable(self, val):
|
||||
"""
|
||||
|
@ -52,20 +65,109 @@ class EmaneConfiguration(Dialog):
|
|||
e = tk.Entry(f, textvariable=self.create_text_variable(""), bg="white")
|
||||
e.grid(row=0, column=1, padx=2, pady=2)
|
||||
|
||||
om = tk.OptionMenu(
|
||||
f,
|
||||
self.create_text_variable("None"),
|
||||
"(none)",
|
||||
"core1",
|
||||
"core2",
|
||||
command=self.choose_core,
|
||||
)
|
||||
om.grid(row=0, column=2, padx=2, pady=2)
|
||||
cbb = ttk.Combobox(f, values=["(none)", "core1", "core2"], state="readonly")
|
||||
cbb.current(0)
|
||||
cbb.grid(row=0, column=2, padx=2, pady=2)
|
||||
|
||||
b = tk.Button(f, image=self.canvas_node.image)
|
||||
b.grid(row=0, column=3, padx=2, pady=2)
|
||||
|
||||
f.grid(row=0, column=0, sticky=tk.N + tk.S + tk.E + tk.W)
|
||||
f.grid(row=0, column=0, sticky="nsew")
|
||||
|
||||
def save_emane_option(self):
|
||||
configutils.parse_config(self.options, self.values)
|
||||
self.emane_dialog.destroy()
|
||||
|
||||
def draw_emane_options(self):
|
||||
if not self.emane_dialog.winfo_exists():
|
||||
self.emane_dialog = Dialog(
|
||||
self, self.app, "emane configuration", modal=False
|
||||
)
|
||||
b1 = tk.Button(self.emane_dialog, text="Appy", command=self.save_emane_option)
|
||||
b2 = tk.Button(
|
||||
self.emane_dialog, text="Cancel", command=self.emane_dialog.destroy
|
||||
)
|
||||
|
||||
if self.options is None:
|
||||
session_id = self.app.core.session_id
|
||||
response = self.app.core.client.get_emane_config(session_id)
|
||||
logging.info("emane config: %s", response)
|
||||
self.options = response.config
|
||||
self.values = configutils.create_config(
|
||||
self.emane_dialog, self.options, PAD_X, PAD_Y
|
||||
)
|
||||
b1.grid(row=1, column=0)
|
||||
b2.grid(row=1, column=1)
|
||||
self.emane_dialog.show()
|
||||
|
||||
def save_emane_model_options(self):
|
||||
"""
|
||||
configure the node's emane model on the fly
|
||||
|
||||
:return: nothing
|
||||
"""
|
||||
# get model name
|
||||
model_name = self.emane_models[self.emane_model_combobox.current()]
|
||||
|
||||
# parse configuration
|
||||
configutils.parse_config(self.model_options, self.model_values)
|
||||
config = {x: self.model_options[x].value for x in self.model_options}
|
||||
|
||||
# add string emane_ infront for grpc call
|
||||
response = self.app.core.client.set_emane_model_config(
|
||||
self.app.core.session_id,
|
||||
self.canvas_node.core_id,
|
||||
"emane_" + model_name,
|
||||
config,
|
||||
)
|
||||
logging.info(
|
||||
"emaneconfig.py config emane model (%s), result: %s",
|
||||
self.canvas_node.core_id,
|
||||
response,
|
||||
)
|
||||
|
||||
self.emane_model_dialog.destroy()
|
||||
|
||||
def draw_model_options(self):
|
||||
"""
|
||||
draw emane model configuration
|
||||
|
||||
:return: nothing
|
||||
"""
|
||||
# get model name
|
||||
model_name = self.emane_models[self.emane_model_combobox.current()]
|
||||
|
||||
# create the dialog and the necessry widget
|
||||
if not self.emane_model_dialog or not self.emane_model_dialog.winfo_exists():
|
||||
self.emane_model_dialog = Dialog(
|
||||
self, self.app, model_name + " configuration", modal=False
|
||||
)
|
||||
|
||||
b1 = tk.Button(
|
||||
self.emane_model_dialog, text="Apply", command=self.save_emane_model_options
|
||||
)
|
||||
b2 = tk.Button(
|
||||
self.emane_model_dialog,
|
||||
text="Cancel",
|
||||
command=self.emane_model_dialog.destroy,
|
||||
)
|
||||
|
||||
# query for configurations
|
||||
session_id = self.app.core.session_id
|
||||
# add string emane_ before model name for grpc call
|
||||
response = self.app.core.client.get_emane_model_config(
|
||||
session_id, self.canvas_node.core_id, "emane_" + model_name
|
||||
)
|
||||
logging.info("emane model config %s", response)
|
||||
|
||||
self.model_options = response.config
|
||||
self.model_values = configutils.create_config(
|
||||
self.emane_model_dialog, self.model_options, PAD_X, PAD_Y
|
||||
)
|
||||
|
||||
b1.grid(row=1, column=0, sticky="nsew")
|
||||
b2.grid(row=1, column=1, sticky="nsew")
|
||||
self.emane_model_dialog.show()
|
||||
|
||||
def draw_option_buttons(self, parent):
|
||||
f = tk.Frame(parent, bg="#d9d9d9")
|
||||
|
@ -73,60 +175,53 @@ class EmaneConfiguration(Dialog):
|
|||
f.columnconfigure(1, weight=1)
|
||||
b = tk.Button(
|
||||
f,
|
||||
text="model options",
|
||||
text=self.emane_models[0] + " options",
|
||||
image=Images.get(ImageEnum.EDITNODE),
|
||||
compound=tk.RIGHT,
|
||||
bg="#d9d9d9",
|
||||
state=tk.DISABLED,
|
||||
command=self.draw_model_options,
|
||||
)
|
||||
b.grid(row=0, column=0, padx=10, pady=2, sticky=tk.N + tk.S + tk.E + tk.W)
|
||||
b.grid(row=0, column=0, padx=10, pady=2, sticky="nsew")
|
||||
b = tk.Button(
|
||||
f,
|
||||
text="EMANE options",
|
||||
image=Images.get(ImageEnum.EDITNODE),
|
||||
compound=tk.RIGHT,
|
||||
bg="#d9d9d9",
|
||||
command=self.draw_emane_options,
|
||||
)
|
||||
b.grid(row=0, column=1, padx=10, pady=2, sticky=tk.N + tk.S + tk.E + tk.W)
|
||||
f.grid(row=4, column=0, sticky=tk.N + tk.S + tk.E + tk.W)
|
||||
b.grid(row=0, column=1, padx=10, pady=2, sticky="nsew")
|
||||
f.grid(row=4, column=0, sticky="nsew")
|
||||
|
||||
def radiobutton_text(self, val):
|
||||
def combobox_select(self, event):
|
||||
"""
|
||||
get appropriate text based on radio value
|
||||
update emane model options button
|
||||
|
||||
:return: the text value to configure button
|
||||
:param event:
|
||||
:return: nothing
|
||||
"""
|
||||
if val == 1:
|
||||
return "none"
|
||||
elif val == 2:
|
||||
return "rfpipe options"
|
||||
elif val == 3:
|
||||
return "ieee80211abg options"
|
||||
elif val == 4:
|
||||
return "commeffect options"
|
||||
elif val == 5:
|
||||
return "bypass options"
|
||||
elif val == 6:
|
||||
return "tdma options"
|
||||
else:
|
||||
logging.debug("emaneconfig.py invalid radio value")
|
||||
return ""
|
||||
# get model name
|
||||
model_name = self.emane_models[self.emane_model_combobox.current()]
|
||||
|
||||
def click_radio_button(self):
|
||||
print(type(self.radiovar.get()))
|
||||
# get the button and configure button text
|
||||
config_frame = self.grid_slaves(row=2, column=0)[0]
|
||||
option_button_frame = config_frame.grid_slaves(row=4, column=0)[0]
|
||||
b = option_button_frame.grid_slaves(row=0, column=0)[0]
|
||||
text = self.radiobutton_text(self.radiovar.get())
|
||||
if text == "none":
|
||||
state = tk.DISABLED
|
||||
else:
|
||||
state = tk.NORMAL
|
||||
b.config(text=text, state=state)
|
||||
# b.config(text=)
|
||||
b.config(text=model_name + " options")
|
||||
|
||||
def draw_emane_models(self, parent):
|
||||
models = ["none", "rfpipe", "ieee80211abg", "commeffect", "bypass", "tdma"]
|
||||
"""
|
||||
create a combobox that has all the known emane models
|
||||
|
||||
:param parent: parent
|
||||
:return: nothing
|
||||
"""
|
||||
# query for all the known model names
|
||||
session_id = self.app.core.session_id
|
||||
response = self.app.core.client.get_emane_models(session_id)
|
||||
self.emane_models = [x.split("_")[1] for x in response.models]
|
||||
|
||||
# create combo box and its binding
|
||||
f = tk.Frame(
|
||||
parent,
|
||||
bg="#d9d9d9",
|
||||
|
@ -135,20 +230,12 @@ class EmaneConfiguration(Dialog):
|
|||
highlightthickness=0.5,
|
||||
bd=0,
|
||||
)
|
||||
value = 1
|
||||
for m in models:
|
||||
b = tk.Radiobutton(
|
||||
f,
|
||||
text=m,
|
||||
variable=self.radiovar,
|
||||
indicatoron=True,
|
||||
value=value,
|
||||
bg="#d9d9d9",
|
||||
highlightthickness=0,
|
||||
command=self.click_radio_button,
|
||||
)
|
||||
b.grid(sticky=tk.W)
|
||||
value = value + 1
|
||||
self.emane_model_combobox = ttk.Combobox(
|
||||
f, values=self.emane_models, state="readonly"
|
||||
)
|
||||
self.emane_model_combobox.grid()
|
||||
self.emane_model_combobox.current(0)
|
||||
self.emane_model_combobox.bind("<<ComboboxSelected>>", self.combobox_select)
|
||||
f.grid(row=3, column=0, sticky=tk.W + tk.E)
|
||||
|
||||
def draw_text_label_and_entry(self, parent, label_text, entry_text):
|
||||
|
@ -164,11 +251,19 @@ class EmaneConfiguration(Dialog):
|
|||
lbl.grid(row=0, column=0)
|
||||
e = tk.Entry(f, textvariable=var, bg="white")
|
||||
e.grid(row=0, column=1)
|
||||
f.grid(stick=tk.W)
|
||||
f.grid(stick=tk.W, padx=2, pady=2)
|
||||
|
||||
def emane_configuration(self):
|
||||
"""
|
||||
draw the main frame for emane configuration
|
||||
|
||||
:return: nothing
|
||||
"""
|
||||
# draw label
|
||||
lbl = tk.Label(self, text="Emane")
|
||||
lbl.grid(row=1, column=0)
|
||||
|
||||
# main frame that has emane wiki, a short description, emane models and the configure buttons
|
||||
f = tk.Frame(
|
||||
self,
|
||||
bg="#d9d9d9",
|
||||
|
@ -187,7 +282,9 @@ class EmaneConfiguration(Dialog):
|
|||
compound=tk.RIGHT,
|
||||
relief=tk.RAISED,
|
||||
bg="#d9d9d9",
|
||||
command=self.browse_emane_wiki,
|
||||
command=lambda: webbrowser.open_new(
|
||||
"https://github.com/adjacentlink/emane/wiki"
|
||||
),
|
||||
)
|
||||
b.grid(row=0, column=0, sticky=tk.W)
|
||||
|
||||
|
@ -197,54 +294,47 @@ class EmaneConfiguration(Dialog):
|
|||
"\nusing pluggable MAC and PHY modules. Refer to the wiki for configuration option details",
|
||||
bg="#d9d9d9",
|
||||
)
|
||||
lbl.grid(row=1, column=0, sticky=tk.N + tk.S + tk.E + tk.W)
|
||||
lbl.grid(row=1, column=0, sticky="nsew")
|
||||
|
||||
lbl = tk.Label(f, text="EMANE Models", bg="#d9d9d9")
|
||||
lbl.grid(row=2, column=0, sticky=tk.W)
|
||||
self.draw_option_buttons(f)
|
||||
|
||||
self.draw_emane_models(f)
|
||||
f.grid(row=2, column=0, sticky=tk.N + tk.S + tk.E + tk.W)
|
||||
self.draw_option_buttons(f)
|
||||
|
||||
f.grid(row=2, column=0, sticky="nsew")
|
||||
|
||||
def draw_ip_subnets(self):
|
||||
self.draw_text_label_and_entry(self, "IPv4 subnet", "")
|
||||
self.draw_text_label_and_entry(self, "IPv6 subnet", "")
|
||||
|
||||
def click_ns2_mobility_script(self):
|
||||
dialog = MobilityConfiguration(self, self.app, self.canvas_node)
|
||||
dialog.show()
|
||||
|
||||
def emane_options(self):
|
||||
"""
|
||||
create wireless node options
|
||||
|
||||
:return:
|
||||
"""
|
||||
f = tk.Frame(self)
|
||||
f = tk.Frame(self, bg="#d9d9d9")
|
||||
f.columnconfigure(0, weight=1)
|
||||
f.columnconfigure(1, weight=1)
|
||||
f.columnconfigure(2, weight=1)
|
||||
b = tk.Button(
|
||||
f,
|
||||
text="ns-2 mobility script...",
|
||||
command=lambda: self.click_ns2_mobility_script(),
|
||||
)
|
||||
# b.pack(side=tk.LEFT, padx=1)
|
||||
b.grid(row=0, column=0, padx=10, pady=2, sticky=tk.N + tk.S + tk.E + tk.W)
|
||||
b = tk.Button(f, text="Link to all routers")
|
||||
b.grid(row=0, column=1, padx=10, pady=2, sticky=tk.N + tk.S + tk.E + tk.W)
|
||||
# b.pack(side=tk.LEFT, padx=1)
|
||||
b = tk.Button(f, text="Choose WLAN members")
|
||||
b.grid(row=0, column=2, padx=10, pady=2, sticky=tk.N + tk.S + tk.E + tk.W)
|
||||
# b.pack(side=tk.LEFT, padx=1)
|
||||
f.grid(row=5, column=0, sticky=tk.N + tk.S + tk.E + tk.W)
|
||||
b = tk.Button(f, text="Link to all routers", bg="#d9d9d9")
|
||||
b.grid(row=0, column=0, padx=10, pady=2, sticky="nsew")
|
||||
b = tk.Button(f, text="Choose WLAN members", bg="#d9d9d9")
|
||||
b.grid(row=0, column=1, padx=10, pady=2, sticky="nsew")
|
||||
f.grid(row=5, column=0, sticky="nsew")
|
||||
|
||||
def apply(self):
|
||||
# save emane configuration
|
||||
self.app.core.emane_config = self.options
|
||||
self.destroy()
|
||||
|
||||
def draw_apply_and_cancel(self):
|
||||
f = tk.Frame(self, bg="#d9d9d9")
|
||||
f.columnconfigure(0, weight=1)
|
||||
f.columnconfigure(1, weight=1)
|
||||
b = tk.Button(f, text="Apply", bg="#d9d9d9")
|
||||
b.grid(row=0, column=0, padx=10, pady=2, sticky=tk.N + tk.S + tk.E + tk.W)
|
||||
b = tk.Button(f, text="Apply", bg="#d9d9d9", command=self.apply)
|
||||
b.grid(row=0, column=0, padx=10, pady=2, sticky="nsew")
|
||||
b = tk.Button(f, text="Cancel", bg="#d9d9d9", command=self.destroy)
|
||||
b.grid(row=0, column=1, padx=10, pady=2, sticky=tk.N + tk.S + tk.E + tk.W)
|
||||
b.grid(row=0, column=1, padx=10, pady=2, sticky="nsew")
|
||||
|
||||
f.grid(sticky=tk.N + tk.S + tk.E + tk.W)
|
||||
f.grid(sticky="nsew")
|
||||
|
|
|
@ -223,12 +223,6 @@ class CanvasGraph(tk.Canvas):
|
|||
for i in self.find_withtag("node"):
|
||||
self.lift(i)
|
||||
|
||||
# def delete_components(self):
|
||||
# tags = ["node", "edge", "linkinfo", "nodename"]
|
||||
# for i in tags:
|
||||
# for id in self.find_withtag(i):
|
||||
# self.delete(id)
|
||||
|
||||
def canvas_xy(self, event):
|
||||
"""
|
||||
Convert window coordinate to canvas coordinate
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
}
|
||||
},
|
||||
"root": {
|
||||
"level": "INFO",
|
||||
"level": "DEBUG",
|
||||
"handlers": ["console"]
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue