using System;
using System.Text;
using Curtain.Net.Sockets.PLC.Model;
namespace Curtain.Net.Sockets.PLC
{
///
/// Socket 客户端
///
public class SocketClient : PLCSocket
where TClientModel : IClientModel, new()
{
#region 属性
///
/// 通信(接收)超时(毫秒)
///
public int ReceiveTimeout
{
get; set;
}
///
/// 通信(发送)超时(毫秒)
///
public int SendTimeout
{
get; set;
}
///
/// 主机地址
///
public string Host
{
get; protected set;
}
///
/// 主机端口
///
public int Port
{
get; protected set;
}
///
/// PLC通信模型
///
public TClientModel PLCModel
{
get; protected set;
}
#endregion
#region 构造
///
/// Socket 客户端
///
/// 新实例
public SocketClient(bool newModel = false)
{
if (newModel)
{
PLCModel = new TClientModel();
}
else
{
PLCModel = Model.ClientModel.CreateModel();
}
this.ReceiveTimeout = this.PLCModel.ReceiveTimeout;
this.SendTimeout = this.PLCModel.SendTimeout;
}
///
/// Socket 客户端
///
/// 新实例
public SocketClient(TClientModel model)
{
if (model == null)
{
throw new NullReferenceException("ClientSocket TPLCModel");
}
PLCModel = model;
this.ReceiveTimeout = this.PLCModel.ReceiveTimeout;
this.SendTimeout = this.PLCModel.SendTimeout;
}
///
/// Socket 客户端
///
/// 主机地址
/// 主机端口
/// 新实例
public SocketClient(string host, int port, bool newModel = false)
: this(newModel)
{
Host = host;
Port = port;
}
///
/// Socket 客户端
///
/// 主机地址
/// 主机端口
/// 新实例
public SocketClient(string host, int port, TClientModel model)
: this(model)
{
Host = host;
Port = port;
}
#endregion
#region Connect
///
/// 连接PLC
///
public virtual void Connect()
{
base.Connect(Host, Port);
}
///
/// 连接PLC
///
/// 主机地址
/// 主机端口
public override void Connect(string host, int port)
{
Host = host;
Port = port;
this.Connect();
}
///
/// Socket连接后PLC初始化
///
public override void OnSocketConnect()
{
PLCModel.OnSocketConnect(this);
}
#endregion
#region Command
///
/// 发送命令报文
///
///
///
protected virtual PLCResult SendByClient(byte[] data)
{
this.Socket.SendTimeout = this.SendTimeout;
//return BeginSend(data);
return Send(data);
}
///
/// 接收响应报文
///
///
///
protected virtual PLCResult ReceiveByClient(int length)
{
this.Socket.ReceiveTimeout = this.ReceiveTimeout;
//return BeginReceive(length);
return Receive(length);
}
///
/// 执行命令(不等待响应)
///
/// 报文
///
public virtual PLCResult DoCommandOneWay(PLCMessage plc_m)
{
PLCResult plcResult = new PLCResult(plc_m);
if (plc_m == null)
{
plcResult.Successed = false;
plcResult.Message = "no plc message";
return plcResult;
}
plc_m.Host = Host;
plc_m.Port = Port;
try
{
if (plc_m.CommandBytes == null ||
plc_m.CommandBytes.Length == 0)
{
if (string.IsNullOrEmpty(plc_m.Command))
{
plcResult.Successed = false;
plcResult.Message = "no command";
return plcResult;
}
else
{
plc_m.CommandBytes = PLCModel.ToSendFromCommand(plc_m.Command);
}
}
this.ThreadLock?.Lock();
this.Connect();
PLCResult result = SendByClient(plcResult.Data.CommandBytes);
if (!result.Successed)
{
plcResult.SetValue(result);
return plcResult;
}
}
catch (Exception ex)
{
//this.Disconnect();
plcResult.Successed = false;
plcResult.Message = ex.Message;
plcResult.MessageDetail = ex.ToString();
}
finally
{
if (this.ThreadLock != null && this.ThreadLock.Locked)
{
this.ThreadLock.Unlock();
}
}
return plcResult;
}
///
/// 执行命令
///
/// 报文
///
public virtual PLCResult DoCommand(PLCMessage plc_m)
{
PLCResult plcResult = new PLCResult(plc_m);
if (plc_m == null)
{
plcResult.Successed = false;
plcResult.Message = "no plc message";
return plcResult;
}
plc_m.Host = Host;
plc_m.Port = Port;
try
{
if (plc_m.CommandBytes == null ||
plc_m.CommandBytes.Length == 0)
{
if (string.IsNullOrEmpty(plc_m.Command))
{
plcResult.Successed = false;
plcResult.Message = "no command";
return plcResult;
}
else
{
plc_m.CommandBytes = PLCModel.ToSendFromCommand(plc_m.Command);
}
}
this.ThreadLock?.Lock();
this.Connect();
PLCResult result = SendByClient(plcResult.Data.CommandBytes);
if (!result.Successed)
{
plcResult.SetValue(result);
return plcResult;
}
// 响应报文-头
int headLength = PLCModel.HeadLength;
if (headLength < 1)
{
return plcResult;
}
PLCResult headResult = ReceiveByClient(headLength);
plcResult.Data.HeadBytes = headResult.Data;
plcResult.Data.Head = PLCModel.ToResponseFromReceive(headResult.Data);
if (!headResult.Successed)
{
plcResult.SetValue(headResult);
return plcResult;
}
if (!PLCModel.CheckHead(plc_m))
{
plcResult.Successed = false;
plcResult.Message = "response head error";
return plcResult;
}
// 响应报文-文本
int dataLength = PLCModel.GetContentLength(plcResult.Data);
if (dataLength > 0)
{
PLCResult dataResult = ReceiveByClient(dataLength);
plcResult.Data.ContentBytes = dataResult.Data;
plcResult.Data.Content = PLCModel.ToResponseFromReceive(dataResult.Data);
if (!dataResult.Successed)
{
plcResult.SetValue(dataResult);
return plcResult;
}
//PLCModel.SetValueFromCommand(plcResult.Data);
}
if (plcResult.Data.PLCError)
{
plcResult.Successed = false;
plcResult.Message = plcResult.Data.Head;
plcResult.MessageDetail = plcResult.Data.Content;
}
}
catch (Exception ex)
{
//this.Disconnect();
plcResult.Successed = false;
plcResult.Message = ex.Message;
plcResult.MessageDetail = ex.ToString();
}
finally
{
if (this.ThreadLock != null && this.ThreadLock.Locked)
{
this.ThreadLock.Unlock();
}
}
return plcResult;
}
///
/// 执行命令
///
///
///
public virtual PLCResult DoCommand(Func func)
{
return DoCommand(func());
}
#endregion
#region Read
///
/// 读取
///
///
///
///
///
public virtual PLCResult Read(char code, int number, int length = 1)
{
return DoCommand(PLCModel.GetReadMessage