sessionlayer.cs
来自「zwave 无线通讯协议 PC controller 控制器源码」· CS 代码 · 共 718 行 · 第 1/2 页
CS
718 行
////////////////////////////////////////////////////////////////////////////////////////////////
//
// #######
// # ## #### ##### ##### ## ## #####
// ## ## ## ## ## ## ## ## ##
// ## # ###### ## ## #### ## ## ####
// ## ## ## ## ## ## ##### ##
// ####### #### ## ## ##### ## #####
// #####
// Z-Wave, the wireless language.
//
// Copyright Zensys A/S, 2005
//
// All Rights Reserved
//
// Description:
//
// Author: Morten Damsgaard, Linkage A/S
//
// Last Changed By: $Author: jrm $
// Revision: $Revision: 1.7 $
// Last Changed: $Date: 2007/02/15 11:34:47 $
//
//////////////////////////////////////////////////////////////////////////////////////////////
#region Using directives
using System;
using System.Threading;
using System.Collections;
using System.Diagnostics;
using System.Resources;
using Zensys.ZWave.Logging;
#endregion
namespace Zensys.ZWave.Communication
{
/// <summary>
///
/// </summary>
public class SessionLayer : ISessionLayer, IFrameLayerAsyncCallback
{
private const int DEFAULT_TIMEOUT = 10000; // How long in ms to wait for an response
// ---- Note ----
// Sequence numbers are appended to the data frame at the _last_ position in the payload,
// just before the checksum byte.
// Not all requests use sequence numbers
// The response from the ZW-module sets the sequence number at the _first_ position in
// the payload, just after the command ID
private const byte MIN_SEQUENCE_NUMBER = 1;
private const byte MAX_SEQUENCE_NUMBER = 127;
private byte sequenceNumber = MIN_SEQUENCE_NUMBER;
private IFrameLayer frameLayer;
private DataPacket request;
private DataFrame.CommandType command;
private ISessionLayerAsyncCallback asyncCallback;
private SessionStatistics stats;
private DataPacketQueue queue;
private ZWaveLogging log = ZWaveLogging.GetInstance("SessionLayer", false);
private DataFrame lastDataFrame = null;
private bool _IsReady;
/// <summary>
///
/// </summary>
public SessionLayer()
{
}
/// <summary>
///
/// </summary>
/// <param name="frameLayer"></param>
/// <param name="transportLayer"></param>
/// <param name="connectionString"></param>
public void Open(IFrameLayer frameLayer, ITransportLayer transportLayer, String connectionString)
{
if (frameLayer == null)
{
throw new ArgumentNullException("frameLayer");
}
this.sequenceNumber = MIN_SEQUENCE_NUMBER;
this.frameLayer = frameLayer;
frameLayer.Open(transportLayer, connectionString);
frameLayer.SetCallbackHandler(this);
queue = new DataPacketQueue();
stats = new SessionStatistics();
}
/// <summary>
///
/// </summary>
public void Close()
{
frameLayer.Close();
}
/// <summary>
///
/// </summary>
/// <returns></returns>
public SessionStatistics GetStatistics()
{
lock (stats)
{
return new SessionStatistics(stats);
}
}
/// <summary>
///
/// </summary>
/// <param name="handler"></param>
public void SetCallbackHandler(ISessionLayerAsyncCallback handler)
{
this.asyncCallback = handler;
}
/// <summary>
///
/// </summary>
/// <param name="cmd"></param>
/// <param name="request"></param>
/// <returns></returns>
public bool RequestWithNoResponse(DataFrame.CommandType cmd, DataPacket request)
{
try
{
if (request == null)
{
throw new ArgumentNullException("request");
}
lock (this)
{
// Construct and setup the new data frame...
DataFrame frame = new DataFrame();
frame.Type = DataFrame.FrameType.Request;
frame.Command = cmd;
// Add the data payload...
frame.AddPayload(request.GetPayload());
// Check if the sequence number should be appended at the last payload position...
if (request.SequenceNumber > 0)
frame.AddPayload(request.SequenceNumber);
stats.transmittedPackets++;
return frameLayer.Write(frame);
}
}
catch (FrameLayerException FLE)
{
throw new FrameLayerException("Error in RequestWithNoRepsonse :" + FLE.Message);
}
}
/// <summary>
///
/// </summary>
/// <param name="cmd"></param>
/// <param name="request"></param>
/// <param name="response"></param>
/// <returns></returns>
public TXStatus RequestWithResponse(DataFrame.CommandType cmd,
DataPacket request,
out DataPacket response)
{
if (request == null)
{
throw new ArgumentNullException("request");
}
return RequestWithResponse(cmd, request, out response, false, DEFAULT_TIMEOUT);
}
/// <summary>
///
/// </summary>
/// <param name="cmd"></param>
/// <param name="request"></param>
/// <param name="response"></param>
/// <param name="sequenceCheck"></param>
/// <returns></returns>
public TXStatus RequestWithResponse(DataFrame.CommandType cmd,
DataPacket request,
out DataPacket response,
bool sequenceCheck )
{
if (request == null)
{
throw new ArgumentNullException("request");
}
return RequestWithResponse(cmd, request, out response, sequenceCheck, DEFAULT_TIMEOUT);
}
/// <summary>
///
/// </summary>
/// <param name="cmd"></param>
/// <param name="request"></param>
/// <param name="response"></param>
/// <param name="sequenceCheck"></param>
/// <param name="timeout"></param>
/// <returns></returns>
public TXStatus RequestWithResponse(DataFrame.CommandType cmd,
DataPacket request,
out DataPacket response,
bool sequenceCheck, int timeout )
{
if (request == null)
{
throw new ArgumentNullException("request");
}
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);
response = null;
// Wait for reponse from peer or timeout...
if (queue.Dequeue(timeout, ref response))
{
this.command = 0;
// Sequence number check...
if (sequenceCheck && response.SequenceNumber != request.SequenceNumber)
{
IsReady = true;
return TXStatus.ResMissing; //false;
}
}
else
{
lock (stats) { stats.receiveTimeouts++; }
IsReady = true;
return TXStatus.NoAcknowledge;
}
IsReady = true;
return TXStatus.CompleteOk;
} // lock
}
/// <summary>
///
/// </summary>
/// <param name="cmd"></param>
/// <param name="request"></param>
/// <param name="responses"></param>
/// <returns></returns>
public TXStatus RequestWithMultipleResponses(DataFrame.CommandType cmd,
DataPacket request,
ref DataPacket[] responses)
{
if (request == null)
{
throw new ArgumentNullException("request");
}
return RequestWithMultipleResponses(cmd, request, ref responses, false, DEFAULT_TIMEOUT);
}
/// <summary>
///
/// </summary>
/// <param name="cmd"></param>
/// <param name="request"></param>
/// <param name="responses"></param>
/// <param name="sequenceCheck"></param>
/// <returns></returns>
public TXStatus RequestWithMultipleResponses(DataFrame.CommandType cmd,
DataPacket request,
ref DataPacket[] responses,
bool sequenceCheck)
{
if (request == null)
{
throw new ArgumentNullException("request");
}
return RequestWithMultipleResponses(cmd, request, ref responses, sequenceCheck, DEFAULT_TIMEOUT);
}
/// <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 RequestWithVariableResponses(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)
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?