using System; using System.Collections.Generic; using System.Linq; using System.Runtime.InteropServices; using System.Text; using System.Text.Json.Serialization; using TSMaster; namespace TSMasterFlexRay { /// /// FlexRay 网络(Cluster) /// public struct flexray_network { [JsonInclude] public string network_name; [JsonInclude] public flexray_node[] flexray_nodes; } /// /// FlexRay 节点(ECU) /// public struct flexray_node { [JsonInclude] public string node_name; [JsonInclude] public flexray_message[] tx_flexray_Messages; [JsonInclude] public flexray_message[] rx_flexray_Messages; } /// /// FlexRay 帧(Frame) /// public struct flexray_message { [JsonInclude] public string message_name; [JsonInclude] public int slot_id; [JsonInclude] public int channel_mask; [JsonInclude] public int base_cycle; [JsonInclude] public int rep_cycle; [JsonInclude] public bool is_startup_frame; [JsonInclude] public int dlc; [JsonInclude] public string[] signals; } /// /// FlexRay 解码后的信号信息 /// public struct FlexRaySignal { /// 信号名称 public string name; /// 起始位 public int start_bit; /// 长度(bit) public int length; /// 因子 public double factor; /// 偏移 public double offset; /// 初始值 public double init_value; /// 信号类型 public TSignalType signal_type; /// 字节序(true=小端) public bool is_intel; } /// /// FlexRay 解码后的报文信息 /// public class FlexRayDBMessage { /// 时隙号 public int nSlotId; /// 周期号 public int nCycleNumber; /// 通道掩码 public int nChannelMask; /// 有效负载长度 public int nDataLength; /// 数据 public byte[] Data = Array.Empty(); } public class FlexRayDBParse { private static FlexRayDBParse? _instance; /// 单例实例 public static FlexRayDBParse Instance => _instance ??= new FlexRayDBParse(); /// 最大通道数(等于 MsgDatabase 的维度) public int MaxChannels => MsgDatabase.Count; /// /// FlexRay 报文数据库(按通道索引,每个通道包含该通道上所有帧)。 /// public static List> MsgDatabase { get; set; } = [.. Enumerable.Range(0, 12).Select(_ => new List())]; /// FlexRay 网络拓扑(Cluster/ECU/Frame/Signal) public static flexray_network Network; /// /// 解析指定索引的 FlexRay 数据库,填充 MsgDatabase 和 Network。 /// FlexRay 数据库由工程加载,通过 tsdb_get_flexray_db_count 获取数量。 /// /// 数据库索引(0-based) /// 映射的通道号 public static void parse(int dbIndex, int channel) { int ASignalCount = 0; int AFrameCount = 0; int AECUcount = 0; long ASupportMask = 0; long AFlags = 0; IntPtr temp1 = IntPtr.Zero; IntPtr temp2 = IntPtr.Zero; // 1. 获取 Cluster 属性 int ret = TsMasterApi.tsdb_get_flexray_db_properties_by_index_verbose( dbIndex, ref ASignalCount, ref AFrameCount, ref AECUcount, ref ASupportMask, ref AFlags, ref temp1, ref temp2); string clusterName = Marshal.PtrToStringAnsi(temp1) ?? ""; Network = new flexray_network { network_name = clusterName, flexray_nodes = new flexray_node[AECUcount] }; // 2. 遍历所有 ECU for (int i = 0; i < AECUcount; i++) { int ATXFramecount = 0; int ARXFramecount = 0; TsMasterApi.tsdb_get_flexray_ecu_properties_by_index_verbose( dbIndex, i, ref ATXFramecount, ref ARXFramecount, ref temp1, ref temp2); string ecuName = Marshal.PtrToStringAnsi(temp1) ?? ""; Network.flexray_nodes[i].node_name = ecuName; Network.flexray_nodes[i].tx_flexray_Messages = new flexray_message[ATXFramecount]; Network.flexray_nodes[i].rx_flexray_Messages = new flexray_message[ARXFramecount]; // TX Frame for (int tx = 0; tx < ATXFramecount; tx++) { var msg = ParseFrame(dbIndex, i, tx, true); Network.flexray_nodes[i].tx_flexray_Messages[tx] = msg; MsgDatabase[channel].Add(msg); } // RX Frame for (int rx = 0; rx < ARXFramecount; rx++) { var msg = ParseFrame(dbIndex, i, rx, false); Network.flexray_nodes[i].rx_flexray_Messages[rx] = msg; } } MsgDatabase[channel].Sort((a, b) => a.slot_id.CompareTo(b.slot_id)); } /// /// 解析单帧属性(TX 或 RX) /// private static flexray_message ParseFrame(int dbIndex, int ecuIndex, int frameIndex, bool isTx) { int AFRChannelMask = 0; int AFRBaseCycle = 0; int ARepCycle = 0; bool isStartupFrame = false; int ASlotID = 0; long CycleMask = 0; int AFRSignalCount = 0; int AFRDLC = 0; IntPtr temp1 = IntPtr.Zero; IntPtr temp2 = IntPtr.Zero; TsMasterApi.tsdb_get_flexray_frame_properties_by_index_verbose( dbIndex, ecuIndex, frameIndex, isTx, ref AFRChannelMask, ref AFRBaseCycle, ref ARepCycle, ref isStartupFrame, ref ASlotID, ref CycleMask, ref AFRSignalCount, ref AFRDLC, ref temp1, ref temp2); string frameName = Marshal.PtrToStringAnsi(temp1) ?? ""; var msg = new flexray_message { message_name = frameName, slot_id = ASlotID, channel_mask = AFRChannelMask, base_cycle = AFRBaseCycle, rep_cycle = ARepCycle, is_startup_frame = isStartupFrame, dlc = AFRDLC, signals = new string[AFRSignalCount] }; // 遍历信号 for (int s = 0; s < AFRSignalCount; s++) { TSignalType Asignaltype = (TSignalType)0; TFlexRayCompuMethod ACompuMethod = (TFlexRayCompuMethod)0; bool AIsIntel = false; int AStartBit = 0; int AUpdateBit = 0; int ALength = 0; double AFactor = 0; double AOffset = 0; double AInitValue = 0; TsMasterApi.tsdb_get_flexray_signal_properties_by_index_verbose( dbIndex, ecuIndex, frameIndex, s, isTx, ref Asignaltype, ref ACompuMethod, ref AIsIntel, ref AStartBit, ref AUpdateBit, ref ALength, ref AFactor, ref AOffset, ref AInitValue, ref temp1, ref temp2); string sigName = Marshal.PtrToStringAnsi(temp1) ?? ""; msg.signals[s] = sigName; } return msg; } /// /// 解析网络拓扑(仅填充 Network,不写入 MsgDatabase) /// public static void rbs_parse(int dbIndex, int channel) { // parse 已同时填充 Network 和 MsgDatabase,此处保持与 CAN 一致的接口 parse(dbIndex, channel); } } }