81 lines
3.2 KiB
Python
81 lines
3.2 KiB
Python
import ctypes
|
|
import struct
|
|
from .structures import Udp1553Message, CommandWord, Marker
|
|
from .constants import Direction
|
|
|
|
class BaseMessage:
|
|
"""
|
|
Base class for all 1553 messages.
|
|
Wraps the specific payload (ctypes structure) and the 1553 transport header.
|
|
"""
|
|
|
|
def __init__(self, label: str, payload_cls, sub_addr: int, frequency: int, is_transmit: bool = True):
|
|
"""
|
|
Args:
|
|
label (str): Human readable label (e.g., "A1", "B7").
|
|
payload_cls (ctypes.Structure): The class definition of the data payload.
|
|
sub_addr (int): 1553 Subaddress (1-30).
|
|
frequency (int): Transmission frequency in Hz.
|
|
is_transmit (bool): True if BC sends to RT, False if BC requests from RT.
|
|
"""
|
|
self.label = label
|
|
self.frequency = frequency
|
|
self.period_ms = 1000.0 / frequency if frequency > 0 else 0
|
|
|
|
# Instantiate the payload
|
|
self.payload = payload_cls()
|
|
self.payload_size = ctypes.sizeof(self.payload)
|
|
|
|
# 1553 Word Count (bytes / 2)
|
|
word_count = self.payload_size // 2
|
|
|
|
# Determine direction bit (BC->RT = 0 (Receive), RT->BC = 1 (Transmit))
|
|
# Note: The original code logic might interpret this differently,
|
|
# usually BC sending is Receive for RT. Adjusting based on standard 1553.
|
|
tr_bit = 0 if is_transmit else 1
|
|
|
|
# Create the 1553 Command Word
|
|
self.cw = CommandWord(wc=word_count, sa=sub_addr, tr=tr_bit, rt=20) # RT 20 hardcoded from original
|
|
|
|
# Create the UDP Encapsulation Header
|
|
self.header = Udp1553Message(
|
|
marker=Marker.CTRL_BEGIN,
|
|
cw=self.cw
|
|
)
|
|
|
|
self._is_request = not is_transmit
|
|
|
|
def pack(self) -> bytes:
|
|
"""
|
|
Serializes the message into bytes for network transmission.
|
|
Includes the quirks from the original protocol (inverted CW at the end).
|
|
"""
|
|
header_bytes = bytes(self.header)
|
|
|
|
# Calculate inverted CW (Protocol specific quirk found in original code)
|
|
inverted_cw_val = ~self.header.cw.raw & 0xFFFF
|
|
inverted_cw_bytes = struct.pack("<H", inverted_cw_val)
|
|
footer_bytes = struct.pack("<H", Marker.CTRL_END)
|
|
|
|
if self._is_request:
|
|
# If requesting data, we send Header + InvertedCW + Footer (No Payload)
|
|
return header_bytes + bytes([]) + inverted_cw_bytes + footer_bytes
|
|
else:
|
|
# If sending data, we send Header + Payload + InvertedCW + Footer
|
|
payload_bytes = bytes(self.payload)
|
|
return header_bytes + payload_bytes + inverted_cw_bytes + footer_bytes
|
|
|
|
def unpack(self, data: bytes):
|
|
"""
|
|
Updates the payload with received binary data.
|
|
"""
|
|
if len(data) >= self.payload_size:
|
|
ctypes.memmove(ctypes.addressof(self.payload), data, self.payload_size)
|
|
|
|
def to_dict(self):
|
|
"""
|
|
Helper for GUI to get values without knowing ctypes.
|
|
Implementation to be expanded recursively.
|
|
"""
|
|
# Placeholder: deep introspection logic goes here later
|
|
return {"label": self.label, "size": self.payload_size} |