using Common.Attributes;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Text.Json;
using TSMaster;
using static Common.Attributes.ATSCommandAttribute;
namespace TSMasterCAN
{
///
/// 同星CAN驱动类
///
[ATSCommand]
[DeviceCategory("CAN卡驱动")]
public class CAN
{
public static event Action ConnectEvent;
public static event Action DisConnectEvent;
public static bool ConnectFlag { get; set; } = false;
///
/// 用于接收CAN报文的队列
///
private static readonly Queue _receivedMessages = new Queue();
private static readonly object _lock = new object(); // 线程安全锁
///
/// 初始化CAN驱动
///
///
///
///
[Browsable(false)]
public static int Init(string ProjectName, string? filePath = null)
{
if (string.IsNullOrEmpty(filePath))
{
return TsMasterApi.initialize_lib_tsmaster(ProjectName);
}
else
{
return TsMasterApi.initialize_lib_tsmaster_with_project(ProjectName, Path.GetFullPath(filePath));
}
}
///
/// 释放CAN驱动
///
[Browsable(false)]
public static void Release()
{
TsMasterApi.finalize_lib_tsmaster();
}
public static int obj = 0;
public static TCANFDQueueEvent_Win32 listener;
[Browsable(false)]
public static int RegisterListener(TCANFDQueueEvent_Win32 listenEvent)
{
listener = listenEvent;
var re = TsMasterApi.tsapp_register_event_canfd(ref obj, listener);
// Debug.Assert(re == 0);
return re;
}
[Browsable(false)]
public static int UnRegisterListener(TCANFDQueueEvent_Win32 listenEvent = null)
{
if (listenEvent is not null)
{
listener = listenEvent;
}
var re = TsMasterApi.tsapp_unregister_event_canfd(ref obj, listener);
Debug.Assert(re == 0);
return re;
}
///
/// 连接
///
///
public static int Connect()
{
var re = TsMasterApi.tsapp_connect();
if (re == 0)
{
re = TsMasterApi.tscom_can_rbs_start();
if (re == 0)
{
ConnectFlag = true;
Task.Run(() => ConnectEvent?.Invoke());
}
else
{
Debug.WriteLine($"CAN_RBS启动失败,错误代码:{re}");
}
}
else
{
Debug.WriteLine($"CAN连接失败,错误代码:{re}");
return re;
}
return re;
}
///
/// 断开
///
///
public static int DisConnect()
{
var re = TsMasterApi.tsapp_disconnect();
if (re == 0)
{
ConnectFlag = false;
Task.Run(() => DisConnectEvent?.Invoke());
}
else
{
Debug.WriteLine($"断开CAN连接失败,错误代码:{re}");
}
return re;
}
///
/// 加载DBC
///
///
///
///
///
[Browsable(false)]
public static int LoadDBC(string filePath, int[] channel, out uint databaseID)
{
databaseID = 0;
var re = TsMasterApi.tsdb_load_can_db(Path.GetFullPath(filePath), string.Join(",", channel), ref databaseID);
foreach (var item in channel)
{
DBCParse.parse(databaseID, item);
DBCParse.rbs_parse(databaseID, item);
}
return re;
}
///
/// 卸载DBC
///
///
///
[Browsable(false)]
public static int UnLoadDBC(uint? databaseID = null)
{
if (databaseID == null)
{
return TsMasterApi.tsdb_unload_can_dbs();
}
else
{
return TsMasterApi.tsdb_unload_can_db(databaseID.Value);
}
}
///
/// 开始记录日志
///
///
///
public static int StartLogging(string filePath)
{
return TsMasterApi.tsapp_start_logging(Path.GetFullPath(filePath));
}
///
/// 结束记录日志
///
///
public static int StopLogging()
{
return TsMasterApi.tsapp_stop_logging();
}
///
/// 弹出通道映射窗口
///
///
///
[Browsable(false)]
public static int ShowChannelMappingWindow(bool isWait = false)
{
return TsMasterApi.tsapp_show_tsmaster_window("Hardware", isWait);
}
#region 信号值获取方法
///
/// 获取信号值 (基于DBC)
///
/// 通道
/// 消息名称
/// 信号名称
/// 信号值
public static double GetSignalValue(byte channel, string AMsgName, string ASgnName)
{
double value = double.NaN;
var find = DBCParse.MsgDatabase[channel].FirstOrDefault(s => s.msg_name == AMsgName);
if (find != null)
{
var re = TsMasterApi.tsdb_get_signal_value_canfd(ref find.ACANFD, AMsgName, ASgnName, ref value);
if (re != 0)
{
Debug.WriteLine($"GetSignalValue: 获取信号值失败, 错误代码: {re}, 消息: {AMsgName}, 信号: {ASgnName}");
}
}
else
{
Debug.WriteLine($"GetSignalValue: 未找到消息定义, 消息: {AMsgName}, 通道: {channel}");
}
return value;
}
///
/// 获取信号值 (基于DBC) - 带返回值
///
/// 通道
/// 消息名称
/// 信号名称
/// 输出信号值
/// TSMaster API 返回值
[Browsable(false)]
public static int GetSignalValue(byte channel, string AMsgName, string ASgnName, ref double value)
{
var find = DBCParse.MsgDatabase[channel].FirstOrDefault(s => s.msg_name == AMsgName);
if (find != null)
{
return TsMasterApi.tsdb_get_signal_value_canfd(ref find.ACANFD, AMsgName, ASgnName, ref value);
}
else
{
Debug.WriteLine($"GetSignalValue: 未找到消息定义, 消息: {AMsgName}, 通道: {channel}");
return -1; // 假设 -1 为未找到定义的错误码
}
}
///
/// 获取信号值 (基于已有的CANFD报文对象) - 已优化,无需用户传入 TLIBCANFD
/// 此方法保留用于高级场景,但通常不推荐外部直接使用
///
/// CANFD报文对象
/// 消息名称
/// 信号名称
/// 输出信号值
/// TSMaster API 返回值
[Browsable(false)]
public static int GetSignalValue(ref TLIBCANFD ACANFD, string AMsgName, string ASgnName, ref double value)
{
return TsMasterApi.tsdb_get_signal_value_canfd(ref ACANFD, AMsgName, ASgnName, ref value);
}
#endregion
#region 信号值设置方法
///
/// 设置信号值 (基于DBC)
///
/// 通道
/// 消息名称
/// 信号名称
/// 信号值
/// 是否立即发送
/// 发送周期 (ms),0表示单次发送
///
///
public static int SetSignalValue(byte channel, string AMsgName, string ASgnName, double AValue, bool isSend = false, float sendPeriod = 0)
{
var find = DBCParse.MsgDatabase[channel].FirstOrDefault(s => s.msg_name == AMsgName);
if (find == null)
{
Debug.WriteLine($"SetSignalValue: 未找到消息定义, 消息: {AMsgName}, 通道: {channel}");
return -1; // 或抛出异常
}
find.ACANFD.FIdxChn = channel;
var re = TsMasterApi.tsdb_set_signal_value_canfd(ref find.ACANFD, AMsgName, ASgnName, AValue);
Debug.Assert(re == 0);
if (re != 0) throw new Exception($"设置信号值失败!返回代码{re}");
if (re != 0) return re;
if (isSend)
{
if (sendPeriod == 0)
{
return TsMasterApi.tsapp_transmit_canfd_async(ref find.ACANFD);
}
else
{
return TsMasterApi.tsapp_add_cyclic_msg_canfd(ref find.ACANFD, sendPeriod);
}
}
return 0;
}
///
/// 设置信号值 (基于DBC) - 仅发送报文
///
/// 通道
/// 消息名称
/// 发送周期 (ms),0表示单次发送
///
public static int SetSignalValue(APP_CHANNEL channel, string AMsgName, float sendPeriod = 0)
{
var find = DBCParse.MsgDatabase[(byte)channel].FirstOrDefault(s => s.msg_name == AMsgName);
if (find == null)
{
Debug.WriteLine($"SetSignalValue: 未找到消息定义, 消息: {AMsgName}, 通道: {channel}");
return -1; // 或抛出异常
}
find.ACANFD.FIdxChn = (byte)channel;
if (sendPeriod == 0)
{
return TsMasterApi.tsapp_transmit_canfd_async(ref find.ACANFD);
}
else
{
return TsMasterApi.tsapp_add_cyclic_msg_canfd(ref find.ACANFD, sendPeriod);
}
}
#endregion
#region 报文发送方法
///
/// 发送自定义报文 (基于 TLIBCANFD 对象) - 已优化,内部使用,外部不直接暴露
///
/// CANFD报文对象
///
[Browsable(false)]
public static int SetMsg(TLIBCANFD msg)
{
return TsMasterApi.tsapp_transmit_canfd_async(ref msg);
}
///
/// 设置报文数据 (在DBC缓存中)
///
/// 通道
/// 报文ID
/// 报文数据数组
public static void SetMsg(APP_CHANNEL channel, int ID, byte[] bytes)
{
var find = DBCParse.MsgDatabase[(byte)channel].FirstOrDefault(s => s.ACANFD.FIdentifier == ID);
if (find != null)
{
Array.Copy(bytes, 0, find.ACANFD.FData, 0, Math.Min(bytes.Length, find.ACANFD.FData.Length));
}
else
{
Debug.WriteLine($"SetMsg: 未找到报文定义, ID: 0x{ID:X}, 通道: {channel}");
}
}
///
/// 发送自定义报文
///
/// 通道
/// 报文ID
/// 是否为发送帧
/// 是否为扩展帧
/// 是否为远程帧
/// 数据长度
/// 数据数组
/// 是否为FD帧
/// 是否为BRS
/// 是否更新DBC数据库
/// 发送周期 (ms)
///
public static int SendMsg(APP_CHANNEL AIdxChn, int AID, bool AIsTx, bool AIsExt,
bool AIsRemote, byte ADLC, byte[] ADataArray, bool AIsFD = true, bool AIsBRS = false,
bool isUpdateDBCDatabase = false, float sendPeriod = 0)
{
var send = new TLIBCANFD
{
FIdxChn = (byte)AIdxChn,
FProperties = 0,
FIdentifier = AID,
FDLC = ADLC,
FTimeUS = 0uL,
FData = new byte[64],
FFDProperties = 0,
FIsTx = AIsTx,
FIsError = false,
FIsExt = AIsExt,
FIsRemote = AIsRemote,
FIsFD = AIsFD,
FIsBRS = AIsBRS
};
int length = Math.Min(ADataArray.Length, 64);
Array.Copy(ADataArray, 0, send.FData, 0, length);
int re;
if (sendPeriod == 0)
{
re = TsMasterApi.tsapp_transmit_canfd_async(ref send);
}
else
{
re = TsMasterApi.tsapp_add_cyclic_msg_canfd(ref send, sendPeriod);
}
if (isUpdateDBCDatabase)
{
var find = DBCParse.MsgDatabase[(byte)AIdxChn].FirstOrDefault(s => s.ACANFD.FIdentifier == send.FIdentifier);
if (find != null)
{
Array.Copy(send.FData, 0, find.ACANFD.FData, 0, Math.Min(ADataArray.Length, find.ACANFD.FData.Length));
}
}
return re;
}
///
/// 添加循环发送报文
///
/// 通道
/// 消息名称
/// 发送周期 (ms)
///
public static int AddCyclicMsg(byte channel, string AMsgName, float sendPeriod)
{
var find = DBCParse.MsgDatabase[channel].FirstOrDefault(s => s.msg_name == AMsgName);
if (find == null)
{
Debug.WriteLine($"AddCyclicMsg: 未找到消息定义, 消息: {AMsgName}, 通道: {channel}");
return -1; // 或抛出异常
}
find.ACANFD.FIdxChn = channel;
return TsMasterApi.tsapp_add_cyclic_msg_canfd(ref find.ACANFD, sendPeriod);
}
///
/// 清除循环发送的报文
///
///
public static int DeleteCyclicMsgs()
{
return TsMasterApi.tsapp_delete_cyclic_msgs();
}
#endregion
#region 接收报文和信号值方法 (新增)
///
/// 符合 TCANFDQueueEvent_Win32 委托签名的回调方法
///
/// 对象句柄
/// 接收到的 CANFD 报文
private static void OnCanFdMessageReceived(ref int AObj, ref TLIBCANFD AData)
{
// 将接收到的报文加入队列
lock (_lock)
{
// 为防止队列无限增长,可以添加一个简单的大小限制
if (_receivedMessages.Count < 10000) // 例如,限制队列最大10000个报文
{
_receivedMessages.Enqueue(AData);
}
// 可选:记录队列溢出
else
{
Debug.WriteLine("接收队列已满,丢弃新报文。");
}
}
}
///
/// 注册接收报文的监听器 (需要在连接前调用)
///
///
public static int RegisterReceiveListener()
{
return RegisterListener(OnCanFdMessageReceived);
}
///
/// 尝试获取一个接收到的CANFD报文
///
/// 输出报文对象
/// 如果队列不为空则返回true,否则返回false
public static bool TryGetReceivedMessage(out TLIBCANFD receivedMsg)
{
lock (_lock)
{
if (_receivedMessages.Count > 0)
{
receivedMsg = _receivedMessages.Dequeue();
return true;
}
else
{
receivedMsg = new TLIBCANFD(); // 返回默认值
return false;
}
}
}
///
/// 获取接收队列中的报文数量
///
///
public static int GetReceivedMessageCount()
{
lock (_lock)
{
return _receivedMessages.Count;
}
}
///
/// 清空接收队列
///
public static void ClearReceivedMessages()
{
lock (_lock)
{
_receivedMessages.Clear();
}
}
///
/// 从接收到的报文中解析信号值 (基于DBC)
///
/// 接收到的报文
/// 消息名称
/// 信号名称
/// 信号值
public static double GetSignalValueFromReceivedMessage(TLIBCANFD receivedMsg, string AMsgName, string ASgnName)
{
double value = double.NaN;
var re = TsMasterApi.tsdb_get_signal_value_canfd(ref receivedMsg, AMsgName, ASgnName, ref value);
if (re != 0)
{
Debug.WriteLine($"GetSignalValueFromReceivedMessage: 从报文中解析信号值失败, 错误代码: {re}, 消息: {AMsgName}, 信号: {ASgnName}");
}
return value;
}
///
/// 从接收到的报文中解析信号值 (基于DBC) - 便捷方法
/// 该方法会先尝试获取一个报文,然后解析信号值
///
/// 期望的通道 (用于过滤)
/// 期望的报文ID (用于过滤, 0 表示不过滤)
/// 消息名称
/// 信号名称
/// 信号值,如果获取失败则返回 NaN
public static double GetSignalValueFromReceivedMessage(byte channel, uint expectedID, string AMsgName, string ASgnName)
{
var value = double.NaN;
// 创建一个临时队列来存放不符合条件的报文
var tempQueue = new Queue();
lock (_lock)
{
while (_receivedMessages.Count > 0)
{
var msg = _receivedMessages.Dequeue();
// 检查是否符合条件
if (msg.FIdxChn == channel && (expectedID == 0 || (uint)msg.FIdentifier == expectedID))
{
// 符合条件,尝试解析信号值
var re = TsMasterApi.tsdb_get_signal_value_canfd(ref msg, AMsgName, ASgnName, ref value);
if (re == 0)
{
// 解析成功,将 tempQueue 中的报文放回主队列
while (tempQueue.Count > 0)
{
_receivedMessages.Enqueue(tempQueue.Dequeue());
}
return value; // 返回解析出的值
}
else
{
Debug.WriteLine($"GetSignalValueFromReceivedMessage: 从报文中解析信号值失败, 错误代码: {re}, 消息: {AMsgName}, 信号: {ASgnName}");
}
}
// 不符合条件或解析失败,放入临时队列
tempQueue.Enqueue(msg);
}
// 将临时队列中的所有报文放回主队列
while (tempQueue.Count > 0)
{
_receivedMessages.Enqueue(tempQueue.Dequeue());
}
}
return value; // 返回 NaN
}
#endregion
///
/// 获取错误提示
///
/// 错误代码
///
public static string GetErrorDescription(int errorCode)
{
IntPtr ADesc = IntPtr.Zero;
TsMasterApi.tsapp_get_error_description(errorCode, ref ADesc);
if (ADesc == IntPtr.Zero) return $"未知错误代码: {errorCode}";
string? description = Marshal.PtrToStringAnsi(ADesc);
return description ?? $"未知错误代码: {errorCode}";
}
#region CANFD转换相关方法
///
/// CANFD转CAN
/// 注意:如果CANFD报文长度超过8字节,转换时会截断数据。
///
/// CANFD消息
/// CAN消息
public static TLIBCAN CANFDToCAN(TLIBCANFD canfdMsg)
{
TLIBCAN canMsg = new TLIBCAN
{
FIdxChn = canfdMsg.FIdxChn,
FProperties = canfdMsg.FProperties,
FIdentifier = canfdMsg.FIdentifier,
FData = new byte[8], // CAN标准数据长度
FTimeUS = canfdMsg.FTimeUS, // 时间戳保持不变
FDLC = canfdMsg.FDLC > 8 ? (byte)8 : canfdMsg.FDLC, // DLC限制在8以内
FIsTx = canfdMsg.FIsTx,
FIsError = canfdMsg.FIsError,
FIsExt = canfdMsg.FIsExt,
FIsRemote = canfdMsg.FIsRemote
};
// 复制数据,只取前8字节
Array.Copy(canfdMsg.FData, 0, canMsg.FData, 0, Math.Min(8, canfdMsg.FData.Length));
return canMsg;
}
///
/// CAN转CANFD
///
/// CAN消息
/// CANFD消息
public static TLIBCANFD CANToCANFD(TLIBCAN canMsg)
{
TLIBCANFD canfdMsg = new TLIBCANFD
{
FIdxChn = canMsg.FIdxChn,
FProperties = canMsg.FProperties, // 保留原始属性
FIdentifier = canMsg.FIdentifier,
FData = new byte[64], // CANFD最大数据长度
FTimeUS = canMsg.FTimeUS,
FDLC = canMsg.FDLC,
FFDProperties = 0, // 新的CANFD报文,FD属性初始化为0
FIsTx = canMsg.FIsTx,
FIsError = canMsg.FIsError,
FIsExt = canMsg.FIsExt,
FIsRemote = canMsg.FIsRemote,
FIsFD = false, // 从CAN转换,明确设置为非FD
FIsBRS = false // 从CAN转换,明确设置为不支持BRS
};
// 复制数据
Array.Copy(canMsg.FData, 0, canfdMsg.FData, 0, Math.Min(64, canMsg.FData.Length));
return canfdMsg;
}
#endregion
#region CANFD报文属性获取方法
///
/// 获取CANFD报文内容
///
/// CANFD消息
/// 报文数据数组,长度为FDLC指定的长度
public static byte[] GetCANFDMsgContent(TLIBCANFD canfdMsg)
{
byte[] content = new byte[Math.Min(canfdMsg.FData.Length, canfdMsg.FDLC)];
Array.Copy(canfdMsg.FData, 0, content, 0, content.Length);
return content;
}
///
/// 获取CANFD报文时间戳 (微秒)
///
/// CANFD消息
/// 时间戳 (微秒)
public static ulong GetCANFDMsgTimestamp(ref TLIBCANFD canfdMsg)
{
return canfdMsg.FTimeUS;
}
///
/// 获取CANFD报文数据长度 (DLC)
///
/// CANFD消息
/// 数据长度 (DLC)
public static byte GetCANFDMsgDataLength(ref TLIBCANFD canfdMsg)
{
return canfdMsg.FDLC;
}
///
/// 获取CANFD报文是否为错误帧
///
/// CANFD消息
/// 是否为错误帧
public static bool GetCANFDMsgIsError(ref TLIBCANFD canfdMsg)
{
return canfdMsg.FIsError;
}
///
/// 获取CANFD报文通道
///
/// CANFD消息
/// 通道号
public static byte GetCANFDMsgChannel(ref TLIBCANFD canfdMsg)
{
return canfdMsg.FIdxChn;
}
///
/// 获取CANFD报文FD相关属性 (具体含义需参考TSMaster文档)
///
/// CANFD消息
/// FD属性
public static uint GetCANFDMsgFDProperties(ref TLIBCANFD canfdMsg)
{
return canfdMsg.FFDProperties;
}
///
/// 获取CANFD报文基础属性 (具体含义需参考TSMaster文档)
///
/// CANFD消息
/// 基础属性
public static uint GetCANFDMsgProperties(ref TLIBCANFD canfdMsg)
{
return canfdMsg.FProperties;
}
///
/// 获取CANFD报文标识符 (ID)
///
/// CANFD消息
/// 标识符 (ID)
public static uint GetCANFDMsgIdentifier(ref TLIBCANFD canfdMsg)
{
return (uint)canfdMsg.FIdentifier;
}
///
/// 获取CANFD报文是否为FD帧
///
/// CANFD消息
/// 是否为FD帧
public static bool GetCANFDMsgIsFD(ref TLIBCANFD canfdMsg)
{
return canfdMsg.FIsFD;
}
///
/// 获取CANFD报文是否为远程帧
///
/// CANFD消息
/// 是否为远程帧
public static bool GetCANFDMsgIsRemote(ref TLIBCANFD canfdMsg)
{
return canfdMsg.FIsRemote;
}
///
/// 获取CANFD报文是否为扩展帧
///
/// CANFD消息
/// 是否为扩展帧
public static bool GetCANFDMsgIsExt(ref TLIBCANFD canfdMsg)
{
return canfdMsg.FIsExt;
}
///
/// 获取CANFD报文是否为BRS (Bit Rate Switch)
///
/// CANFD消息
/// 是否为BRS
public static bool GetCANFDMsgIsBRS(ref TLIBCANFD canfdMsg)
{
return canfdMsg.FIsBRS;
}
///
/// 获取CANFD报文是否为发送帧
///
/// CANFD消息
/// 是否为发送帧
public static bool GetCANFDMsgIsTx(ref TLIBCANFD canfdMsg)
{
return canfdMsg.FIsTx;
}
///
/// 获取CANFD报文是否为ESI (Error State Indicator)
/// 注意:此API接口可能无法直接从TLIBCANFD结构获取ESI值。
/// ESI通常由总线决定,接收时反映发送节点的错误状态。
/// 当前实现返回FFDProperties的最低位,但这可能不准确。
/// 实际使用中可能需要通过其他方式或API获取。
///
/// CANFD消息
/// 是否为ESI (当前实现仅供参考)
public static bool GetCANFDMsgIsESI(ref TLIBCANFD canfdMsg)
{
return (canfdMsg.FFDProperties & 0x01) != 0; // 警告:此实现可能不正确
}
#endregion
#region CANFD报文设置方法
///
/// 设置CANFD报文内容
///
/// CANFD消息
/// 要设置的数据
/// 设置结果 (0为成功)
public static int SetCANFDMsgContent(ref TLIBCANFD canfdMsg, byte[] data)
{
if (data == null || data.Length == 0)
return -1; // 错误代码
int length = Math.Min(data.Length, canfdMsg.FData.Length);
Array.Copy(data, 0, canfdMsg.FData, 0, length);
canfdMsg.FDLC = (byte)length; // 同时更新DLC
return 0;
}
///
/// 设置CANFD报文时间戳 (微秒)
/// 注意:此时间戳通常由硬件/驱动在接收时设置,发送时设置可能无效或有特殊用途。
///
/// CANFD消息
/// 时间戳 (微秒)
/// 设置结果 (0为成功)
public static int SetCANFDMsgTimestamp(ref TLIBCANFD canfdMsg, ulong timestamp)
{
canfdMsg.FTimeUS = timestamp;
return 0;
}
///
/// 设置CANFD报文数据长度 (DLC)
///
/// CANFD消息
/// 数据长度 (DLC)
/// 设置结果 (0为成功)
public static int SetCANFDMsgDataLength(ref TLIBCANFD canfdMsg, byte length)
{
if (length > canfdMsg.FData.Length)
return -1; // 错误代码,长度超出数组大小
canfdMsg.FDLC = length;
return 0;
}
///
/// 设置CANFD报文是否为错误帧
///
/// CANFD消息
/// 是否为错误帧
/// 设置结果 (0为成功)
public static int SetCANFDMsgIsError(ref TLIBCANFD canfdMsg, bool isError)
{
canfdMsg.FIsError = isError;
return 0;
}
///
/// 设置CANFD报文通道
///
/// CANFD消息
/// 通道号
/// 设置结果 (0为成功)
public static int SetCANFDMsgChannel(ref TLIBCANFD canfdMsg, byte channel)
{
canfdMsg.FIdxChn = channel;
return 0;
}
///
/// 设置CANFD报文FD相关属性
///
/// CANFD消息
/// FD属性
/// 设置结果 (0为成功)
public static int SetCANFDMsgFDProperties(ref TLIBCANFD canfdMsg, uint fdProperties)
{
canfdMsg.FFDProperties = (byte)fdProperties;
return 0;
}
///
/// 设置CANFD报文基础属性
///
/// CANFD消息
/// 基础属性
/// 设置结果 (0为成功)
public static int SetCANFDMsgProperties(ref TLIBCANFD canfdMsg, uint properties)
{
canfdMsg.FProperties = (byte)properties;
return 0;
}
///
/// 设置CANFD报文标识符 (ID)
///
/// CANFD消息
/// 标识符 (ID)
/// 设置结果 (0为成功)
public static int SetCANFDMsgIdentifier(ref TLIBCANFD canfdMsg, uint identifier)
{
canfdMsg.FIdentifier = (int)identifier;
return 0;
}
///
/// 设置CANFD报文是否为FD帧
///
/// CANFD消息
/// 是否为FD帧
/// 设置结果 (0为成功)
public static int SetCANFDMsgIsFD(ref TLIBCANFD canfdMsg, bool isFD)
{
canfdMsg.FIsFD = isFD;
return 0;
}
///
/// 设置CANFD报文是否为远程帧
///
/// CANFD消息
/// 是否为远程帧
/// 设置结果 (0为成功)
public static int SetCANFDMsgIsRemote(ref TLIBCANFD canfdMsg, bool isRemote)
{
canfdMsg.FIsRemote = isRemote;
return 0;
}
///
/// 设置CANFD报文是否为扩展帧
///
/// CANFD消息
/// 是否为扩展帧
/// 设置结果 (0为成功)
public static int SetCANFDMsgIsExt(ref TLIBCANFD canfdMsg, bool isExt)
{
canfdMsg.FIsExt = isExt;
return 0;
}
///
/// 设置CANFD报文是否为BRS (Bit Rate Switch)
///
/// CANFD消息
/// 是否为BRS
/// 设置结果 (0为成功)
public static int SetCANFDMsgIsBRS(ref TLIBCANFD canfdMsg, bool isBRS)
{
canfdMsg.FIsBRS = isBRS;
return 0;
}
///
/// 设置CANFD报文是否为发送帧
///
/// CANFD消息
/// 是否为发送帧
/// 设置结果 (0为成功)
public static int SetCANFDMsgIsTx(ref TLIBCANFD canfdMsg, bool isTx)
{
canfdMsg.FIsTx = isTx;
return 0;
}
///
/// 设置CANFD报文是否为ESI (Error State Indicator)
/// 注意:此API接口可能无法直接设置TLIBCANFD结构中的ESI值。
/// ESI通常由硬件根据发送节点的错误状态自动设置。
/// 当前实现通过操作FFDProperties的最低位来模拟,但这可能无效或不正确。
/// 实际使用中可能无法或不应通过这种方式设置。
///
/// CANFD消息
/// 是否为ESI (当前实现仅供参考,可能无效)
/// 设置结果 (0为成功)
public static int SetCANFDMsgIsESI(ref TLIBCANFD canfdMsg, bool isESI)
{
byte mask = 0x01; // 最低位
if (isESI)
canfdMsg.FFDProperties |= mask; // 设置最低位
else
canfdMsg.FFDProperties &= (byte)~mask; // 清除最低位 (注意:~mask 会得到 -2,所以需要强制转换为 byte)
return 0;
}
#endregion
///
/// 获取CANFD报文指定字节的指定位的值 (0 或 1)
///
/// CANFD消息
/// 字节索引 (0-63 for CANFD)
/// 位索引 (0-7)
/// 位的值 (0 或 1),如果索引无效则返回 -1
public static int GetCANFDMsgBitValue(ref TLIBCANFD canfdMsg, int byteIndex, int bitIndex)
{
if (byteIndex < 0 || byteIndex >= canfdMsg.FData.Length || bitIndex < 0 || bitIndex > 7)
{
Debug.WriteLine($"GetCANFDMsgBitValue: Invalid index - byteIndex: {byteIndex}, bitIndex: {bitIndex}");
return -1; // 或者抛出异常
}
byte mask = (byte)(1 << bitIndex);
return (canfdMsg.FData[byteIndex] & mask) != 0 ? 1 : 0;
}
///
/// 设置CANFD报文指定字节的指定位的值
///
/// CANFD消息
/// 字节索引 (0-63 for CANFD)
/// 位索引 (0-7)
/// 要设置的值 (0 或 1)
/// 操作结果 (0为成功, -1为失败)
public static int SetCANFDMsgBitValue(ref TLIBCANFD canfdMsg, int byteIndex, int bitIndex, int value)
{
if (byteIndex < 0 || byteIndex >= canfdMsg.FData.Length || bitIndex < 0 || bitIndex > 7 || (value != 0 && value != 1))
{
Debug.WriteLine($"SetCANFDMsgBitValue: Invalid input - byteIndex: {byteIndex}, bitIndex: {bitIndex}, value: {value}");
return -1; // 或者抛出异常
}
byte mask = (byte)(1 << bitIndex);
if (value == 1)
{
canfdMsg.FData[byteIndex] |= mask; // 设置该位
}
else
{
canfdMsg.FData[byteIndex] &= (byte)~mask; // 清除该位
}
return 0;
}
///
/// 对CANFD报文指定字节执行按位与(&)操作
///
/// CANFD消息
/// 字节索引 (0-63 for CANFD)
/// 要与的掩码值 (byte)
/// 操作结果 (0为成功, -1为失败)
public static int BitwiseAndCANFDMsgByte(ref TLIBCANFD canfdMsg, int byteIndex, byte mask)
{
if (byteIndex < 0 || byteIndex >= canfdMsg.FData.Length)
{
Debug.WriteLine($"BitwiseAndCANFDMsgByte: Invalid byteIndex - {byteIndex}");
return -1;
}
canfdMsg.FData[byteIndex] &= mask;
return 0;
}
///
/// 对CANFD报文指定字节执行按位或(|)操作
///
/// CANFD消息
/// 字节索引 (0-63 for CANFD)
/// 要或的掩码值 (byte)
/// 操作结果 (0为成功, -1为失败)
public static int BitwiseOrCANFDMsgByte(ref TLIBCANFD canfdMsg, int byteIndex, byte mask)
{
if (byteIndex < 0 || byteIndex >= canfdMsg.FData.Length)
{
Debug.WriteLine($"BitwiseOrCANFDMsgByte: Invalid byteIndex - {byteIndex}");
return -1;
}
canfdMsg.FData[byteIndex] |= mask;
return 0;
}
///
/// 对CANFD报文指定字节执行按位异或(^)操作
///
/// CANFD消息
/// 字节索引 (0-63 for CANFD)
/// 要异或的掩码值 (byte)
/// 操作结果 (0为成功, -1为失败)
public static int BitwiseXorCANFDMsgByte(ref TLIBCANFD canfdMsg, int byteIndex, byte mask)
{
if (byteIndex < 0 || byteIndex >= canfdMsg.FData.Length)
{
Debug.WriteLine($"BitwiseXorCANFDMsgByte: Invalid byteIndex - {byteIndex}");
return -1;
}
canfdMsg.FData[byteIndex] ^= mask;
return 0;
}
#region CAN Message Handling (为CAN添加位操作方法)
///
/// 获取CAN报文指定字节的指定位的值 (0 或 1)
///
/// CAN消息
/// 字节索引 (0-7 for CAN)
/// 位索引 (0-7)
/// 位的值 (0 或 1),如果索引无效则返回 -1
public static int GetCANMsgBitValue(ref TLIBCAN canMsg, int byteIndex, int bitIndex)
{
if (byteIndex < 0 || byteIndex >= canMsg.FData.Length || bitIndex < 0 || bitIndex > 7)
{
Debug.WriteLine($"GetCANMsgBitValue: Invalid index - byteIndex: {byteIndex}, bitIndex: {bitIndex}");
return -1;
}
byte mask = (byte)(1 << bitIndex);
return (canMsg.FData[byteIndex] & mask) != 0 ? 1 : 0;
}
///
/// 设置CAN报文指定字节的指定位的值
///
/// CAN消息
/// 字节索引 (0-7 for CAN)
/// 位索引 (0-7)
/// 要设置的值 (0 或 1)
/// 操作结果 (0为成功, -1为失败)
public static int SetCANMsgBitValue(ref TLIBCAN canMsg, int byteIndex, int bitIndex, int value)
{
if (byteIndex < 0 || byteIndex >= canMsg.FData.Length || bitIndex < 0 || bitIndex > 7 || (value != 0 && value != 1))
{
Debug.WriteLine($"SetCANMsgBitValue: Invalid input - byteIndex: {byteIndex}, bitIndex: {bitIndex}, value: {value}");
return -1;
}
byte mask = (byte)(1 << bitIndex);
if (value == 1)
{
canMsg.FData[byteIndex] |= mask;
}
else
{
canMsg.FData[byteIndex] &= (byte)~mask;
}
return 0;
}
///
/// 对CAN报文指定字节执行按位与(&)操作
///
/// CAN消息
/// 字节索引 (0-7 for CAN)
/// 要与的掩码值 (byte)
/// 操作结果 (0为成功, -1为失败)
public static int BitwiseAndCANMsgByte(ref TLIBCAN canMsg, int byteIndex, byte mask)
{
if (byteIndex < 0 || byteIndex >= canMsg.FData.Length)
{
Debug.WriteLine($"BitwiseAndCANMsgByte: Invalid byteIndex - {byteIndex}");
return -1;
}
canMsg.FData[byteIndex] &= mask;
return 0;
}
///
/// 对CAN报文指定字节执行按位或(|)操作
///
/// CAN消息
/// 字节索引 (0-7 for CAN)
/// 要或的掩码值 (byte)
/// 操作结果 (0为成功, -1为失败)
public static int BitwiseOrCANMsgByte(ref TLIBCAN canMsg, int byteIndex, byte mask)
{
if (byteIndex < 0 || byteIndex >= canMsg.FData.Length)
{
Debug.WriteLine($"BitwiseOrCANMsgByte: Invalid byteIndex - {byteIndex}");
return -1;
}
canMsg.FData[byteIndex] |= mask;
return 0;
}
///
/// 对CAN报文指定字节执行按位异或(^)操作
///
/// CAN消息
/// 字节索引 (0-7 for CAN)
/// 要异或的掩码值 (byte)
/// 操作结果 (0为成功, -1为失败)
public static int BitwiseXorCANMsgByte(ref TLIBCAN canMsg, int byteIndex, byte mask)
{
if (byteIndex < 0 || byteIndex >= canMsg.FData.Length)
{
Debug.WriteLine($"BitwiseXorCANMsgByte: Invalid byteIndex - {byteIndex}");
return -1;
}
canMsg.FData[byteIndex] ^= mask;
return 0;
}
#endregion
}
}