SXXXXXXX_PyBusMonitor1553/pybusmonitor1553/core/handshake.py
2025-12-11 13:38:49 +01:00

128 lines
5.0 KiB
Python

import socket
import time
import ctypes
from typing import List
from ..lib1553.headers import UDP1553Header, UDP1553MessageHeader, CommandWordUnion
from ..lib1553.messages.msg_a1 import MsgA1
from ..lib1553.messages.msg_a2 import MsgA2
from ..lib1553.messages.msg_a3 import MsgA3
from ..lib1553.messages.msg_a4 import MsgA4
from ..lib1553.messages.msg_a5 import MsgA5
from ..lib1553.constants import TargetHistory, AltitudeBlock, RadarMode
def _struct_to_bytes(s) -> bytes:
return ctypes.string_at(ctypes.addressof(s), ctypes.sizeof(s))
def _create_packet(msg_obj) -> bytes:
"""Wrap a 1553 message into the proprietary UDP packet used by this project."""
# Build 1553 message header (UDP1553Message equivalent)
wc_val = 32 if len(msg_obj.data) == 32 else len(msg_obj.data)
if wc_val == 32:
wc_val = 0
cw_union = CommandWordUnion(rt_addr=1, sub_addr=msg_obj.SUBADDRESS, word_count=wc_val, transmit=msg_obj.IS_TRANSMIT)
msg_hdr = UDP1553MessageHeader(command_word_union=cw_union)
# The legacy implementation appends inverted CW and a control end marker (0x3E3E)
payload = msg_obj.pack()
# inverted cw (bitwise NOT of cw.raw) as uint16
inverted_cw = (~msg_hdr.command_word.raw) & 0xFFFF if hasattr(msg_hdr.command_word, 'raw') else (~cw_union.raw) & 0xFFFF
pkt = _struct_to_bytes(msg_hdr)
pkt += payload
# append inverted cw then control marker 0x3E3E
pkt += ctypes.string_at(ctypes.addressof(ctypes.c_uint16(inverted_cw)), ctypes.sizeof(ctypes.c_uint16))
pkt += ctypes.string_at(ctypes.addressof(ctypes.c_uint16(UDP1553MessageHeader.MARKER_END)), ctypes.sizeof(ctypes.c_uint16))
return pkt
_mcounter = 0
def perform_initialization(target_ip: str = "127.0.0.1", target_port: int = 51553, repeat: int = 1, delay: float = 0.05) -> List[bytes]:
"""Send the initial set of 1553 control messages to the server.
Default messages and field values mirror the legacy `test_1553.py` script.
Returns the list of raw packets that were sent.
"""
sent_packets = []
global _mcounter
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
try:
for _ in range(max(1, int(repeat))):
# A1
a1 = MsgA1()
a1.target_history = TargetHistory.LEVEL_4
a1.symbol_intensity = 127
a1.beacon_delay = 12.5
a1.altitude_block = AltitudeBlock.TPBK
pkt = _create_packet(a1)
udp_header = UDP1553Header()
udp_header.mcounter = _mcounter
_mcounter += 1
header_bytes = _struct_to_bytes(udp_header)
final_pkt = header_bytes + pkt + ctypes.string_at(ctypes.addressof(ctypes.c_uint16(UDP1553Header.MARKER_END_1553)), ctypes.sizeof(ctypes.c_uint16))
sock.sendto(final_pkt, (target_ip, int(target_port)))
sent_packets.append(final_pkt)
time.sleep(delay)
# A2
a2 = MsgA2()
a2.master_mode = RadarMode.RWS
pkt = _create_packet(a2)
udp_header = UDP1553Header()
udp_header.mcounter = _mcounter
_mcounter += 1
final_pkt = _struct_to_bytes(udp_header) + pkt + ctypes.string_at(ctypes.addressof(ctypes.c_uint16(UDP1553Header.MARKER_END_1553)), ctypes.sizeof(ctypes.c_uint16))
sock.sendto(final_pkt, (target_ip, int(target_port)))
sent_packets.append(final_pkt)
time.sleep(delay)
# A3
a3 = MsgA3()
pkt = _create_packet(a3)
udp_header = UDP1553Header()
udp_header.mcounter = _mcounter
_mcounter += 1
final_pkt = _struct_to_bytes(udp_header) + pkt + ctypes.string_at(ctypes.addressof(ctypes.c_uint16(UDP1553Header.MARKER_END_1553)), ctypes.sizeof(ctypes.c_uint16))
sock.sendto(final_pkt, (target_ip, int(target_port)))
sent_packets.append(final_pkt)
time.sleep(delay)
# A4
a4 = MsgA4()
a4.validity_and_slew = 0
pkt = _create_packet(a4)
udp_header = UDP1553Header()
udp_header.mcounter = _mcounter
_mcounter += 1
final_pkt = _struct_to_bytes(udp_header) + pkt + ctypes.string_at(ctypes.addressof(ctypes.c_uint16(UDP1553Header.MARKER_END_1553)), ctypes.sizeof(ctypes.c_uint16))
sock.sendto(final_pkt, (target_ip, int(target_port)))
sent_packets.append(final_pkt)
time.sleep(delay)
# A5
a5 = MsgA5()
# default timetag = 0 as in legacy script
pkt = _create_packet(a5)
udp_header = UDP1553Header()
udp_header.mcounter = _mcounter
_mcounter += 1
final_pkt = _struct_to_bytes(udp_header) + pkt + ctypes.string_at(ctypes.addressof(ctypes.c_uint16(UDP1553Header.MARKER_END_1553)), ctypes.sizeof(ctypes.c_uint16))
sock.sendto(final_pkt, (target_ip, int(target_port)))
sent_packets.append(final_pkt)
time.sleep(delay)
finally:
sock.close()
return sent_packets