SXXXXXXX_PyBusMonitor1553/pybusmonitor1553/__main__.py
2025-12-11 14:00:24 +01:00

207 lines
6.6 KiB
Python

import time
import sys
import os
import argparse
import tkinter as tk
from .core.network import UdpHandler
from .core.dispatcher import MessageDispatcher
from .core.scheduler import TrafficScheduler
from .core.controller import RadarController
from .utils.printer import dump_message
from .gui.main_window import BusMonitorApp
#Configuration
RX_IP = os.getenv("PYBM_RX_IP", "127.0.0.1")
RX_PORT = int(os.getenv("PYBM_RX_PORT", str(61553)))
TARGET_IP = os.getenv("PYBM_TARGET_IP", "127.0.0.1")
TARGET_PORT = int(os.getenv("PYBM_TARGET_PORT", "51553"))
def main_cli():
"""Command-line interface mode (original behavior)"""
print("--------------------------------------------------")
print(" PyBusMonitor1553 - Active Controller (CLI Mode)")
print("--------------------------------------------------")
# 1. Initialize Components
dispatcher = MessageDispatcher()
network = UdpHandler(rx_ip=RX_IP, rx_port=RX_PORT)
# 2. Initialize Radar Logic Controller
radar_ctrl = RadarController()
# 3. Initialize Scheduler with the Controller
scheduler = TrafficScheduler(network, radar_ctrl, TARGET_IP, TARGET_PORT)
# 4. Define the callback for received messages
def on_packet(data, addr):
header, messages = dispatcher.parse_packet(data)
if messages:
for msg in messages:
if msg.IS_TRANSMIT:
print(f"\n[RX] {msg.__class__.__name__} from RT{header.ta if header else '?'}")
dump_message(msg)
elif header and header.errors != 0:
print(f"[RX] Server Error Code: {header.errors}")
# 5. Start everything
network.register_callback(on_packet)
network.start()
scheduler.start()
print(f"System Running.")
print(f"RX: {RX_IP}:{RX_PORT} | TX: {TARGET_IP}:{TARGET_PORT}")
print("Press Ctrl+C to stop.")
try:
while True:
time.sleep(1)
except KeyboardInterrupt:
print("\nStopping...")
finally:
scheduler.stop()
network.stop()
sys.exit(0)
def main_gui():
"""Graphical user interface mode"""
# Enable quiet mode for scheduler
from .core import scheduler as sched_module
sched_module.QUIET_MODE = True
print("--------------------------------------------------")
print(" PyBusMonitor1553 - Active Controller (GUI Mode)")
print("--------------------------------------------------")
# Initialize Tkinter
root = tk.Tk()
app = BusMonitorApp(root)
# Initialize Components
dispatcher = MessageDispatcher()
network = UdpHandler(rx_ip=RX_IP, rx_port=RX_PORT)
radar_ctrl = RadarController()
scheduler = TrafficScheduler(network, radar_ctrl, TARGET_IP, TARGET_PORT)
# Counters for status bar
tx_count = [0]
rx_count = [0]
# Define the callback for received messages
def on_packet(data, addr):
header, messages = dispatcher.parse_packet(data)
rx_count[0] += 1
if messages:
for msg in messages:
if msg.IS_TRANSMIT:
msg_name = msg.__class__.__name__
# Convert MsgB6 -> B6, MsgA1 -> A1, etc.
short_name = msg_name.replace("Msg", "")
# Extract raw words if available
raw_words = []
if hasattr(msg, '_raw_data') and msg._raw_data:
import struct
data_bytes = msg._raw_data
for i in range(0, len(data_bytes), 2):
if i + 1 < len(data_bytes):
word = struct.unpack('<H', data_bytes[i:i+2])[0]
raw_words.append(word)
# Update GUI (thread-safe via after())
root.after(0, lambda n=short_name, m=msg, r=raw_words:
app.update_message_stats(n, m, r))
# Update status bar
root.after(0, lambda: app.update_connection_status(
True, tx_count[0], rx_count[0], ""
))
# Wrap scheduler send to count TX
original_send = network.send
def counted_send(data, ip, port):
tx_count[0] += 1
return original_send(data, ip, port)
network.send = counted_send
# Wire up menu actions
def on_connect():
network.start()
scheduler.start()
app.update_connection_status(True, tx_count[0], rx_count[0], "")
def on_disconnect():
scheduler.stop()
network.stop()
app.update_connection_status(False, tx_count[0], rx_count[0], "")
app._on_connect = on_connect
app._on_disconnect = on_disconnect
# Start networking
network.register_callback(on_packet)
network.start()
scheduler.start()
# Update initial status
app.update_connection_status(True, 0, 0, "")
print(f"GUI Running.")
print(f"RX: {RX_IP}:{RX_PORT} | TX: {TARGET_IP}:{TARGET_PORT}")
# Handle window close
def on_closing():
scheduler.stop()
network.stop()
root.destroy()
root.protocol("WM_DELETE_WINDOW", on_closing)
# Run the GUI main loop
try:
root.mainloop()
except KeyboardInterrupt:
on_closing()
def main():
"""Main entry point with mode selection"""
global TARGET_IP, TARGET_PORT
parser = argparse.ArgumentParser(
description='PyBusMonitor1553 - MIL-STD-1553 Bus Monitor',
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog='''
Examples:
python -m pybusmonitor1553 # Launch GUI mode (default)
python -m pybusmonitor1553 --cli # Launch CLI mode
python -m pybusmonitor1553 --gui # Launch GUI mode explicitly
'''
)
parser.add_argument('--cli', action='store_true',
help='Run in command-line interface mode')
parser.add_argument('--gui', action='store_true',
help='Run in graphical user interface mode (default)')
parser.add_argument('--target', type=str, default=None,
help=f'Target IP address (default: {TARGET_IP})')
parser.add_argument('--port', type=int, default=None,
help=f'Target port (default: {TARGET_PORT})')
args = parser.parse_args()
# Update globals if specified
if args.target:
TARGET_IP = args.target
if args.port:
TARGET_PORT = args.port
if args.cli:
main_cli()
else:
main_gui()
if __name__ == "__main__":
main()