426 lines
12 KiB
C#
426 lines
12 KiB
C#
|
using System;
|
|||
|
using System.Collections.Generic;
|
|||
|
using System.Linq;
|
|||
|
using System.Text;
|
|||
|
using System.Threading.Tasks;
|
|||
|
|
|||
|
namespace UDS
|
|||
|
{
|
|||
|
|
|||
|
public enum UDSFrameType
|
|||
|
{
|
|||
|
SingleFrame = 0,
|
|||
|
FirstFrame = 1,
|
|||
|
ConsecutiveFrames = 2,
|
|||
|
FlowControlFrame = 3,
|
|||
|
};
|
|||
|
|
|||
|
public delegate void ReceivePackageEventHandler(byte[] data, int len);
|
|||
|
public delegate void SendMessageEventHandler(UInt32 id, byte[] data, int len);
|
|||
|
|
|||
|
|
|||
|
|
|||
|
public class UDSBase
|
|||
|
{
|
|||
|
public UInt32 CANPhyDevRxId;
|
|||
|
public UInt32 CANPhyDevTxId;
|
|||
|
public UInt32 CANFuncDevRxId;
|
|||
|
|
|||
|
//是否是功能寻址
|
|||
|
protected bool IsFunc;
|
|||
|
|
|||
|
protected int CANDL;
|
|||
|
|
|||
|
//发送的数据
|
|||
|
protected byte[] SendData;
|
|||
|
//发送包的大小
|
|||
|
protected int SendPackageSize;
|
|||
|
protected int NowSendDataIndex;
|
|||
|
|
|||
|
//用于判断接收到流控后 是否需要发送连续帧
|
|||
|
protected bool IsSendFirstFrame;
|
|||
|
|
|||
|
//接收到的数据
|
|||
|
protected byte[] ReceiveData;
|
|||
|
//接收到包的大小
|
|||
|
protected int ReceivePackageSize;
|
|||
|
//当前接收到数据的在整个接收包的下标
|
|||
|
protected int NowReceiveDataIndex;
|
|||
|
protected byte ConsecutiveFramesHead;
|
|||
|
|
|||
|
//发送和接受事件
|
|||
|
public event ReceivePackageEventHandler ReceivedPackage;
|
|||
|
public event SendMessageEventHandler SendMessage;
|
|||
|
|
|||
|
//设置ID
|
|||
|
public void SetId(UInt32 phyDevRxId, UInt32 phyDevTxId, UInt32 funcDevRxId)
|
|||
|
{
|
|||
|
this.CANPhyDevRxId = phyDevRxId;
|
|||
|
this.CANPhyDevTxId = phyDevTxId;
|
|||
|
this.CANFuncDevRxId = funcDevRxId;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
public void SetCANDL(int canDL)
|
|||
|
{
|
|||
|
this.CANDL = canDL;
|
|||
|
}
|
|||
|
|
|||
|
//触发发送报文事件
|
|||
|
protected void SendMessageInvoke(byte[] data, int len)
|
|||
|
{
|
|||
|
UInt32 id;
|
|||
|
|
|||
|
if (this.IsFunc)
|
|||
|
{
|
|||
|
id = this.CANFuncDevRxId;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
id = this.CANPhyDevRxId;
|
|||
|
}
|
|||
|
|
|||
|
if (null != this.SendMessage)
|
|||
|
{
|
|||
|
this.SendMessage.Invoke(id, data, len);
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//触发事件
|
|||
|
protected void ReceivedPackageInvoke()
|
|||
|
{
|
|||
|
if (null != this.ReceivedPackage)
|
|||
|
{
|
|||
|
this.ReceivedPackage.Invoke(this.ReceiveData, this.ReceivePackageSize);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//发送一个包
|
|||
|
virtual public void SendPackage(byte[] data, int len, bool isFunc)
|
|||
|
{
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//将数据插入接受缓存中
|
|||
|
virtual public int InsertReceiveData(UInt32 id, byte[] data)
|
|||
|
{
|
|||
|
return 1;
|
|||
|
}
|
|||
|
|
|||
|
//注册发送报文的事件
|
|||
|
public void RegisterSendMessageEvent(SendMessageEventHandler func)
|
|||
|
{
|
|||
|
this.SendMessage += func;
|
|||
|
}
|
|||
|
|
|||
|
//删除发送报文的事件
|
|||
|
public void UnregisterSendMessageEvent(SendMessageEventHandler func)
|
|||
|
{
|
|||
|
this.SendMessage -= func;
|
|||
|
}
|
|||
|
|
|||
|
//删除所有发送报文的事件
|
|||
|
public void UnregisterSendMessageEventAll()
|
|||
|
{
|
|||
|
this.SendMessage = null;
|
|||
|
}
|
|||
|
|
|||
|
//注册接收完成一个包的事件
|
|||
|
public void RegisterReceivedPackageEvent(ReceivePackageEventHandler func)
|
|||
|
{
|
|||
|
this.ReceivedPackage += func;
|
|||
|
}
|
|||
|
|
|||
|
//删除接收完成一个包的事件
|
|||
|
public void UnregisterReceivedPackageEvent(ReceivePackageEventHandler func)
|
|||
|
{
|
|||
|
this.ReceivedPackage -= func;
|
|||
|
}
|
|||
|
|
|||
|
//删除所有接收完成一个包的事件
|
|||
|
public void UnregisterReceivedPackageEventAll()
|
|||
|
{
|
|||
|
this.ReceivedPackage = null;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
public class UDSInfo : UDSBase
|
|||
|
{
|
|||
|
public UDSInfo(UInt32 phyDevRxId = 0, UInt32 phyDevTxId = 0, UInt32 funcDevRxId = 0, int canDL = 8)
|
|||
|
{
|
|||
|
|
|||
|
//设置ID
|
|||
|
this.SetId(phyDevRxId, phyDevTxId, funcDevRxId);
|
|||
|
|
|||
|
this.CANDL = canDL;
|
|||
|
|
|||
|
|
|||
|
IsFunc = false;
|
|||
|
IsSendFirstFrame = false;
|
|||
|
|
|||
|
//加一帧数据的大小 防止填充溢出
|
|||
|
this.SendData = new byte[65535 + 64];
|
|||
|
this.ReceiveData = new byte[65535 + 64];
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//发送一个包 需要多帧则发送首帧后等待流控
|
|||
|
override public void SendPackage(byte[] data, int len, bool isFunc)
|
|||
|
{
|
|||
|
byte[] dataFrame = new byte[8];
|
|||
|
|
|||
|
//byte[] dataFrame_64 = new byte[64];
|
|||
|
this.SendPackageSize = len;
|
|||
|
|
|||
|
//是否发送首帧 先置false
|
|||
|
IsSendFirstFrame = false;
|
|||
|
|
|||
|
//拷贝数据到缓存中
|
|||
|
Array.Copy(data, 0, this.SendData, 0, len);
|
|||
|
|
|||
|
/*************************ISO15765-2******************************/
|
|||
|
//8字节内单帧
|
|||
|
//if ((this.CANDL <= 8)&& (len <= (this.CANDL - 1)))
|
|||
|
if (len > 7)
|
|||
|
{
|
|||
|
//填充
|
|||
|
for (int i = len; i < len + (7 - (len - 6 % 7)); i++)
|
|||
|
{
|
|||
|
this.SendData[i] = 0xAA;
|
|||
|
}
|
|||
|
|
|||
|
//设置头数据
|
|||
|
dataFrame[0] = (byte)(0x10 | ((len >> 8) & 0x0f));
|
|||
|
dataFrame[1] = (byte)(len & 0xff);
|
|||
|
|
|||
|
Array.Copy(this.SendData, 0, dataFrame, 2, 6);
|
|||
|
|
|||
|
//发送了首帧
|
|||
|
IsSendFirstFrame = true;
|
|||
|
NowSendDataIndex = 6;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
|
|||
|
//填充
|
|||
|
for (int i = len; i < 8; i++)
|
|||
|
{
|
|||
|
this.SendData[i] = 0xAA;
|
|||
|
}
|
|||
|
|
|||
|
//设置头数据
|
|||
|
dataFrame[0] = (byte)(len & 0xff);
|
|||
|
|
|||
|
Array.Copy(this.SendData, 0, dataFrame, 1, 7);
|
|||
|
}
|
|||
|
|
|||
|
this.IsFunc = isFunc;
|
|||
|
SendMessageInvoke(dataFrame, 8/*this.CANDL*/);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//发送连续帧
|
|||
|
//内部调用
|
|||
|
private void SendConsecutiveFrames()
|
|||
|
{
|
|||
|
byte[] dataFrame = new byte[this.CANDL];
|
|||
|
int frameHead = 0x21;
|
|||
|
|
|||
|
//计算需要发送的连续帧数量
|
|||
|
int framesNum = (this.SendPackageSize - this.NowSendDataIndex) / (this.CANDL - 1) + 1;
|
|||
|
|
|||
|
//未发送首帧 不应发送连续帧
|
|||
|
if (!this.IsSendFirstFrame)
|
|||
|
{
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
//发送连续帧
|
|||
|
for (int i = 0; i < framesNum; i++)
|
|||
|
{
|
|||
|
dataFrame[0] = (byte)frameHead;
|
|||
|
Array.Copy(SendData, this.NowSendDataIndex, dataFrame, 1, this.CANDL - 1);
|
|||
|
|
|||
|
frameHead++;
|
|||
|
if (0x30 == frameHead)
|
|||
|
{
|
|||
|
frameHead = 0x20;
|
|||
|
}
|
|||
|
this.NowSendDataIndex += this.CANDL - 1;
|
|||
|
|
|||
|
SendMessageInvoke(dataFrame, this.CANDL);
|
|||
|
}
|
|||
|
|
|||
|
//发送完成后 将发送首帧标志置0
|
|||
|
this.IsSendFirstFrame = false;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//发送流控帧
|
|||
|
private void SendFlowControlFrame()
|
|||
|
{
|
|||
|
byte[] data = new byte[8] { 0x30, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
|||
|
|
|||
|
this.IsFunc = false;
|
|||
|
SendMessageInvoke(data, 8);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//插入单帧
|
|||
|
//内部调用
|
|||
|
private void InsertSingleFrameData(byte[] data)
|
|||
|
{
|
|||
|
//获取大小
|
|||
|
this.ReceivePackageSize = data[1];
|
|||
|
|
|||
|
//判断单帧格式
|
|||
|
if (0 != data[0])
|
|||
|
{
|
|||
|
this.ReceivePackageSize = data[0];
|
|||
|
//拷贝数据
|
|||
|
Array.Copy(data, 1, this.ReceiveData, 0, this.ReceivePackageSize);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
this.ReceivePackageSize = data[1];
|
|||
|
//拷贝数据
|
|||
|
Array.Copy(data, 2, this.ReceiveData, 0, this.ReceivePackageSize);
|
|||
|
}
|
|||
|
|
|||
|
//方便字符串截取
|
|||
|
this.ReceiveData[this.ReceivePackageSize] = 0;
|
|||
|
|
|||
|
//触发事件
|
|||
|
this.ReceivedPackageInvoke();
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//插入首帧
|
|||
|
//内部调用
|
|||
|
private void InsertFirstFrameData(byte[] data)
|
|||
|
{
|
|||
|
//获取大小
|
|||
|
this.ReceivePackageSize = (((int)data[0] & 0x0f) << 8) | (int)data[1];
|
|||
|
|
|||
|
if (0 != ReceivePackageSize)
|
|||
|
{
|
|||
|
//拷贝首帧数据
|
|||
|
Array.Copy(data, 2, this.ReceiveData, 0, this.CANDL - 2);
|
|||
|
NowReceiveDataIndex = this.CANDL - 2;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
//拷贝首帧数据
|
|||
|
Array.Copy(data, 6, this.ReceiveData, 0, this.CANDL - 6);
|
|||
|
NowReceiveDataIndex = this.CANDL - 6;
|
|||
|
}
|
|||
|
|
|||
|
//连续帧头设置为0x20方便后面累加计算
|
|||
|
ConsecutiveFramesHead = 0x20;
|
|||
|
|
|||
|
//发送流控帧
|
|||
|
this.SendFlowControlFrame();
|
|||
|
}
|
|||
|
|
|||
|
//插入的是连续帧
|
|||
|
//内部调用
|
|||
|
private int InsertConsecutiveFramesData(byte[] data)
|
|||
|
{
|
|||
|
int ret = 0;
|
|||
|
int readDataLen;
|
|||
|
|
|||
|
|
|||
|
//对上一次的头累加
|
|||
|
ConsecutiveFramesHead++;
|
|||
|
if (0x30 == ConsecutiveFramesHead)
|
|||
|
{
|
|||
|
ConsecutiveFramesHead = 0x20;
|
|||
|
}
|
|||
|
|
|||
|
//判断是否连续
|
|||
|
if (data[0] == ConsecutiveFramesHead)
|
|||
|
{
|
|||
|
//判断需要读取的长度
|
|||
|
if ((this.NowReceiveDataIndex + this.CANDL - 1) > this.ReceivePackageSize)
|
|||
|
{
|
|||
|
readDataLen = this.ReceivePackageSize - this.NowReceiveDataIndex;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
readDataLen = this.CANDL - 1;
|
|||
|
}
|
|||
|
|
|||
|
Array.Copy(data, 1, this.ReceiveData, this.NowReceiveDataIndex, readDataLen);
|
|||
|
this.NowReceiveDataIndex += readDataLen;
|
|||
|
|
|||
|
//判断接收一个包是否完成
|
|||
|
if (this.NowReceiveDataIndex == this.ReceivePackageSize)
|
|||
|
{
|
|||
|
//方便字符串截取
|
|||
|
this.ReceiveData[this.ReceivePackageSize] = 0;
|
|||
|
|
|||
|
//触发事件
|
|||
|
this.ReceivedPackageInvoke();
|
|||
|
}
|
|||
|
|
|||
|
ret = 0;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
ret = 1;
|
|||
|
}
|
|||
|
|
|||
|
return ret;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
//插入接收数据解析
|
|||
|
//在接收到数据时使用 传入一帧的数据 完成一包的接收后触发事件
|
|||
|
override public int InsertReceiveData(UInt32 id, byte[] data)
|
|||
|
{
|
|||
|
int ret = 0;
|
|||
|
|
|||
|
if (id != this.CANPhyDevTxId)
|
|||
|
{
|
|||
|
return 1;
|
|||
|
}
|
|||
|
|
|||
|
//取出帧类型
|
|||
|
UDSFrameType frameType = (UDSFrameType)((uint)data[0] >> 4);
|
|||
|
|
|||
|
//判断帧类型
|
|||
|
switch (frameType)
|
|||
|
{
|
|||
|
case UDSFrameType.SingleFrame://收到单帧
|
|||
|
InsertSingleFrameData(data);
|
|||
|
break;
|
|||
|
case UDSFrameType.FirstFrame://收到首帧
|
|||
|
InsertFirstFrameData(data);
|
|||
|
break;
|
|||
|
case UDSFrameType.ConsecutiveFrames://收到连续帧
|
|||
|
ret = InsertConsecutiveFramesData(data);
|
|||
|
break;
|
|||
|
case UDSFrameType.FlowControlFrame://收到流控帧
|
|||
|
//发送连续帧
|
|||
|
this.SendConsecutiveFrames();
|
|||
|
break;
|
|||
|
default:
|
|||
|
ret = 1;
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
return ret;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
}
|