| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608 |
-
- using System;
- using System.Text;
- using Curtain.Net.Sockets.PLC.Model;
- namespace Curtain.Net.Sockets.PLC
- {
- /// <summary>
- /// Socket 客户端
- /// </summary>
- public class SocketClient<TClientModel> : PLCSocket
- where TClientModel : IClientModel, new()
- {
- #region 属性
- /// <summary>
- /// 通信(接收)超时(毫秒)
- /// </summary>
- public int ReceiveTimeout
- {
- get; set;
- }
- /// <summary>
- /// 通信(发送)超时(毫秒)
- /// </summary>
- public int SendTimeout
- {
- get; set;
- }
- /// <summary>
- /// 主机地址
- /// </summary>
- public string Host
- {
- get; protected set;
- }
- /// <summary>
- /// 主机端口
- /// </summary>
- public int Port
- {
- get; protected set;
- }
- /// <summary>
- /// PLC通信模型
- /// </summary>
- public TClientModel PLCModel
- {
- get; protected set;
- }
- #endregion
- #region 构造
- /// <summary>
- /// Socket 客户端
- /// </summary>
- /// <param name="newModel">新实例</param>
- public SocketClient(bool newModel = false)
- {
- if (newModel)
- {
- PLCModel = new TClientModel();
- }
- else
- {
- PLCModel = Model.ClientModel.CreateModel<TClientModel>();
- }
- this.ReceiveTimeout = this.PLCModel.ReceiveTimeout;
- this.SendTimeout = this.PLCModel.SendTimeout;
- }
- /// <summary>
- /// Socket 客户端
- /// </summary>
- /// <param name="model">新实例</param>
- public SocketClient(TClientModel model)
- {
- if (model == null)
- {
- throw new NullReferenceException("ClientSocket TPLCModel");
- }
- PLCModel = model;
- this.ReceiveTimeout = this.PLCModel.ReceiveTimeout;
- this.SendTimeout = this.PLCModel.SendTimeout;
- }
- /// <summary>
- /// Socket 客户端
- /// </summary>
- /// <param name="host">主机地址</param>
- /// <param name="port">主机端口</param>
- /// <param name="newModel">新实例</param>
- public SocketClient(string host, int port, bool newModel = false)
- : this(newModel)
- {
- Host = host;
- Port = port;
- }
- /// <summary>
- /// Socket 客户端
- /// </summary>
- /// <param name="host">主机地址</param>
- /// <param name="port">主机端口</param>
- /// <param name="model">新实例</param>
- public SocketClient(string host, int port, TClientModel model)
- : this(model)
- {
- Host = host;
- Port = port;
- }
- #endregion
- #region Connect
- /// <summary>
- /// 连接PLC
- /// </summary>
- public virtual void Connect()
- {
- base.Connect(Host, Port);
- }
- /// <summary>
- /// 连接PLC
- /// </summary>
- /// <param name="host">主机地址</param>
- /// <param name="port">主机端口</param>
- public override void Connect(string host, int port)
- {
- Host = host;
- Port = port;
- this.Connect();
- }
- /// <summary>
- /// Socket连接后PLC初始化
- /// </summary>
- public override void OnSocketConnect()
- {
- PLCModel.OnSocketConnect(this);
- }
- #endregion
- #region Command
- /// <summary>
- /// 发送命令报文
- /// </summary>
- /// <param name="data"></param>
- /// <returns></returns>
- protected virtual PLCResult SendByClient(byte[] data)
- {
- this.Socket.SendTimeout = this.SendTimeout;
- //return BeginSend(data);
- return Send(data);
- }
- /// <summary>
- /// 接收响应报文
- /// </summary>
- /// <param name="length"></param>
- /// <returns></returns>
- protected virtual PLCResult<byte[]> ReceiveByClient(int length)
- {
- this.Socket.ReceiveTimeout = this.ReceiveTimeout;
- //return BeginReceive(length);
- return Receive(length);
- }
- /// <summary>
- /// 执行命令(不等待响应)
- /// </summary>
- /// <param name="plc_m">报文</param>
- /// <returns></returns>
- public virtual PLCResult<PLCMessage> DoCommandOneWay(PLCMessage plc_m)
- {
- PLCResult<PLCMessage> plcResult = new PLCResult<PLCMessage>(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;
- }
- /// <summary>
- /// 执行命令
- /// </summary>
- /// <param name="plc_m">报文</param>
- /// <returns></returns>
- public virtual PLCResult<PLCMessage> DoCommand(PLCMessage plc_m)
- {
- PLCResult<PLCMessage> plcResult = new PLCResult<PLCMessage>(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<byte[]> 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<byte[]> 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;
- }
- /// <summary>
- /// 执行命令
- /// </summary>
- /// <param name="func"></param>
- /// <returns></returns>
- public virtual PLCResult<PLCMessage> DoCommand(Func<PLCMessage> func)
- {
- return DoCommand(func());
- }
- #endregion
- #region Read
- /// <summary>
- /// 读取
- /// </summary>
- /// <param name="code"></param>
- /// <param name="number"></param>
- /// <param name="length"></param>
- /// <returns></returns>
- public virtual PLCResult<PLCMessage> Read(char code, int number, int length = 1)
- {
- return DoCommand(PLCModel.GetReadMessage<object>(code, number, length));
- }
- /// <summary>
- /// 读取
- /// </summary>
- /// <param name="code"></param>
- /// <param name="number"></param>
- /// <param name="length"></param>
- /// <returns></returns>
- public virtual PLCResult<PLCMessage> Read(string code, string number, int length = 1)
- {
- return DoCommand(PLCModel.GetReadMessage<object>(code, number, length));
- }
- /// <summary>
- /// 读取
- /// </summary>
- /// <param name="code"></param>
- /// <param name="length"></param>
- /// <returns></returns>
- public virtual PLCResult<PLCMessage> Read(string code, int length = 1)
- {
- return DoCommand(PLCModel.GetReadMessage<object>(code, length));
- }
- /// <summary>
- /// 读取
- /// </summary>
- /// <param name="code"></param>
- /// <param name="number"></param>
- /// <param name="length"></param>
- /// <returns></returns>
- public virtual PLCResult<TValue> Read<TValue>(char code, int number, int length = 1)
- {
- //PLCResult<PLCMessage<TValue>> plcResult = ReadValue<TValue>(code, number, length);
- //if (plcResult?.Successed ?? false)
- //{
- // return new PLCResult<TValue>(plcResult, plcResult.Data.Value);
- //}
- //return new PLCResult<TValue>(plcResult);
- PLCResult<PLCMessage> plcResult = DoCommand(PLCModel.GetReadMessage<TValue>(code, number, length));
- if (plcResult.Successed)
- {
- PLCMessage<TValue> p_value = (PLCMessage<TValue>)plcResult.Data;
- PLCModel.SetReadValueFromBytes<TValue>(p_value);
- return new PLCResult<TValue>(plcResult, p_value.Value);
- }
- return new PLCResult<TValue>(plcResult);
- }
- /// <summary>
- /// 读取
- /// </summary>
- /// <param name="code"></param>
- /// <param name="number"></param>
- /// <param name="length"></param>
- /// <returns></returns>
- public virtual PLCResult<TValue> Read<TValue>(string code, string number, int length = 1)
- {
- //PLCResult<PLCMessage<TValue>> plcResult = ReadValue<TValue>(code, number, length);
- //if (plcResult?.Successed ?? false)
- //{
- // return new PLCResult<TValue>(plcResult, plcResult.Data.Value);
- //}
- //return new PLCResult<TValue>(plcResult);
- PLCResult<PLCMessage> plcResult = DoCommand(PLCModel.GetReadMessage<TValue>(code, number, length));
- if (plcResult.Successed)
- {
- PLCMessage<TValue> p_value = (PLCMessage<TValue>)plcResult.Data;
- PLCModel.SetReadValueFromBytes<TValue>(p_value);
- return new PLCResult<TValue>(plcResult, p_value.Value);
- }
- return new PLCResult<TValue>(plcResult);
- }
- /// <summary>
- /// 读取
- /// </summary>
- /// <param name="code"></param>
- /// <param name="length"></param>
- /// <returns></returns>
- public virtual PLCResult<TValue> Read<TValue>(string code, int length = 1)
- {
- //PLCResult<PLCMessage<TValue>> plcResult = ReadValue<TValue>(code, length);
- //if (plcResult?.Successed ?? false)
- //{
- // return new PLCResult<TValue>(plcResult, plcResult.Data.Value);
- //}
- //return new PLCResult<TValue>(plcResult);
- PLCResult<PLCMessage> plcResult = DoCommand(PLCModel.GetReadMessage<TValue>(code, length));
- if (plcResult.Successed)
- {
- PLCMessage<TValue> p_value = (PLCMessage<TValue>)plcResult.Data;
- PLCModel.SetReadValueFromBytes<TValue>(p_value);
- return new PLCResult<TValue>(plcResult, p_value.Value);
- }
- return new PLCResult<TValue>(plcResult);
- }
- /// <summary>
- /// 读取
- /// </summary>
- /// <param name="code"></param>
- /// <param name="number"></param>
- /// <param name="length"></param>
- /// <returns></returns>
- public virtual PLCResult<PLCMessage<TValue>> ReadValue<TValue>(char code, int number, int length = 1)
- {
- PLCResult<PLCMessage> plcResult = DoCommand(PLCModel.GetReadMessage<TValue>(code, number, length));
- if (plcResult.Successed)
- {
- PLCModel.SetReadValueFromBytes<TValue>((PLCMessage<TValue>)plcResult.Data);
- }
- return new PLCResult<PLCMessage<TValue>>(plcResult, (PLCMessage<TValue>)plcResult.Data);
- }
- /// <summary>
- /// 读取
- /// </summary>
- /// <param name="code"></param>
- /// <param name="number"></param>
- /// <param name="length"></param>
- /// <returns></returns>
- public virtual PLCResult<PLCMessage<TValue>> ReadValue<TValue>(string code, string number, int length = 1)
- {
- PLCResult<PLCMessage> plcResult = DoCommand(PLCModel.GetReadMessage<TValue>(code, number, length));
- if (plcResult.Successed)
- {
- PLCModel.SetReadValueFromBytes<TValue>((PLCMessage<TValue>)plcResult.Data);
- }
- return new PLCResult<PLCMessage<TValue>>(plcResult, (PLCMessage<TValue>)plcResult.Data);
- }
- /// <summary>
- /// 读取
- /// </summary>
- /// <param name="code"></param>
- /// <param name="length"></param>
- /// <returns></returns>
- public virtual PLCResult<PLCMessage<TValue>> ReadValue<TValue>(string code, int length = 1)
- {
- PLCResult<PLCMessage> plcResult = DoCommand(PLCModel.GetReadMessage<TValue>(code, length));
- if (plcResult.Successed)
- {
- PLCModel.SetReadValueFromBytes<TValue>((PLCMessage<TValue>)plcResult.Data);
- }
- return new PLCResult<PLCMessage<TValue>>(plcResult, (PLCMessage<TValue>)plcResult.Data);
- }
- #endregion
- #region Write
- /// <summary>
- /// 写入
- /// </summary>
- /// <typeparam name="TValue"></typeparam>
- /// <param name="code"></param>
- /// <param name="number"></param>
- /// <param name="value"></param>
- /// <param name="length"></param>
- /// <returns></returns>
- public virtual PLCResult Write<TValue>(char code, int number, TValue value, int length = 0)
- {
- return DoCommand(PLCModel.GetWriteMessage(code, number, value, length));
- }
- /// <summary>
- /// 写入
- /// </summary>
- /// <typeparam name="TValue"></typeparam>
- /// <param name="code"></param>
- /// <param name="number"></param>
- /// <param name="value"></param>
- /// <param name="length"></param>
- /// <returns></returns>
- public virtual PLCResult Write<TValue>(string code, string number, TValue value, int length = 0)
- {
- return DoCommand(PLCModel.GetWriteMessage(code, number, value, length));
- }
- /// <summary>
- /// 写入
- /// </summary>
- /// <typeparam name="TValue"></typeparam>
- /// <param name="code"></param>
- /// <param name="value"></param>
- /// <param name="length"></param>
- /// <returns></returns>
- public virtual PLCResult Write<TValue>(string code, TValue value, int length = 0)
- {
- return DoCommand(PLCModel.GetWriteMessage(code, value, length));
- }
- /// <summary>
- /// 写入
- /// </summary>
- /// <param name="code"></param>
- /// <param name="number"></param>
- /// <param name="value"></param>
- /// <param name="encoding"></param>
- /// <param name="length"></param>
- /// <returns></returns>
- public virtual PLCResult Write(char code, int number, string value, Encoding encoding, int length = 0)
- {
- return DoCommand(PLCModel.GetWriteMessage(code, number, value, encoding, length));
- }
- /// <summary>
- /// 写入
- /// </summary>
- /// <param name="code"></param>
- /// <param name="number"></param>
- /// <param name="value"></param>
- /// <param name="encoding"></param>
- /// <param name="length"></param>
- /// <returns></returns>
- public virtual PLCResult Write(string code, string number, string value, Encoding encoding, int length = 0)
- {
- return DoCommand(PLCModel.GetWriteMessage(code, number, value, encoding, length));
- }
- /// <summary>
- /// 写入
- /// </summary>
- /// <param name="code"></param>
- /// <param name="value"></param>
- /// <param name="encoding"></param>
- /// <param name="length"></param>
- /// <returns></returns>
- public virtual PLCResult Write(string code, string value, Encoding encoding, int length = 0)
- {
- return DoCommand(PLCModel.GetWriteMessage(code, value, encoding, length));
- }
- #endregion
- #region Send
- /// <summary>
- /// 发送
- /// </summary>
- /// <param name="value"></param>
- /// <returns></returns>
- public virtual PLCResult Send(string value)
- {
- return DoCommandOneWay(PLCModel.GetSendMessage(value));
- }
- /// <summary>
- /// 发送
- /// </summary>
- /// <param name="value"></param>
- /// <returns></returns>
- public virtual PLCResult<PLCMessage> SendByResult(string value)
- {
- return DoCommand(PLCModel.GetSendMessage(value));
- }
- #endregion
- }
- }
|