mirror of
https://github.com/pdxlocations/contact.git
synced 2026-08-06 08:53:29 +02:00
initial commit
This commit is contained in:
@@ -12,6 +12,7 @@ import os
|
||||
import logging
|
||||
import traceback
|
||||
import threading
|
||||
import asyncio
|
||||
|
||||
from utilities.arg_parser import setup_parser
|
||||
from utilities.interfaces import initialize_interface
|
||||
@@ -19,6 +20,7 @@ from message_handlers.rx_handler import on_receive
|
||||
from ui.curses_ui import main_ui, draw_splash
|
||||
from input_handlers import get_list_input
|
||||
from utilities.utils import get_channels, get_node_list, get_nodeNum
|
||||
from utilities.watchdog import watchdog
|
||||
from settings import set_region
|
||||
from db_handler import init_nodedb, load_messages_from_db
|
||||
import default_config as config
|
||||
@@ -37,7 +39,7 @@ if os.environ.get("COLORTERM") == "gnome-terminal":
|
||||
# Run `tail -f client.log` in another terminal to view live
|
||||
logging.basicConfig(
|
||||
filename=config.log_file_path,
|
||||
level=logging.INFO, # DEBUG, INFO, WARNING, ERROR, CRITICAL)
|
||||
level=logging.WARNING, # DEBUG, INFO, WARNING, ERROR, CRITICAL)
|
||||
format="%(asctime)s - %(levelname)s - %(message)s"
|
||||
)
|
||||
|
||||
@@ -50,14 +52,20 @@ def main(stdscr):
|
||||
args = parser.parse_args()
|
||||
|
||||
logging.info("Initializing interface %s", args)
|
||||
with globals.lock:
|
||||
with globals.lock:
|
||||
globals.interface = initialize_interface(args)
|
||||
|
||||
# Run watchdog in a separate thread
|
||||
threading.Thread(target=lambda: asyncio.run(watchdog(args)), daemon=True).start()
|
||||
|
||||
# Continue with the rest of the initialization
|
||||
if globals.interface.localNode.localConfig.lora.region == 0:
|
||||
confirmation = get_list_input("Your region is UNSET. Set it now?", "Yes", ["Yes", "No"])
|
||||
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()
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
from datetime import datetime
|
||||
import google.protobuf.json_format
|
||||
from meshtastic import BROADCAST_NUM
|
||||
|
||||
from meshtastic.protobuf import mesh_pb2, portnums_pb2
|
||||
|
||||
from db_handler import save_message_to_db, update_ack_nak, get_name_from_database, is_chat_archived, update_node_info_in_db
|
||||
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
from meshtastic.protobuf import channel_pb2
|
||||
from google.protobuf.message import Message
|
||||
import logging
|
||||
import base64
|
||||
from google.protobuf.message import Message
|
||||
from meshtastic.protobuf import channel_pb2
|
||||
from db_handler import update_node_info_in_db
|
||||
import globals
|
||||
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
from collections import OrderedDict
|
||||
from meshtastic.protobuf import config_pb2, module_config_pb2, channel_pb2
|
||||
import logging
|
||||
import base64
|
||||
from meshtastic.protobuf import config_pb2, module_config_pb2, channel_pb2
|
||||
|
||||
|
||||
def extract_fields(message_instance, current_config=None):
|
||||
|
||||
@@ -3,6 +3,7 @@ import yaml
|
||||
import logging
|
||||
from typing import List
|
||||
from google.protobuf.json_format import MessageToDict
|
||||
|
||||
from meshtastic import BROADCAST_ADDR, mt_config
|
||||
from meshtastic.util import camel_to_snake, snake_to_camel, fromStr
|
||||
|
||||
|
||||
+13
-5
@@ -1,7 +1,10 @@
|
||||
import logging
|
||||
import contextlib
|
||||
import io
|
||||
import meshtastic.serial_interface, meshtastic.tcp_interface, meshtastic.ble_interface
|
||||
import globals
|
||||
|
||||
|
||||
def initialize_interface(args):
|
||||
try:
|
||||
if args.ble:
|
||||
@@ -10,14 +13,19 @@ def initialize_interface(args):
|
||||
return meshtastic.tcp_interface.TCPInterface(args.host)
|
||||
else:
|
||||
try:
|
||||
return meshtastic.serial_interface.SerialInterface(args.port)
|
||||
# Suppress stdout and stderr during SerialInterface initialization
|
||||
with contextlib.redirect_stdout(io.StringIO()), contextlib.redirect_stderr(io.StringIO()):
|
||||
return meshtastic.serial_interface.SerialInterface(args.port)
|
||||
except PermissionError as ex:
|
||||
logging.error(f"You probably need to add yourself to the `dialout` group to use a serial connection. {ex}")
|
||||
except Exception as ex:
|
||||
logging.error(f"Unexpected error initializing interface: {ex}")
|
||||
# Suppress specific message but log unexpected errors
|
||||
if "No Serial Meshtastic device detected" not in str(ex):
|
||||
logging.error(f"Unexpected error initializing interface: {ex}")
|
||||
|
||||
# Attempt TCP connection if Serial fails
|
||||
if globals.interface.devPath is None:
|
||||
return meshtastic.tcp_interface.TCPInterface("meshtastic.local")
|
||||
|
||||
|
||||
except Exception as ex:
|
||||
logging.critical(f"Fatal error initializing interface: {ex}")
|
||||
|
||||
logging.critical(f"Fatal error initializing interface: {ex}")
|
||||
@@ -0,0 +1,75 @@
|
||||
import asyncio
|
||||
import io
|
||||
import contextlib
|
||||
import socket
|
||||
import logging
|
||||
import logging
|
||||
|
||||
from .interfaces import initialize_interface
|
||||
import globals
|
||||
|
||||
|
||||
test_connection_seconds = 10
|
||||
retry_connection_seconds = 3
|
||||
|
||||
# Function to get firmware version
|
||||
def getNodeFirmware(interface):
|
||||
try:
|
||||
output_capture = io.StringIO()
|
||||
with contextlib.redirect_stdout(output_capture), contextlib.redirect_stderr(output_capture):
|
||||
interface.localNode.getMetadata()
|
||||
|
||||
console_output = output_capture.getvalue()
|
||||
|
||||
if "firmware_version" in console_output:
|
||||
return console_output.split("firmware_version: ")[1].split("\n")[0]
|
||||
|
||||
return -1
|
||||
except (socket.error, BrokenPipeError, ConnectionResetError, Exception) as e:
|
||||
logging.info(f"Error retrieving firmware: {e}")
|
||||
raise e # Propagate the error to handle reconnection
|
||||
|
||||
# Async function to retry connection
|
||||
async def retry_interface(args):
|
||||
logging.info("Retrying connection to the interface...")
|
||||
await asyncio.sleep(retry_connection_seconds) # Wait before retrying
|
||||
|
||||
try:
|
||||
globals.interface = initialize_interface(args)
|
||||
|
||||
logging.info("Interface reinitialized successfully.")
|
||||
return globals.interface
|
||||
except (ConnectionRefusedError, socket.error, Exception) as e:
|
||||
logging.error(f"Failed to reinitialize interface: {e}")
|
||||
return None
|
||||
|
||||
# Function to check connection and reconnect if needed
|
||||
async def check_and_reconnect(args):
|
||||
if globals.interface is None:
|
||||
logging.error("No valid interface. Attempting to reconnect...")
|
||||
interface = await retry_interface(args)
|
||||
return interface
|
||||
|
||||
try:
|
||||
# logging.info("Checking interface connection...")
|
||||
fw_ver = getNodeFirmware(globals.interface)
|
||||
if fw_ver != -1:
|
||||
return globals.interface
|
||||
else:
|
||||
raise Exception("Failed to retrieve firmware version.")
|
||||
|
||||
except (socket.error, BrokenPipeError, ConnectionResetError, Exception) as e:
|
||||
logging.error(f"Error with the interface, setting to None and attempting reconnect: {e}")
|
||||
return await retry_interface(args)
|
||||
|
||||
# Main watchdog loop
|
||||
async def watchdog(args):
|
||||
while True: # Infinite loop for continuous monitoring
|
||||
await asyncio.sleep(test_connection_seconds)
|
||||
globals.interface = await check_and_reconnect(args)
|
||||
if globals.interface:
|
||||
pass # Interface is connected
|
||||
else:
|
||||
logging.error("Interface connection failed. Retrying...")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user