diff --git a/IoTClient.Tests/ModBus/ModBusTcpClient_tests.cs b/IoTClient.Tests/ModBus/ModBusTcpClient_tests.cs
index 99cea14..962be3a 100644
--- a/IoTClient.Tests/ModBus/ModBusTcpClient_tests.cs
+++ b/IoTClient.Tests/ModBus/ModBusTcpClient_tests.cs
@@ -1,5 +1,4 @@
using IoTClient.Clients.ModBus;
-using IoTServer.Common;
using System.Net;
using System.Threading.Tasks;
using Xunit;
diff --git a/IoTClient.Tool/Controls/ModBusRtuControl.Designer.cs b/IoTClient.Tool/Controls/ModBusRtuControl.Designer.cs
index 754a595..5f1b3ec 100644
--- a/IoTClient.Tool/Controls/ModBusRtuControl.Designer.cs
+++ b/IoTClient.Tool/Controls/ModBusRtuControl.Designer.cs
@@ -40,6 +40,7 @@
this.label4 = new System.Windows.Forms.Label();
this.button6 = new System.Windows.Forms.Button();
this.groupBox1 = new System.Windows.Forms.GroupBox();
+ this.rd_discrete = new System.Windows.Forms.RadioButton();
this.rd_float = new System.Windows.Forms.RadioButton();
this.rd_double = new System.Windows.Forms.RadioButton();
this.rd_short = new System.Windows.Forms.RadioButton();
@@ -58,13 +59,15 @@
this.txt_dataBit = new System.Windows.Forms.TextBox();
this.cb_portNameSend = new System.Windows.Forms.ComboBox();
this.but_close = new System.Windows.Forms.Button();
- this.button2 = new System.Windows.Forms.Button();
- this.button1 = new System.Windows.Forms.Button();
+ this.but_server_close = new System.Windows.Forms.Button();
+ this.but_server_open = new System.Windows.Forms.Button();
this.but_open = new System.Windows.Forms.Button();
this.label5 = new System.Windows.Forms.Label();
this.txt_stationNumber = new System.Windows.Forms.TextBox();
this.label1 = new System.Windows.Forms.Label();
this.label2 = new System.Windows.Forms.Label();
+ this.cb_portNameSend_server = new System.Windows.Forms.ComboBox();
+ this.label8 = new System.Windows.Forms.Label();
this.groupBox3.SuspendLayout();
this.groupBox1.SuspendLayout();
this.groupBox2.SuspendLayout();
@@ -104,7 +107,7 @@
this.but_write.TabIndex = 10;
this.but_write.Text = "写入";
this.but_write.UseVisualStyleBackColor = true;
- this.but_write.Click += new System.EventHandler(this.butWrite_Click);
+ this.but_write.Click += new System.EventHandler(this.but_write_Click);
//
// txt_value
//
@@ -158,6 +161,7 @@
//
// groupBox1
//
+ this.groupBox1.Controls.Add(this.rd_discrete);
this.groupBox1.Controls.Add(this.button6);
this.groupBox1.Controls.Add(this.rd_float);
this.groupBox1.Controls.Add(this.rd_double);
@@ -174,10 +178,20 @@
this.groupBox1.TabIndex = 32;
this.groupBox1.TabStop = false;
//
+ // rd_discrete
+ //
+ this.rd_discrete.AutoSize = true;
+ this.rd_discrete.Location = new System.Drawing.Point(64, 23);
+ this.rd_discrete.Name = "rd_discrete";
+ this.rd_discrete.Size = new System.Drawing.Size(47, 16);
+ this.rd_discrete.TabIndex = 24;
+ this.rd_discrete.Text = "离散";
+ this.rd_discrete.UseVisualStyleBackColor = true;
+ //
// rd_float
//
this.rd_float.AutoSize = true;
- this.rd_float.Location = new System.Drawing.Point(436, 23);
+ this.rd_float.Location = new System.Drawing.Point(486, 23);
this.rd_float.Name = "rd_float";
this.rd_float.Size = new System.Drawing.Size(53, 16);
this.rd_float.TabIndex = 22;
@@ -187,7 +201,7 @@
// rd_double
//
this.rd_double.AutoSize = true;
- this.rd_double.Location = new System.Drawing.Point(495, 23);
+ this.rd_double.Location = new System.Drawing.Point(545, 23);
this.rd_double.Name = "rd_double";
this.rd_double.Size = new System.Drawing.Size(59, 16);
this.rd_double.TabIndex = 23;
@@ -198,7 +212,7 @@
//
this.rd_short.AutoSize = true;
this.rd_short.Checked = true;
- this.rd_short.Location = new System.Drawing.Point(70, 23);
+ this.rd_short.Location = new System.Drawing.Point(120, 23);
this.rd_short.Name = "rd_short";
this.rd_short.Size = new System.Drawing.Size(53, 16);
this.rd_short.TabIndex = 6;
@@ -219,7 +233,7 @@
// rd_ulong
//
this.rd_ulong.AutoSize = true;
- this.rd_ulong.Location = new System.Drawing.Point(374, 23);
+ this.rd_ulong.Location = new System.Drawing.Point(424, 23);
this.rd_ulong.Name = "rd_ulong";
this.rd_ulong.Size = new System.Drawing.Size(53, 16);
this.rd_ulong.TabIndex = 21;
@@ -229,7 +243,7 @@
// rd_ushort
//
this.rd_ushort.AutoSize = true;
- this.rd_ushort.Location = new System.Drawing.Point(129, 23);
+ this.rd_ushort.Location = new System.Drawing.Point(179, 23);
this.rd_ushort.Name = "rd_ushort";
this.rd_ushort.Size = new System.Drawing.Size(59, 16);
this.rd_ushort.TabIndex = 17;
@@ -239,7 +253,7 @@
// rd_long
//
this.rd_long.AutoSize = true;
- this.rd_long.Location = new System.Drawing.Point(315, 23);
+ this.rd_long.Location = new System.Drawing.Point(365, 23);
this.rd_long.Name = "rd_long";
this.rd_long.Size = new System.Drawing.Size(47, 16);
this.rd_long.TabIndex = 20;
@@ -249,7 +263,7 @@
// rd_int
//
this.rd_int.AutoSize = true;
- this.rd_int.Location = new System.Drawing.Point(194, 23);
+ this.rd_int.Location = new System.Drawing.Point(244, 23);
this.rd_int.Name = "rd_int";
this.rd_int.Size = new System.Drawing.Size(41, 16);
this.rd_int.TabIndex = 18;
@@ -259,7 +273,7 @@
// rd_uint
//
this.rd_uint.AutoSize = true;
- this.rd_uint.Location = new System.Drawing.Point(253, 23);
+ this.rd_uint.Location = new System.Drawing.Point(303, 23);
this.rd_uint.Name = "rd_uint";
this.rd_uint.Size = new System.Drawing.Size(47, 16);
this.rd_uint.TabIndex = 19;
@@ -268,7 +282,7 @@
//
// txt_baudRate
//
- this.txt_baudRate.Location = new System.Drawing.Point(131, 19);
+ this.txt_baudRate.Location = new System.Drawing.Point(127, 19);
this.txt_baudRate.Name = "txt_baudRate";
this.txt_baudRate.Size = new System.Drawing.Size(42, 21);
this.txt_baudRate.TabIndex = 5;
@@ -286,14 +300,16 @@
//
// groupBox2
//
+ this.groupBox2.Controls.Add(this.cb_portNameSend_server);
+ this.groupBox2.Controls.Add(this.label8);
this.groupBox2.Controls.Add(this.label7);
this.groupBox2.Controls.Add(this.txt_stopBit);
this.groupBox2.Controls.Add(this.label6);
this.groupBox2.Controls.Add(this.txt_dataBit);
this.groupBox2.Controls.Add(this.cb_portNameSend);
this.groupBox2.Controls.Add(this.but_close);
- this.groupBox2.Controls.Add(this.button2);
- this.groupBox2.Controls.Add(this.button1);
+ this.groupBox2.Controls.Add(this.but_server_close);
+ this.groupBox2.Controls.Add(this.but_server_open);
this.groupBox2.Controls.Add(this.but_open);
this.groupBox2.Controls.Add(this.label5);
this.groupBox2.Controls.Add(this.txt_stationNumber);
@@ -309,7 +325,7 @@
// label7
//
this.label7.AutoSize = true;
- this.label7.Location = new System.Drawing.Point(253, 23);
+ this.label7.Location = new System.Drawing.Point(250, 23);
this.label7.Name = "label7";
this.label7.Size = new System.Drawing.Size(41, 12);
this.label7.TabIndex = 21;
@@ -317,7 +333,7 @@
//
// txt_stopBit
//
- this.txt_stopBit.Location = new System.Drawing.Point(296, 19);
+ this.txt_stopBit.Location = new System.Drawing.Point(292, 19);
this.txt_stopBit.Name = "txt_stopBit";
this.txt_stopBit.Size = new System.Drawing.Size(24, 21);
this.txt_stopBit.TabIndex = 22;
@@ -326,7 +342,7 @@
// label6
//
this.label6.AutoSize = true;
- this.label6.Location = new System.Drawing.Point(178, 24);
+ this.label6.Location = new System.Drawing.Point(176, 24);
this.label6.Name = "label6";
this.label6.Size = new System.Drawing.Size(41, 12);
this.label6.TabIndex = 19;
@@ -334,7 +350,7 @@
//
// txt_dataBit
//
- this.txt_dataBit.Location = new System.Drawing.Point(219, 20);
+ this.txt_dataBit.Location = new System.Drawing.Point(217, 20);
this.txt_dataBit.Name = "txt_dataBit";
this.txt_dataBit.Size = new System.Drawing.Size(24, 21);
this.txt_dataBit.TabIndex = 20;
@@ -343,14 +359,14 @@
// cb_portNameSend
//
this.cb_portNameSend.FormattingEnabled = true;
- this.cb_portNameSend.Location = new System.Drawing.Point(35, 20);
+ this.cb_portNameSend.Location = new System.Drawing.Point(34, 20);
this.cb_portNameSend.Name = "cb_portNameSend";
this.cb_portNameSend.Size = new System.Drawing.Size(47, 20);
this.cb_portNameSend.TabIndex = 18;
//
// but_close
//
- this.but_close.Location = new System.Drawing.Point(419, 19);
+ this.but_close.Location = new System.Drawing.Point(466, 19);
this.but_close.Name = "but_close";
this.but_close.Size = new System.Drawing.Size(75, 23);
this.but_close.TabIndex = 17;
@@ -360,25 +376,27 @@
//
// button2
//
- this.button2.Location = new System.Drawing.Point(768, 19);
- this.button2.Name = "button2";
- this.button2.Size = new System.Drawing.Size(75, 23);
- this.button2.TabIndex = 16;
- this.button2.Text = "关闭服务";
- this.button2.UseVisualStyleBackColor = true;
+ this.but_server_close.Location = new System.Drawing.Point(768, 19);
+ this.but_server_close.Name = "button2";
+ this.but_server_close.Size = new System.Drawing.Size(75, 23);
+ this.but_server_close.TabIndex = 16;
+ this.but_server_close.Text = "关闭服务";
+ this.but_server_close.UseVisualStyleBackColor = true;
+ this.but_server_close.Click += new System.EventHandler(this.but_close_server_Click);
//
// button1
//
- this.button1.Location = new System.Drawing.Point(663, 19);
- this.button1.Name = "button1";
- this.button1.Size = new System.Drawing.Size(99, 23);
- this.button1.TabIndex = 0;
- this.button1.Text = "本地模拟服务";
- this.button1.UseVisualStyleBackColor = true;
+ this.but_server_open.Location = new System.Drawing.Point(665, 19);
+ this.but_server_open.Name = "button1";
+ this.but_server_open.Size = new System.Drawing.Size(99, 23);
+ this.but_server_open.TabIndex = 0;
+ this.but_server_open.Text = "本地模拟服务";
+ this.but_server_open.UseVisualStyleBackColor = true;
+ this.but_server_open.Click += new System.EventHandler(this.but_open_server_Click);
//
// but_open
//
- this.but_open.Location = new System.Drawing.Point(338, 18);
+ this.but_open.Location = new System.Drawing.Point(385, 18);
this.but_open.Name = "but_open";
this.but_open.Size = new System.Drawing.Size(75, 23);
this.but_open.TabIndex = 1;
@@ -389,7 +407,7 @@
// label5
//
this.label5.AutoSize = true;
- this.label5.Location = new System.Drawing.Point(528, 23);
+ this.label5.Location = new System.Drawing.Point(324, 23);
this.label5.Name = "label5";
this.label5.Size = new System.Drawing.Size(29, 12);
this.label5.TabIndex = 15;
@@ -397,9 +415,9 @@
//
// txt_stationNumber
//
- this.txt_stationNumber.Location = new System.Drawing.Point(563, 19);
+ this.txt_stationNumber.Location = new System.Drawing.Point(353, 19);
this.txt_stationNumber.Name = "txt_stationNumber";
- this.txt_stationNumber.Size = new System.Drawing.Size(35, 21);
+ this.txt_stationNumber.Size = new System.Drawing.Size(25, 21);
this.txt_stationNumber.TabIndex = 14;
this.txt_stationNumber.Text = "1";
//
@@ -415,12 +433,29 @@
// label2
//
this.label2.AutoSize = true;
- this.label2.Location = new System.Drawing.Point(90, 24);
+ this.label2.Location = new System.Drawing.Point(86, 24);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(41, 12);
this.label2.TabIndex = 4;
this.label2.Text = "波特率";
//
+ // cb_portNameSend_server
+ //
+ this.cb_portNameSend_server.FormattingEnabled = true;
+ this.cb_portNameSend_server.Location = new System.Drawing.Point(614, 21);
+ this.cb_portNameSend_server.Name = "cb_portNameSend_server";
+ this.cb_portNameSend_server.Size = new System.Drawing.Size(47, 20);
+ this.cb_portNameSend_server.TabIndex = 24;
+ //
+ // label8
+ //
+ this.label8.AutoSize = true;
+ this.label8.Location = new System.Drawing.Point(587, 25);
+ this.label8.Name = "label8";
+ this.label8.Size = new System.Drawing.Size(29, 12);
+ this.label8.TabIndex = 23;
+ this.label8.Text = "端口";
+ //
// ModBusRtuControl
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
@@ -468,8 +503,8 @@
private System.Windows.Forms.TextBox txt_content;
private System.Windows.Forms.GroupBox groupBox2;
private System.Windows.Forms.Button but_close;
- private System.Windows.Forms.Button button2;
- private System.Windows.Forms.Button button1;
+ private System.Windows.Forms.Button but_server_close;
+ private System.Windows.Forms.Button but_server_open;
private System.Windows.Forms.Button but_open;
private System.Windows.Forms.Label label5;
private System.Windows.Forms.TextBox txt_stationNumber;
@@ -480,5 +515,8 @@
private System.Windows.Forms.TextBox txt_stopBit;
private System.Windows.Forms.Label label6;
private System.Windows.Forms.TextBox txt_dataBit;
+ private System.Windows.Forms.RadioButton rd_discrete;
+ private System.Windows.Forms.ComboBox cb_portNameSend_server;
+ private System.Windows.Forms.Label label8;
}
}
diff --git a/IoTClient.Tool/Controls/ModBusRtuControl.cs b/IoTClient.Tool/Controls/ModBusRtuControl.cs
index 489d302..1552358 100644
--- a/IoTClient.Tool/Controls/ModBusRtuControl.cs
+++ b/IoTClient.Tool/Controls/ModBusRtuControl.cs
@@ -1,20 +1,16 @@
using IoTClient.Clients.ModBus;
+using IoTServer.Servers.ModBus;
using System;
using System.Drawing;
using System.IO.Ports;
-using System.Text;
using System.Windows.Forms;
namespace IoTClient.Tool.Controls
{
public partial class ModBusRtuControl : UserControl
{
- ///
- /// 串行端口对象
- ///
- //private SerialPort serialPort;
- private ModBusRtuClient modBusRtuClient;
-
+ private ModBusRtuClient client;
+ private ModBusRtuServer server;
public ModBusRtuControl()
{
InitializeComponent();
@@ -29,10 +25,11 @@ namespace IoTClient.Tool.Controls
txt_content.Location = new Point(13, 160);
but_read.Enabled = false;
but_write.Enabled = false;
- button2.Enabled = false;
+ but_server_close.Enabled = false;
but_close.Enabled = false;
UpdatePortNames();
cb_portNameSend.DropDownStyle = ComboBoxStyle.DropDownList;
+ cb_portNameSend_server.DropDownStyle = ComboBoxStyle.DropDownList;
}
///
@@ -40,9 +37,15 @@ namespace IoTClient.Tool.Controls
///
public void UpdatePortNames()
{
- cb_portNameSend.DataSource = SerialPort.GetPortNames();
+ cb_portNameSend.DataSource = ModBusRtuClient.GetPortNames();
+ cb_portNameSend_server.DataSource = ModBusRtuClient.GetPortNames();
}
+ ///
+ /// 打开连接
+ ///
+ ///
+ ///
private void but_open_Click(object sender, EventArgs e)
{
try
@@ -51,9 +54,9 @@ namespace IoTClient.Tool.Controls
var BaudRate = int.Parse(txt_baudRate.Text.ToString());
var DataBits = int.Parse(txt_dataBit.Text.ToString());
var StopBits = (StopBits)int.Parse(txt_stopBit.Text.ToString());
-
- if (modBusRtuClient == null) modBusRtuClient = new ModBusRtuClient(PortName, BaudRate, DataBits, StopBits);
- var result = modBusRtuClient.Open();
+ client?.Close();
+ client = new ModBusRtuClient(PortName, BaudRate, DataBits, StopBits);
+ var result = client.Open();
if (result.IsSucceed)
{
but_open.Enabled = false;
@@ -66,7 +69,6 @@ namespace IoTClient.Tool.Controls
}
else
AppendText($"连接失败:{result.Err}");
- UpdatePortNames();
}
catch (Exception ex)
{
@@ -74,22 +76,101 @@ namespace IoTClient.Tool.Controls
}
}
- private void AppendText(string content)
- {
- txt_content.Invoke((Action)(() =>
- {
- txt_content.AppendText($"[{DateTime.Now.ToLongTimeString()}]{content}\r\n");
- }));
- }
-
///
- /// 发送数据
+ /// 关闭连接
///
///
///
- private void butWrite_Click(object sender, EventArgs e)
+ private void butClose_Click(object sender, EventArgs e)
{
- var address = txt_address.Text?.Trim();
+ client?.Close();
+ AppendText("关闭连接");
+ but_open.Enabled = true;
+ but_close.Enabled = false;
+ cb_portNameSend.Enabled = true;
+ }
+
+ ///
+ /// 读数据
+ ///
+ ///
+ ///
+ private void but_read_Click(object sender, EventArgs e)
+ {
+ byte.TryParse(txt_stationNumber.Text?.Trim(), out byte stationNumber);
+ if (string.IsNullOrWhiteSpace(txt_address.Text))
+ {
+ MessageBox.Show("请输入地址");
+ return;
+ }
+ try
+ {
+ dynamic result = null;
+ if (rd_bit.Checked)
+ {
+ result = client.ReadCoil(txt_address.Text, stationNumber);
+ }
+ else if (rd_short.Checked)
+ {
+ result = client.ReadInt16(txt_address.Text, stationNumber);
+ }
+ else if (rd_ushort.Checked)
+ {
+ result = client.ReadUInt16(txt_address.Text, stationNumber);
+ }
+ else if (rd_int.Checked)
+ {
+ result = client.ReadInt32(txt_address.Text, stationNumber);
+ }
+ else if (rd_uint.Checked)
+ {
+ result = client.ReadUInt32(txt_address.Text, stationNumber);
+ }
+ else if (rd_long.Checked)
+ {
+ result = client.ReadInt64(txt_address.Text, stationNumber);
+ }
+ else if (rd_ulong.Checked)
+ {
+ result = client.ReadUInt64(txt_address.Text, stationNumber);
+ }
+ else if (rd_float.Checked)
+ {
+ result = client.ReadFloat(txt_address.Text, stationNumber);
+ }
+ else if (rd_double.Checked)
+ {
+ result = client.ReadDouble(txt_address.Text, stationNumber);
+ }
+ else if (rd_discrete.Checked)
+ {
+ result = client.ReadDiscrete(txt_address.Text, stationNumber);
+ }
+
+ if (result.IsSucceed)
+ 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\r\n");
+ }
+ }
+ catch (Exception ex)
+ {
+ MessageBox.Show(ex.Message);
+ }
+ }
+
+ ///
+ /// 写数据
+ ///
+ ///
+ ///
+ private void but_write_Click(object sender, EventArgs e)
+ {
+ var address = txt_address.Text?.Trim();
byte.TryParse(txt_stationNumber.Text?.Trim(), out byte stationNumber);
if (string.IsNullOrWhiteSpace(txt_address.Text))
{
@@ -119,40 +200,45 @@ namespace IoTClient.Tool.Controls
return;
}
}
- result = modBusRtuClient.Write(address, coil, stationNumber);
+ result = client.Write(address, coil, stationNumber);
}
else if (rd_short.Checked)
{
- result = modBusRtuClient.Write(address, short.Parse(txt_value.Text?.Trim()), stationNumber);
+ result = client.Write(address, short.Parse(txt_value.Text?.Trim()), stationNumber);
}
else if (rd_ushort.Checked)
{
- result = modBusRtuClient.Write(address, ushort.Parse(txt_value.Text?.Trim()), stationNumber);
+ result = client.Write(address, ushort.Parse(txt_value.Text?.Trim()), stationNumber);
}
else if (rd_int.Checked)
{
- result = modBusRtuClient.Write(address, int.Parse(txt_value.Text?.Trim()), stationNumber);
+ result = client.Write(address, int.Parse(txt_value.Text?.Trim()), stationNumber);
}
else if (rd_uint.Checked)
{
- result = modBusRtuClient.Write(address, uint.Parse(txt_value.Text?.Trim()), stationNumber);
+ result = client.Write(address, uint.Parse(txt_value.Text?.Trim()), stationNumber);
}
else if (rd_long.Checked)
{
- result = modBusRtuClient.Write(address, long.Parse(txt_value.Text?.Trim()), stationNumber);
+ result = client.Write(address, long.Parse(txt_value.Text?.Trim()), stationNumber);
}
else if (rd_ulong.Checked)
{
- result = modBusRtuClient.Write(address, ulong.Parse(txt_value.Text?.Trim()), stationNumber);
+ result = client.Write(address, ulong.Parse(txt_value.Text?.Trim()), stationNumber);
}
else if (rd_float.Checked)
{
- result = modBusRtuClient.Write(address, float.Parse(txt_value.Text?.Trim()), stationNumber);
+ result = client.Write(address, float.Parse(txt_value.Text?.Trim()), stationNumber);
}
else if (rd_double.Checked)
{
- result = modBusRtuClient.Write(address, double.Parse(txt_value.Text?.Trim()), stationNumber);
- }
+ result = client.Write(address, double.Parse(txt_value.Text?.Trim()), stationNumber);
+ }
+ else if (rd_discrete.Checked)
+ {
+ txt_content.AppendText($"[{DateTime.Now.ToLongTimeString()}]离散类型只读\r\n");
+ return;
+ }
if (result.IsSucceed)
txt_content.AppendText($"[{DateTime.Now.ToLongTimeString()}][写入 {address?.Trim()} 成功]:{txt_value.Text?.Trim()} OK\r\n");
@@ -170,76 +256,53 @@ namespace IoTClient.Tool.Controls
}
}
- private void butClose_Click(object sender, EventArgs e)
+ ///
+ /// 启动仿真服务
+ ///
+ ///
+ ///
+ private void but_open_server_Click(object sender, EventArgs e)
{
- modBusRtuClient?.Close();
- AppendText("关闭连接");
- but_open.Enabled = true;
- but_close.Enabled = false;
- }
-
- private void but_read_Click(object sender, EventArgs e)
- {
- byte.TryParse(txt_stationNumber.Text?.Trim(), out byte stationNumber);
- if (string.IsNullOrWhiteSpace(txt_address.Text))
- {
- MessageBox.Show("请输入地址");
- return;
- }
try
{
- dynamic result = null;
- if (rd_bit.Checked)
- {
- result = modBusRtuClient.ReadCoil(txt_address.Text, stationNumber);
- }
- else if (rd_short.Checked)
- {
- result = modBusRtuClient.ReadInt16(txt_address.Text, stationNumber);
- }
- else if (rd_ushort.Checked)
- {
- result = modBusRtuClient.ReadUInt16(txt_address.Text, stationNumber);
- }
- else if (rd_int.Checked)
- {
- result = modBusRtuClient.ReadInt32(txt_address.Text, stationNumber);
- }
- else if (rd_uint.Checked)
- {
- result = modBusRtuClient.ReadUInt32(txt_address.Text, stationNumber);
- }
- else if (rd_long.Checked)
- {
- result = modBusRtuClient.ReadInt64(txt_address.Text, stationNumber);
- }
- else if (rd_ulong.Checked)
- {
- result = modBusRtuClient.ReadUInt64(txt_address.Text, stationNumber);
- }
- else if (rd_float.Checked)
- {
- result = modBusRtuClient.ReadFloat(txt_address.Text, stationNumber);
- }
- else if (rd_double.Checked)
- {
- result = modBusRtuClient.ReadDouble(txt_address.Text, stationNumber);
- }
-
- if (result.IsSucceed)
- 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\r\n");
- }
+ var PortName = cb_portNameSend_server.Text.ToString();
+ var BaudRate = int.Parse(txt_baudRate.Text.ToString());
+ var DataBits = int.Parse(txt_dataBit.Text.ToString());
+ var StopBits = (StopBits)int.Parse(txt_stopBit.Text.ToString());
+ server?.Stop();
+ server = new ModBusRtuServer(PortName, BaudRate, DataBits, StopBits);
+ server.Start();
+ AppendText("开启仿真服务");
+ but_server_open.Enabled = false;
+ but_server_close.Enabled = true;
+ cb_portNameSend_server.Enabled = false;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
+
+ ///
+ /// 关闭仿真服务
+ ///
+ ///
+ ///
+ private void but_close_server_Click(object sender, EventArgs e)
+ {
+ server?.Stop();
+ AppendText("关闭仿真服务");
+ but_server_open.Enabled = true;
+ but_server_close.Enabled = false;
+ cb_portNameSend_server.Enabled = true;
+ }
+
+ private void AppendText(string content)
+ {
+ txt_content.Invoke((Action)(() =>
+ {
+ txt_content.AppendText($"[{DateTime.Now.ToLongTimeString()}]{content}\r\n");
+ }));
+ }
}
}
diff --git a/IoTClient.Tool/Controls/ModBusTcpControl.Designer.cs b/IoTClient.Tool/Controls/ModBusTcpControl.Designer.cs
index b2c1e4d..9bf8160 100644
--- a/IoTClient.Tool/Controls/ModBusTcpControl.Designer.cs
+++ b/IoTClient.Tool/Controls/ModBusTcpControl.Designer.cs
@@ -61,6 +61,7 @@
this.label4 = new System.Windows.Forms.Label();
this.txt_content = new System.Windows.Forms.TextBox();
this.toolTip1 = new System.Windows.Forms.ToolTip(this.components);
+ this.rd_discrete = new System.Windows.Forms.RadioButton();
this.groupBox2.SuspendLayout();
this.groupBox1.SuspendLayout();
this.groupBox3.SuspendLayout();
@@ -187,6 +188,7 @@
//
// groupBox1
//
+ this.groupBox1.Controls.Add(this.rd_discrete);
this.groupBox1.Controls.Add(this.button6);
this.groupBox1.Controls.Add(this.rd_float);
this.groupBox1.Controls.Add(this.rd_double);
@@ -216,7 +218,7 @@
// rd_float
//
this.rd_float.AutoSize = true;
- this.rd_float.Location = new System.Drawing.Point(436, 23);
+ this.rd_float.Location = new System.Drawing.Point(486, 23);
this.rd_float.Name = "rd_float";
this.rd_float.Size = new System.Drawing.Size(53, 16);
this.rd_float.TabIndex = 22;
@@ -226,7 +228,7 @@
// rd_double
//
this.rd_double.AutoSize = true;
- this.rd_double.Location = new System.Drawing.Point(495, 23);
+ this.rd_double.Location = new System.Drawing.Point(545, 23);
this.rd_double.Name = "rd_double";
this.rd_double.Size = new System.Drawing.Size(59, 16);
this.rd_double.TabIndex = 23;
@@ -237,7 +239,7 @@
//
this.rd_short.AutoSize = true;
this.rd_short.Checked = true;
- this.rd_short.Location = new System.Drawing.Point(70, 23);
+ this.rd_short.Location = new System.Drawing.Point(120, 23);
this.rd_short.Name = "rd_short";
this.rd_short.Size = new System.Drawing.Size(53, 16);
this.rd_short.TabIndex = 6;
@@ -258,7 +260,7 @@
// rd_ulong
//
this.rd_ulong.AutoSize = true;
- this.rd_ulong.Location = new System.Drawing.Point(374, 23);
+ this.rd_ulong.Location = new System.Drawing.Point(424, 23);
this.rd_ulong.Name = "rd_ulong";
this.rd_ulong.Size = new System.Drawing.Size(53, 16);
this.rd_ulong.TabIndex = 21;
@@ -268,7 +270,7 @@
// rd_ushort
//
this.rd_ushort.AutoSize = true;
- this.rd_ushort.Location = new System.Drawing.Point(129, 23);
+ this.rd_ushort.Location = new System.Drawing.Point(179, 23);
this.rd_ushort.Name = "rd_ushort";
this.rd_ushort.Size = new System.Drawing.Size(59, 16);
this.rd_ushort.TabIndex = 17;
@@ -278,7 +280,7 @@
// rd_long
//
this.rd_long.AutoSize = true;
- this.rd_long.Location = new System.Drawing.Point(315, 23);
+ this.rd_long.Location = new System.Drawing.Point(365, 23);
this.rd_long.Name = "rd_long";
this.rd_long.Size = new System.Drawing.Size(47, 16);
this.rd_long.TabIndex = 20;
@@ -288,7 +290,7 @@
// rd_int
//
this.rd_int.AutoSize = true;
- this.rd_int.Location = new System.Drawing.Point(194, 23);
+ this.rd_int.Location = new System.Drawing.Point(244, 23);
this.rd_int.Name = "rd_int";
this.rd_int.Size = new System.Drawing.Size(41, 16);
this.rd_int.TabIndex = 18;
@@ -298,7 +300,7 @@
// rd_uint
//
this.rd_uint.AutoSize = true;
- this.rd_uint.Location = new System.Drawing.Point(253, 23);
+ this.rd_uint.Location = new System.Drawing.Point(303, 23);
this.rd_uint.Name = "rd_uint";
this.rd_uint.Size = new System.Drawing.Size(47, 16);
this.rd_uint.TabIndex = 19;
@@ -382,6 +384,16 @@
this.txt_content.Size = new System.Drawing.Size(855, 272);
this.txt_content.TabIndex = 27;
//
+ // radioButton1
+ //
+ this.rd_discrete.AutoSize = true;
+ this.rd_discrete.Location = new System.Drawing.Point(64, 23);
+ this.rd_discrete.Name = "radioButton1";
+ this.rd_discrete.Size = new System.Drawing.Size(47, 16);
+ this.rd_discrete.TabIndex = 24;
+ this.rd_discrete.Text = "离散";
+ this.rd_discrete.UseVisualStyleBackColor = true;
+ //
// ModBusTcpControl
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
@@ -437,5 +449,6 @@
private System.Windows.Forms.Button button2;
private System.Windows.Forms.Button button5;
private System.Windows.Forms.Button button6;
+ private System.Windows.Forms.RadioButton rd_discrete;
}
}
diff --git a/IoTClient.Tool/Controls/ModBusTcpControl.cs b/IoTClient.Tool/Controls/ModBusTcpControl.cs
index 88d4038..485c324 100644
--- a/IoTClient.Tool/Controls/ModBusTcpControl.cs
+++ b/IoTClient.Tool/Controls/ModBusTcpControl.cs
@@ -32,7 +32,7 @@ namespace IoTClient.Tool
private void button1_Click(object sender, EventArgs e)
{
- server?.Close();
+ server?.Stop();
server = new ModBusTcpServer(502);
server.Start();
button1.Enabled = false;
@@ -42,7 +42,7 @@ namespace IoTClient.Tool
private void button2_Click(object sender, EventArgs e)
{
- server?.Close();
+ server?.Stop();
button1.Enabled = true;
button2.Enabled = false;
txt_content.AppendText($"[{DateTime.Now.ToLongTimeString()}]关闭仿真模拟服务\r\n");
@@ -120,6 +120,10 @@ namespace IoTClient.Tool
{
result = client.ReadDouble(txt_address.Text, stationNumber);
}
+ else if (rd_discrete.Checked)
+ {
+ result = client.ReadDiscrete(txt_address.Text, stationNumber);
+ }
if (result.IsSucceed)
txt_content.AppendText($"[{DateTime.Now.ToLongTimeString()}][读取 {txt_address.Text?.Trim()} 成功]:{result.Value}\r\n");
@@ -202,7 +206,11 @@ namespace IoTClient.Tool
{
result = client.Write(txt_address.Text, double.Parse(txt_value.Text?.Trim()), stationNumber);
}
-
+ else if (rd_discrete.Checked)
+ {
+ txt_content.AppendText($"[{DateTime.Now.ToLongTimeString()}]离散类型只读\r\n");
+ return;
+ }
if (result.IsSucceed)
txt_content.AppendText($"[{DateTime.Now.ToLongTimeString()}][写入 {txt_address.Text?.Trim()} 成功]:{txt_value.Text?.Trim()} OK\r\n");
diff --git a/IoTClient.Tool/Controls/SiemensControl.cs b/IoTClient.Tool/Controls/SiemensControl.cs
index d7a9758..5ddc7f5 100644
--- a/IoTClient.Tool/Controls/SiemensControl.cs
+++ b/IoTClient.Tool/Controls/SiemensControl.cs
@@ -31,7 +31,7 @@ namespace IoTClient.Tool
private void but_server_Click(object sender, EventArgs e)
{
- server?.Close();
+ server?.Stop();
server = new SiemensServer(int.Parse(txt_port.Text.Trim()));
server.Start();
but_server.Enabled = false;
@@ -41,7 +41,7 @@ namespace IoTClient.Tool
private void button2_Click(object sender, EventArgs e)
{
- server?.Close();
+ server?.Stop();
but_server.Enabled = true;
button2.Enabled = false;
txt_content.AppendText($"[{DateTime.Now.ToLongTimeString()}]关闭仿真模拟服务\r\n");
diff --git a/IoTClient.Tool/IndexForm.Designer.cs b/IoTClient.Tool/IndexForm.Designer.cs
index f303381..7915266 100644
--- a/IoTClient.Tool/IndexForm.Designer.cs
+++ b/IoTClient.Tool/IndexForm.Designer.cs
@@ -182,8 +182,8 @@
//
this.toolStripMenuItem1.ForeColor = System.Drawing.Color.White;
this.toolStripMenuItem1.Name = "toolStripMenuItem1";
- this.toolStripMenuItem1.Size = new System.Drawing.Size(87, 21);
- this.toolStripMenuItem1.Text = "测试版 0.0.3";
+ this.toolStripMenuItem1.Size = new System.Drawing.Size(75, 21);
+ this.toolStripMenuItem1.Text = "版本 0.0.3";
this.toolStripMenuItem1.Click += new System.EventHandler(this.toolStripMenuItem1_Click);
//
// IndexForm
diff --git a/IoTClient/Clients/ModBus/ModBusRtuClient.cs b/IoTClient/Clients/ModBus/ModBusRtuClient.cs
index e361903..609b4a7 100644
--- a/IoTClient/Clients/ModBus/ModBusRtuClient.cs
+++ b/IoTClient/Clients/ModBus/ModBusRtuClient.cs
@@ -1,5 +1,5 @@
using IoTClient.Common.Helpers;
-using IoTClient.Core;
+using IoTClient.Models;
using System;
using System.IO.Ports;
using System.Linq;
@@ -47,7 +47,7 @@ namespace IoTClient.Clients.ModBus
/// 获取设备上的COM端口集合
///
///
- public string[] GetPortNames()
+ public static string[] GetPortNames()
{
return SerialPort.GetPortNames();
}
@@ -138,6 +138,19 @@ namespace IoTClient.Clients.ModBus
//3 获取响应报文
var responsePackage = SerialPortRead(serialPort);
+ if (!responsePackage.Any())
+ {
+ result.IsSucceed = false;
+ result.Err = "响应结果为空,请检查是否连上了服务端";
+ return result;
+ }
+ else if (!CRC16.CheckCRC16(responsePackage))
+ {
+ result.IsSucceed = false;
+ result.Err = "响应结果CRC16验证失败";
+ return result;
+ }
+
byte[] resultData = new byte[responsePackage.Length - 2];
Array.Copy(responsePackage, 0, resultData, 0, resultData.Length);
@@ -363,7 +376,30 @@ namespace IoTClient.Clients.ModBus
if (result.IsSucceed)
result.Value = BitConverter.ToBoolean(readResut.Value, 0);
return result;
- }
+ }
+
+ ///
+ /// 读取离散
+ ///
+ ///
+ ///
+ ///
+ ///
+ public Result ReadDiscrete(string address, byte stationNumber = 1, byte functionCode = 2)
+ {
+ var readResut = Read(address, stationNumber, functionCode);
+ var result = new Result()
+ {
+ 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);
+ return result;
+ }
#endregion
#region Write 写入
@@ -385,10 +421,16 @@ namespace IoTClient.Clients.ModBus
serialPort.Write(commandCRC16, 0, commandCRC16.Length);
result.Requst = string.Join(" ", commandCRC16.Select(t => t.ToString("X2")));
//3 获取响应报文
- var dataPackage = SerialPortRead(serialPort);
- byte[] resultBuffer = new byte[dataPackage.Length - 2];
- Array.Copy(dataPackage, 0, resultBuffer, 0, resultBuffer.Length);
- result.Response = string.Join(" ", dataPackage.Select(t => t.ToString("X2")));
+ var responsePackage = SerialPortRead(serialPort);
+ if (!CRC16.CheckCRC16(responsePackage))
+ {
+ result.IsSucceed = false;
+ result.Err = "响应结果CRC16验证失败";
+ return result;
+ }
+ byte[] resultBuffer = new byte[responsePackage.Length - 2];
+ Array.Copy(responsePackage, 0, resultBuffer, 0, resultBuffer.Length);
+ result.Response = string.Join(" ", responsePackage.Select(t => t.ToString("X2")));
}
catch (Exception ex)
{
@@ -424,10 +466,16 @@ namespace IoTClient.Clients.ModBus
serialPort.Write(commandCRC16, 0, commandCRC16.Length);
result.Requst = string.Join(" ", commandCRC16.Select(t => t.ToString("X2")));
//3 获取响应报文
- var dataPackage = SerialPortRead(serialPort);
- byte[] resultBuffer = new byte[dataPackage.Length - 2];
- Array.Copy(dataPackage, 0, resultBuffer, 0, resultBuffer.Length);
- result.Response = string.Join(" ", dataPackage.Select(t => t.ToString("X2")));
+ var responsePackage = SerialPortRead(serialPort);
+ if (!CRC16.CheckCRC16(responsePackage))
+ {
+ result.IsSucceed = false;
+ result.Err = "响应结果CRC16验证失败";
+ return result;
+ }
+ byte[] resultBuffer = new byte[responsePackage.Length - 2];
+ Array.Copy(responsePackage, 0, resultBuffer, 0, resultBuffer.Length);
+ result.Response = string.Join(" ", responsePackage.Select(t => t.ToString("X2")));
}
catch (Exception ex)
{
diff --git a/IoTClient/Clients/ModBus/ModBusTcpClient.cs b/IoTClient/Clients/ModBus/ModBusTcpClient.cs
index 9386566..9f46b70 100644
--- a/IoTClient/Clients/ModBus/ModBusTcpClient.cs
+++ b/IoTClient/Clients/ModBus/ModBusTcpClient.cs
@@ -1,4 +1,5 @@
using IoTClient.Core;
+using IoTClient.Models;
using System;
using System.Linq;
using System.Net;
@@ -73,8 +74,9 @@ namespace IoTClient.Clients.ModBus
var result = new Result();
try
{
+ var chenkHead = GetCheckHead(functionCode);
//1 获取命令(组装报文)
- byte[] command = GetReadCommand(address, stationNumber, functionCode, readLength);
+ byte[] command = GetReadCommand(address, stationNumber, functionCode, readLength, chenkHead);
result.Requst = string.Join(" ", command.Select(t => t.ToString("X2")));
//2 发送命令
socket.Send(command);
@@ -82,13 +84,17 @@ namespace IoTClient.Clients.ModBus
var headPackage = SocketRead(socket, 8);
int length = headPackage[4] * 256 + headPackage[5] - 2;
var dataPackage = SocketRead(socket, length);
-
byte[] resultBuffer = new byte[dataPackage.Length - 1];
Array.Copy(dataPackage, 1, resultBuffer, 0, resultBuffer.Length);
-
result.Response = string.Join(" ", headPackage.Concat(dataPackage).Select(t => t.ToString("X2")));
//4 获取响应报文数据(字节数组形式)
result.Value = resultBuffer.Reverse().ToArray();
+ if (chenkHead[0] != headPackage[0] || chenkHead[1] != headPackage[1])
+ {
+ result.IsSucceed = false;
+ result.Err = "响应结果校验失败";
+ result.ErrList.Add("响应结果校验失败");
+ }
}
catch (SocketException ex)
{
@@ -319,6 +325,29 @@ namespace IoTClient.Clients.ModBus
result.Value = BitConverter.ToBoolean(readResut.Value, 0);
return result;
}
+
+ ///
+ /// 读取离散
+ ///
+ ///
+ ///
+ ///
+ ///
+ public Result ReadDiscrete(string address, byte stationNumber = 1, byte functionCode = 2)
+ {
+ var readResut = Read(address, stationNumber, functionCode);
+ var result = new Result()
+ {
+ 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);
+ return result;
+ }
#endregion
#region Write 写入
@@ -336,14 +365,21 @@ namespace IoTClient.Clients.ModBus
var result = new Result();
try
{
- var command = GetWriteCoilCommand(address, value, stationNumber, functionCode);
+ var chenkHead = GetCheckHead(functionCode);
+ var command = GetWriteCoilCommand(address, value, stationNumber, functionCode, chenkHead);
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;
- var dataBytes = SocketRead(socket, length);
- result.Response = string.Join(" ", headBytes.Concat(dataBytes).Select(t => t.ToString("X2")));
+ var headPackage = SocketRead(socket, 8);
+ int length = headPackage[4] * 256 + headPackage[5] - 2;
+ var dataPackage = SocketRead(socket, length);
+ result.Response = string.Join(" ", headPackage.Concat(dataPackage).Select(t => t.ToString("X2")));
+ if (chenkHead[0] != headPackage[0] || chenkHead[1] != headPackage[1])
+ {
+ result.IsSucceed = false;
+ result.Err = "响应结果校验失败";
+ result.ErrList.Add("响应结果校验失败");
+ }
}
catch (SocketException ex)
{
@@ -383,14 +419,21 @@ namespace IoTClient.Clients.ModBus
var result = new Result();
try
{
- var command = GetWriteCommand(address, values, stationNumber, functionCode);
+ var chenkHead = GetCheckHead(functionCode);
+ var command = GetWriteCommand(address, values, stationNumber, functionCode, chenkHead);
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;
- var dataBytes = SocketRead(socket, length);
- result.Response = string.Join(" ", headBytes.Concat(dataBytes).Select(t => t.ToString("X2")));
+ var headPackage = SocketRead(socket, 8);
+ int length = headPackage[4] * 256 + headPackage[5] - 2;
+ var dataPackage = SocketRead(socket, length);
+ result.Response = string.Join(" ", headPackage.Concat(dataPackage).Select(t => t.ToString("X2")));
+ if (chenkHead[0] != headPackage[0] || chenkHead[1] != headPackage[1])
+ {
+ result.IsSucceed = false;
+ result.Err = "响应结果校验失败";
+ result.ErrList.Add("响应结果校验失败");
+ }
}
catch (SocketException ex)
{
@@ -522,6 +565,16 @@ namespace IoTClient.Clients.ModBus
#region 获取命令
+ ///
+ /// 获取随机校验头
+ ///
+ ///
+ private byte[] GetCheckHead(int seed)
+ {
+ var random = new Random(DateTime.Now.Millisecond + seed);
+ return new byte[] { (byte)random.Next(255), (byte)random.Next(255) };
+ }
+
///
/// 获取读取命令
///
@@ -530,12 +583,12 @@ namespace IoTClient.Clients.ModBus
/// 功能码
/// 读取长度
///
- public byte[] GetReadCommand(string address, byte stationNumber, byte functionCode, ushort length)
+ public byte[] GetReadCommand(string address, byte stationNumber, byte functionCode, ushort length, byte[] check = null)
{
var readAddress = ushort.Parse(address?.Trim());
byte[] buffer = new byte[12];
- buffer[0] = 0x19;
- buffer[1] = 0xB2;//Client发出的检验信息
+ buffer[0] = check?[0] ?? 0x19;
+ buffer[1] = check?[1] ?? 0xB2;//Client发出的检验信息
buffer[2] = 0x00;
buffer[3] = 0x00;//表示tcp/ip 的协议的modbus的协议
buffer[4] = 0x00;
@@ -558,12 +611,12 @@ namespace IoTClient.Clients.ModBus
/// 站号
/// 功能码
///
- public byte[] GetWriteCommand(string address, byte[] values, byte stationNumber, byte functionCode)
+ public byte[] GetWriteCommand(string address, byte[] values, byte stationNumber, byte functionCode, byte[] check = null)
{
var writeAddress = ushort.Parse(address?.Trim());
byte[] buffer = new byte[13 + values.Length];
- buffer[0] = 0x19;
- buffer[1] = 0xB2;//检验信息,用来验证response是否串数据了
+ buffer[0] = check?[0] ?? 0x19;
+ buffer[1] = check?[1] ?? 0xB2;//检验信息,用来验证response是否串数据了
buffer[4] = BitConverter.GetBytes(7 + values.Length)[1];
buffer[5] = BitConverter.GetBytes(7 + values.Length)[0];//表示的是header handle后面还有多长的字节
@@ -586,12 +639,12 @@ namespace IoTClient.Clients.ModBus
/// 站号
/// 功能码
///
- public byte[] GetWriteCoilCommand(string address, bool value, byte stationNumber, byte functionCode)
+ public byte[] GetWriteCoilCommand(string address, bool value, byte stationNumber, byte functionCode, byte[] check = null)
{
var writeAddress = ushort.Parse(address?.Trim());
byte[] buffer = new byte[12];
- buffer[0] = 0x19;
- buffer[1] = 0xB2;//Client发出的检验信息
+ buffer[0] = check?[0] ?? 0x19;
+ buffer[1] = check?[1] ?? 0xB2;//Client发出的检验信息
buffer[4] = 0x00;
buffer[5] = 0x06;//表示的是该字节以后的字节长度
diff --git a/IoTClient/Clients/PLC/SiemensClient.cs b/IoTClient/Clients/PLC/SiemensClient.cs
index 809e03f..a4a2485 100644
--- a/IoTClient/Clients/PLC/SiemensClient.cs
+++ b/IoTClient/Clients/PLC/SiemensClient.cs
@@ -2,6 +2,7 @@
using IoTClient.Common.Enums;
using IoTClient.Core;
using IoTClient.Core.Models;
+using IoTClient.Models;
using System;
using System.Collections.Generic;
using System.Linq;
diff --git a/IoTClient/IoTClient/IoTClient.xml b/IoTClient/IoTClient/IoTClient.xml
index 62f1831..bffc7b9 100644
--- a/IoTClient/IoTClient/IoTClient.xml
+++ b/IoTClient/IoTClient/IoTClient.xml
@@ -149,6 +149,15 @@
功能码
+
+
+ 读取离散
+
+
+
+
+
+
线圈写入
@@ -379,6 +388,15 @@
功能码
+
+
+ 读取离散
+
+
+
+
+
+
线圈写入
@@ -470,7 +488,13 @@
站号
功能码
-
+
+
+ 获取随机校验头
+
+
+
+
获取读取命令
@@ -480,7 +504,7 @@
读取长度
-
+
获取写入命令
@@ -490,7 +514,7 @@
功能码
-
+
获取线圈写入命令
@@ -805,42 +829,42 @@
西门子S7-200Smar
-
+
请求结果
-
+
是否成功
-
+
异常消息
-
+
异常集合
-
+
请求报文
-
+
响应报文
-
+
请求结果
-
+
数据结果
diff --git a/IoTClient/Models/Result.cs b/IoTClient/Models/Result.cs
new file mode 100644
index 0000000..979f617
--- /dev/null
+++ b/IoTClient/Models/Result.cs
@@ -0,0 +1,61 @@
+using System.Collections.Generic;
+
+namespace IoTClient.Models
+{
+ ///
+ /// 请求结果
+ ///
+ public class Result
+ {
+ public Result()
+ {
+ }
+
+ ///
+ /// 是否成功
+ ///
+ public bool IsSucceed { get; set; } = true;
+
+ ///
+ /// 异常消息
+ ///
+ public string Err { get; set; }
+
+ ///
+ /// 异常集合
+ ///
+ 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/IoTClient/Models/SiemensData.cs b/IoTClient/Models/SiemensData.cs
index 8c105f9..9313c92 100644
--- a/IoTClient/Models/SiemensData.cs
+++ b/IoTClient/Models/SiemensData.cs
@@ -1,8 +1,4 @@
-using System;
-using System.Collections.Generic;
-using System.Text;
-
-namespace IoTClient.Core.Models
+namespace IoTClient.Core.Models
{
public class SiemensData
{
diff --git a/IoTClient/SocketBase.cs b/IoTClient/SocketBase.cs
index 8db2e7c..b95503d 100644
--- a/IoTClient/SocketBase.cs
+++ b/IoTClient/SocketBase.cs
@@ -1,4 +1,5 @@
-using System;
+using IoTClient.Models;
+using System;
using System.Net.Sockets;
namespace IoTClient.Core
diff --git a/IoTServer/IoTServer/IoTServer.xml b/IoTServer/IoTServer/IoTServer.xml
index aa22e21..3ab6e6c 100644
--- a/IoTServer/IoTServer/IoTServer.xml
+++ b/IoTServer/IoTServer/IoTServer.xml
@@ -39,11 +39,33 @@
初始化加载数据
+
+
+ 启动服务
+
+
+
+
+ 停止服务
+
+
+
+
+ 接收数据回调用
+
+
+
+
启动服务
+
+
+ 停止服务
+
+
客户端连接到服务端
@@ -61,6 +83,11 @@
启动服务
+
+
+ 停止服务
+
+
客户端连接到服务端
diff --git a/IoTServer/Servers/ModBus/ModBusRtuServer.cs b/IoTServer/Servers/ModBus/ModBusRtuServer.cs
new file mode 100644
index 0000000..a7b54a7
--- /dev/null
+++ b/IoTServer/Servers/ModBus/ModBusRtuServer.cs
@@ -0,0 +1,117 @@
+using IoTClient.Common.Helpers;
+using IoTServer.Common;
+using Newtonsoft.Json;
+using System;
+using System.IO.Ports;
+using System.Linq;
+using System.Text;
+
+namespace IoTServer.Servers.ModBus
+{
+ public class ModBusRtuServer
+ {
+ private SerialPort serialPort;
+ DataPersist dataPersist;
+ public ModBusRtuServer(string portName, int baudRate, int dataBits, StopBits stopBits)
+ {
+ if (serialPort == null) serialPort = new SerialPort();
+ serialPort.PortName = portName;
+ serialPort.BaudRate = baudRate;
+ serialPort.DataBits = dataBits;
+ serialPort.StopBits = stopBits;
+ serialPort.Encoding = Encoding.ASCII;
+#if !DEBUG
+ serialPort.ReadTimeout = 1000;//1秒
+#endif
+ serialPort.DataReceived += new SerialDataReceivedEventHandler(DataReceived);
+ dataPersist = new DataPersist("ModBusTcpServer");
+ }
+
+ ///
+ /// 启动服务
+ ///
+ public void Start()
+ {
+ serialPort.Open();
+ }
+
+ ///
+ /// 停止服务
+ ///
+ public void Stop()
+ {
+ serialPort.Close();
+ serialPort.Dispose();
+ }
+
+ ///
+ /// 接收数据回调用
+ ///
+ ///
+ ///
+ private void DataReceived(object sender, SerialDataReceivedEventArgs e)
+ {
+ try
+ {
+ byte[] requetData = new byte[serialPort.BytesToRead];
+ serialPort.Read(requetData, 0, requetData.Length);
+ var address = requetData[2] * 256 + requetData[3];
+ switch (requetData[1])
+ {
+ //读取线圈
+ case 1:
+ {
+ var value = dataPersist.Read(address);
+ var bytes = JsonConvert.DeserializeObject(value).Reverse().ToArray();
+ var tempData = new byte[4];
+ tempData[0] = 1;
+ tempData[1] = 1;
+ Buffer.BlockCopy(bytes, 0, tempData, 2, 2);
+ var responseData = CRC16.GetCRC16(tempData);
+ serialPort.Write(responseData, 0, responseData.Length);
+ }
+ break;
+ //写入线圈
+ case 5:
+ {
+ var value = new byte[2];
+ Buffer.BlockCopy(requetData, requetData.Length - 4, value, 0, value.Length);
+ dataPersist.Write(address, JsonConvert.SerializeObject(value));
+ serialPort.Write(requetData, 0, requetData.Length);
+ }
+ break;
+ //读取
+ case 3:
+ {
+ var value = dataPersist.Read(address);
+ var bytes = JsonConvert.DeserializeObject(value);
+ if (bytes == null)
+ {
+ var length = requetData[requetData.Length - 4] * 256 + requetData[requetData.Length - 5];
+ bytes = new byte[length * 2];
+ }
+ var dataHead = new byte[] { 1, 3, (byte)bytes.Length };
+ var tempData = dataHead.Concat(bytes).ToArray();
+ var responseData = CRC16.GetCRC16(tempData);
+ serialPort.Write(responseData, 0, responseData.Length);
+ }
+ break;
+ //写入
+ case 16:
+ {
+ var value = new byte[requetData[6]];
+ Buffer.BlockCopy(requetData, 7, value, 0, value.Length);
+ dataPersist.Write(address, JsonConvert.SerializeObject(value));
+ var tempData = new byte[6];
+ Buffer.BlockCopy(requetData, 0, tempData, 0, tempData.Length);
+ var responseData = CRC16.GetCRC16(tempData);
+ serialPort.Write(responseData, 0, responseData.Length);
+ }
+ break;
+ }
+ }
+ catch (Exception ex)
+ { }
+ }
+ }
+}
diff --git a/IoTServer/Servers/ModBus/ModBusTcpServer.cs b/IoTServer/Servers/ModBus/ModBusTcpServer.cs
index 8c9a43c..5beaeae 100644
--- a/IoTServer/Servers/ModBus/ModBusTcpServer.cs
+++ b/IoTServer/Servers/ModBus/ModBusTcpServer.cs
@@ -42,7 +42,10 @@ namespace IoTServer.Servers.ModBus
Task.Run(() => { Accept(socketServer); });
}
- public void Close()
+ ///
+ /// 停止服务
+ ///
+ public void Stop()
{
if (socketServer?.Connected ?? false)
socketServer.Shutdown(SocketShutdown.Both);
@@ -148,7 +151,6 @@ namespace IoTServer.Servers.ModBus
//读取
case 3:
{
-
var value = dataPersist.Read(address);// 数据存在 8、9
var bytes = JsonConvert.DeserializeObject(value);
if (bytes == null)
diff --git a/IoTServer/Servers/PLC/SiemensServer.cs b/IoTServer/Servers/PLC/SiemensServer.cs
index 6f6aca8..f8c8c64 100644
--- a/IoTServer/Servers/PLC/SiemensServer.cs
+++ b/IoTServer/Servers/PLC/SiemensServer.cs
@@ -44,7 +44,10 @@ namespace IoTServer.Servers.PLC
Task.Run(() => { Accept(socketServer); });
}
- public void Close()
+ ///
+ /// 停止服务
+ ///
+ public void Stop()
{
if (socketServer?.Connected ?? false)
socketServer.Shutdown(SocketShutdown.Both);
diff --git a/README.md b/README.md
index f0d4692..4e2693e 100644
--- a/README.md
+++ b/README.md
@@ -3,10 +3,14 @@
QQ交流群:[995475200](https://jq.qq.com/?_wv=1027&k=5bz0ne5)
# Demo效果图
-
+
-
+
-
+
-
\ No newline at end of file
+
+
+
+
+