public class SerialFreePortClass
{
private string Name;
private SerialPort Port;
private List<byte> TempBuffer;
private bool DataSendAllow;
private int ReadTimeOut;
private object LockObj;
public CommunicationTime TimeComm;
private byte lenRcv = 255;
public int BytesReceived { get { return lenRcv; } }
private byte lenSend = 0;
public int BytesSend { get { return lenSend; } }
public bool ReadyToSend
{
get { return ((Port != null) && Port.IsOpen && ((DataSendAllow) || ((TimeComm.ExceededTime(ReadTimeOut)) && (ReadTimeOut > 0)))); }
}
public delegate void DataReceivedDelegate(object sender, byte[] xData);
public event DataReceivedDelegate DataReceivedCompleted;
public SerialFreePortClass(string xName)
{
Name = xName;
TempBuffer = new List<byte>();
TimeComm = new CommunicationTime();
DataSendAllow = true;
ReadTimeOut = -1;
LockObj = new object();
Port = new SerialPort();
}
void Port_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
try
{
// pocet dostupnych bytu
int no = Port.BytesToRead;
if (no <= 0)
return;
// nacteni dostupnych vzorku
byte[] receivedData = new byte[no];
Port.Read(receivedData, 0, receivedData.Length);
// ulozeni do pomocneho bufferu
TempBuffer.AddRange(receivedData);
// delka protokolu
lenRcv = TempBuffer[0];
// kdyz je v bufferu dostatecny pocet vzorku
if (TempBuffer.Count >= lenRcv)
{
// prekopirovani pomocneho bufferu do bufferu aplikace
// velikost umele o 1B vetsi, aby se shodovaly adresy v PC a PLC
// kopiruje se od druheho bytu (index=1)
byte[] appBuffer = new byte[lenRcv + 1];
TempBuffer.CopyTo(0, appBuffer, 1, lenRcv);
// zpracovani bufferu na promenne
if (DataReceivedCompleted != null)
DataReceivedCompleted(this, appBuffer);
// vymazani dat, ktera se poslala ke zpracovani
TempBuffer.RemoveRange(0, lenRcv);
lock (LockObj)
{
DataSendAllow = true;
TimeComm.Stop();
}
}
}
catch (Exception exc)
{
Port.DiscardInBuffer();
Port.DiscardOutBuffer();
TempBuffer.Clear();
DataSendAllow = true;
}
}
public void SendData(byte[] xBuffer, int xLen)
{
try
{
if (Port == null)
return;
if (ReadyToSend)
{
if (TimeComm.ExceededTime(ReadTimeOut))
{
Port.DiscardInBuffer();
Port.DiscardOutBuffer();
TempBuffer.Clear();
}
lock (LockObj)
{
DataSendAllow = false;
TimeComm.Start();
}
int len = Math.Min(Math.Min(xLen, xBuffer.Length - 1), 255);
lenSend = (byte)len;
// prvni byte se neposila, je tu jen kvuli stejnemu adresovani v PC a PLC
Port.Write(xBuffer, 1, len);
}
}
catch (Exception exc)
{
Port.DiscardInBuffer();
Port.DiscardOutBuffer();
}
}
public void Close()
{
if (Port.IsOpen)
Port.Close();
}
// toto je k pocitani casu komunikace
public class CommunicationTime
{
private Stopwatch T1;
protected long mActual;
public long Actual
{
get { return mActual; }
set
{
mActual = value;
mMin = ((mActual < mMin) && (mActual > 0)) ? mActual : mMin;
mMax = (mActual > mMax) ? mActual : mMax;
}
}
private long mMax;
private long mMin;
public CommunicationTime()
{
T1 = new Stopwatch();
Reset();
}
public bool ExceededTime(long xTimeMs)
{
return T1.ElapsedMilliseconds > xTimeMs;
}
public void Reset()
{
mActual = 0;
mMin = long.MaxValue;
mMax = long.MinValue;
}
public void Start()
{
T1.Reset();
T1.Start();
}
public void Stop()
{
T1.Stop();
Actual = T1.ElapsedMilliseconds;
}
public override string ToString()
{
return string.Format("Timeout={0} ms, Last={1} ms, Min={2} ms, Max={3} ", T1.ElapsedMilliseconds, mActual, mMin, mMax);
}
}
}
|