From fc5dc3545dd5222da05535fc3e1ba21e12432394 Mon Sep 17 00:00:00 2001 From: BennyZhao Date: Tue, 15 Oct 2019 11:05:17 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E8=AF=B7=E6=B1=82=E6=8A=A5?= =?UTF-8?q?=E6=96=87=20=E5=92=8C=20=E5=93=8D=E5=BA=94=E6=8A=A5=E6=96=87?= =?UTF-8?q?=E7=9A=84=E7=9B=91=E6=8E=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- IoTClient.Demo/ModBusTcpForm.Designer.cs | 19 +++++- IoTClient.Demo/ModBusTcpForm.cs | 14 ++++- .../Core/Clients/ModBus/ModBusTcpClient.cs | 48 ++++++++++---- IoTClient/Core/Result.cs | 63 ++++++++++--------- IoTServer/Servers/ModBus/ModBusTcpServer.cs | 3 +- README.md | 3 + 6 files changed, 100 insertions(+), 50 deletions(-) diff --git a/IoTClient.Demo/ModBusTcpForm.Designer.cs b/IoTClient.Demo/ModBusTcpForm.Designer.cs index e29b73d..e59b628 100644 --- a/IoTClient.Demo/ModBusTcpForm.Designer.cs +++ b/IoTClient.Demo/ModBusTcpForm.Designer.cs @@ -57,6 +57,7 @@ this.groupBox1 = new System.Windows.Forms.GroupBox(); this.groupBox2 = new System.Windows.Forms.GroupBox(); this.groupBox3 = new System.Windows.Forms.GroupBox(); + this.checkBox1 = new System.Windows.Forms.CheckBox(); this.groupBox1.SuspendLayout(); this.groupBox2.SuspendLayout(); this.groupBox3.SuspendLayout(); @@ -156,7 +157,7 @@ // // txt_value // - this.txt_value.Location = new System.Drawing.Point(447, 16); + this.txt_value.Location = new System.Drawing.Point(359, 15); this.txt_value.Name = "txt_value"; this.txt_value.Size = new System.Drawing.Size(100, 21); this.txt_value.TabIndex = 12; @@ -164,7 +165,7 @@ // label4 // this.label4.AutoSize = true; - this.label4.Location = new System.Drawing.Point(400, 22); + this.label4.Location = new System.Drawing.Point(312, 21); this.label4.Name = "label4"; this.label4.Size = new System.Drawing.Size(29, 12); this.label4.TabIndex = 11; @@ -172,7 +173,7 @@ // // button4 // - this.button4.Location = new System.Drawing.Point(567, 15); + this.button4.Location = new System.Drawing.Point(479, 14); this.button4.Name = "button4"; this.button4.Size = new System.Drawing.Size(75, 23); this.button4.TabIndex = 10; @@ -321,6 +322,7 @@ // // groupBox3 // + this.groupBox3.Controls.Add(this.checkBox1); this.groupBox3.Controls.Add(this.button3); this.groupBox3.Controls.Add(this.label3); this.groupBox3.Controls.Add(this.txt_address); @@ -333,6 +335,16 @@ this.groupBox3.TabIndex = 26; this.groupBox3.TabStop = false; // + // checkBox1 + // + this.checkBox1.AutoSize = true; + this.checkBox1.Location = new System.Drawing.Point(575, 17); + this.checkBox1.Name = "checkBox1"; + this.checkBox1.Size = new System.Drawing.Size(72, 16); + this.checkBox1.TabIndex = 13; + this.checkBox1.Text = "显示报文"; + this.checkBox1.UseVisualStyleBackColor = true; + // // ModBusTcpForm // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); @@ -386,6 +398,7 @@ private System.Windows.Forms.GroupBox groupBox1; private System.Windows.Forms.GroupBox groupBox2; private System.Windows.Forms.GroupBox groupBox3; + private System.Windows.Forms.CheckBox checkBox1; } } diff --git a/IoTClient.Demo/ModBusTcpForm.cs b/IoTClient.Demo/ModBusTcpForm.cs index 81a7397..93ff45b 100644 --- a/IoTClient.Demo/ModBusTcpForm.cs +++ b/IoTClient.Demo/ModBusTcpForm.cs @@ -113,6 +113,11 @@ namespace IoTClient.Demo txt_content.AppendText($"[{DateTime.Now.ToLongTimeString()}][读取 {txt_address.Text?.Trim()} 成功]:{result.Value}\r\n"); else txt_content.AppendText($"[{DateTime.Now.ToLongTimeString()}][读取 {txt_address.Text?.Trim()} 失败]:{result.Err}\r\n"); + if (checkBox1.Checked) + { + txt_content.AppendText($"[请求报文]{result.Requst}\r\n"); + txt_content.AppendText($"[响应报文]{result.Response}\r\n"); + } } private void button4_Click(object sender, EventArgs e) @@ -143,7 +148,7 @@ namespace IoTClient.Demo MessageBox.Show("请输入 True 或 False"); return; } - } + } result = client.Write(txt_address.Text, coil, stationNumber); } else if (rd_short.Checked) @@ -181,9 +186,14 @@ namespace IoTClient.Demo if (result.IsSucceed) - txt_content.AppendText($"[{DateTime.Now.ToLongTimeString()}][写入 {txt_address.Text?.Trim()} 成功]:OK\r\n"); + txt_content.AppendText($"[{DateTime.Now.ToLongTimeString()}][写入 {txt_address.Text?.Trim()} 成功]:{txt_value.Text?.Trim()} OK\r\n"); else txt_content.AppendText($"[{DateTime.Now.ToLongTimeString()}][写入 {txt_address.Text?.Trim()} 失败]:{result.Err}\r\n"); + if (checkBox1.Checked) + { + txt_content.AppendText($"[请求报文]{result.Requst}\r\n"); + txt_content.AppendText($"[响应报文]{result.Response}\r\n"); + } } private void ModBusTcp_Load(object sender, EventArgs e) diff --git a/IoTClient/Core/Clients/ModBus/ModBusTcpClient.cs b/IoTClient/Core/Clients/ModBus/ModBusTcpClient.cs index 9191cc7..7033cbe 100644 --- a/IoTClient/Core/Clients/ModBus/ModBusTcpClient.cs +++ b/IoTClient/Core/Clients/ModBus/ModBusTcpClient.cs @@ -69,42 +69,45 @@ namespace IoTClient.Clients.ModBus public Result Read(string address, byte stationNumber = 1, byte functionCode = 3, ushort readLength = 1) { ConnectManager(); - var readResult = new Result(); + var result = new Result(); try { //1 获取命令(组装报文) byte[] command = GetReadCommand(address, stationNumber, functionCode, readLength); + result.Requst = string.Join(" ", command.Select(t => t.ToString("X2"))); //2 发送命令 socket.Send(command); //3 获取响应报文 var headBytes = SocketRead(socket, 8); int length = headBytes[4] * 256 + headBytes[5] - 2; - var result = SocketRead(socket, length); + var dataBytes = SocketRead(socket, length); - byte[] resultBuffer = new byte[result.Length - 1]; - Array.Copy(result, 1, resultBuffer, 0, resultBuffer.Length); + byte[] resultBuffer = new byte[dataBytes.Length - 1]; + Array.Copy(dataBytes, 1, resultBuffer, 0, resultBuffer.Length); + + result.Response = string.Join(" ", headBytes.Concat(dataBytes).Select(t => t.ToString("X2"))); //4 获取响应报文数据(字节数组形式) - readResult.Value = resultBuffer.Reverse().ToArray(); + result.Value = resultBuffer.Reverse().ToArray(); } catch (SocketException ex) { - readResult.IsSucceed = false; + result.IsSucceed = false; if (ex.SocketErrorCode == SocketError.TimedOut) { - readResult.Err = "连接超时"; - readResult.ErrList.Add("连接超时"); + result.Err = "连接超时"; + result.ErrList.Add("连接超时"); } else { - readResult.Err = ex.Message; - readResult.ErrList.Add(ex.Message); + result.Err = ex.Message; + result.ErrList.Add(ex.Message); } } finally { if (isAutoOpen.Value) Dispose(); } - return readResult; + return result; } /// @@ -122,6 +125,8 @@ namespace IoTClient.Clients.ModBus IsSucceed = readResut.IsSucceed, Err = readResut.Err, ErrList = readResut.ErrList, + Requst = readResut.Requst, + Response = readResut.Response, }; if (result.IsSucceed) result.Value = BitConverter.ToInt16(readResut.Value, 0); @@ -143,6 +148,8 @@ namespace IoTClient.Clients.ModBus IsSucceed = readResut.IsSucceed, Err = readResut.Err, ErrList = readResut.ErrList, + Requst = readResut.Requst, + Response = readResut.Response, }; if (result.IsSucceed) result.Value = BitConverter.ToUInt16(readResut.Value, 0); @@ -164,6 +171,8 @@ namespace IoTClient.Clients.ModBus IsSucceed = readResut.IsSucceed, Err = readResut.Err, ErrList = readResut.ErrList, + Requst = readResut.Requst, + Response = readResut.Response, }; if (result.IsSucceed) result.Value = BitConverter.ToInt32(readResut.Value, 0); @@ -185,6 +194,8 @@ namespace IoTClient.Clients.ModBus IsSucceed = readResut.IsSucceed, Err = readResut.Err, ErrList = readResut.ErrList, + Requst = readResut.Requst, + Response = readResut.Response, }; if (result.IsSucceed) result.Value = BitConverter.ToUInt32(readResut.Value, 0); @@ -206,6 +217,8 @@ namespace IoTClient.Clients.ModBus IsSucceed = readResut.IsSucceed, Err = readResut.Err, ErrList = readResut.ErrList, + Requst = readResut.Requst, + Response = readResut.Response, }; if (result.IsSucceed) result.Value = BitConverter.ToInt64(readResut.Value, 0); @@ -227,6 +240,8 @@ namespace IoTClient.Clients.ModBus IsSucceed = readResut.IsSucceed, Err = readResut.Err, ErrList = readResut.ErrList, + Requst = readResut.Requst, + Response = readResut.Response, }; if (result.IsSucceed) result.Value = BitConverter.ToUInt64(readResut.Value, 0); @@ -248,6 +263,8 @@ namespace IoTClient.Clients.ModBus IsSucceed = readResut.IsSucceed, Err = readResut.Err, ErrList = readResut.ErrList, + Requst = readResut.Requst, + Response = readResut.Response, }; if (result.IsSucceed) result.Value = BitConverter.ToSingle(readResut.Value, 0); @@ -269,6 +286,8 @@ namespace IoTClient.Clients.ModBus IsSucceed = readResut.IsSucceed, Err = readResut.Err, ErrList = readResut.ErrList, + Requst = readResut.Requst, + Response = readResut.Response, }; if (result.IsSucceed) result.Value = BitConverter.ToDouble(readResut.Value, 0); @@ -290,6 +309,8 @@ namespace IoTClient.Clients.ModBus IsSucceed = readResut.IsSucceed, Err = readResut.Err, ErrList = readResut.ErrList, + Requst = readResut.Requst, + Response = readResut.Response, }; if (result.IsSucceed) result.Value = BitConverter.ToBoolean(readResut.Value, 0); @@ -357,11 +378,12 @@ namespace IoTClient.Clients.ModBus { var command = GetWriteCommand(address, values, stationNumber, functionCode); socket.Send(command); - + result.Requst = string.Join(" ", command.Select(t => t.ToString("X2"))); //获取响应报文 var headBytes = SocketRead(socket, 8); int length = headBytes[4] * 256 + headBytes[5] - 2; - SocketRead(socket, length); + var dataBytes = SocketRead(socket, length); + result.Response = string.Join(" ", headBytes.Concat(dataBytes).Select(t => t.ToString("X2"))); } catch (SocketException ex) { diff --git a/IoTClient/Core/Result.cs b/IoTClient/Core/Result.cs index f0f14a1..fa19207 100644 --- a/IoTClient/Core/Result.cs +++ b/IoTClient/Core/Result.cs @@ -5,37 +5,6 @@ namespace IoTClient.Core /// /// 请求结果 /// - public class Result - { - public Result() - { - } - - public Result(T data) - { - Value = data; - } - /// - /// 是否成功 - /// - public bool IsSucceed { get; set; } = true; - - /// - /// 异常消息 - /// - public string Err { get; set; } - - /// - /// 异常集合 - /// - public List ErrList { get; set; } = new List(); - - /// - /// 数据结果 - /// - public T Value { get; set; } - } - public class Result { public Result() @@ -56,5 +25,37 @@ namespace IoTClient.Core /// 异常集合 /// public List ErrList { get; set; } = new List(); + + /// + /// 请求报文 + /// + public string Requst { get; set; } + + /// + /// 响应报文 + /// + public string Response { get; set; } } + + /// + /// 请求结果 + /// + public class Result : Result + { + public Result() + { + } + + public Result(T data) + { + Value = data; + } + + /// + /// 数据结果 + /// + public T Value { get; set; } + } + + } diff --git a/IoTServer/Servers/ModBus/ModBusTcpServer.cs b/IoTServer/Servers/ModBus/ModBusTcpServer.cs index b202288..af84205 100644 --- a/IoTServer/Servers/ModBus/ModBusTcpServer.cs +++ b/IoTServer/Servers/ModBus/ModBusTcpServer.cs @@ -143,7 +143,8 @@ namespace IoTServer.Servers.ModBus catch (SocketException ex) { //todo - if (ex.SocketErrorCode != SocketError.ConnectionRefused) + if (ex.SocketErrorCode != SocketError.ConnectionRefused || + ex.SocketErrorCode != SocketError.ConnectionReset) throw ex; } } diff --git a/README.md b/README.md index 2b0b9c9..e32cf10 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,5 @@ # IoTClient 这是一个物联网设备通讯协议实现客户端,将包括主流PLC通信读取、modbus协议、Bacnet协议等常用工业通讯协议。本组件终身开源免费,采用最宽松MIT协议,您也可以随意修改和商业使用(商业使用请做好评估和测试)。 + +# Demo效果图 +![ModBusTcpForm](https://user-images.githubusercontent.com/5820324/66796754-3e5e7f00-ef3b-11e9-8fd3-73648b96bc09.png) \ No newline at end of file