/// <summary> /// 从三菱PLC中读取想要的数据,返回读取结果 /// </summary> /// <param name="address">读取地址,格式为"M100","D100","W1A0"</param> /// <param name="length">读取的数据长度,字最大值960,位最大值7168</param> /// <returns>带成功标志的结果数据对象</returns> public override OperateResult <byte[]> Read(string address, ushort length) { var result = new OperateResult <byte[]>( ); //获取指令 var command = BuildReadCommand(address, length); if (!command.IsSuccess) { result.CopyErrorFromOther(command); return(result); } var read = ReadFromCoreServer(command.Content2); if (read.IsSuccess) { byte[] buffer = new byte[4]; buffer[0] = read.Content[18]; buffer[1] = read.Content[19]; buffer[2] = read.Content[20]; buffer[3] = read.Content[21]; result.ErrorCode = Convert.ToUInt16(Encoding.ASCII.GetString(buffer), 16); if (result.ErrorCode == 0) { if (command.Content1.DataType == 0x01) { result.Content = new byte[read.Content.Length - 22]; for (int i = 22; i < read.Content.Length; i++) { if (read.Content[i] == 0x30) { result.Content[i - 22] = 0x00; } else { result.Content[i - 22] = 0x01; } } } else { result.Content = new byte[(read.Content.Length - 22) / 2]; for (int i = 0; i < result.Content.Length / 2; i++) { buffer = new byte[4]; buffer[0] = read.Content[i * 4 + 22]; buffer[1] = read.Content[i * 4 + 23]; buffer[2] = read.Content[i * 4 + 24]; buffer[3] = read.Content[i * 4 + 25]; ushort tmp = Convert.ToUInt16(Encoding.ASCII.GetString(buffer), 16); BitConverter.GetBytes(tmp).CopyTo(result.Content, i * 2); } } result.IsSuccess = true; } else { result.Message = "请翻查三菱通讯手册来查看具体的信息。"; } } else { result.ErrorCode = read.ErrorCode; result.Message = read.Message; } return(result); }
/// <summary> /// 将指定的OperateResult类型转化 /// </summary> /// <param name="result">原始的类型</param> /// <returns>转化后的类型</returns> protected OperateResult <double> GetDoubleResultFromBytes(OperateResult <byte[]> result) { return(ByteTransformHelper.GetDoubleResultFromBytes(result, byteTransform)); }
private void AddTreeNode(TreeNode parent, string key, string infactKey) { int index = key.IndexOf(':'); if (index <= 0) { // 不存在冒号 TreeNode node = new TreeNode(infactKey); node.Tag = infactKey; // 读取类型 OperateResult <string> type = redisClient.ReadKeyType(infactKey); if (type.Content == "string") { node.ImageKey = "Enum_582"; node.SelectedImageKey = "Enum_582"; } else if (type.Content == "list") { node.ImageKey = "brackets_Square_16xMD"; node.SelectedImageKey = "brackets_Square_16xMD"; } else if (type.Content == "hash") { node.ImageKey = "Method_636"; node.SelectedImageKey = "Method_636"; } else if (type.Content == "set") { node.ImageKey = "Module_648"; node.SelectedImageKey = "Module_648"; } else if (type.Content == "zset") { node.ImageKey = "Structure_507"; node.SelectedImageKey = "Structure_507"; } parent.Nodes.Add(node); } else { TreeNode node = null; for (int i = 0; i < parent.Nodes.Count; i++) { if (parent.Nodes[i].Text == key.Substring(0, index)) { node = parent.Nodes[i]; break; } } if (node == null) { node = new TreeNode(key.Substring(0, index)); node.ImageKey = "Class_489"; node.SelectedImageKey = "Class_489"; AddTreeNode(node, key.Substring(index + 1), infactKey); parent.Nodes.Add(node); } else { AddTreeNode(node, key.Substring(index + 1), infactKey); } } }
/// <summary> /// 将指定的OperateResult类型转化 /// </summary> /// <param name="result">原始的类型</param> /// <returns>转化后的类型</returns> protected OperateResult <bool> GetBoolResultFromBytes(OperateResult <byte[]> result) { return(ByteTransformHelper.GetBoolResultFromBytes(result, byteTransform)); }
/// <summary> /// 将指定的OperateResult类型转化 /// </summary> /// <param name="result">原始的类型</param> /// <returns>转化后的类型</returns> protected OperateResult <ulong> GetUInt64ResultFromBytes(OperateResult <byte[]> result) { return(ByteTransformHelper.GetUInt64ResultFromBytes(result, byteTransform)); }
/// <summary> /// 创建一个新的socket对象并连接到远程的地址 /// </summary> /// <param name="endPoint">连接的目标终结点</param> /// <param name="timeOut">连接的超时时间</param> /// <returns>返回套接字的封装结果对象</returns> /// <example> /// <code lang="cs" source="Communication_Net45.Test\Documentation\Samples\Core\NetworkBase.cs" region="CreateSocketAndConnectExample" title="创建连接示例" /> /// </example> protected OperateResult <Socket> CreateSocketAndConnect(IPEndPoint endPoint, int timeOut) { if (UseSynchronousNet)//使用同步网络 { var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); try { TimeOut connectTimeout = new TimeOut() { WorkSocket = socket, DelayTime = timeOut }; ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadPoolCheckTimeOut), connectTimeout); socket.Connect(endPoint); connectTimeout.IsSuccessful = true; return(OperateResult.CreateSuccessResult(socket)); } catch (Exception ex) { socket?.Close(); LogNet?.WriteException("CreateSocketAndConnect", ex); return(new OperateResult <Socket>(ex.Message)); } } else { OperateResult <Socket> result = new OperateResult <Socket>(); ManualResetEvent connectDone = null; StateObject state = null; try { connectDone = new ManualResetEvent(false); state = new StateObject(); } catch (Exception ex) { return(new OperateResult <Socket>(ex.Message)); } var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); // 超时验证的信息 TimeOut connectTimeout = new TimeOut() { WorkSocket = socket, DelayTime = timeOut }; ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadPoolCheckTimeOut), connectTimeout); try { state.WaitDone = connectDone; state.WorkSocket = socket; socket.BeginConnect(endPoint, new AsyncCallback(ConnectCallBack), state);// 当连接的结果返回 } catch (Exception ex) { // 直接失败 connectTimeout.IsSuccessful = true; // 退出线程池的超时检查 LogNet?.WriteException(ToString(), ex); // 记录错误日志 socket.Close(); // 关闭网络信息 connectDone.Close(); // 释放等待资源 result.Message = StringResources.Language.ConnectedFailed + ex.Message; // 传递错误消息 return(result); } // 等待连接完成 connectDone.WaitOne(); connectDone.Close(); connectTimeout.IsSuccessful = true; if (state.IsError) { // 连接失败 result.Message = StringResources.Language.ConnectedFailed + state.ErrerMsg; socket?.Close(); return(result); } result.Content = socket; result.IsSuccess = true; state.Clear(); state = null; return(result); } }
/// <summary> /// 连接上服务器后需要进行的初始化操作 /// </summary> /// <param name="socket">网络套接字</param> /// <returns></returns> protected virtual OperateResult InitilizationOnConnect(Socket socket) { return(OperateResult.CreateSuccessResult()); }
/// <summary> /// 接收一条完整的数据,使用异步接收完成,包含了指令头信息 /// </summary> /// <param name="socket">已经打开的网络套接字</param> /// <param name="timeOut">超时时间</param> /// <param name="netMsg">消息规则</param> /// <returns>数据的接收结果对象</returns> protected OperateResult <TNetMessage> ReceiveMessage <TNetMessage>(Socket socket, int timeOut, TNetMessage netMsg) where TNetMessage : INetMessage { OperateResult <TNetMessage> result = new OperateResult <TNetMessage>( ); // 超时接收的代码验证 HslTimeOut hslTimeOut = new HslTimeOut( ) { DelayTime = timeOut, WorkSocket = socket, }; if (timeOut > 0) { ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadPoolCheckTimeOut), hslTimeOut); } // 接收指令头 OperateResult <byte[]> headResult = Receive(socket, netMsg.ProtocolHeadBytesLength); if (!headResult.IsSuccess) { hslTimeOut.IsSuccessful = true; result.CopyErrorFromOther(headResult); return(result); } netMsg.HeadBytes = headResult.Content; if (!netMsg.CheckHeadBytesLegal(Token.ToByteArray( ))) { // 令牌校验失败 hslTimeOut.IsSuccessful = true; socket?.Close( ); LogNet?.WriteError(ToString( ), StringResources.TokenCheckFailed); result.Message = StringResources.TokenCheckFailed; return(result); } int contentLength = netMsg.GetContentLengthByHeadBytes( ); if (contentLength == 0) { netMsg.ContentBytes = new byte[0]; } else { OperateResult <byte[]> contentResult = Receive(socket, contentLength); if (!headResult.IsSuccess) { hslTimeOut.IsSuccessful = true; result.CopyErrorFromOther(contentResult); return(result); } netMsg.ContentBytes = contentResult.Content; } // 防止没有实例化造成后续的操作失败 if (netMsg.ContentBytes == null) { netMsg.ContentBytes = new byte[0]; } hslTimeOut.IsSuccessful = true; result.Content = netMsg; result.IsSuccess = true; return(result); }
/// <summary> /// 解析数据地址,解析出地址类型,起始地址,DB块的地址 /// </summary> /// <param name="address">数据地址</param> /// <returns>解析出地址类型,起始地址,DB块的地址</returns> private OperateResult <byte, int, ushort> AnalysisAddress(string address) { var result = new OperateResult <byte, int, ushort>( ); try { result.Content3 = 0; if (address[0] == 'I') { result.Content1 = 0x03; result.Content2 = CalculateAddressStarted(address.Substring(1)); } else if (address[0] == 'Q') { result.Content1 = 0x04; result.Content2 = CalculateAddressStarted(address.Substring(1)); } else if (address[0] == 'M') { result.Content1 = 0x02; result.Content2 = CalculateAddressStarted(address.Substring(1)); } else if (address[0] == 'D' || address.Substring(0, 2) == "DB") { result.Content1 = 0x01; string[] adds = address.Split('.'); if (address[1] == 'B') { result.Content3 = Convert.ToUInt16(adds[0].Substring(2)); } else { result.Content3 = Convert.ToUInt16(adds[0].Substring(1)); } if (result.Content3 > 255) { result.Message = "DB块数据无法大于255"; return(result); } result.Content2 = CalculateAddressStarted(address.Substring(address.IndexOf('.') + 1)); } else if (address[0] == 'T') { result.Content1 = 0x07; result.Content2 = CalculateAddressStarted(address.Substring(1)); } else if (address[0] == 'C') { result.Content1 = 0x06; result.Content2 = CalculateAddressStarted(address.Substring(1)); } else { result.Message = "不支持的数据类型"; result.Content1 = 0; result.Content2 = 0; result.Content3 = 0; return(result); } } catch (Exception ex) { result.Message = ex.Message; return(result); } result.IsSuccess = true; return(result); }
/// <summary> /// 写入自定义的数据到数据内存中去 /// </summary> /// <param name="address">地址</param> /// <param name="value">数据值</param> /// <returns>是否写入成功的结果对象</returns> public override OperateResult Write(string address, byte[] value) { OperateResult <string> analysis = XGBFastEnet.AnalysisAddress(address, false); if (!analysis.IsSuccess) { return(OperateResult.CreateFailedResult <byte[]>(analysis)); } int startIndex = int.Parse(analysis.Content.Substring(3)); switch (analysis.Content[1]) { case 'P': pBuffer.SetBytes(value, startIndex); return(OperateResult.CreateSuccessResult()); case 'Q': qBuffer.SetBytes(value, startIndex); return(OperateResult.CreateSuccessResult()); case 'M': mBuffer.SetBytes(value, startIndex); return(OperateResult.CreateSuccessResult()); case 'D': dBuffer.SetBytes(value, startIndex == 0 ? startIndex : startIndex *= 2); return(OperateResult.CreateSuccessResult()); default: return(new OperateResult <byte[]>(StringResources.Language.NotSupportedDataType)); } }
/***************************************************************************** * * 说明: * 下面的三个模块代码指示了如何接收数据,如何发送数据,如何连接网络 * ********************************************************************************/ #region Reveive Content /// <summary> /// 接收固定长度的字节数组 /// </summary> /// <remarks> /// Receive Special Length Bytes /// </remarks> /// <param name="socket">网络通讯的套接字</param> /// <param name="length">准备接收的数据长度</param> /// <returns>包含了字节数据的结果类</returns> protected OperateResult <byte[]> Receive(Socket socket, int length) { if (length == 0) { return(OperateResult.CreateSuccessResult(new byte[0])); } var result = new OperateResult <byte[]>( ); var receiveDone = new ManualResetEvent(false); var state = new StateObject(length); try { state.WaitDone = receiveDone; state.WorkSocket = socket; // Begin receiving the data from the remote device. socket.BeginReceive(state.Buffer, state.AlreadyDealLength, state.DataLength - state.AlreadyDealLength, SocketFlags.None, new AsyncCallback(ReceiveCallback), state); } catch (Exception ex) { // 发生了错误,直接返回 LogNet?.WriteException(ToString( ), ex); result.Message = ex.Message; receiveDone.Close( ); socket?.Close( ); return(result); } // 等待接收完成,或是发生异常 receiveDone.WaitOne( ); receiveDone.Close( ); // 接收数据失败 if (state.IsError) { socket?.Close( ); result.Message = state.ErrerMsg; return(result); } // 远程关闭了连接 if (state.IsClose) { result.IsSuccess = true; result.Message = "远程关闭了连接"; socket?.Close( ); return(result); } // 正常接收到数据 result.Content = state.Buffer; result.IsSuccess = true; state.Clear( ); state = null; return(result); }
/// <summary> /// 返回视图结果 /// </summary> /// <typeparam name="TController">控制器类型</typeparam> /// <typeparam name="T">返回结果类型</typeparam> /// <param name="controller">当前控制器</param> /// <param name="operateResult">操作结果</param> /// <param name="redirectViewName">指定的返回页面</param> /// <returns></returns> public static IActionResult ViewResult <TController, T>(this TController controller, OperateResult <T> operateResult, string redirectViewName = null) where TController : Controller { if (!operateResult.SuccessAndValueNotNull) { return(controller.View(redirectViewName ?? "/Views/Shared/NotFind.cshtml")); } else { return(controller.View(operateResult.Value)); } }
/// <summary> /// 将操作结果转为Json返回类 /// </summary> /// <param name="operateResult">操作结果</param> /// <returns>Json返回类</returns> public static IActionResult ToJsonResult(this OperateResult operateResult) { return(new JsonResult(operateResult.ToAjaxResult())); }
/// <summary> /// 向PLC写入数据,数据格式为原始的字节类型 /// </summary> /// <param name="address">初始地址</param> /// <param name="value">原始的字节数据</param> /// <returns>结果</returns> public override OperateResult Write(string address, byte[] value) { // Console.WriteLine( BasicFramework.SoftBasic.ByteToHexString( value ) ); OperateResult <byte[]> result = new OperateResult <byte[]>( ); //获取指令 var analysis = AnalysisAddress(address); if (!analysis.IsSuccess) { result.CopyErrorFromOther(analysis); return(result); } OperateResult <MelsecMcDataType, byte[]> command; // 预处理指令 if (analysis.Content1.DataType == 0x01) { byte[] buffer = new byte[value.Length]; for (int i = 0; i < buffer.Length; i++) { if (value[i] == 0x00) { buffer[i] = 0x30; } else { buffer[i] = 0x31; } } // 位写入 command = BuildWriteCommand(address, buffer); } else { // 字写入 byte[] buffer = new byte[value.Length * 2]; for (int i = 0; i < value.Length / 2; i++) { BuildBytesFromData(BitConverter.ToUInt16(value, i * 2)).CopyTo(buffer, 4 * i); } command = BuildWriteCommand(address, buffer); } if (!command.IsSuccess) { result.CopyErrorFromOther(command); return(result); } OperateResult <byte[]> read = ReadFromCoreServer(command.Content2); if (read.IsSuccess) { byte[] buffer = new byte[4]; buffer[0] = read.Content[18]; buffer[1] = read.Content[19]; buffer[2] = read.Content[20]; buffer[3] = read.Content[21]; result.ErrorCode = Convert.ToInt16(Encoding.ASCII.GetString(buffer), 16); if (result.ErrorCode == 0) { result.IsSuccess = true; } } else { result.ErrorCode = read.ErrorCode; result.Message = read.Message; } return(result); }
/***************************************************************************** * * 说明: * 下面的三个模块代码指示了如何接收数据,如何发送数据,如何连接网络 * ********************************************************************************/ #region Reveive Content /// <summary> /// 接收固定长度的字节数组 /// </summary> /// <remarks> /// Receive Special Length Bytes /// </remarks> /// <param name="socket">网络通讯的套接字</param> /// <param name="length">准备接收的数据长度</param> /// <returns>包含了字节数据的结果类</returns> protected OperateResult <byte[]> Receive(Socket socket, int length) { if (length == 0) { return(OperateResult.CreateSuccessResult(new byte[0])); } if (UseSynchronousNet) { try { byte[] data = NetSupport.ReadBytesFromSocket(socket, length); return(OperateResult.CreateSuccessResult(data)); } catch (Exception ex) { socket?.Close(); LogNet?.WriteException(ToString(), "Receive", ex); return(new OperateResult <byte[]>(ex.Message)); } } OperateResult <byte[]> result = new OperateResult <byte[]>(); ManualResetEvent receiveDone = null; StateObject state = null; try { receiveDone = new ManualResetEvent(false); state = new StateObject(length); } catch (Exception ex) { return(new OperateResult <byte[]>(ex.Message)); } try { state.WaitDone = receiveDone; state.WorkSocket = socket; // Begin receiving the data from the remote device. socket.BeginReceive(state.Buffer, state.AlreadyDealLength, state.DataLength - state.AlreadyDealLength, SocketFlags.None, new AsyncCallback(ReceiveCallback), state); // 接收数据异步返回的方法 } catch (Exception ex) { // 发生了错误,直接返回 LogNet?.WriteException(ToString(), ex); result.Message = ex.Message; receiveDone.Close(); socket?.Close(); return(result); } // 等待接收完成,或是发生异常 receiveDone.WaitOne(); receiveDone.Close(); // 接收数据失败 if (state.IsError) { socket?.Close(); result.Message = state.ErrerMsg; return(result); } // 远程关闭了连接 if (state.IsClose) { // result.IsSuccess = true; result.Message = StringResources.Language.RemoteClosedConnection; socket?.Close(); return(result); } // 正常接收到数据 result.Content = state.Buffer; result.IsSuccess = true; state.Clear(); state = null; return(result); }
/// <summary> /// 根据类型地址以及需要写入的数据来生成指令头 /// </summary> /// <param name="address">起始地址</param> /// <param name="value">数据值,对于写入位地址来说,应该传入{0x01,0x00,0x01} 通断通这样的数组</param> /// <param name="networkNumber">网络号</param> /// <param name="networkStationNumber">网络站号</param> /// <returns>解析后的指令</returns> public static OperateResult <byte[]> BuildWriteCommand(string address, byte[] value, byte networkNumber = 0, byte networkStationNumber = 0) { OperateResult <MelsecMcDataType, int> analysis = MelsecHelper.McAnalysisAddress(address); if (!analysis.IsSuccess) { return(OperateResult.CreateFailedResult <byte[]>(analysis)); } int length = -1; if (analysis.Content1.DataType == 1) { // 按照位写入的操作,数据需要重新计算 length = value.Length; value = MelsecHelper.TransBoolArrayToByteData(value); } byte[] _PLCCommand = new byte[21 + value.Length]; _PLCCommand[0] = 0x50; // 副标题 _PLCCommand[1] = 0x00; _PLCCommand[2] = networkNumber; // 网络号 _PLCCommand[3] = 0xFF; // PLC编号 _PLCCommand[4] = 0xFF; // 目标模块IO编号 _PLCCommand[5] = 0x03; _PLCCommand[6] = networkStationNumber; // 目标模块站号 _PLCCommand[7] = (byte)((_PLCCommand.Length - 9) % 256); // 请求数据长度 _PLCCommand[8] = (byte)((_PLCCommand.Length - 9) / 256); _PLCCommand[9] = 0x0A; // CPU监视定时器 _PLCCommand[10] = 0x00; _PLCCommand[11] = 0x01; // 批量读取数据命令 _PLCCommand[12] = 0x14; _PLCCommand[13] = analysis.Content1.DataType; // 以点为单位还是字为单位成批读取 _PLCCommand[14] = 0x00; _PLCCommand[15] = BitConverter.GetBytes(analysis.Content2)[0]; // 起始地址的地位 _PLCCommand[16] = BitConverter.GetBytes(analysis.Content2)[1]; _PLCCommand[17] = BitConverter.GetBytes(analysis.Content2)[2]; _PLCCommand[18] = analysis.Content1.DataCode; // 指明写入的数据 // 判断是否进行位操作 if (analysis.Content1.DataType == 1) { if (length > 0) { _PLCCommand[19] = (byte)(length % 256); // 软元件长度的地位 _PLCCommand[20] = (byte)(length / 256); } else { _PLCCommand[19] = (byte)(value.Length * 2 % 256); // 软元件长度的地位 _PLCCommand[20] = (byte)(value.Length * 2 / 256); } } else { _PLCCommand[19] = (byte)(value.Length / 2 % 256); // 软元件长度的地位 _PLCCommand[20] = (byte)(value.Length / 2 / 256); } Array.Copy(value, 0, _PLCCommand, 21, value.Length); return(OperateResult.CreateSuccessResult(_PLCCommand)); }
/// <summary> /// 发送消息给套接字,直到完成的时候返回 /// </summary> /// <param name="socket">网络套接字</param> /// <param name="data">字节数据</param> /// <returns>发送是否成功的结果</returns> protected OperateResult Send(Socket socket, byte[] data) { if (data == null) { return(OperateResult.CreateSuccessResult()); } if (UseSynchronousNet) { try { socket.Send(data); return(OperateResult.CreateSuccessResult()); } catch (Exception ex) { socket?.Close(); LogNet?.WriteException("Send", ex); return(new OperateResult <byte[]>(ex.Message)); } } OperateResult result = new OperateResult(); ManualResetEvent sendDone = null; StateObject state = null; try { sendDone = new ManualResetEvent(false); state = new StateObject(data.Length); } catch (Exception ex) { return(new OperateResult(ex.Message)); } try { state.WaitDone = sendDone; state.WorkSocket = socket; state.Buffer = data; socket.BeginSend(state.Buffer, state.AlreadyDealLength, state.DataLength - state.AlreadyDealLength, SocketFlags.None, new AsyncCallback(SendCallBack), state);// 发送数据异步返回的方法 Console.WriteLine($"发送:{SoftBasic.ByteToHexString(state.Buffer, ' ')}"); } catch (Exception ex) { // 发生了错误,直接返回 LogNet?.WriteException(ToString(), ex); result.Message = ex.Message; socket?.Close(); sendDone.Close(); return(result); } // 等待发送完成 sendDone.WaitOne(); sendDone.Close(); if (state.IsError) { socket.Close(); result.Message = state.ErrerMsg; return(result); } state.Clear(); state = null; result.IsSuccess = true; result.Message = StringResources.Language.SuccessText; return(result); }
/// <summary> /// 测试通讯 /// </summary> /// <param name="args"></param> static void Main(string[] args) { //测试 Modbus_TCPrealize modbus_TC = new Modbus_TCPrealize(new IPEndPoint(IPAddress.Parse("192.168.3.2"), int.Parse("502"))); OperateResult <int> operateResult = modbus_TC.Open(); Console.WriteLine(operateResult.IsSuccess); //发送第一个报文测试 for (int i = 0; i < 90; i++) { Console.WriteLine(modbus_TC.write_multi_Bool(20, 3, 0).Content); Console.WriteLine((modbus_TC.Read_Byet(0).Content.ToString())); //读取设备第一个寄存器 Thread.Sleep(10); Console.WriteLine((modbus_TC.Read_short(0).Content.ToString())); //读取设备第一个寄存器 Thread.Sleep(10); Console.WriteLine((modbus_TC.Read_int(0).Content.ToString())); //读取设备第一个寄存器 Thread.Sleep(10); //Console.WriteLine((modbus_TC.Write_Byte(0,20).Content.ToString()));//写入设备第一个寄存器 //Thread.Sleep(100); Console.WriteLine((modbus_TC.Write_short(0, 5252).Content.ToString())); //写入设备第一个寄存器 //Thread.Sleep(10); Console.WriteLine((modbus_TC.Read_Bool(0).Content.ToString())); //读取设备的线圈 Thread.Sleep(10); var dx = modbus_TC.Read_multi_Bool(0, 17); //读取设备的多个线圈 Console.WriteLine(modbus_TC.write_multi_Bool(20, 3, 15).Content); Thread.Sleep(10); } //反射加载 //Assembly assembly = Assembly.LoadFrom(@"D:\C#项目\Modbus客户端报文产生\Modbus_Class\bin\Debug\Modbus_Class.dll"); //Type type = assembly.GetType("Modbus_Class.Class1");//获取type实例 //var activator = Activator.CreateInstance(type);//实例化类 //var inx = type.GetMethods(BindingFlags.Public|BindingFlags.NonPublic|BindingFlags.Instance); // var dxd= inx[0].Invoke(activator, new object[] { 11 }); Console.WriteLine("测试准备开始"); //实例化套接字 Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); Inex: Console.WriteLine("请输入IP: 默认端口502"); if (!System.Net.IPAddress.TryParse(Console.ReadLine(), out System.Net.IPAddress address)) { Console.WriteLine("输入IP错误请重新输入"); goto Inex; } IPEndPoint iPEndPoint = new IPEndPoint(address, int.Parse("502")); Console.WriteLine("下位机是否准备好????--准备开始链接"); Console.ReadLine(); try { socket.Connect(iPEndPoint); } catch (Exception e) { Console.WriteLine(e.Message); goto Inex; } Modbus_name modbus_RTU = new Modbus_RTU(); Console.WriteLine(BitConverter.ToString(communication(message(modbus_RTU.GenerateH01(function.H01, 1, 0, 10).ToList()), socket))); //H01发送 Thread.Sleep(500); Console.WriteLine(BitConverter.ToString(communication(message(modbus_RTU.GenerateH02(function.H02, 1, 0, 10).ToList()), socket))); //H01发送 Thread.Sleep(500); Console.WriteLine(BitConverter.ToString(communication(message(modbus_RTU.GenerateH03(function.H03, 1, 0, 4).ToList()), socket))); //H03发送 Thread.Sleep(500); Console.WriteLine(BitConverter.ToString(communication(message(modbus_RTU.GenerateH05(function.H05, 1, 0, coil.ON).ToList()), socket))); //H05发送 Thread.Sleep(500); Console.WriteLine(BitConverter.ToString(communication(message(modbus_RTU.GenerateH06(function.H06, 1, 1, 12345).ToList()), socket))); //H06发送 Thread.Sleep(500); //多线圈写入测试 for (int i = 0; i < 50; i++) { Console.WriteLine(BitConverter.ToString(communication(message(modbus_RTU.GenerateH15(function.H15, 1, 0, 3, Convert.ToByte((3 * i))).ToList()), socket)));//H06发送 Thread.Sleep(500); } //多寄存器写入 Console.WriteLine(BitConverter.ToString(communication(message(modbus_RTU.GenerateH16(function.H16, 1, 0, 3, new byte[] { 0x1, 0x2, 0x3, 0x4, 0x5, 0x66 }).ToList()), socket)));//H06发送 Thread.Sleep(500); Console.ReadLine(); }
/// <summary> /// 登录的回调方法 /// </summary> /// <param name="obj">传入的异步对象</param> protected override void ThreadPoolLogin(object obj) { if (obj is Socket socket) { // 注册包 // 0x48 0x73 0x6E 0x00 0x17 0x31 0x32 0x33 0x34 0x35 0x36 0x37 0x38 0x39 0x30 0x31 0x00 0x00 0x00 0x00 0x00 0x00 0xC0 0xA8 0x00 0x01 0x17 0x10 // +------------+ +--+ +--+ +----------------------------------------------------+ +---------------------------+ +-----------------+ +-------+ // + 固定消息头 +备用 长度 DTU码 12345678901 (唯一标识) 登录密码(不受信的排除) Ip:192.168.0.1 端口10000 // +------------+ +--+ +--+ +----------------------------------------------------+ +---------------------------+ +-----------------+ // 返回 // 0x48 0x73 0x6E 0x00 0x01 0x00 // +------------+ +--+ +--+ +--+ // 固定消息头 备用 长度 结果代码 // 结果代码 // 0x00: 登录成功 // 0x01: DTU重复登录 // 0x02: DTU禁止登录 // 0x03: 密码验证失败 OperateResult <AlienMessage> check = ReceiveMessage(socket, 5000, new AlienMessage( )); if (!check.IsSuccess) { return; } if (check.Content.HeadBytes[4] != 0x17 || check.Content.ContentBytes.Length != 0x17) { socket?.Close( ); LogNet?.WriteWarn(ToString( ), "Length Check Failed"); return; } // 密码验证 bool isPasswrodRight = true; for (int i = 0; i < password.Length; i++) { if (check.Content.ContentBytes[11 + i] != password[i]) { isPasswrodRight = false; break; } } string dtu = Encoding.ASCII.GetString(check.Content.ContentBytes, 0, 11).Trim( ); // 密码失败的情况 if (!isPasswrodRight) { OperateResult send = Send(socket, GetResponse(StatusPasswodWrong)); if (send.IsSuccess) { socket?.Close( ); } LogNet?.WriteWarn(ToString( ), "Login Password Wrong, Id:" + dtu); return; } AlienSession session = new AlienSession( ) { DTU = dtu, Socket = socket, }; // 检测是否禁止登录 if (!IsClientPermission(session)) { OperateResult send = Send(socket, GetResponse(StatusLoginForbidden)); if (send.IsSuccess) { socket?.Close( ); } LogNet?.WriteWarn(ToString( ), "Login Forbidden, Id:" + session.DTU); return; } // 检测是否重复登录,不重复的话,也就是意味着登录成功了 if (IsClientOnline(session)) { OperateResult send = Send(socket, GetResponse(StatusLoginRepeat)); if (send.IsSuccess) { socket?.Close( ); } LogNet?.WriteWarn(ToString( ), "Login Repeat, Id:" + session.DTU); return; } else { OperateResult send = Send(socket, GetResponse(StatusOk)); if (!send.IsSuccess) { return; } } // 触发上线消息 OnClientConnected?.Invoke(this, session); } }
/// <summary> /// 解析数据地址 /// </summary> /// <param name="address">数据地址</param> /// <returns>解析值</returns> public static OperateResult <MelsecMcDataType, ushort> McAnalysisAddress(string address) { var result = new OperateResult <MelsecMcDataType, ushort>( ); try { switch (address[0]) { case 'M': case 'm': { result.Content1 = MelsecMcDataType.M; result.Content2 = Convert.ToUInt16(address.Substring(1), MelsecMcDataType.M.FromBase); break; } case 'X': case 'x': { result.Content1 = MelsecMcDataType.X; result.Content2 = Convert.ToUInt16(address.Substring(1), MelsecMcDataType.X.FromBase); break; } case 'Y': case 'y': { result.Content1 = MelsecMcDataType.Y; result.Content2 = Convert.ToUInt16(address.Substring(1), MelsecMcDataType.Y.FromBase); break; } case 'D': case 'd': { result.Content1 = MelsecMcDataType.D; result.Content2 = Convert.ToUInt16(address.Substring(1), MelsecMcDataType.D.FromBase); break; } case 'W': case 'w': { result.Content1 = MelsecMcDataType.W; result.Content2 = Convert.ToUInt16(address.Substring(1), MelsecMcDataType.W.FromBase); break; } case 'L': case 'l': { result.Content1 = MelsecMcDataType.L; result.Content2 = Convert.ToUInt16(address.Substring(1), MelsecMcDataType.L.FromBase); break; } case 'F': case 'f': { result.Content1 = MelsecMcDataType.F; result.Content2 = Convert.ToUInt16(address.Substring(1), MelsecMcDataType.F.FromBase); break; } case 'V': case 'v': { result.Content1 = MelsecMcDataType.V; result.Content2 = Convert.ToUInt16(address.Substring(1), MelsecMcDataType.V.FromBase); break; } case 'B': case 'b': { result.Content1 = MelsecMcDataType.B; result.Content2 = Convert.ToUInt16(address.Substring(1), MelsecMcDataType.B.FromBase); break; } case 'R': case 'r': { result.Content1 = MelsecMcDataType.R; result.Content2 = Convert.ToUInt16(address.Substring(1), MelsecMcDataType.R.FromBase); break; } case 'S': case 's': { result.Content1 = MelsecMcDataType.S; result.Content2 = Convert.ToUInt16(address.Substring(1), MelsecMcDataType.S.FromBase); break; } case 'Z': case 'z': { result.Content1 = MelsecMcDataType.Z; result.Content2 = Convert.ToUInt16(address.Substring(1), MelsecMcDataType.Z.FromBase); break; } case 'T': case 't': { result.Content1 = MelsecMcDataType.T; result.Content2 = Convert.ToUInt16(address.Substring(1), MelsecMcDataType.T.FromBase); break; } case 'C': case 'c': { result.Content1 = MelsecMcDataType.C; result.Content2 = Convert.ToUInt16(address.Substring(1), MelsecMcDataType.C.FromBase); break; } default: throw new Exception(StringResources.NotSupportedDataType); } } catch (Exception ex) { result.Message = ex.Message; return(result); } result.IsSuccess = true; result.Message = StringResources.SuccessText; return(result); }
/// <summary> /// 在将要和服务器进行断开的情况下额外的操作 /// </summary> /// <param name="socket">网络套接字</param> /// <returns></returns> protected virtual OperateResult ExtraOnDisconnect(Socket socket) { return(OperateResult.CreateSuccessResult()); }
/// <summary> /// 解析数据地址,Omron手册第188页 /// </summary> /// <param name="address">数据地址</param> /// <param name="isBit">是否是位地址</param> /// <returns>解析后的结果地址对象</returns> public static OperateResult <OmronFinsDataType, byte[]> AnalysisAddress(string address, bool isBit) { var result = new OperateResult <OmronFinsDataType, byte[]>( ); try { switch (address[0]) { case 'D': case 'd': { // DM区数据 result.Content1 = OmronFinsDataType.DM; break; } case 'C': case 'c': { // CIO区数据 result.Content1 = OmronFinsDataType.CIO; break; } case 'W': case 'w': { // WR区 result.Content1 = OmronFinsDataType.WR; break; } case 'H': case 'h': { // HR区 result.Content1 = OmronFinsDataType.HR; break; } case 'A': case 'a': { // AR区 result.Content1 = OmronFinsDataType.AR; break; } default: throw new Exception(StringResources.Language.NotSupportedDataType); } if (isBit) { // 位操作 string[] splits = address.Substring(1).Split(new char[] { '.' }, StringSplitOptions.RemoveEmptyEntries); ushort addr = ushort.Parse(splits[0]); result.Content2 = new byte[3]; result.Content2[0] = BitConverter.GetBytes(addr)[1]; result.Content2[1] = BitConverter.GetBytes(addr)[0]; if (splits.Length > 1) { result.Content2[2] = byte.Parse(splits[1]); if (result.Content2[2] > 15) { throw new Exception(StringResources.Language.OmronAddressMustBeZeroToFiveteen); } } } else { // 字操作 ushort addr = ushort.Parse(address.Substring(1)); result.Content2 = new byte[3]; result.Content2[0] = BitConverter.GetBytes(addr)[1]; result.Content2[1] = BitConverter.GetBytes(addr)[0]; } } catch (Exception ex) { result.Message = ex.Message; return(result); } result.IsSuccess = true; return(result); }
/// <summary> /// 将指定的OperateResult类型转化 /// </summary> /// <param name="result">原始的类型</param> /// <returns>转化后的类型</returns> protected OperateResult <int> GetInt32ResultFromBytes(OperateResult <byte[]> result) { return(ByteTransformHelper.GetInt32ResultFromBytes(result, byteTransform)); }
private static OperateResult <LSDataType> AnalysisAddressDataType(string address) { LSDataType lSDataType = LSDataType.Continuous; try { if (address[0] == 'D') { if (address[1] == 'W') { lSDataType = LSDataType.Word; } else if (address[1] == 'D') { lSDataType = LSDataType.DWord; } else if (address[1] == 'L') { lSDataType = LSDataType.LWord; } else if (address[1] == 'B') { lSDataType = LSDataType.Continuous; } } else if (address[0] == 'M') { if (address[1] == 'X') { lSDataType = LSDataType.Bit; } else if (address[1] == 'W') { lSDataType = LSDataType.Word; } else if (address[1] == 'D') { lSDataType = LSDataType.DWord; } else if (address[1] == 'L') { lSDataType = LSDataType.LWord; } else if (address[1] == 'B') { lSDataType = LSDataType.Continuous; } } else if (address[0] == 'T') { if (address[1] == 'X') { lSDataType = LSDataType.Bit; } else if (address[1] == 'W') { lSDataType = LSDataType.Word; } else if (address[1] == 'D') { lSDataType = LSDataType.DWord; } else if (address[1] == 'L') { lSDataType = LSDataType.LWord; } else if (address[1] == 'B') { lSDataType = LSDataType.Continuous; } } else if (address[0] == 'C') { if (address[1] == 'X') { lSDataType = LSDataType.Bit; } else if (address[1] == 'W') { lSDataType = LSDataType.Word; } else if (address[1] == 'D') { lSDataType = LSDataType.DWord; } else if (address[1] == 'L') { lSDataType = LSDataType.LWord; } else if (address[1] == 'B') { lSDataType = LSDataType.Continuous; } } } catch (Exception ex) { return(new OperateResult <LSDataType>(ex.Message)); } return(OperateResult.CreateSuccessResult(lSDataType)); }
/// <summary> /// 将指定的OperateResult类型转化 /// </summary> /// <param name="result">原始的类型</param> /// <returns>转化后的类型</returns> protected OperateResult <float> GetSingleResultFromBytes(OperateResult <byte[]> result) { return(ByteTransformHelper.GetSingleResultFromBytes(result, byteTransform)); }
/// <summary> /// 生成一个读取寄存器的指令头 /// </summary> /// <param name="address">地址</param> /// <param name="length">长度</param> /// <returns>携带有命令字节</returns> private OperateResult <byte[]> BuildReadRegisterCommand(ModbusAddress address, ushort length) { // 生成最终rtu指令 byte[] buffer = ModbusInfo.PackCommandToRtu(address.CreateReadRegister(station, length)); return(OperateResult.CreateSuccessResult(buffer)); }
/// <summary> /// 将指定的OperateResult类型转化 /// </summary> /// <param name="result">原始的类型</param> /// <returns>转化后的类型</returns> protected OperateResult <string> GetStringResultFromBytes(OperateResult <byte[]> result) { return(ByteTransformHelper.GetStringResultFromBytes(result, byteTransform)); }
/// <summary> /// 系统的登录方法 /// </summary> /// <param name="obj">接收的socket对象</param> protected override void ThreadPoolLogin(object obj) { Socket socket = obj as Socket; try { OperateResult <byte[]> receive = Receive(socket, 4); if (!receive.IsSuccess) { return; } byte[] ReceiveByte = receive.Content; int Protocol = BitConverter.ToInt32(ReceiveByte, 0); if (Protocol == 0x1001 || Protocol == 0x1002) { // 安装系统和更新系统 if (Protocol == 0x1001) { LogNet?.WriteInfo(ToString(), StringResources.Language.SystemInstallOperater + ((IPEndPoint)socket.RemoteEndPoint).Address.ToString()); } else { LogNet?.WriteInfo(ToString( ), StringResources.Language.SystemUpdateOperater + ((IPEndPoint)socket.RemoteEndPoint).Address.ToString()); } if (Directory.Exists(FileUpdatePath)) { string[] files = Directory.GetFiles(FileUpdatePath); List <string> Files = new List <string>(files); for (int i = Files.Count - 1; i >= 0; i--) { FileInfo finfo = new FileInfo(Files[i]); if (finfo.Length > 200000000) { Files.RemoveAt(i); } if (Protocol == 0x1002) { if (finfo.Name == this.updateExeFileName) { Files.RemoveAt(i); } } } files = Files.ToArray(); socket.BeginReceive(new byte[4], 0, 4, SocketFlags.None, new AsyncCallback(ReceiveCallBack), socket); socket.Send(BitConverter.GetBytes(files.Length)); for (int i = 0; i < files.Length; i++) { // 传送数据包含了本次数据大小,文件数据大小,文件名(带后缀) FileInfo finfo = new FileInfo(files[i]); string fileName = finfo.Name; byte[] ByteName = Encoding.Unicode.GetBytes(fileName); int First = 4 + 4 + ByteName.Length; byte[] FirstSend = new byte[First]; FileStream fs = new FileStream(files[i], FileMode.Open, FileAccess.Read); Array.Copy(BitConverter.GetBytes(First), 0, FirstSend, 0, 4); Array.Copy(BitConverter.GetBytes((int)fs.Length), 0, FirstSend, 4, 4); Array.Copy(ByteName, 0, FirstSend, 8, ByteName.Length); socket.Send(FirstSend); Thread.Sleep(10); byte[] buffer = new byte[4096]; int sended = 0; while (sended < fs.Length) { int count = fs.Read(buffer, 0, 4096); socket.Send(buffer, 0, count, SocketFlags.None); sended += count; } fs.Close(); fs.Dispose(); Thread.Sleep(20); } } } else { // 兼容原先版本的更新,新的验证方式无需理会 socket.Send(BitConverter.GetBytes(10000f)); Thread.Sleep(20); socket?.Close(); } } catch (Exception ex) { Thread.Sleep(20); socket?.Close(); LogNet?.WriteException(ToString( ), StringResources.Language.FileSendClientFailed, ex); } }
private void treeView1_AfterSelect(object sender, TreeViewEventArgs e) { // 点击了数据信息 if (e.Node.ImageKey == "Enum_582") { panel4.Visible = true; panel4.BringToFront( ); textBox4.Text = e.Node.Tag.ToString( ); DateTime start = DateTime.Now; OperateResult <string> read = redisClient.ReadKey(e.Node.Tag.ToString( )); label5.Text = "Time: " + (DateTime.Now - start).TotalMilliseconds.ToString("F0") + " ms"; label4.Text = "Size: " + HslCommunication.BasicFramework.SoftBasic.GetSizeDescription(Encoding.UTF8.GetBytes(read.Content).Length); if (read.IsSuccess) { textBox5.Text = read.Content; lastNodeSelected = e.Node.Tag.ToString( ); selectRowIndex = -1; } else { MessageBox.Show(read.Message); } } else if (e.Node.ImageKey == "brackets_Square_16xMD") { panel5.Visible = true; panel5.BringToFront( ); label7.Text = "list key:"; textBox7.Text = string.Empty; dataGridView1.Rows.Clear( ); if (e.Node.Tag.ToString( ) != lastNodeSelected) { selectRowIndex = -1; } this.Refresh( ); textBox6.Text = e.Node.Tag.ToString( ); DateTime start = DateTime.Now; OperateResult <string[]> read = redisClient.ListRange(e.Node.Tag.ToString( ), 0, -1); if (!read.IsSuccess) { textBox7.Text = read.Message; return; } label12.Text = "Time: " + (DateTime.Now - start).TotalMilliseconds.ToString("F0") + " ms"; int size = 0; for (int i = 0; i < read.Content.Length; i++) { size += Encoding.UTF8.GetBytes(read.Content[i]).Length; } label13.Text = "Size: " + HslCommunication.BasicFramework.SoftBasic.GetSizeDescription(size); label11.Text = "Array: " + read.Content.Length; if (read.IsSuccess) { for (int i = 0; i < read.Content.Length; i++) { dataGridView1.Rows.Add(i, read.Content[i]); } lastNodeSelected = e.Node.Tag.ToString( ); } else { MessageBox.Show(read.Message); } } else if (e.Node.ImageKey == "Method_636") { panel5.Visible = true; panel5.BringToFront( ); label7.Text = "hash key:"; textBox7.Text = string.Empty; dataGridView1.Rows.Clear( ); if (e.Node.Tag.ToString( ) != lastNodeSelected) { selectRowIndex = -1; } this.Refresh( ); textBox6.Text = e.Node.Tag.ToString( ); DateTime start = DateTime.Now; OperateResult <string[]> read = redisClient.ReadHashKeyAll(e.Node.Tag.ToString( )); if (!read.IsSuccess) { textBox7.Text = read.Message; return; } label12.Text = "Time: " + (DateTime.Now - start).TotalMilliseconds.ToString("F0") + " ms"; int size = 0; for (int i = 0; i < read.Content.Length; i++) { size += Encoding.UTF8.GetBytes(read.Content[i]).Length; } label13.Text = "Size: " + HslCommunication.BasicFramework.SoftBasic.GetSizeDescription(size); label11.Text = "Array: " + read.Content.Length; if (read.IsSuccess) { for (int i = 0; i < read.Content.Length / 2; i++) { dataGridView1.Rows.Add(read.Content[2 * i + 0], read.Content[2 * i + 1]); } lastNodeSelected = e.Node.Tag.ToString( ); } else { MessageBox.Show(read.Message); } } else if (e.Node.ImageKey == "Class_489") { } else { MessageBox.Show("Not supported"); } treeViewSelectedNode = e.Node; }
/// <summary> /// 根据类型地址以及需要写入的数据来生成指令头 /// </summary> /// <param name="address">起始地址</param> /// <param name="value"></param> /// <returns></returns> private OperateResult <MelsecMcDataType, byte[]> BuildWriteCommand(string address, byte[] value) { var result = new OperateResult <MelsecMcDataType, byte[]>( ); var analysis = AnalysisAddress(address); if (!analysis.IsSuccess) { result.CopyErrorFromOther(analysis); return(result); } // 默认信息----注意:高低字节交错 byte[] _PLCCommand = new byte[42 + value.Length]; _PLCCommand[0] = 0x35; // 副标题 _PLCCommand[1] = 0x30; _PLCCommand[2] = 0x30; _PLCCommand[3] = 0x30; _PLCCommand[4] = BuildBytesFromData(NetworkNumber)[0]; // 网络号 _PLCCommand[5] = BuildBytesFromData(NetworkNumber)[1]; _PLCCommand[6] = 0x46; // PLC编号 _PLCCommand[7] = 0x46; _PLCCommand[8] = 0x30; // 目标模块IO编号 _PLCCommand[9] = 0x33; _PLCCommand[10] = 0x46; _PLCCommand[11] = 0x46; _PLCCommand[12] = BuildBytesFromData(NetworkStationNumber)[0]; // 目标模块站号 _PLCCommand[13] = BuildBytesFromData(NetworkStationNumber)[1]; _PLCCommand[14] = BuildBytesFromData((ushort)(_PLCCommand.Length - 18))[0]; // 请求数据长度 _PLCCommand[15] = BuildBytesFromData((ushort)(_PLCCommand.Length - 18))[1]; _PLCCommand[16] = BuildBytesFromData((ushort)(_PLCCommand.Length - 18))[2]; _PLCCommand[17] = BuildBytesFromData((ushort)(_PLCCommand.Length - 18))[3]; _PLCCommand[18] = 0x30; // CPU监视定时器 _PLCCommand[19] = 0x30; _PLCCommand[20] = 0x31; _PLCCommand[21] = 0x30; _PLCCommand[22] = 0x31; // 批量写入的命令 _PLCCommand[23] = 0x34; _PLCCommand[24] = 0x30; _PLCCommand[25] = 0x31; _PLCCommand[26] = 0x30; // 子命令 _PLCCommand[27] = 0x30; _PLCCommand[28] = 0x30; _PLCCommand[29] = analysis.Content1.DataType == 0 ? (byte)0x30 : (byte)0x31; _PLCCommand[30] = Encoding.ASCII.GetBytes(analysis.Content1.AsciiCode)[0]; // 软元件类型 _PLCCommand[31] = Encoding.ASCII.GetBytes(analysis.Content1.AsciiCode)[1]; _PLCCommand[32] = BuildBytesFromAddress(analysis.Content2, analysis.Content1)[0]; // 起始地址的地位 _PLCCommand[33] = BuildBytesFromAddress(analysis.Content2, analysis.Content1)[1]; _PLCCommand[34] = BuildBytesFromAddress(analysis.Content2, analysis.Content1)[2]; _PLCCommand[35] = BuildBytesFromAddress(analysis.Content2, analysis.Content1)[3]; _PLCCommand[36] = BuildBytesFromAddress(analysis.Content2, analysis.Content1)[4]; _PLCCommand[37] = BuildBytesFromAddress(analysis.Content2, analysis.Content1)[5]; // 判断是否进行位操作 if (analysis.Content1.DataType == 1) { _PLCCommand[38] = BuildBytesFromData((ushort)value.Length)[0]; // 软元件点数 _PLCCommand[39] = BuildBytesFromData((ushort)value.Length)[1]; _PLCCommand[40] = BuildBytesFromData((ushort)value.Length)[2]; _PLCCommand[41] = BuildBytesFromData((ushort)value.Length)[3]; } else { _PLCCommand[38] = BuildBytesFromData((ushort)(value.Length / 4))[0]; // 软元件点数 _PLCCommand[39] = BuildBytesFromData((ushort)(value.Length / 4))[1]; _PLCCommand[40] = BuildBytesFromData((ushort)(value.Length / 4))[2]; _PLCCommand[41] = BuildBytesFromData((ushort)(value.Length / 4))[3]; } Array.Copy(value, 0, _PLCCommand, 42, value.Length); result.Content1 = analysis.Content1; result.Content2 = _PLCCommand; result.IsSuccess = true; // Console.WriteLine( value.Length ); // Console.WriteLine( Encoding.ASCII.GetString(_PLCCommand )); return(result); }