From 6f492ef38236babe84a79704448368aab2a29c6c Mon Sep 17 00:00:00 2001 From: SpudGunMan Date: Sun, 5 Jan 2025 13:15:54 -0800 Subject: [PATCH] interface Expansion --- config.template | 4 +- mesh_bot.py | 22 ++++++---- modules/settings.py | 72 +++++++++++++++++++++++++++++++ modules/system.py | 102 ++++++++++++++++++-------------------------- modules/web.py | 1 + 5 files changed, 132 insertions(+), 69 deletions(-) create mode 100644 modules/web.py diff --git a/config.template b/config.template index 430a093..fe22350 100644 --- a/config.template +++ b/config.template @@ -12,7 +12,7 @@ port = /dev/ttyACM0 # hostname = localhost # mac = 00:11:22:33:44:55 -# Additional interface for dual radio support +# Additional interface for multi radio support [interface2] enabled = False type = serial @@ -22,6 +22,8 @@ port = /dev/ttyUSB0 # hostname = meshtastic.local # mac = 00:11:22:33:44:55 +# example, the third interface would be [interface3] up to 9 + [general] # if False will respond on all channels but the default channel respond_by_dm_only = True diff --git a/mesh_bot.py b/mesh_bot.py index 52d9c52..a99d869 100755 --- a/mesh_bot.py +++ b/mesh_bot.py @@ -1229,18 +1229,24 @@ def onReceive(packet, interface): async def start_rx(): print (CustomFormatter.bold_white + f"\nMeshtastic Autoresponder Bot CTL+C to exit\n" + CustomFormatter.reset) + + # Start the receive subscriber using pubsub via meshtastic library + pub.subscribe(onReceive, 'meshtastic.receive') + pub.subscribe(onDisconnect, 'meshtastic.connection.lost') + + logger.info(f"System: Autoresponder Started for Device1 {get_name_from_number(myNodeNum1, 'long', 1)}," + f"{get_name_from_number(myNodeNum1, 'short', 1)}. NodeID: {myNodeNum1}, {decimal_to_hex(myNodeNum1)}") + + + if interface2_enabled: + logger.info(f"System: Autoresponder Started for Device2 {get_name_from_number(myNodeNum2, 'long', 2)}," + f"{get_name_from_number(myNodeNum2, 'short', 2)}. NodeID: {myNodeNum2}, {decimal_to_hex(myNodeNum2)}") + if llm_enabled: logger.debug(f"System: Ollama LLM Enabled, loading model {llmModel} please wait") llm_query(" ", myNodeNum1) logger.debug(f"System: LLM model {llmModel} loaded") - # Start the receive subscriber using pubsub via meshtastic library - pub.subscribe(onReceive, 'meshtastic.receive') - pub.subscribe(onDisconnect, 'meshtastic.connection.lost') - logger.info(f"System: Autoresponder Started for Device1 {get_name_from_number(myNodeNum1, 'long', 1)}," - f"{get_name_from_number(myNodeNum1, 'short', 1)}. NodeID: {myNodeNum1}, {decimal_to_hex(myNodeNum1)}") - if interface2_enabled: - logger.info(f"System: Autoresponder Started for Device2 {get_name_from_number(myNodeNum2, 'long', 2)}," - f"{get_name_from_number(myNodeNum2, 'short', 2)}. NodeID: {myNodeNum2}, {decimal_to_hex(myNodeNum2)}") + if log_messages_to_file: logger.debug("System: Logging Messages to disk") if syslog_to_file: diff --git a/modules/settings.py b/modules/settings.py index 034ae8c..0b1a0b0 100644 --- a/modules/settings.py +++ b/modules/settings.py @@ -96,6 +96,7 @@ interface1_type = config['interface'].get('type', 'serial') port1 = config['interface'].get('port', '') hostname1 = config['interface'].get('hostname', '') mac1 = config['interface'].get('mac', '') +interface1_enabled = True # gotta have at least one interface # interface2 settings if 'interface2' in config: @@ -107,6 +108,77 @@ if 'interface2' in config: else: interface2_enabled = False +# interface3 settings +if 'interface3' in config: + interface3_type = config['interface3'].get('type', 'serial') + port3 = config['interface3'].get('port', '') + hostname3 = config['interface3'].get('hostname', '') + mac3 = config['interface3'].get('mac', '') + interface3_enabled = config['interface3'].getboolean('enabled', False) +else: + interface3_enabled = False + +# interface4 settings +if 'interface4' in config: + interface4_type = config['interface4'].get('type', 'serial') + port4 = config['interface4'].get('port', '') + hostname4 = config['interface4'].get('hostname', '') + mac4 = config['interface4'].get('mac', '') + interface4_enabled = config['interface4'].getboolean('enabled', False) +else: + interface4_enabled = False + +# interface5 settings +if 'interface5' in config: + interface5_type = config['interface5'].get('type', 'serial') + port5 = config['interface5'].get('port', '') + hostname5 = config['interface5'].get('hostname', '') + mac5 = config['interface5'].get('mac', '') + interface5_enabled = config['interface5'].getboolean('enabled', False) +else: + interface5_enabled = False + +# interface6 settings +if 'interface6' in config: + interface6_type = config['interface6'].get('type', 'serial') + port6 = config['interface6'].get('port', '') + hostname6 = config['interface6'].get('hostname', '') + mac6 = config['interface6'].get('mac', '') + interface6_enabled = config['interface6'].getboolean('enabled', False) +else: + interface6_enabled = False + +# interface7 settings +if 'interface7' in config: + interface7_type = config['interface7'].get('type', 'serial') + port7 = config['interface7'].get('port', '') + hostname7 = config['interface7'].get('hostname', '') + mac7 = config['interface7'].get('mac', '') + interface7_enabled = config['interface7'].getboolean('enabled', False) +else: + interface7_enabled = False + +# interface8 settings +if 'interface8' in config: + interface8_type = config['interface8'].get('type', 'serial') + port8 = config['interface8'].get('port', '') + hostname8 = config['interface8'].get('hostname', '') + mac8 = config['interface8'].get('mac', '') + interface8_enabled = config['interface8'].getboolean('enabled', False) +else: + interface8_enabled = False + +# interface9 settings +if 'interface9' in config: + interface9_type = config['interface9'].get('type', 'serial') + port9 = config['interface9'].get('port', '') + hostname9 = config['interface9'].get('hostname', '') + mac9 = config['interface9'].get('mac', '') + interface9_enabled = config['interface9'].getboolean('enabled', False) +else: + interface9_enabled = False + + # variables from the config.ini file try: # general diff --git a/modules/system.py b/modules/system.py index 84dc77a..aa9d6b8 100644 --- a/modules/system.py +++ b/modules/system.py @@ -208,62 +208,44 @@ if len(help_message) > 20: help_message = ", ".join(help_message) # BLE dual interface prevention -if interface1_type == 'ble' and interface2_type == 'ble': - logger.critical(f"System: BLE Interface1 and Interface2 cannot both be BLE. Exiting") +ble_count = sum(1 for i in range(1, 10) if globals().get(f'interface{i}_type') == 'ble') +if ble_count > 1: + logger.critical(f"System: Multiple BLE interfaces detected. Only one BLE interface is allowed. Exiting") exit() -#initialize_interfaces(): -# Interface1 Configuration -try: - logger.debug(f"System: Initializing Interface1") - if interface1_type == 'serial': - interface1 = meshtastic.serial_interface.SerialInterface(port1) - elif interface1_type == 'tcp': - interface1 = meshtastic.tcp_interface.TCPInterface(hostname1) - elif interface1_type == 'ble': - interface1 = meshtastic.ble_interface.BLEInterface(mac1) +# Initialize interfaces +interface1 = interface2 = interface3 = interface4 = interface5 = interface6 = interface7 = interface8 = interface9 = None +for i in range(1, 10): + interface_type = globals().get(f'interface{i}_type') + if not interface_type or interface_type == 'none' or globals().get(f'interface{i}_enabled') == False: + # no valid interface found + continue + try: + if globals().get(f'interface{i}_enabled'): + if interface_type == 'serial': + globals()[f'interface{i}'] = meshtastic.serial_interface.SerialInterface(globals().get(f'port{i}')) + elif interface_type == 'tcp': + globals()[f'interface{i}'] = meshtastic.tcp_interface.TCPInterface(globals().get(f'hostname{i}')) + elif interface_type == 'ble': + globals()[f'interface{i}'] = meshtastic.ble_interface.BLEInterface(globals().get(f'mac{i}')) + else: + logger.critical(f"System: Interface Type: {interface_type} not supported. Validate your config against config.template Exiting") + exit() + except Exception as e: + logger.critical(f"System: abort. Initializing Interface{i} {e}") + exit() + +# Get the node number of the devices, check if the devices are connected meshtastic devices +for i in range(1, 10): + if globals().get(f'interface{i}'): + if globals().get(f'interface{i}_enabled'): + try: + globals()[f'myNodeNum{i}'] = globals()[f'interface{i}'].getMyNodeInfo()['num'] + logger.debug(f"System: Initalized Radio Device{i} Node Number: {globals()[f'myNodeNum{i}']}") + except Exception as e: + logger.critical(f"System: critical error initializing interface{i} {e}") else: - logger.critical(f"System: Interface Type: {interface1_type} not supported. Validate your config against config.template Exiting") - exit() -except Exception as e: - logger.critical(f"System: script abort. Initializing Interface1 {e}") - exit() - -# Interface2 Configuration -if interface2_enabled: - logger.debug(f"System: Initializing Interface2") - try: - if interface2_type == 'serial': - interface2 = meshtastic.serial_interface.SerialInterface(port2) - elif interface2_type == 'tcp': - interface2 = meshtastic.tcp_interface.TCPInterface(hostname2) - elif interface2_type == 'ble': - interface2 = meshtastic.ble_interface.BLEInterface(mac2) - else: - logger.critical(f"System: Interface Type: {interface2_type} not supported. Validate your config against config.template Exiting") - exit() - except Exception as e: - logger.critical(f"System: script abort. Initializing Interface2 {e}") - exit() - -#Get the node number of the device, check if the device is connected -try: - myinfo = interface1.getMyNodeInfo() - myNodeNum1 = myinfo['num'] -except Exception as e: - logger.critical(f"System: script abort. {e}") - exit() - -if interface2_enabled: - try: - myinfo2 = interface2.getMyNodeInfo() - myNodeNum2 = myinfo2['num'] - except Exception as e: - logger.critical(f"System: script abort. {e}") - exit() -else: - myNodeNum2 = 777 - + globals()[f'myNodeNum{i}'] = 777 #### FUN-ctions #### @@ -271,7 +253,7 @@ def decimal_to_hex(decimal_number): return f"!{decimal_number:08x}" def get_name_from_number(number, type='long', nodeInt=1): - interface = interface1 if nodeInt == 1 else interface2 + interface = globals()[f'interface{nodeInt}'] name = "" for node in interface.nodes.values(): @@ -288,7 +270,7 @@ def get_name_from_number(number, type='long', nodeInt=1): def get_num_from_short_name(short_name, nodeInt=1): - interface = interface1 if nodeInt == 1 else interface2 + interface = globals()[f'interface{nodeInt}'] # Get the node number from the short name, converting all to lowercase for comparison (good practice?) logger.debug(f"System: Getting Node Number from Short Name: {short_name} on Device: {nodeInt}") for node in interface.nodes.values(): @@ -308,7 +290,7 @@ def get_num_from_short_name(short_name, nodeInt=1): return 0 def get_node_list(nodeInt=1): - interface = interface1 if nodeInt == 1 else interface2 + interface = globals()[f'interface{nodeInt}'] # Get a list of nodes on the device node_list = "" node_list1 = [] @@ -362,7 +344,7 @@ def get_node_list(nodeInt=1): return node_list def get_node_location(number, nodeInt=1, channel=0): - interface = interface1 if nodeInt == 1 else interface2 + interface = globals()[f'interface{nodeInt}'] # Get the location of a node by its number from nodeDB on device latitude = latitudeValue longitude = longitudeValue @@ -395,7 +377,7 @@ def get_node_location(number, nodeInt=1, channel=0): def get_closest_nodes(nodeInt=1,returnCount=3): - interface = interface1 if nodeInt == 1 else interface2 + interface = globals()[f'interface{nodeInt}'] node_list = [] if interface.nodes: @@ -509,7 +491,7 @@ def messageChunker(message): def send_message(message, ch, nodeid=0, nodeInt=1, bypassChuncking=False): # Send a message to a channel or DM - interface = interface1 if nodeInt == 1 else interface2 + interface = globals()[f'interface{nodeInt}'] # Check if the message is empty if message == "" or message == None or len(message) == 0: return False @@ -784,7 +766,7 @@ def initialize_telemetryData(): initialize_telemetryData() def getNodeFirmware(nodeID=0, nodeInt=1): - interface = interface1 if nodeInt == 1 else interface2 + interface = globals()[f'interface{nodeInt}'] # get the firmware version of the node # this is a workaround because .localNode.getMetadata spits out a lot of debug info which cant be suppressed # Create a StringIO object to capture the diff --git a/modules/web.py b/modules/web.py new file mode 100644 index 0000000..59d76c4 --- /dev/null +++ b/modules/web.py @@ -0,0 +1 @@ +# investigate python3 -m http.server to serve up reports and config data?