249 lines
8.4 KiB
C#
249 lines
8.4 KiB
C#
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);
|
||
}
|
||
}
|
||
}
|