sessionlayer.cs
来自「zwave 无线通讯协议 PC controller 控制器源码」· CS 代码 · 共 718 行 · 第 1/2 页
CS
718 行
{
stats.receiveTimeouts++;
}
IsReady = true;
return TXStatus.NoAcknowledge;
//return false;
}
} // for
IsReady = true;
return TXStatus.CompleteOk;
// return true;
} // lock
}
/// <summary>
/// Requests a command which may give different numbers of callbacks.
/// Supply with Responses array that have room for worst case number of callbacks
/// </summary>
/// <param name="cmd">Zwave Cmd</param>
/// <param name="request">Parms for command</param>
/// <param name="responses">Max number of responses</param>
/// <param name="breakVal">Values to end one</param>
/// <param name="sequenceCheck">if true use sequence check</param>
/// <param name="timeout">Timeout in ms</param>
/// <returns></returns>
public TXStatus RequestWithVariableReturnsAndResponses(DataFrame.CommandType cmd,
DataPacket request,
ref DataPacket[] responses,
byte[] breakVal,
bool sequenceCheck,
int timeout)
{
if (request == null)
{
throw new ArgumentNullException("request");
}
if (responses == null)
{
throw new ArgumentNullException("responses");
}
IsReady = false;
lock (this)
{
if (sequenceCheck)
request.SequenceNumber = SequenceNumber++;
lastDataFrame = null;
queue.Clear();
// Store the command...
this.command = cmd;
// Store the request...
this.request = request;
RequestWithNoResponse(cmd, request);
// Wait for reponse from peer or timeout...
for (int i = 0; i < responses.Length; i++)
{
if (queue.Dequeue(timeout, ref responses[i]))
{
// Strip the sequence number if used by the request
// The sequence number is placed as the first byte in the payload
if (sequenceCheck && responses[i].SequenceNumber > 0 &&
responses[i].SequenceNumber != request.SequenceNumber)
{
IsReady = true;
return TXStatus.ResMissing;
}
if (i >= 0)
{
for (int n = 0; n < breakVal.Length; n++)
{
if (responses[i].GetPayload()[0] == breakVal[n])
{
return TXStatus.CompleteFail;
}
}
}
}
else
{
lock (stats)
{
stats.receiveTimeouts++;
}
IsReady = true;
return TXStatus.NoAcknowledge;
//return false;
}
} // for
IsReady = true;
return TXStatus.CompleteOk;
// return true;
} // lock
}
/// <summary>
///
/// </summary>
/// <param name="cmd"></param>
/// <param name="request"></param>
/// <param name="responses"></param>
/// <param name="sequenceCheck"></param>
/// <param name="timeout"></param>
/// <returns></returns>
public TXStatus RequestWithMultipleResponses(DataFrame.CommandType cmd,
DataPacket request,
ref DataPacket[] responses,
bool sequenceCheck,
int timeout)
{
if (request == null)
{
throw new ArgumentNullException("request");
}
if (responses == null)
{
throw new ArgumentNullException("responses");
}
IsReady = false;
lock(this)
{
if (sequenceCheck) request.SequenceNumber = SequenceNumber++;
lastDataFrame = null;
queue.Clear();
// Store the command...
this.command = cmd;
// Store the request...
this.request = request;
RequestWithNoResponse(cmd, request);
// Wait for reponse from peer or timeout...
for(int i=0; i<responses.Length; i++)
{
if (queue.Dequeue(timeout, ref responses[i]))
{
// Strip the sequence number if used by the request
// The sequence number is placed as the first byte in the payload
if (sequenceCheck && responses[i].SequenceNumber > 0 &&
responses[i].SequenceNumber != request.SequenceNumber)
{
IsReady = true;
return TXStatus.ResMissing;
}
}
else
{
lock (stats) { stats.receiveTimeouts++; }
IsReady = true;
return TXStatus.NoAcknowledge;
//return false;
}
} // for
IsReady = true;
return TXStatus.CompleteOk;
// return true;
} // lock
}
/// <summary>
///
/// </summary>
/// <param name="frame"></param>
public void FrameReceived(DataFrame frame)
{
if (frame == null)
{
throw new ArgumentNullException("frame");
}
// Called from FrameLayer thread scope...
lock (stats) { stats.receivedPackets++; }
if (frame.Command == command)
{
// The peer ZWave module could be tranmitting the same frame twice.
// so check if the frame was retransmitted from module
if (lastDataFrame != null && lastDataFrame == frame)
{
lock (stats) { stats.duplicatePackets++; }
log.Write("COM - Duplicate packet received...");
return;
}
lastDataFrame = frame;
DataPacket dp;
// Check and extract (strip) sequence number from frame...
if (request.SequenceNumber > 0 && frame.Type == DataFrame.FrameType.Request)
{
byte[] payload = frame.GetPayloadBuffer();
byte[] data = new byte[payload.Length - 1];
Array.Copy(payload, 1, data, 0, data.Length);
dp = new DataPacket(data);
dp.Timestamp = frame.Timestamp;
dp.SequenceNumber = payload[0];
}
else
{
dp = new DataPacket(frame.GetPayloadBuffer());
dp.Timestamp = frame.Timestamp;
}
// Put the DataPacket in the Queue...
queue.Enqueue(dp);
}
else
if (asyncCallback != null)
{
DataPacket dp = new DataPacket(frame.GetPayloadBuffer());
dp.Timestamp = frame.Timestamp;
asyncCallback.DataPacketReceived(frame.Command, dp);
lock (stats) { stats.asyncPackets++; }
}
}
private byte SequenceNumber
{
get
{
return sequenceNumber;
}
set
{
// Test if sequence number should wrap-around...
if (sequenceNumber == MAX_SEQUENCE_NUMBER)
sequenceNumber = MIN_SEQUENCE_NUMBER;
else
sequenceNumber = value;
}
}
/// <summary>
///
/// </summary>
public bool IsReady
{
get{return _IsReady;}
set{_IsReady = value;}
}
}
internal class DataPacketQueue
{
private Queue rxQueue;
private TimeoutEvent responseEvent;
public DataPacketQueue()
{
rxQueue = new Queue(10);
responseEvent = new TimeoutEvent();
}
public void Enqueue(DataPacket packet)
{
lock (rxQueue.SyncRoot)
{
rxQueue.Enqueue(packet);
}
// Signal any waiting calls
responseEvent.Set();
}
public bool Dequeue(int timeout, ref DataPacket packet)
{
bool rc = false;
// First check if there is something in the queue...
lock (rxQueue.SyncRoot)
{
if (rxQueue.Count > 0)
{
packet = (DataPacket)rxQueue.Dequeue();
responseEvent.Reset(); // sync'ed with WaitOne in next call - TellITOnline DLI
rc = true;
}
}
if (!rc && responseEvent.WaitOne(timeout))
{
// Check that sequence number from the received packet equals the one transmitted...
lock (rxQueue.SyncRoot)
{
if (rxQueue.Count > 0)
{
packet = (DataPacket)rxQueue.Dequeue();
rc = true;
}
}
}
return rc;
}
public void Clear()
{
lock (rxQueue.SyncRoot)
{
rxQueue.Clear();
}
responseEvent.Reset();
}
}
internal class TimeoutEvent
{
private AutoResetEvent responseEvent = new AutoResetEvent(false);
private System.Threading.Timer timeoutTimer;
private bool timertimeout;
public TimeoutEvent()
{
TimerCallback tc = new TimerCallback(this.TimerCallbackHandler);
this.timeoutTimer = new Timer(tc, this, System.Threading.Timeout.Infinite, System.Threading.Timeout.Infinite);
}
public bool WaitOne(int timeout)
{
// Reset the timer...
timeoutTimer.Change(timeout, System.Threading.Timeout.Infinite);
// Clear the timeout flag...
timertimeout = false;
// Wait for the event to be signaled...
responseEvent.WaitOne();
// Disable the timer
timeoutTimer.Change(System.Threading.Timeout.Infinite, System.Threading.Timeout.Infinite);
return !timertimeout;
}
public void Reset()
{
responseEvent.Reset();
}
public void Set()
{
responseEvent.Set();
}
public void TimerCallbackHandler(Object state)
{
timertimeout = true;
responseEvent.Set();
}
}
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?