mirror of
https://github.com/zhaopeiym/IoTClient
synced 2025-10-12 21:20:37 +08:00
update ModobusTcp demo
This commit is contained in:
parent
1d604c9d68
commit
5a44588ba4
|
@ -83,16 +83,16 @@
|
|||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="ModBusTcp.cs">
|
||||
<Compile Include="ModBusTcpForm.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Include="ModBusTcp.Designer.cs">
|
||||
<DependentUpon>ModBusTcp.cs</DependentUpon>
|
||||
<Compile Include="ModBusTcpForm.Designer.cs">
|
||||
<DependentUpon>ModBusTcpForm.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<EmbeddedResource Include="ModBusTcp.resx">
|
||||
<DependentUpon>ModBusTcp.cs</DependentUpon>
|
||||
<EmbeddedResource Include="ModBusTcpForm.resx">
|
||||
<DependentUpon>ModBusTcpForm.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Properties\Resources.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
|
|
391
IoTClient.Demo/ModBusTcpForm.Designer.cs
generated
Normal file
391
IoTClient.Demo/ModBusTcpForm.Designer.cs
generated
Normal file
|
@ -0,0 +1,391 @@
|
|||
namespace IoTClient.Demo
|
||||
{
|
||||
partial class ModBusTcpForm
|
||||
{
|
||||
/// <summary>
|
||||
/// 必需的设计器变量。
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// 清理所有正在使用的资源。
|
||||
/// </summary>
|
||||
/// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Windows 窗体设计器生成的代码
|
||||
|
||||
/// <summary>
|
||||
/// 设计器支持所需的方法 - 不要修改
|
||||
/// 使用代码编辑器修改此方法的内容。
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
this.components = new System.ComponentModel.Container();
|
||||
this.toolTip1 = new System.Windows.Forms.ToolTip(this.components);
|
||||
this.button1 = new System.Windows.Forms.Button();
|
||||
this.but_open = new System.Windows.Forms.Button();
|
||||
this.txt_ip = new System.Windows.Forms.TextBox();
|
||||
this.label1 = new System.Windows.Forms.Label();
|
||||
this.label2 = new System.Windows.Forms.Label();
|
||||
this.txt_port = new System.Windows.Forms.TextBox();
|
||||
this.rd_short = new System.Windows.Forms.RadioButton();
|
||||
this.txt_address = new System.Windows.Forms.TextBox();
|
||||
this.label3 = new System.Windows.Forms.Label();
|
||||
this.button3 = new System.Windows.Forms.Button();
|
||||
this.txt_value = new System.Windows.Forms.TextBox();
|
||||
this.label4 = new System.Windows.Forms.Label();
|
||||
this.button4 = new System.Windows.Forms.Button();
|
||||
this.txt_content = new System.Windows.Forms.TextBox();
|
||||
this.txt_stationNumber = new System.Windows.Forms.TextBox();
|
||||
this.label5 = new System.Windows.Forms.Label();
|
||||
this.rd_bit = new System.Windows.Forms.RadioButton();
|
||||
this.rd_ushort = new System.Windows.Forms.RadioButton();
|
||||
this.rd_uint = new System.Windows.Forms.RadioButton();
|
||||
this.rd_int = new System.Windows.Forms.RadioButton();
|
||||
this.rd_ulong = new System.Windows.Forms.RadioButton();
|
||||
this.rd_long = new System.Windows.Forms.RadioButton();
|
||||
this.rd_double = new System.Windows.Forms.RadioButton();
|
||||
this.rd_float = new System.Windows.Forms.RadioButton();
|
||||
this.groupBox1 = new System.Windows.Forms.GroupBox();
|
||||
this.groupBox2 = new System.Windows.Forms.GroupBox();
|
||||
this.groupBox3 = new System.Windows.Forms.GroupBox();
|
||||
this.groupBox1.SuspendLayout();
|
||||
this.groupBox2.SuspendLayout();
|
||||
this.groupBox3.SuspendLayout();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// button1
|
||||
//
|
||||
this.button1.Location = new System.Drawing.Point(548, 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.button1.Click += new System.EventHandler(this.button1_Click);
|
||||
//
|
||||
// but_open
|
||||
//
|
||||
this.but_open.Location = new System.Drawing.Point(309, 18);
|
||||
this.but_open.Name = "but_open";
|
||||
this.but_open.Size = new System.Drawing.Size(75, 23);
|
||||
this.but_open.TabIndex = 1;
|
||||
this.but_open.Text = "连接";
|
||||
this.but_open.UseVisualStyleBackColor = true;
|
||||
this.but_open.Click += new System.EventHandler(this.button2_Click);
|
||||
//
|
||||
// txt_ip
|
||||
//
|
||||
this.txt_ip.Location = new System.Drawing.Point(37, 19);
|
||||
this.txt_ip.Name = "txt_ip";
|
||||
this.txt_ip.Size = new System.Drawing.Size(100, 21);
|
||||
this.txt_ip.TabIndex = 2;
|
||||
this.txt_ip.Text = "127.0.0.1";
|
||||
//
|
||||
// label1
|
||||
//
|
||||
this.label1.AutoSize = true;
|
||||
this.label1.Location = new System.Drawing.Point(8, 24);
|
||||
this.label1.Name = "label1";
|
||||
this.label1.Size = new System.Drawing.Size(29, 12);
|
||||
this.label1.TabIndex = 3;
|
||||
this.label1.Text = "IP:";
|
||||
//
|
||||
// label2
|
||||
//
|
||||
this.label2.AutoSize = true;
|
||||
this.label2.Location = new System.Drawing.Point(148, 24);
|
||||
this.label2.Name = "label2";
|
||||
this.label2.Size = new System.Drawing.Size(41, 12);
|
||||
this.label2.TabIndex = 4;
|
||||
this.label2.Text = "端口:";
|
||||
//
|
||||
// txt_port
|
||||
//
|
||||
this.txt_port.Location = new System.Drawing.Point(193, 19);
|
||||
this.txt_port.Name = "txt_port";
|
||||
this.txt_port.Size = new System.Drawing.Size(100, 21);
|
||||
this.txt_port.TabIndex = 5;
|
||||
this.txt_port.Text = "502";
|
||||
//
|
||||
// rd_short
|
||||
//
|
||||
this.rd_short.AutoSize = true;
|
||||
this.rd_short.Checked = true;
|
||||
this.rd_short.Location = new System.Drawing.Point(70, 23);
|
||||
this.rd_short.Name = "rd_short";
|
||||
this.rd_short.Size = new System.Drawing.Size(53, 16);
|
||||
this.rd_short.TabIndex = 6;
|
||||
this.rd_short.TabStop = true;
|
||||
this.rd_short.Text = "short";
|
||||
this.rd_short.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// txt_address
|
||||
//
|
||||
this.txt_address.Location = new System.Drawing.Point(56, 16);
|
||||
this.txt_address.Name = "txt_address";
|
||||
this.txt_address.Size = new System.Drawing.Size(121, 21);
|
||||
this.txt_address.TabIndex = 9;
|
||||
//
|
||||
// label3
|
||||
//
|
||||
this.label3.AutoSize = true;
|
||||
this.label3.Location = new System.Drawing.Point(9, 22);
|
||||
this.label3.Name = "label3";
|
||||
this.label3.Size = new System.Drawing.Size(41, 12);
|
||||
this.label3.TabIndex = 8;
|
||||
this.label3.Text = "地址:";
|
||||
//
|
||||
// button3
|
||||
//
|
||||
this.button3.Location = new System.Drawing.Point(196, 14);
|
||||
this.button3.Name = "button3";
|
||||
this.button3.Size = new System.Drawing.Size(75, 23);
|
||||
this.button3.TabIndex = 7;
|
||||
this.button3.Text = "读取";
|
||||
this.button3.UseVisualStyleBackColor = true;
|
||||
this.button3.Click += new System.EventHandler(this.button3_Click);
|
||||
//
|
||||
// txt_value
|
||||
//
|
||||
this.txt_value.Location = new System.Drawing.Point(447, 16);
|
||||
this.txt_value.Name = "txt_value";
|
||||
this.txt_value.Size = new System.Drawing.Size(100, 21);
|
||||
this.txt_value.TabIndex = 12;
|
||||
//
|
||||
// label4
|
||||
//
|
||||
this.label4.AutoSize = true;
|
||||
this.label4.Location = new System.Drawing.Point(400, 22);
|
||||
this.label4.Name = "label4";
|
||||
this.label4.Size = new System.Drawing.Size(29, 12);
|
||||
this.label4.TabIndex = 11;
|
||||
this.label4.Text = "值:";
|
||||
//
|
||||
// button4
|
||||
//
|
||||
this.button4.Location = new System.Drawing.Point(567, 15);
|
||||
this.button4.Name = "button4";
|
||||
this.button4.Size = new System.Drawing.Size(75, 23);
|
||||
this.button4.TabIndex = 10;
|
||||
this.button4.Text = "写入";
|
||||
this.button4.UseVisualStyleBackColor = true;
|
||||
this.button4.Click += new System.EventHandler(this.button4_Click);
|
||||
//
|
||||
// txt_content
|
||||
//
|
||||
this.txt_content.Location = new System.Drawing.Point(25, 166);
|
||||
this.txt_content.Multiline = true;
|
||||
this.txt_content.Name = "txt_content";
|
||||
this.txt_content.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
|
||||
this.txt_content.Size = new System.Drawing.Size(656, 272);
|
||||
this.txt_content.TabIndex = 13;
|
||||
//
|
||||
// txt_stationNumber
|
||||
//
|
||||
this.txt_stationNumber.Location = new System.Drawing.Point(457, 18);
|
||||
this.txt_stationNumber.Name = "txt_stationNumber";
|
||||
this.txt_stationNumber.Size = new System.Drawing.Size(35, 21);
|
||||
this.txt_stationNumber.TabIndex = 14;
|
||||
this.txt_stationNumber.Text = "1";
|
||||
//
|
||||
// label5
|
||||
//
|
||||
this.label5.AutoSize = true;
|
||||
this.label5.Location = new System.Drawing.Point(410, 22);
|
||||
this.label5.Name = "label5";
|
||||
this.label5.Size = new System.Drawing.Size(41, 12);
|
||||
this.label5.TabIndex = 15;
|
||||
this.label5.Text = "站号:";
|
||||
//
|
||||
// rd_bit
|
||||
//
|
||||
this.rd_bit.AutoSize = true;
|
||||
this.rd_bit.Location = new System.Drawing.Point(11, 23);
|
||||
this.rd_bit.Name = "rd_bit";
|
||||
this.rd_bit.Size = new System.Drawing.Size(47, 16);
|
||||
this.rd_bit.TabIndex = 16;
|
||||
this.rd_bit.Text = "线圈";
|
||||
this.rd_bit.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// rd_ushort
|
||||
//
|
||||
this.rd_ushort.AutoSize = true;
|
||||
this.rd_ushort.Location = new System.Drawing.Point(129, 23);
|
||||
this.rd_ushort.Name = "rd_ushort";
|
||||
this.rd_ushort.Size = new System.Drawing.Size(59, 16);
|
||||
this.rd_ushort.TabIndex = 17;
|
||||
this.rd_ushort.Text = "ushort";
|
||||
this.rd_ushort.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// rd_uint
|
||||
//
|
||||
this.rd_uint.AutoSize = true;
|
||||
this.rd_uint.Location = new System.Drawing.Point(253, 23);
|
||||
this.rd_uint.Name = "rd_uint";
|
||||
this.rd_uint.Size = new System.Drawing.Size(47, 16);
|
||||
this.rd_uint.TabIndex = 19;
|
||||
this.rd_uint.Text = "uint";
|
||||
this.rd_uint.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// rd_int
|
||||
//
|
||||
this.rd_int.AutoSize = true;
|
||||
this.rd_int.Location = new System.Drawing.Point(194, 23);
|
||||
this.rd_int.Name = "rd_int";
|
||||
this.rd_int.Size = new System.Drawing.Size(41, 16);
|
||||
this.rd_int.TabIndex = 18;
|
||||
this.rd_int.Text = "int";
|
||||
this.rd_int.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// rd_ulong
|
||||
//
|
||||
this.rd_ulong.AutoSize = true;
|
||||
this.rd_ulong.Location = new System.Drawing.Point(374, 23);
|
||||
this.rd_ulong.Name = "rd_ulong";
|
||||
this.rd_ulong.Size = new System.Drawing.Size(53, 16);
|
||||
this.rd_ulong.TabIndex = 21;
|
||||
this.rd_ulong.Text = "ulong";
|
||||
this.rd_ulong.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// rd_long
|
||||
//
|
||||
this.rd_long.AutoSize = true;
|
||||
this.rd_long.Location = new System.Drawing.Point(315, 23);
|
||||
this.rd_long.Name = "rd_long";
|
||||
this.rd_long.Size = new System.Drawing.Size(47, 16);
|
||||
this.rd_long.TabIndex = 20;
|
||||
this.rd_long.Text = "long";
|
||||
this.rd_long.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// rd_double
|
||||
//
|
||||
this.rd_double.AutoSize = true;
|
||||
this.rd_double.Location = new System.Drawing.Point(495, 23);
|
||||
this.rd_double.Name = "rd_double";
|
||||
this.rd_double.Size = new System.Drawing.Size(59, 16);
|
||||
this.rd_double.TabIndex = 23;
|
||||
this.rd_double.Text = "double";
|
||||
this.rd_double.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// rd_float
|
||||
//
|
||||
this.rd_float.AutoSize = true;
|
||||
this.rd_float.Location = new System.Drawing.Point(436, 23);
|
||||
this.rd_float.Name = "rd_float";
|
||||
this.rd_float.Size = new System.Drawing.Size(53, 16);
|
||||
this.rd_float.TabIndex = 22;
|
||||
this.rd_float.Text = "float";
|
||||
this.rd_float.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// groupBox1
|
||||
//
|
||||
this.groupBox1.Controls.Add(this.rd_float);
|
||||
this.groupBox1.Controls.Add(this.rd_double);
|
||||
this.groupBox1.Controls.Add(this.rd_short);
|
||||
this.groupBox1.Controls.Add(this.rd_bit);
|
||||
this.groupBox1.Controls.Add(this.rd_ulong);
|
||||
this.groupBox1.Controls.Add(this.rd_ushort);
|
||||
this.groupBox1.Controls.Add(this.rd_long);
|
||||
this.groupBox1.Controls.Add(this.rd_int);
|
||||
this.groupBox1.Controls.Add(this.rd_uint);
|
||||
this.groupBox1.Location = new System.Drawing.Point(25, 61);
|
||||
this.groupBox1.Name = "groupBox1";
|
||||
this.groupBox1.Size = new System.Drawing.Size(656, 53);
|
||||
this.groupBox1.TabIndex = 24;
|
||||
this.groupBox1.TabStop = false;
|
||||
//
|
||||
// groupBox2
|
||||
//
|
||||
this.groupBox2.Controls.Add(this.button1);
|
||||
this.groupBox2.Controls.Add(this.but_open);
|
||||
this.groupBox2.Controls.Add(this.label5);
|
||||
this.groupBox2.Controls.Add(this.txt_ip);
|
||||
this.groupBox2.Controls.Add(this.txt_stationNumber);
|
||||
this.groupBox2.Controls.Add(this.label1);
|
||||
this.groupBox2.Controls.Add(this.label2);
|
||||
this.groupBox2.Controls.Add(this.txt_port);
|
||||
this.groupBox2.Location = new System.Drawing.Point(25, 9);
|
||||
this.groupBox2.Name = "groupBox2";
|
||||
this.groupBox2.Size = new System.Drawing.Size(656, 54);
|
||||
this.groupBox2.TabIndex = 25;
|
||||
this.groupBox2.TabStop = false;
|
||||
//
|
||||
// groupBox3
|
||||
//
|
||||
this.groupBox3.Controls.Add(this.button3);
|
||||
this.groupBox3.Controls.Add(this.label3);
|
||||
this.groupBox3.Controls.Add(this.txt_address);
|
||||
this.groupBox3.Controls.Add(this.button4);
|
||||
this.groupBox3.Controls.Add(this.txt_value);
|
||||
this.groupBox3.Controls.Add(this.label4);
|
||||
this.groupBox3.Location = new System.Drawing.Point(25, 113);
|
||||
this.groupBox3.Name = "groupBox3";
|
||||
this.groupBox3.Size = new System.Drawing.Size(656, 47);
|
||||
this.groupBox3.TabIndex = 26;
|
||||
this.groupBox3.TabStop = false;
|
||||
//
|
||||
// ModBusTcpForm
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.ClientSize = new System.Drawing.Size(707, 450);
|
||||
this.Controls.Add(this.groupBox3);
|
||||
this.Controls.Add(this.groupBox2);
|
||||
this.Controls.Add(this.groupBox1);
|
||||
this.Controls.Add(this.txt_content);
|
||||
this.Name = "ModBusTcpForm";
|
||||
this.Text = "ModBusTcp";
|
||||
this.Load += new System.EventHandler(this.ModBusTcp_Load);
|
||||
this.groupBox1.ResumeLayout(false);
|
||||
this.groupBox1.PerformLayout();
|
||||
this.groupBox2.ResumeLayout(false);
|
||||
this.groupBox2.PerformLayout();
|
||||
this.groupBox3.ResumeLayout(false);
|
||||
this.groupBox3.PerformLayout();
|
||||
this.ResumeLayout(false);
|
||||
this.PerformLayout();
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private System.Windows.Forms.ToolTip toolTip1;
|
||||
private System.Windows.Forms.Button button1;
|
||||
private System.Windows.Forms.Button but_open;
|
||||
private System.Windows.Forms.TextBox txt_ip;
|
||||
private System.Windows.Forms.Label label1;
|
||||
private System.Windows.Forms.Label label2;
|
||||
private System.Windows.Forms.TextBox txt_port;
|
||||
private System.Windows.Forms.RadioButton rd_short;
|
||||
private System.Windows.Forms.TextBox txt_address;
|
||||
private System.Windows.Forms.Label label3;
|
||||
private System.Windows.Forms.Button button3;
|
||||
private System.Windows.Forms.TextBox txt_value;
|
||||
private System.Windows.Forms.Label label4;
|
||||
private System.Windows.Forms.Button button4;
|
||||
private System.Windows.Forms.TextBox txt_content;
|
||||
private System.Windows.Forms.TextBox txt_stationNumber;
|
||||
private System.Windows.Forms.Label label5;
|
||||
private System.Windows.Forms.RadioButton rd_bit;
|
||||
private System.Windows.Forms.RadioButton rd_ushort;
|
||||
private System.Windows.Forms.RadioButton rd_uint;
|
||||
private System.Windows.Forms.RadioButton rd_int;
|
||||
private System.Windows.Forms.RadioButton rd_ulong;
|
||||
private System.Windows.Forms.RadioButton rd_long;
|
||||
private System.Windows.Forms.RadioButton rd_double;
|
||||
private System.Windows.Forms.RadioButton rd_float;
|
||||
private System.Windows.Forms.GroupBox groupBox1;
|
||||
private System.Windows.Forms.GroupBox groupBox2;
|
||||
private System.Windows.Forms.GroupBox groupBox3;
|
||||
}
|
||||
}
|
||||
|
194
IoTClient.Demo/ModBusTcpForm.cs
Normal file
194
IoTClient.Demo/ModBusTcpForm.cs
Normal file
|
@ -0,0 +1,194 @@
|
|||
using IoTClient.Clients.ModBus;
|
||||
using IoTServer.Servers.ModBus;
|
||||
using System;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace IoTClient.Demo
|
||||
{
|
||||
public partial class ModBusTcpForm : Form
|
||||
{
|
||||
ModBusTcpClient client;
|
||||
ModBusTcpServer server;
|
||||
public ModBusTcpForm()
|
||||
{
|
||||
InitializeComponent();
|
||||
button3.Enabled = false;
|
||||
button4.Enabled = false;
|
||||
toolTip1.SetToolTip(button1, "开启本地ModBusTcp服务端仿真模拟服务");
|
||||
toolTip1.SetToolTip(but_open, "点击打开连接");
|
||||
}
|
||||
|
||||
private void button1_Click(object sender, EventArgs e)
|
||||
{
|
||||
if (server == null)
|
||||
{
|
||||
server = new ModBusTcpServer("127.0.0.1", 502);
|
||||
|
||||
}
|
||||
if (button1.Text == "本地模拟服务")
|
||||
{
|
||||
server.Start();
|
||||
button1.Text = "模拟服务已启动";
|
||||
}
|
||||
else
|
||||
{
|
||||
server.Close();
|
||||
button1.Text = "本地模拟服务";
|
||||
}
|
||||
}
|
||||
|
||||
private void button2_Click(object sender, EventArgs e)
|
||||
{
|
||||
if (but_open.Text == "连接")
|
||||
{
|
||||
client?.Close();
|
||||
client = new ModBusTcpClient(txt_ip.Text?.Trim(), int.Parse(txt_port.Text?.Trim()));
|
||||
if (client.Open())
|
||||
{
|
||||
but_open.Text = "已连接";
|
||||
button3.Enabled = true;
|
||||
button4.Enabled = true;
|
||||
toolTip1.SetToolTip(but_open, "点击关闭连接");
|
||||
}
|
||||
else
|
||||
{
|
||||
MessageBox.Show("连接失败");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
client?.Close();
|
||||
but_open.Text = "连接";
|
||||
toolTip1.SetToolTip(but_open, "点击打开连接");
|
||||
}
|
||||
}
|
||||
|
||||
private void button3_Click(object sender, EventArgs e)
|
||||
{
|
||||
byte.TryParse(txt_stationNumber.Text?.Trim(), out byte stationNumber);
|
||||
if (string.IsNullOrWhiteSpace(txt_address.Text))
|
||||
{
|
||||
MessageBox.Show("请输入地址");
|
||||
return;
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
private void button4_Click(object sender, EventArgs e)
|
||||
{
|
||||
byte.TryParse(txt_stationNumber.Text?.Trim(), out byte stationNumber);
|
||||
if (string.IsNullOrWhiteSpace(txt_address.Text))
|
||||
{
|
||||
MessageBox.Show("请输入地址");
|
||||
return;
|
||||
}
|
||||
if (string.IsNullOrWhiteSpace(txt_value.Text))
|
||||
{
|
||||
MessageBox.Show("请输入值");
|
||||
return;
|
||||
}
|
||||
|
||||
dynamic result = null;
|
||||
if (rd_bit.Checked)
|
||||
{
|
||||
if (!bool.TryParse(txt_value.Text?.Trim(), out bool coil))
|
||||
{
|
||||
if (txt_value.Text?.Trim() == "0")
|
||||
coil = false;
|
||||
else if (txt_value.Text?.Trim() == "1")
|
||||
coil = true;
|
||||
else
|
||||
{
|
||||
MessageBox.Show("请输入 True 或 False");
|
||||
return;
|
||||
}
|
||||
}
|
||||
result = client.Write(txt_address.Text, coil, stationNumber);
|
||||
}
|
||||
else if (rd_short.Checked)
|
||||
{
|
||||
result = client.Write(txt_address.Text, short.Parse(txt_value.Text?.Trim()), stationNumber);
|
||||
}
|
||||
else if (rd_ushort.Checked)
|
||||
{
|
||||
result = client.Write(txt_address.Text, ushort.Parse(txt_value.Text?.Trim()), stationNumber);
|
||||
}
|
||||
else if (rd_int.Checked)
|
||||
{
|
||||
result = client.Write(txt_address.Text, int.Parse(txt_value.Text?.Trim()), stationNumber);
|
||||
}
|
||||
else if (rd_uint.Checked)
|
||||
{
|
||||
result = client.Write(txt_address.Text, uint.Parse(txt_value.Text?.Trim()), stationNumber);
|
||||
}
|
||||
else if (rd_long.Checked)
|
||||
{
|
||||
result = client.Write(txt_address.Text, long.Parse(txt_value.Text?.Trim()), stationNumber);
|
||||
}
|
||||
else if (rd_ulong.Checked)
|
||||
{
|
||||
result = client.Write(txt_address.Text, ulong.Parse(txt_value.Text?.Trim()), stationNumber);
|
||||
}
|
||||
else if (rd_float.Checked)
|
||||
{
|
||||
result = client.Write(txt_address.Text, float.Parse(txt_value.Text?.Trim()), stationNumber);
|
||||
}
|
||||
else if (rd_double.Checked)
|
||||
{
|
||||
result = client.Write(txt_address.Text, double.Parse(txt_value.Text?.Trim()), stationNumber);
|
||||
}
|
||||
|
||||
|
||||
if (result.IsSucceed)
|
||||
txt_content.AppendText($"[{DateTime.Now.ToLongTimeString()}][写入 {txt_address.Text?.Trim()} 成功]:OK\r\n");
|
||||
else
|
||||
txt_content.AppendText($"[{DateTime.Now.ToLongTimeString()}][写入 {txt_address.Text?.Trim()} 失败]:{result.Err}\r\n");
|
||||
}
|
||||
|
||||
private void ModBusTcp_Load(object sender, EventArgs e)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
123
IoTClient.Demo/ModBusTcpForm.resx
Normal file
123
IoTClient.Demo/ModBusTcpForm.resx
Normal file
|
@ -0,0 +1,123 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<metadata name="toolTip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>17, 17</value>
|
||||
</metadata>
|
||||
</root>
|
|
@ -16,7 +16,7 @@ namespace IoTClient.Demo
|
|||
{
|
||||
Application.EnableVisualStyles();
|
||||
Application.SetCompatibleTextRenderingDefault(false);
|
||||
Application.Run(new ModBusTcp());
|
||||
Application.Run(new ModBusTcpForm());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,23 +25,23 @@ namespace IoTClient.Tests.ModBus
|
|||
public async Task 短连接自动开关()
|
||||
{
|
||||
short Number = 33;
|
||||
client.Write(4, Number, stationNumber);
|
||||
client.Write("4", Number, stationNumber);
|
||||
await Task.Delay(500);
|
||||
Assert.True(client.ReadInt16(4, stationNumber).Value == Number);
|
||||
Assert.True(client.ReadInt16("4", stationNumber).Value == Number);
|
||||
|
||||
Number = 34;
|
||||
client.Write(4, Number, stationNumber);
|
||||
client.Write("4", Number, stationNumber);
|
||||
await Task.Delay(500);
|
||||
Assert.True(client.ReadInt16(4, stationNumber).Value == Number);
|
||||
Assert.True(client.ReadInt16("4", stationNumber).Value == Number);
|
||||
|
||||
Number = 1;
|
||||
client.Write(12, Number, stationNumber);
|
||||
client.Write("12", Number, stationNumber);
|
||||
await Task.Delay(500);
|
||||
Assert.True(client.ReadInt16(12, stationNumber).Value == 1);
|
||||
Assert.True(client.ReadInt16("12", stationNumber).Value == 1);
|
||||
Number = 0;
|
||||
client.Write(12, Number, stationNumber);
|
||||
client.Write("12", Number, stationNumber);
|
||||
await Task.Delay(500);
|
||||
Assert.True(client.ReadInt16(12, stationNumber).Value == 0);
|
||||
Assert.True(client.ReadInt16("12", stationNumber).Value == 0);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
@ -50,23 +50,23 @@ namespace IoTClient.Tests.ModBus
|
|||
client.Open();
|
||||
|
||||
short Number = 33;
|
||||
client.Write(4, Number, stationNumber);
|
||||
client.Write("4", Number, stationNumber);
|
||||
await Task.Delay(500);
|
||||
Assert.True(client.ReadInt16(4, stationNumber).Value == Number);
|
||||
Assert.True(client.ReadInt16("4", stationNumber).Value == Number);
|
||||
|
||||
Number = 34;
|
||||
client.Write(4, Number, stationNumber);
|
||||
client.Write("4", Number, stationNumber);
|
||||
await Task.Delay(500);
|
||||
Assert.True(client.ReadInt16(4, stationNumber).Value == Number);
|
||||
Assert.True(client.ReadInt16("4", stationNumber).Value == Number);
|
||||
|
||||
Number = 1;
|
||||
client.Write(12, Number, stationNumber);
|
||||
client.Write("12", Number, stationNumber);
|
||||
await Task.Delay(500);
|
||||
Assert.True(client.ReadInt16(12, stationNumber).Value == 1);
|
||||
Assert.True(client.ReadInt16("12", stationNumber).Value == 1);
|
||||
Number = 0;
|
||||
client.Write(12, Number, stationNumber);
|
||||
client.Write("12", Number, stationNumber);
|
||||
await Task.Delay(500);
|
||||
Assert.True(client.ReadInt16(12, stationNumber).Value == 0);
|
||||
Assert.True(client.ReadInt16("12", stationNumber).Value == 0);
|
||||
|
||||
client.Close();
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@ namespace IoTClient.Clients.ModBus
|
|||
/// <returns></returns>
|
||||
protected override bool Connect()
|
||||
{
|
||||
socket?.Close();
|
||||
socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
||||
try
|
||||
{
|
||||
|
@ -65,7 +66,7 @@ namespace IoTClient.Clients.ModBus
|
|||
/// <param name="functionCode">功能码</param>
|
||||
/// <param name="readLength">读取长度</param>
|
||||
/// <returns></returns>
|
||||
public Result<byte[]> Read(ushort address, byte stationNumber = 1, byte functionCode = 3, ushort readLength = 1)
|
||||
public Result<byte[]> Read(string address, byte stationNumber = 1, byte functionCode = 3, ushort readLength = 1)
|
||||
{
|
||||
ConnectManager();
|
||||
var readResult = new Result<byte[]>();
|
||||
|
@ -113,7 +114,7 @@ namespace IoTClient.Clients.ModBus
|
|||
/// <param name="stationNumber">站号</param>
|
||||
/// <param name="functionCode">功能码</param>
|
||||
/// <returns></returns>
|
||||
public Result<short> ReadInt16(ushort address, byte stationNumber = 1, byte functionCode = 3)
|
||||
public Result<short> ReadInt16(string address, byte stationNumber = 1, byte functionCode = 3)
|
||||
{
|
||||
var readResut = Read(address, stationNumber, functionCode);
|
||||
var result = new Result<short>()
|
||||
|
@ -127,6 +128,27 @@ namespace IoTClient.Clients.ModBus
|
|||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 读取UInt16
|
||||
/// </summary>
|
||||
/// <param name="address">寄存器起始地址</param>
|
||||
/// <param name="stationNumber">站号</param>
|
||||
/// <param name="functionCode">功能码</param>
|
||||
/// <returns></returns>
|
||||
public Result<ushort> ReadUInt16(string address, byte stationNumber = 1, byte functionCode = 3)
|
||||
{
|
||||
var readResut = Read(address, stationNumber, functionCode);
|
||||
var result = new Result<ushort>()
|
||||
{
|
||||
IsSucceed = readResut.IsSucceed,
|
||||
Err = readResut.Err,
|
||||
ErrList = readResut.ErrList,
|
||||
};
|
||||
if (result.IsSucceed)
|
||||
result.Value = BitConverter.ToUInt16(readResut.Value, 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 读取Int32
|
||||
/// </summary>
|
||||
|
@ -134,7 +156,7 @@ namespace IoTClient.Clients.ModBus
|
|||
/// <param name="stationNumber">站号</param>
|
||||
/// <param name="functionCode">功能码</param>
|
||||
/// <returns></returns>
|
||||
public Result<int> ReadInt32(ushort address, byte stationNumber = 1, byte functionCode = 3)
|
||||
public Result<int> ReadInt32(string address, byte stationNumber = 1, byte functionCode = 3)
|
||||
{
|
||||
var readResut = Read(address, stationNumber, functionCode, readLength: 2);
|
||||
var result = new Result<int>()
|
||||
|
@ -148,6 +170,27 @@ namespace IoTClient.Clients.ModBus
|
|||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 读取UInt32
|
||||
/// </summary>
|
||||
/// <param name="address">寄存器起始地址</param>
|
||||
/// <param name="stationNumber">站号</param>
|
||||
/// <param name="functionCode">功能码</param>
|
||||
/// <returns></returns>
|
||||
public Result<uint> ReadUInt32(string address, byte stationNumber = 1, byte functionCode = 3)
|
||||
{
|
||||
var readResut = Read(address, stationNumber, functionCode, readLength: 2);
|
||||
var result = new Result<uint>()
|
||||
{
|
||||
IsSucceed = readResut.IsSucceed,
|
||||
Err = readResut.Err,
|
||||
ErrList = readResut.ErrList,
|
||||
};
|
||||
if (result.IsSucceed)
|
||||
result.Value = BitConverter.ToUInt32(readResut.Value, 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 读取Int64
|
||||
/// </summary>
|
||||
|
@ -155,9 +198,9 @@ namespace IoTClient.Clients.ModBus
|
|||
/// <param name="stationNumber">站号</param>
|
||||
/// <param name="functionCode">功能码</param>
|
||||
/// <returns></returns>
|
||||
public Result<long> ReadInt64(ushort address, byte stationNumber = 1, byte functionCode = 3)
|
||||
public Result<long> ReadInt64(string address, byte stationNumber = 1, byte functionCode = 3)
|
||||
{
|
||||
var readResut = Read(address, stationNumber, functionCode, readLength: 2);
|
||||
var readResut = Read(address, stationNumber, functionCode, readLength: 4);
|
||||
var result = new Result<long>()
|
||||
{
|
||||
IsSucceed = readResut.IsSucceed,
|
||||
|
@ -169,6 +212,27 @@ namespace IoTClient.Clients.ModBus
|
|||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 读取UInt64
|
||||
/// </summary>
|
||||
/// <param name="address">寄存器起始地址</param>
|
||||
/// <param name="stationNumber">站号</param>
|
||||
/// <param name="functionCode">功能码</param>
|
||||
/// <returns></returns>
|
||||
public Result<ulong> ReadUInt64(string address, byte stationNumber = 1, byte functionCode = 3)
|
||||
{
|
||||
var readResut = Read(address, stationNumber, functionCode, readLength: 4);
|
||||
var result = new Result<ulong>()
|
||||
{
|
||||
IsSucceed = readResut.IsSucceed,
|
||||
Err = readResut.Err,
|
||||
ErrList = readResut.ErrList,
|
||||
};
|
||||
if (result.IsSucceed)
|
||||
result.Value = BitConverter.ToUInt64(readResut.Value, 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 读取Float
|
||||
/// </summary>
|
||||
|
@ -176,7 +240,7 @@ namespace IoTClient.Clients.ModBus
|
|||
/// <param name="stationNumber">站号</param>
|
||||
/// <param name="functionCode">功能码</param>
|
||||
/// <returns></returns>
|
||||
public Result<float> ReadFloat(ushort address, byte stationNumber = 1, byte functionCode = 3)
|
||||
public Result<float> ReadFloat(string address, byte stationNumber = 1, byte functionCode = 3)
|
||||
{
|
||||
var readResut = Read(address, stationNumber, functionCode, readLength: 2);
|
||||
var result = new Result<float>()
|
||||
|
@ -197,9 +261,9 @@ namespace IoTClient.Clients.ModBus
|
|||
/// <param name="stationNumber">站号</param>
|
||||
/// <param name="functionCode">功能码</param>
|
||||
/// <returns></returns>
|
||||
public Result<double> ReadDouble(ushort address, byte stationNumber = 1, byte functionCode = 3)
|
||||
public Result<double> ReadDouble(string address, byte stationNumber = 1, byte functionCode = 3)
|
||||
{
|
||||
var readResut = Read(address, stationNumber, functionCode, readLength: 2);
|
||||
var readResut = Read(address, stationNumber, functionCode, readLength: 4);
|
||||
var result = new Result<double>()
|
||||
{
|
||||
IsSucceed = readResut.IsSucceed,
|
||||
|
@ -218,7 +282,7 @@ namespace IoTClient.Clients.ModBus
|
|||
/// <param name="stationNumber">站号</param>
|
||||
/// <param name="functionCode">功能码</param>
|
||||
/// <returns></returns>
|
||||
public Result<bool> ReadCoil(ushort address, byte stationNumber = 1, byte functionCode = 1)
|
||||
public Result<bool> ReadCoil(string address, byte stationNumber = 1, byte functionCode = 1)
|
||||
{
|
||||
var readResut = Read(address, stationNumber, functionCode);
|
||||
var result = new Result<bool>()
|
||||
|
@ -234,6 +298,7 @@ namespace IoTClient.Clients.ModBus
|
|||
#endregion
|
||||
|
||||
#region Write 写入
|
||||
|
||||
/// <summary>
|
||||
/// 线圈写入
|
||||
/// </summary>
|
||||
|
@ -241,7 +306,7 @@ namespace IoTClient.Clients.ModBus
|
|||
/// <param name="value"></param>
|
||||
/// <param name="stationNumber"></param>
|
||||
/// <param name="functionCode"></param>
|
||||
public Result Write(ushort address, bool value, byte stationNumber = 1, byte functionCode = 5)
|
||||
public Result Write(string address, bool value, byte stationNumber = 1, byte functionCode = 5)
|
||||
{
|
||||
ConnectManager();
|
||||
var result = new Result();
|
||||
|
@ -249,6 +314,11 @@ namespace IoTClient.Clients.ModBus
|
|||
{
|
||||
var command = GetWriteCoilCommand(address, value, stationNumber, functionCode);
|
||||
socket.Send(command);
|
||||
|
||||
//获取响应报文
|
||||
var headBytes = SocketRead(socket, 8);
|
||||
int length = headBytes[4] * 256 + headBytes[5] - 2;
|
||||
SocketRead(socket, length);
|
||||
}
|
||||
catch (SocketException ex)
|
||||
{
|
||||
|
@ -274,17 +344,17 @@ namespace IoTClient.Clients.ModBus
|
|||
/// <summary>
|
||||
/// 写入
|
||||
/// </summary>
|
||||
/// <param name="address">寄存器地址</param>
|
||||
/// <param name="value">写入的值</param>
|
||||
/// <param name="stationNumber">站号</param>
|
||||
/// <param name="functionCode">功能码</param>
|
||||
public Result Write(ushort address, short value, byte stationNumber = 1, byte functionCode = 16)
|
||||
/// <param name="address"></param>
|
||||
/// <param name="values"></param>
|
||||
/// <param name="stationNumber"></param>
|
||||
/// <param name="functionCode"></param>
|
||||
/// <returns></returns>
|
||||
public Result Write(string address, byte[] values, byte stationNumber = 1, byte functionCode = 16)
|
||||
{
|
||||
ConnectManager();
|
||||
var result = new Result();
|
||||
try
|
||||
{
|
||||
var values = BitConverter.GetBytes(value).Reverse().ToArray();
|
||||
var command = GetWriteCommand(address, values, stationNumber, functionCode);
|
||||
socket.Send(command);
|
||||
|
||||
|
@ -321,40 +391,10 @@ namespace IoTClient.Clients.ModBus
|
|||
/// <param name="value">写入的值</param>
|
||||
/// <param name="stationNumber">站号</param>
|
||||
/// <param name="functionCode">功能码</param>
|
||||
public Result Write(ushort address, int value, byte stationNumber = 1, byte functionCode = 16)
|
||||
public Result Write(string address, short value, byte stationNumber = 1, byte functionCode = 16)
|
||||
{
|
||||
ConnectManager();
|
||||
var result = new Result();
|
||||
try
|
||||
{
|
||||
var values = BitConverter.GetBytes(value).Reverse().ToArray();
|
||||
var command = GetWriteCommand(address, values, stationNumber, functionCode);
|
||||
socket.Send(command);
|
||||
|
||||
//获取响应报文
|
||||
var headBytes = SocketRead(socket, 8);
|
||||
int length = headBytes[4] * 256 + headBytes[5] - 2;
|
||||
SocketRead(socket, length);
|
||||
}
|
||||
catch (SocketException ex)
|
||||
{
|
||||
result.IsSucceed = false;
|
||||
if (ex.SocketErrorCode == SocketError.TimedOut)
|
||||
{
|
||||
result.Err = "连接超时";
|
||||
result.ErrList.Add("连接超时");
|
||||
}
|
||||
else
|
||||
{
|
||||
result.Err = ex.Message;
|
||||
result.ErrList.Add(ex.Message);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (isAutoOpen.Value) Dispose();
|
||||
}
|
||||
return result;
|
||||
var values = BitConverter.GetBytes(value).Reverse().ToArray();
|
||||
return Write(address, values, stationNumber, functionCode);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -364,40 +404,10 @@ namespace IoTClient.Clients.ModBus
|
|||
/// <param name="value">写入的值</param>
|
||||
/// <param name="stationNumber">站号</param>
|
||||
/// <param name="functionCode">功能码</param>
|
||||
public Result Write(ushort address, long value, byte stationNumber = 1, byte functionCode = 16)
|
||||
public Result Write(string address, ushort value, byte stationNumber = 1, byte functionCode = 16)
|
||||
{
|
||||
ConnectManager();
|
||||
var result = new Result();
|
||||
try
|
||||
{
|
||||
var values = BitConverter.GetBytes(value).Reverse().ToArray();
|
||||
var command = GetWriteCommand(address, values, stationNumber, functionCode);
|
||||
socket.Send(command);
|
||||
|
||||
//获取响应报文
|
||||
var headBytes = SocketRead(socket, 8);
|
||||
int length = headBytes[4] * 256 + headBytes[5] - 2;
|
||||
SocketRead(socket, length);
|
||||
}
|
||||
catch (SocketException ex)
|
||||
{
|
||||
result.IsSucceed = false;
|
||||
if (ex.SocketErrorCode == SocketError.TimedOut)
|
||||
{
|
||||
result.Err = "连接超时";
|
||||
result.ErrList.Add("连接超时");
|
||||
}
|
||||
else
|
||||
{
|
||||
result.Err = ex.Message;
|
||||
result.ErrList.Add(ex.Message);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (isAutoOpen.Value) Dispose();
|
||||
}
|
||||
return result;
|
||||
var values = BitConverter.GetBytes(value).Reverse().ToArray();
|
||||
return Write(address, values, stationNumber, functionCode);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -407,40 +417,10 @@ namespace IoTClient.Clients.ModBus
|
|||
/// <param name="value">写入的值</param>
|
||||
/// <param name="stationNumber">站号</param>
|
||||
/// <param name="functionCode">功能码</param>
|
||||
public Result Write(ushort address, float value, byte stationNumber = 1, byte functionCode = 16)
|
||||
public Result Write(string address, int value, byte stationNumber = 1, byte functionCode = 16)
|
||||
{
|
||||
ConnectManager();
|
||||
var result = new Result();
|
||||
try
|
||||
{
|
||||
var values = BitConverter.GetBytes(value).Reverse().ToArray();
|
||||
var command = GetWriteCommand(address, values, stationNumber, functionCode);
|
||||
socket.Send(command);
|
||||
|
||||
//获取响应报文
|
||||
var headBytes = SocketRead(socket, 8);
|
||||
int length = headBytes[4] * 256 + headBytes[5] - 2;
|
||||
SocketRead(socket, length);
|
||||
}
|
||||
catch (SocketException ex)
|
||||
{
|
||||
result.IsSucceed = false;
|
||||
if (ex.SocketErrorCode == SocketError.TimedOut)
|
||||
{
|
||||
result.Err = "连接超时";
|
||||
result.ErrList.Add("连接超时");
|
||||
}
|
||||
else
|
||||
{
|
||||
result.Err = ex.Message;
|
||||
result.ErrList.Add(ex.Message);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (isAutoOpen.Value) Dispose();
|
||||
}
|
||||
return result;
|
||||
var values = BitConverter.GetBytes(value).Reverse().ToArray();
|
||||
return Write(address, values, stationNumber, functionCode);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -450,40 +430,62 @@ namespace IoTClient.Clients.ModBus
|
|||
/// <param name="value">写入的值</param>
|
||||
/// <param name="stationNumber">站号</param>
|
||||
/// <param name="functionCode">功能码</param>
|
||||
public Result Write(ushort address, double value, byte stationNumber = 1, byte functionCode = 16)
|
||||
public Result Write(string address, uint value, byte stationNumber = 1, byte functionCode = 16)
|
||||
{
|
||||
ConnectManager();
|
||||
var result = new Result();
|
||||
try
|
||||
{
|
||||
var values = BitConverter.GetBytes(value).Reverse().ToArray();
|
||||
var command = GetWriteCommand(address, values, stationNumber, functionCode);
|
||||
socket.Send(command);
|
||||
var values = BitConverter.GetBytes(value).Reverse().ToArray();
|
||||
return Write(address, values, stationNumber, functionCode);
|
||||
}
|
||||
|
||||
//获取响应报文
|
||||
var headBytes = SocketRead(socket, 8);
|
||||
int length = headBytes[4] * 256 + headBytes[5] - 2;
|
||||
SocketRead(socket, length);
|
||||
}
|
||||
catch (SocketException ex)
|
||||
{
|
||||
result.IsSucceed = false;
|
||||
if (ex.SocketErrorCode == SocketError.TimedOut)
|
||||
{
|
||||
result.Err = "连接超时";
|
||||
result.ErrList.Add("连接超时");
|
||||
}
|
||||
else
|
||||
{
|
||||
result.Err = ex.Message;
|
||||
result.ErrList.Add(ex.Message);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (isAutoOpen.Value) Dispose();
|
||||
}
|
||||
return result;
|
||||
/// <summary>
|
||||
/// 写入
|
||||
/// </summary>
|
||||
/// <param name="address">寄存器地址</param>
|
||||
/// <param name="value">写入的值</param>
|
||||
/// <param name="stationNumber">站号</param>
|
||||
/// <param name="functionCode">功能码</param>
|
||||
public Result Write(string address, long value, byte stationNumber = 1, byte functionCode = 16)
|
||||
{
|
||||
var values = BitConverter.GetBytes(value).Reverse().ToArray();
|
||||
return Write(address, values, stationNumber, functionCode);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 写入
|
||||
/// </summary>
|
||||
/// <param name="address">寄存器地址</param>
|
||||
/// <param name="value">写入的值</param>
|
||||
/// <param name="stationNumber">站号</param>
|
||||
/// <param name="functionCode">功能码</param>
|
||||
public Result Write(string address, ulong value, byte stationNumber = 1, byte functionCode = 16)
|
||||
{
|
||||
var values = BitConverter.GetBytes(value).Reverse().ToArray();
|
||||
return Write(address, values, stationNumber, functionCode);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 写入
|
||||
/// </summary>
|
||||
/// <param name="address">寄存器地址</param>
|
||||
/// <param name="value">写入的值</param>
|
||||
/// <param name="stationNumber">站号</param>
|
||||
/// <param name="functionCode">功能码</param>
|
||||
public Result Write(string address, float value, byte stationNumber = 1, byte functionCode = 16)
|
||||
{
|
||||
var values = BitConverter.GetBytes(value).Reverse().ToArray();
|
||||
return Write(address, values, stationNumber, functionCode);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 写入
|
||||
/// </summary>
|
||||
/// <param name="address">寄存器地址</param>
|
||||
/// <param name="value">写入的值</param>
|
||||
/// <param name="stationNumber">站号</param>
|
||||
/// <param name="functionCode">功能码</param>
|
||||
public Result Write(string address, double value, byte stationNumber = 1, byte functionCode = 16)
|
||||
{
|
||||
var values = BitConverter.GetBytes(value).Reverse().ToArray();
|
||||
return Write(address, values, stationNumber, functionCode);
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
@ -497,8 +499,9 @@ namespace IoTClient.Clients.ModBus
|
|||
/// <param name="functionCode">功能码</param>
|
||||
/// <param name="length">读取长度</param>
|
||||
/// <returns></returns>
|
||||
public byte[] GetReadCommand(ushort address, byte stationNumber, byte functionCode, ushort length)
|
||||
public byte[] GetReadCommand(string address, byte stationNumber, byte functionCode, ushort length)
|
||||
{
|
||||
var readAddress = ushort.Parse(address?.Trim());
|
||||
byte[] buffer = new byte[12];
|
||||
buffer[0] = 0x19;
|
||||
buffer[1] = 0xB2;//Client发出的检验信息
|
||||
|
@ -509,8 +512,8 @@ namespace IoTClient.Clients.ModBus
|
|||
|
||||
buffer[6] = stationNumber; //站号
|
||||
buffer[7] = functionCode; //功能码
|
||||
buffer[8] = BitConverter.GetBytes(address)[1];
|
||||
buffer[9] = BitConverter.GetBytes(address)[0];//寄存器地址
|
||||
buffer[8] = BitConverter.GetBytes(readAddress)[1];
|
||||
buffer[9] = BitConverter.GetBytes(readAddress)[0];//寄存器地址
|
||||
buffer[10] = BitConverter.GetBytes(length)[1];
|
||||
buffer[11] = BitConverter.GetBytes(length)[0];//表示request 寄存器的长度(寄存器个数)
|
||||
return buffer;
|
||||
|
@ -524,8 +527,9 @@ namespace IoTClient.Clients.ModBus
|
|||
/// <param name="stationNumber">站号</param>
|
||||
/// <param name="functionCode">功能码</param>
|
||||
/// <returns></returns>
|
||||
public byte[] GetWriteCommand(ushort address, byte[] values, byte stationNumber, byte functionCode)
|
||||
public byte[] GetWriteCommand(string address, byte[] values, byte stationNumber, byte functionCode)
|
||||
{
|
||||
var writeAddress = ushort.Parse(address?.Trim());
|
||||
byte[] buffer = new byte[13 + values.Length];
|
||||
buffer[0] = 0x19;
|
||||
buffer[1] = 0xB2;//检验信息,用来验证response是否串数据了
|
||||
|
@ -534,8 +538,8 @@ namespace IoTClient.Clients.ModBus
|
|||
|
||||
buffer[6] = stationNumber; //站号
|
||||
buffer[7] = functionCode; //功能码
|
||||
buffer[8] = BitConverter.GetBytes(address)[1];
|
||||
buffer[9] = BitConverter.GetBytes(address)[0];//寄存器地址
|
||||
buffer[8] = BitConverter.GetBytes(writeAddress)[1];
|
||||
buffer[9] = BitConverter.GetBytes(writeAddress)[0];//寄存器地址
|
||||
buffer[10] = (byte)(values.Length / 2 / 256);
|
||||
buffer[11] = (byte)(values.Length / 2 % 256);//写寄存器数量(除2是两个字节一个寄存器,寄存器16位。除以256是byte最大存储255。)
|
||||
buffer[12] = (byte)(values.Length); //写字节的个数
|
||||
|
@ -551,8 +555,9 @@ namespace IoTClient.Clients.ModBus
|
|||
/// <param name="stationNumber">站号</param>
|
||||
/// <param name="functionCode">功能码</param>
|
||||
/// <returns></returns>
|
||||
public byte[] GetWriteCoilCommand(ushort address, bool value, byte stationNumber, byte functionCode)
|
||||
public byte[] GetWriteCoilCommand(string address, bool value, byte stationNumber, byte functionCode)
|
||||
{
|
||||
var writeAddress = ushort.Parse(address?.Trim());
|
||||
byte[] buffer = new byte[12];
|
||||
buffer[0] = 0x19;
|
||||
buffer[1] = 0xB2;//Client发出的检验信息
|
||||
|
@ -561,8 +566,8 @@ namespace IoTClient.Clients.ModBus
|
|||
|
||||
buffer[6] = stationNumber;//站号
|
||||
buffer[7] = functionCode; //功能码
|
||||
buffer[8] = BitConverter.GetBytes(address)[1];
|
||||
buffer[9] = BitConverter.GetBytes(address)[0];//寄存器地址
|
||||
buffer[8] = BitConverter.GetBytes(writeAddress)[1];
|
||||
buffer[9] = BitConverter.GetBytes(writeAddress)[0];//寄存器地址
|
||||
buffer[10] = (byte)(value ? 0xFF : 0x00); //此处只可以是FF表示闭合00表示断开,其他数值非法
|
||||
buffer[11] = 0x00;
|
||||
return buffer;
|
||||
|
|
|
@ -50,7 +50,7 @@ namespace IoTClient.Core
|
|||
{
|
||||
try
|
||||
{
|
||||
socket?.Shutdown(SocketShutdown.Both);//正常关闭连接
|
||||
if (socket.Connected) socket?.Shutdown(SocketShutdown.Both);//正常关闭连接
|
||||
socket?.Close();
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -11,16 +11,13 @@ namespace IoTServer.Servers.ModBus
|
|||
{
|
||||
private Socket socketServer;
|
||||
private string redisConfig;
|
||||
private string ip;
|
||||
private int port;
|
||||
public ModBusTcpServer(string ip, int port, string redisConfig = null)
|
||||
{
|
||||
this.redisConfig = redisConfig;
|
||||
|
||||
//1 创建Socket对象
|
||||
socketServer = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
||||
|
||||
//2 绑定ip和端口
|
||||
IPEndPoint ipEndPoint = new IPEndPoint(IPAddress.Parse(ip), port);
|
||||
socketServer.Bind(ipEndPoint);
|
||||
this.ip = ip;
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -28,12 +25,26 @@ namespace IoTServer.Servers.ModBus
|
|||
/// </summary>
|
||||
public void Start()
|
||||
{
|
||||
//1 创建Socket对象
|
||||
socketServer = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
||||
|
||||
//2 绑定ip和端口
|
||||
IPEndPoint ipEndPoint = new IPEndPoint(IPAddress.Parse(ip), port);
|
||||
socketServer.Bind(ipEndPoint);
|
||||
|
||||
//3、开启侦听(等待客户机发出的连接),并设置最大客户端连接数为10
|
||||
socketServer.Listen(10);
|
||||
|
||||
Task.Run(() => { Accept(socketServer); });
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
if (socketServer?.Connected ?? false)
|
||||
socketServer.Shutdown(SocketShutdown.Both);
|
||||
socketServer?.Close();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 客户端连接到服务端
|
||||
/// </summary>
|
||||
|
@ -42,9 +53,18 @@ namespace IoTServer.Servers.ModBus
|
|||
{
|
||||
while (true)
|
||||
{
|
||||
//阻塞等待客户端连接
|
||||
Socket newSocket = socket.Accept();
|
||||
Task.Run(() => { Receive(newSocket); });
|
||||
try
|
||||
{
|
||||
//阻塞等待客户端连接
|
||||
Socket newSocket = socket.Accept();
|
||||
Task.Run(() => { Receive(newSocket); });
|
||||
}
|
||||
catch (SocketException ex)
|
||||
{
|
||||
if (ex.SocketErrorCode != SocketError.Interrupted)
|
||||
throw ex;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -84,6 +104,14 @@ namespace IoTServer.Servers.ModBus
|
|||
|
||||
switch (requetData[7])
|
||||
{
|
||||
//读取线圈
|
||||
case 1:
|
||||
//TODO
|
||||
break;
|
||||
//写入线圈
|
||||
case 5:
|
||||
//TODO
|
||||
break;
|
||||
//读取
|
||||
case 3:
|
||||
{
|
||||
|
@ -102,7 +130,8 @@ namespace IoTServer.Servers.ModBus
|
|||
case 16:
|
||||
{
|
||||
//TODO
|
||||
data.Write(requetData[9], requetData[requetData.Length - 1].ToString());
|
||||
var value = requetData[requetData.Length - 2] * 256 + requetData[requetData.Length - 1];
|
||||
data.Write(requetData[9], value.ToString());
|
||||
var responseData = new byte[12];
|
||||
Buffer.BlockCopy(requetData, 0, responseData, 0, responseData.Length);
|
||||
responseData[5] = 6;
|
||||
|
@ -111,10 +140,11 @@ namespace IoTServer.Servers.ModBus
|
|||
break;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
catch (SocketException ex)
|
||||
{
|
||||
//todo
|
||||
throw ex;
|
||||
if (ex.SocketErrorCode != SocketError.ConnectionRefused)
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user