forked from iarv/contact
Compare commits
5 Commits
reinitiali
...
don't-skip
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
49281f9106 | ||
|
|
f644b92356 | ||
|
|
3db44f4ae3 | ||
|
|
8c837e68a0 | ||
|
|
5dd06624e3 |
@@ -1,4 +1,5 @@
|
||||
interface = None
|
||||
lock = None
|
||||
display_log = False
|
||||
all_messages = {}
|
||||
channel_list = []
|
||||
@@ -9,5 +10,4 @@ myNodeNum = 0
|
||||
selected_channel = 0
|
||||
selected_message = 0
|
||||
selected_node = 0
|
||||
current_window = 0
|
||||
lock = None
|
||||
current_window = 0
|
||||
2
main.py
2
main.py
@@ -56,6 +56,8 @@ def main(stdscr):
|
||||
confirmation = get_list_input("Your region is UNSET. Set it now?", "Yes", ["Yes", "No"])
|
||||
if confirmation == "Yes":
|
||||
set_region()
|
||||
globals.interface.close()
|
||||
globals.interface = initialize_interface(args)
|
||||
logging.info("Interface initialized")
|
||||
globals.myNodeNum = get_nodeNum()
|
||||
globals.channel_list = get_channels()
|
||||
|
||||
@@ -5,7 +5,7 @@ import base64
|
||||
from db_handler import update_node_info_in_db
|
||||
import globals
|
||||
|
||||
def save_changes(interface, menu_path, modified_settings):
|
||||
def save_changes(menu_path, modified_settings):
|
||||
"""
|
||||
Save changes to the device based on modified settings.
|
||||
:param interface: Meshtastic interface instance
|
||||
@@ -17,7 +17,7 @@ def save_changes(interface, menu_path, modified_settings):
|
||||
logging.info("No changes to save. modified_settings is empty.")
|
||||
return
|
||||
|
||||
node = interface.getNode('^local')
|
||||
node = globals.interface.getNode('^local')
|
||||
|
||||
if menu_path[1] == "Radio Settings" or menu_path[1] == "Module Settings":
|
||||
config_category = menu_path[2].lower() # for radio and module configs
|
||||
@@ -27,7 +27,7 @@ def save_changes(interface, menu_path, modified_settings):
|
||||
lon = float(modified_settings.get('longitude', 0.0))
|
||||
alt = int(modified_settings.get('altitude', 0))
|
||||
|
||||
interface.localNode.setFixedPosition(lat, lon, alt)
|
||||
globals.interface.localNode.setFixedPosition(lat, lon, alt)
|
||||
logging.info(f"Updated {config_category} with Latitude: {lat} and Longitude {lon} and Altitude {alt}")
|
||||
return
|
||||
|
||||
@@ -122,10 +122,5 @@ def save_changes(interface, menu_path, modified_settings):
|
||||
except Exception as e:
|
||||
logging.error(f"Failed to write configuration for category '{config_category}': {e}")
|
||||
|
||||
|
||||
node.writeConfig(config_category)
|
||||
|
||||
logging.info(f"Changes written to config category: {config_category}")
|
||||
|
||||
except Exception as e:
|
||||
logging.error(f"Error saving changes: {e}")
|
||||
logging.error(f"Error saving changes: {e}")
|
||||
@@ -152,7 +152,7 @@ def settings_menu(stdscr, interface):
|
||||
menu_win.erase()
|
||||
menu_win.refresh()
|
||||
if show_save_option and selected_index == len(options):
|
||||
save_changes(interface, menu_path, modified_settings)
|
||||
save_changes(menu_path, modified_settings)
|
||||
modified_settings.clear()
|
||||
logging.info("Changes Saved")
|
||||
|
||||
|
||||
@@ -74,7 +74,6 @@ def handle_resize(stdscr, firstrun):
|
||||
win.box()
|
||||
win.refresh()
|
||||
|
||||
|
||||
entry_win.keypad(True)
|
||||
curses.curs_set(1)
|
||||
|
||||
@@ -90,13 +89,12 @@ def handle_resize(stdscr, firstrun):
|
||||
|
||||
|
||||
def main_ui(stdscr):
|
||||
|
||||
global input_text
|
||||
input_text = ""
|
||||
stdscr.keypad(True)
|
||||
get_channels()
|
||||
|
||||
handle_resize(stdscr, True)
|
||||
|
||||
input_text = ""
|
||||
while True:
|
||||
draw_text_field(entry_win, f"Input: {input_text[-(stdscr.getmaxyx()[1] - 10):]}", get_color("input"))
|
||||
|
||||
@@ -444,6 +442,11 @@ def draw_node_list():
|
||||
|
||||
refresh_pad(2)
|
||||
|
||||
# Restore cursor to input field
|
||||
entry_win.move(1, len("Input: ") + len(input_text)+1)
|
||||
entry_win.refresh()
|
||||
curses.curs_set(1)
|
||||
|
||||
def select_channel(idx):
|
||||
old_selected_channel = globals.selected_channel
|
||||
globals.selected_channel = max(0, min(idx, len(globals.channel_list) - 1))
|
||||
@@ -540,6 +543,11 @@ def draw_packetlog_win():
|
||||
packetlog_win.box()
|
||||
packetlog_win.refresh()
|
||||
|
||||
# Restore cursor to input field
|
||||
entry_win.move(1, len("Input: ") + len(input_text)+1)
|
||||
entry_win.refresh()
|
||||
curses.curs_set(1)
|
||||
|
||||
def search(win):
|
||||
start_idx = globals.selected_node
|
||||
select_func = select_node
|
||||
|
||||
72
ui/menus.py
72
ui/menus.py
@@ -4,39 +4,59 @@ import logging
|
||||
import base64
|
||||
|
||||
|
||||
def extract_fields(message_instance, current_config=None):
|
||||
FIELD_EXCLUSION_MAP = {
|
||||
"global": {"sessionkey"},
|
||||
"channel": {"channel_num", "id"},
|
||||
"radio": {"ignore_incoming"},
|
||||
"module": None
|
||||
}
|
||||
|
||||
def extract_fields(message_instance, current_config=None, parent_context=None, exclusion_map=None):
|
||||
if isinstance(current_config, dict): # Handle dictionaries
|
||||
return {key: (None, current_config.get(key, "Not Set")) for key in current_config}
|
||||
|
||||
if not hasattr(message_instance, "DESCRIPTOR"):
|
||||
return {}
|
||||
|
||||
|
||||
if exclusion_map is None:
|
||||
exclusion_map = FIELD_EXCLUSION_MAP # Use default if not provided
|
||||
|
||||
# Combine global exclusions with context-specific exclusions
|
||||
global_exclusions = exclusion_map.get("global", set())
|
||||
context_exclusions = exclusion_map.get(parent_context, set())
|
||||
total_exclusions = global_exclusions.union(context_exclusions)
|
||||
|
||||
menu = {}
|
||||
fields = message_instance.DESCRIPTOR.fields
|
||||
|
||||
for field in fields:
|
||||
if field.name in {"sessionkey", "channel_num", "id", "ignore_incoming"}: # Skip certain fields
|
||||
if field.name in total_exclusions:
|
||||
continue
|
||||
|
||||
if field.message_type: # Nested message
|
||||
nested_instance = getattr(message_instance, field.name)
|
||||
nested_config = getattr(current_config, field.name, None) if current_config else None
|
||||
menu[field.name] = extract_fields(nested_instance, nested_config)
|
||||
menu[field.name] = extract_fields(
|
||||
nested_instance,
|
||||
nested_config,
|
||||
parent_context=parent_context,
|
||||
exclusion_map=exclusion_map
|
||||
)
|
||||
elif field.enum_type: # Handle enum fields
|
||||
current_value = getattr(current_config, field.name, "Not Set") if current_config else "Not Set"
|
||||
if isinstance(current_value, int): # If the value is a number, map it to its name
|
||||
if isinstance(current_value, int): # Map enum number to name
|
||||
enum_value = field.enum_type.values_by_number.get(current_value)
|
||||
if enum_value: # Check if the enum value exists
|
||||
current_value_name = f"{enum_value.name}"
|
||||
else:
|
||||
current_value_name = f"Unknown ({current_value})"
|
||||
current_value_name = f"{enum_value.name}" if enum_value else f"Unknown ({current_value})"
|
||||
menu[field.name] = (field, current_value_name)
|
||||
else:
|
||||
menu[field.name] = (field, current_value) # Non-integer values
|
||||
else: # Handle other field types
|
||||
menu[field.name] = (field, current_value)
|
||||
else: # Other field types
|
||||
current_value = getattr(current_config, field.name, "Not Set") if current_config else "Not Set"
|
||||
menu[field.name] = (field, current_value)
|
||||
|
||||
return menu
|
||||
|
||||
|
||||
def generate_menu_from_protobuf(interface):
|
||||
# Function to generate the menu structure from protobuf messages
|
||||
menu_structure = {"Main Menu": {}}
|
||||
@@ -68,9 +88,18 @@ def generate_menu_from_protobuf(interface):
|
||||
for i in range(8):
|
||||
current_channel = interface.localNode.getChannelByChannelIndex(i)
|
||||
if current_channel:
|
||||
channel_config = extract_fields(channel, current_channel.settings)
|
||||
# Convert 'psk' field to Base64
|
||||
channel_config["psk"] = (channel_config["psk"][0], base64.b64encode(channel_config["psk"][1]).decode('utf-8'))
|
||||
# Apply 'channel' context here
|
||||
channel_config = extract_fields(
|
||||
channel,
|
||||
current_channel.settings,
|
||||
parent_context="channel", # Dynamic context
|
||||
exclusion_map=FIELD_EXCLUSION_MAP # Pass exclusion map
|
||||
)
|
||||
# Convert 'psk' to Base64
|
||||
channel_config["psk"] = (
|
||||
channel_config["psk"][0],
|
||||
base64.b64encode(channel_config["psk"][1]).decode('utf-8')
|
||||
)
|
||||
menu_structure["Main Menu"]["Channels"][f"Channel {i + 1}"] = channel_config
|
||||
|
||||
# Add Radio Settings
|
||||
@@ -99,14 +128,23 @@ def generate_menu_from_protobuf(interface):
|
||||
ordered_position_menu[key] = value
|
||||
|
||||
# Update the menu with the new order
|
||||
menu_structure["Main Menu"]["Radio Settings"]["position"] = ordered_position_menu
|
||||
|
||||
menu_structure["Main Menu"]["Radio Settings"] = extract_fields(
|
||||
radio,
|
||||
current_radio_config,
|
||||
parent_context="radio",
|
||||
exclusion_map=FIELD_EXCLUSION_MAP
|
||||
)
|
||||
|
||||
# Add Module Settings
|
||||
module = module_config_pb2.ModuleConfig()
|
||||
current_module_config = interface.localNode.moduleConfig if interface else None
|
||||
menu_structure["Main Menu"]["Module Settings"] = extract_fields(module, current_module_config)
|
||||
|
||||
menu_structure["Main Menu"]["Module Settings"] = extract_fields(
|
||||
module,
|
||||
current_module_config,
|
||||
parent_context="module", # Apply 'module' context
|
||||
exclusion_map=FIELD_EXCLUSION_MAP
|
||||
)
|
||||
# Add App Settings
|
||||
menu_structure["Main Menu"]["App Settings"] = {"Open": "app_settings"}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user