Files
ACP/TSMasterFlexRay/FlexRayDBParse.cs
T
2026-08-05 11:53:51 +08:00

249 lines
8.4 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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
{
/// <summary>
/// FlexRay 网络(Cluster
/// </summary>
public struct flexray_network
{
[JsonInclude]
public string network_name;
[JsonInclude]
public flexray_node[] flexray_nodes;
}
/// <summary>
/// FlexRay 节点(ECU
/// </summary>
public struct flexray_node
{
[JsonInclude]
public string node_name;
[JsonInclude]
public flexray_message[] tx_flexray_Messages;
[JsonInclude]
public flexray_message[] rx_flexray_Messages;
}
/// <summary>
/// FlexRay 帧(Frame
/// </summary>
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;
}
/// <summary>
/// FlexRay 解码后的信号信息
/// </summary>
public struct FlexRaySignal
{
/// <summary>信号名称</summary>
public string name;
/// <summary>起始位</summary>
public int start_bit;
/// <summary>长度(bit</summary>
public int length;
/// <summary>因子</summary>
public double factor;
/// <summary>偏移</summary>
public double offset;
/// <summary>初始值</summary>
public double init_value;
/// <summary>信号类型</summary>
public TSignalType signal_type;
/// <summary>字节序(true=小端)</summary>
public bool is_intel;
}
/// <summary>
/// FlexRay 解码后的报文信息
/// </summary>
public class FlexRayDBMessage
{
/// <summary>时隙号</summary>
public int nSlotId;
/// <summary>周期号</summary>
public int nCycleNumber;
/// <summary>通道掩码</summary>
public int nChannelMask;
/// <summary>有效负载长度</summary>
public int nDataLength;
/// <summary>数据</summary>
public byte[] Data = Array.Empty<byte>();
}
public class FlexRayDBParse
{
private static FlexRayDBParse? _instance;
/// <summary>单例实例</summary>
public static FlexRayDBParse Instance => _instance ??= new FlexRayDBParse();
/// <summary>最大通道数(等于 MsgDatabase 的维度)</summary>
public int MaxChannels => MsgDatabase.Count;
/// <summary>
/// FlexRay 报文数据库(按通道索引,每个通道包含该通道上所有帧)。
/// </summary>
public static List<List<flexray_message>> MsgDatabase { get; set; } =
[.. Enumerable.Range(0, 12).Select(_ => new List<flexray_message>())];
/// <summary>FlexRay 网络拓扑(Cluster/ECU/Frame/Signal</summary>
public static flexray_network Network;
/// <summary>
/// 解析指定索引的 FlexRay 数据库,填充 MsgDatabase 和 Network。
/// FlexRay 数据库由工程加载,通过 tsdb_get_flexray_db_count 获取数量。
/// </summary>
/// <param name="dbIndex">数据库索引(0-based</param>
/// <param name="channel">映射的通道号</param>
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));
}
/// <summary>
/// 解析单帧属性(TX 或 RX
/// </summary>
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;
}
/// <summary>
/// 解析网络拓扑(仅填充 Network,不写入 MsgDatabase
/// </summary>
public static void rbs_parse(int dbIndex, int channel)
{
// parse 已同时填充 Network 和 MsgDatabase,此处保持与 CAN 一致的接口
parse(dbIndex, channel);
}
}
}