1
0
mirror of https://github.com/zhaopeiym/IoTClient synced 2025-10-12 21:20:37 +08:00

S7-200Smart 批量读取

This commit is contained in:
BennyZhao 2020-01-06 08:53:40 +08:00
parent 67d5457e28
commit c817874462
12 changed files with 659 additions and 156 deletions

View File

@ -359,7 +359,6 @@ namespace IoTClient.Tool.Controls
/// <param name="e"></param>
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))
{
@ -373,7 +372,7 @@ namespace IoTClient.Tool.Controls
}
try
{
var address = txt_address.Text?.Trim().Split('-')[0];
dynamic result = null;
if (rd_bit.Checked)
{

View File

@ -241,7 +241,7 @@ namespace IoTClient.Tool
}
try
{
var address = txt_address.Text.Split('-')[0];
dynamic result = null;
if (rd_bit.Checked)
{
@ -257,39 +257,39 @@ namespace IoTClient.Tool
return;
}
}
result = client.Write(txt_address.Text, coil, stationNumber);
result = client.Write(address, coil, stationNumber);
}
else if (rd_short.Checked)
{
result = client.Write(txt_address.Text, short.Parse(txt_value.Text?.Trim()), stationNumber);
result = client.Write(address, 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);
result = client.Write(address, 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);
result = client.Write(address, 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);
result = client.Write(address, 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);
result = client.Write(address, 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);
result = client.Write(address, 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);
result = client.Write(address, 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);
result = client.Write(address, double.Parse(txt_value.Text?.Trim()), stationNumber);
}
else if (rd_discrete.Checked)
{
@ -298,9 +298,9 @@ namespace IoTClient.Tool
}
if (result.IsSucceed)
AppendText($"[写入 {txt_address.Text?.Trim()} 成功]{txt_value.Text?.Trim()} OK");
AppendText($"[写入 {address?.Trim()} 成功]{txt_value.Text?.Trim()} OK");
else
AppendText($"[写入 {txt_address.Text?.Trim()} 失败]{result.Err}");
AppendText($"[写入 {address?.Trim()} 失败]{result.Err}");
if (chb_show_package.Checked || (ModifierKeys & Keys.Control) == Keys.Control)
{
AppendText($"[请求报文]{result.Requst}");

View File

@ -22,6 +22,12 @@ namespace IoTClient.Tool.Controls
private void but_crc16calculate_Click(object sender, EventArgs e)
{
if (string.IsNullOrWhiteSpace(txt_crcstr.Text) || txt_crcstr.Text.Trim().Replace(" ", "").Length % 2 != 0)
{
MessageBox.Show("请传入有效的参数");
return;
}
var byteArry = DataConvert.StringToByteArray(txt_crcstr.Text?.Trim(), false);
var crc16 = CRC16.GetCRC16(byteArry);
AppendText($"CRC16计算结果{DataConvert.ByteArrayToString(crc16)}");
@ -37,6 +43,12 @@ namespace IoTClient.Tool.Controls
private void but_crc16validation_Click(object sender, EventArgs e)
{
if (string.IsNullOrWhiteSpace(txt_crcstr.Text) || txt_crcstr.Text.Trim().Replace(" ", "").Length % 2 != 0)
{
MessageBox.Show("请传入有效的参数");
return;
}
var byteArry = DataConvert.StringToByteArray(txt_crcstr.Text?.Trim(), false);
var checkCrc16 = CRC16.CheckCRC16(byteArry);
AppendText($"CRC16验证结果{txt_crcstr.Text} {checkCrc16}");
@ -54,6 +66,12 @@ namespace IoTClient.Tool.Controls
private void but_tcpOpen_Click(object sender, EventArgs e)
{
if (string.IsNullOrWhiteSpace(txt_tcpip.Text) || string.IsNullOrWhiteSpace(txt_tcpport.Text))
{
MessageBox.Show("请传入有效的IP和端口");
return;
}
socketTcp?.Close();
socketTcp = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
try
@ -113,6 +131,12 @@ namespace IoTClient.Tool.Controls
private void but_udpOpen_Click(object sender, EventArgs e)
{
if (string.IsNullOrWhiteSpace(txt_tcpip.Text) || string.IsNullOrWhiteSpace(txt_tcpport.Text))
{
MessageBox.Show("请传入有效的IP和端口");
return;
}
try
{
udpClient = new UdpClient();

View File

@ -59,9 +59,9 @@
this.but_close_server = new System.Windows.Forms.Button();
this.but_close = new System.Windows.Forms.Button();
this.groupBox1 = new System.Windows.Forms.GroupBox();
this.rd_byte = new System.Windows.Forms.RadioButton();
this.button3 = new System.Windows.Forms.Button();
this.txt_content = new System.Windows.Forms.TextBox();
this.rd_byte = new System.Windows.Forms.RadioButton();
this.groupBox3.SuspendLayout();
this.groupBox2.SuspendLayout();
this.groupBox1.SuspendLayout();
@ -366,6 +366,16 @@
this.groupBox1.TabIndex = 32;
this.groupBox1.TabStop = false;
//
// rd_byte
//
this.rd_byte.AutoSize = true;
this.rd_byte.Location = new System.Drawing.Point(54, 23);
this.rd_byte.Name = "rd_byte";
this.rd_byte.Size = new System.Drawing.Size(47, 16);
this.rd_byte.TabIndex = 25;
this.rd_byte.Text = "byte";
this.rd_byte.UseVisualStyleBackColor = true;
//
// button3
//
this.button3.Location = new System.Drawing.Point(762, 17);
@ -386,16 +396,6 @@
this.txt_content.Size = new System.Drawing.Size(855, 272);
this.txt_content.TabIndex = 31;
//
// rd_byte
//
this.rd_byte.AutoSize = true;
this.rd_byte.Location = new System.Drawing.Point(54, 23);
this.rd_byte.Name = "rd_byte";
this.rd_byte.Size = new System.Drawing.Size(47, 16);
this.rd_byte.TabIndex = 25;
this.rd_byte.Text = "byte";
this.rd_byte.UseVisualStyleBackColor = true;
//
// SiemensControl
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
@ -406,6 +406,7 @@
this.Controls.Add(this.txt_content);
this.Name = "SiemensControl";
this.Size = new System.Drawing.Size(880, 450);
this.ControlRemoved += new System.Windows.Forms.ControlEventHandler(this.SiemensControl_ControlRemoved);
this.groupBox3.ResumeLayout(false);
this.groupBox3.PerformLayout();
this.groupBox2.ResumeLayout(false);

View File

@ -47,12 +47,17 @@ namespace IoTClient.Tool
but_close_server.Enabled = false;
but_close.Enabled = false;
but_sendData.Enabled = false;
toolTip1.SetToolTip(but_open, "点击打开连接");
toolTip1.SetToolTip(txt_address, "支持批量读取如V2634-3将会读取V2634、V2638、V2642地址对应的数据");
txt_content.Text = "小技巧:\r\n1、读取地址支持批量读取如V2634-3将会读取V2634、V2638、V2642地址对应的数据\r\n";
}
private void but_server_Click(object sender, EventArgs e)
{
try
{
if (txt_content.Text.Contains("小技巧")) txt_content.Text = string.Empty;
server?.Stop();
server = new SiemensServer(int.Parse(txt_port.Text.Trim()));
server.Start();
@ -78,6 +83,7 @@ namespace IoTClient.Tool
{
try
{
if (txt_content.Text.Contains("小技巧")) txt_content.Text = string.Empty;
client?.Close();
client = new SiemensClient(SiemensVersion.S7_200Smart, txt_ip.Text?.Trim(), int.Parse(txt_port.Text.Trim()));
var result = client.Open();
@ -122,51 +128,118 @@ namespace IoTClient.Tool
return;
}
dynamic result = null;
if (rd_byte.Checked)
//bool类型不进行批量读取
if (rd_bit.Checked) txt_address.Text = txt_address.Text.Split('-')[0];
var addressAndReadLength = txt_address.Text.Split('-');
//批量读取
if (addressAndReadLength.Length == 2)
{
result = client.ReadByte(txt_address.Text);
var address = addressAndReadLength[0];
var readNumber = ushort.Parse(addressAndReadLength[1]);
ushort bLength = 1;
if (rd_bit.Checked)
bLength = 2;
else if (rd_byte.Checked)
bLength = 1;
else if (rd_short.Checked || rd_ushort.Checked)
bLength = 2;
else if (rd_int.Checked || rd_uint.Checked || rd_float.Checked)
bLength = 4;
else if (rd_long.Checked || rd_ulong.Checked || rd_double.Checked)
bLength = 8;
var readLength = Convert.ToUInt16(bLength * readNumber);
if (!rd_bit.Checked) result = client.Read(address.ToString(), readLength, false);
else result = client.Read(address.ToString(), readLength, true);
var addressNumber = int.Parse(address.Substring(1));
if (result.IsSucceed)
{
AppendEmptyText();
byte[] rValue = result.Value;
rValue = rValue.Reverse().ToArray();
for (int i = 0; i < readNumber; i++)
{
var cAddress = (addressNumber + i * bLength).ToString();
var addressStr = address.Substring(0, 1) + (addressNumber + i * bLength);
if (rd_short.Checked)
AppendText($"[读取 {addressStr} 成功]{ client.ReadInt16(addressNumber.ToString(), cAddress, rValue).Value}");
else if (rd_ushort.Checked)
AppendText($"[读取 {addressStr} 成功]{ client.ReadUInt16(addressNumber.ToString(), cAddress, rValue).Value}");
else if (rd_int.Checked)
AppendText($"[读取 {addressStr} 成功]{ client.ReadInt32(addressNumber.ToString(), cAddress, rValue).Value}");
else if (rd_uint.Checked)
AppendText($"[读取 {addressStr} 成功]{ client.ReadUInt32(addressNumber.ToString(), cAddress, rValue).Value}");
else if (rd_long.Checked)
AppendText($"[读取 {addressStr} 成功]{ client.ReadInt64(addressNumber.ToString(), cAddress, rValue).Value}");
else if (rd_ulong.Checked)
AppendText($"[读取 {addressStr} 成功]{ client.ReadUInt64(addressNumber.ToString(), cAddress, rValue).Value}");
else if (rd_float.Checked)
AppendText($"[读取 {addressStr} 成功]{ client.ReadFloat(addressNumber.ToString(), cAddress, rValue).Value}");
else if (rd_double.Checked)
AppendText($"[读取 {addressStr} 成功]{ client.ReadDouble(addressNumber.ToString(), cAddress, rValue).Value}");
else if (rd_byte.Checked)
AppendText($"[读取 {addressStr} 成功]{ client.ReadByte(addressNumber.ToString(), cAddress, rValue).Value}");
//else if (rd_bit.Checked)
// AppendText($"[读取 {addressStr} 成功]{ client.ReadBoolean(addressNumber.ToString(), cAddress, rValue).Value}");
}
}
else
AppendText($"[读取 {txt_address.Text?.Trim()} 失败]{result.Err}");
}
else if (rd_bit.Checked)
//单个读取
else
{
result = client.ReadBoolean(txt_address.Text);
}
else if (rd_short.Checked)
{
result = client.ReadInt16(txt_address.Text);
}
else if (rd_ushort.Checked)
{
result = client.ReadUInt16(txt_address.Text);
}
else if (rd_int.Checked)
{
result = client.ReadInt32(txt_address.Text);
}
else if (rd_uint.Checked)
{
result = client.ReadUInt32(txt_address.Text);
}
else if (rd_long.Checked)
{
result = client.ReadInt64(txt_address.Text);
}
else if (rd_ulong.Checked)
{
result = client.ReadUInt64(txt_address.Text);
}
else if (rd_float.Checked)
{
result = client.ReadFloat(txt_address.Text);
}
else if (rd_double.Checked)
{
result = client.ReadDouble(txt_address.Text);
if (rd_byte.Checked)
{
result = client.ReadByte(txt_address.Text);
}
else if (rd_bit.Checked)
{
result = client.ReadBoolean(txt_address.Text);
}
else if (rd_short.Checked)
{
result = client.ReadInt16(txt_address.Text);
}
else if (rd_ushort.Checked)
{
result = client.ReadUInt16(txt_address.Text);
}
else if (rd_int.Checked)
{
result = client.ReadInt32(txt_address.Text);
}
else if (rd_uint.Checked)
{
result = client.ReadUInt32(txt_address.Text);
}
else if (rd_long.Checked)
{
result = client.ReadInt64(txt_address.Text);
}
else if (rd_ulong.Checked)
{
result = client.ReadUInt64(txt_address.Text);
}
else if (rd_float.Checked)
{
result = client.ReadFloat(txt_address.Text);
}
else if (rd_double.Checked)
{
result = client.ReadDouble(txt_address.Text);
}
if (result.IsSucceed)
AppendText($"[读取 {txt_address.Text?.Trim()} 成功]{result.Value}");
else
AppendText($"[读取 {txt_address.Text?.Trim()} 失败]{result.Err}");
}
if (result.IsSucceed)
AppendText($"[读取 {txt_address.Text?.Trim()} 成功]{result.Value}");
else
AppendText($"[读取 {txt_address.Text?.Trim()} 失败]{result.Err}");
if (chb_show_package.Checked || (ModifierKeys & Keys.Control) == Keys.Control)
{
AppendText($"[请求报文]{result.Requst}");
@ -200,6 +273,7 @@ namespace IoTClient.Tool
try
{
var address = txt_address.Text.Split('-')[0];
dynamic result = null;
if (rd_bit.Checked)
{
@ -215,50 +289,50 @@ namespace IoTClient.Tool
return;
}
}
result = client.Write(txt_address.Text, bit);
result = client.Write(address, bit);
}
else if (rd_byte.Checked)
{
result = client.Write(txt_address.Text, byte.Parse(txt_value.Text?.Trim()));
result = client.Write(address, byte.Parse(txt_value.Text?.Trim()));
}
else if (rd_short.Checked)
{
result = client.Write(txt_address.Text, short.Parse(txt_value.Text?.Trim()));
result = client.Write(address, short.Parse(txt_value.Text?.Trim()));
}
else if (rd_ushort.Checked)
{
result = client.Write(txt_address.Text, ushort.Parse(txt_value.Text?.Trim()));
result = client.Write(address, ushort.Parse(txt_value.Text?.Trim()));
}
else if (rd_int.Checked)
{
result = client.Write(txt_address.Text, int.Parse(txt_value.Text?.Trim()));
result = client.Write(address, int.Parse(txt_value.Text?.Trim()));
}
else if (rd_uint.Checked)
{
result = client.Write(txt_address.Text, uint.Parse(txt_value.Text?.Trim()));
result = client.Write(address, uint.Parse(txt_value.Text?.Trim()));
}
else if (rd_long.Checked)
{
result = client.Write(txt_address.Text, long.Parse(txt_value.Text?.Trim()));
result = client.Write(address, long.Parse(txt_value.Text?.Trim()));
}
else if (rd_ulong.Checked)
{
result = client.Write(txt_address.Text, ulong.Parse(txt_value.Text?.Trim()));
result = client.Write(address, ulong.Parse(txt_value.Text?.Trim()));
}
else if (rd_float.Checked)
{
result = client.Write(txt_address.Text, float.Parse(txt_value.Text?.Trim()));
result = client.Write(address, float.Parse(txt_value.Text?.Trim()));
}
else if (rd_double.Checked)
{
result = client.Write(txt_address.Text, double.Parse(txt_value.Text?.Trim()));
result = client.Write(address, double.Parse(txt_value.Text?.Trim()));
}
if (result.IsSucceed)
AppendText($"[写入 {txt_address.Text?.Trim()} 成功]{txt_value.Text?.Trim()} OK");
AppendText($"[写入 {address?.Trim()} 成功]{txt_value.Text?.Trim()} OK");
else
AppendText($"[写入 {txt_address.Text?.Trim()} 失败]{result.Err}");
AppendText($"[写入 {address?.Trim()} 失败]{result.Err}");
if (chb_show_package.Checked || (ModifierKeys & Keys.Control) == Keys.Control)
{
AppendText($"[请求报文]{result.Requst}");
@ -313,5 +387,18 @@ namespace IoTClient.Tool
txt_content.AppendText($"[{DateTime.Now.ToLongTimeString()}]{content}\r\n");
}));
}
private void AppendEmptyText()
{
txt_content.Invoke((Action)(() =>
{
txt_content.AppendText($"\r\n");
}));
}
private void SiemensControl_ControlRemoved(object sender, ControlEventArgs e)
{
}
}
}

View File

@ -39,6 +39,7 @@
this.OmronFinsTcp = new System.Windows.Forms.TabPage();
this.BACnet = new System.Windows.Forms.TabPage();
this.Ports = new System.Windows.Forms.TabPage();
this.Other = new System.Windows.Forms.TabPage();
this.menuStrip1 = new System.Windows.Forms.MenuStrip();
this.toolStripMenuItem5 = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripMenuItem2 = new System.Windows.Forms.ToolStripMenuItem();
@ -46,7 +47,7 @@
this.toolStripMenuItemBlogPath = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripMenuItem4 = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem();
this.Other = new System.Windows.Forms.TabPage();
this.ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.modBusTcpControl1 = new IoTClient.Tool.ModBusTcpControl();
this.tabControl1.SuspendLayout();
this.ModBusTcp.SuspendLayout();
@ -164,6 +165,16 @@
this.Ports.Text = " ";
this.Ports.UseVisualStyleBackColor = true;
//
// Other
//
this.Other.Location = new System.Drawing.Point(4, 22);
this.Other.Name = "Other";
this.Other.Padding = new System.Windows.Forms.Padding(3);
this.Other.Size = new System.Drawing.Size(886, 448);
this.Other.TabIndex = 9;
this.Other.Text = "工具";
this.Other.UseVisualStyleBackColor = true;
//
// menuStrip1
//
this.menuStrip1.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(0)))), ((int)(((byte)(148)))), ((int)(((byte)(255)))));
@ -173,6 +184,7 @@
this.toolStripMenuItem3,
this.toolStripMenuItemBlogPath,
this.toolStripMenuItem4,
this.ToolStripMenuItem,
this.toolStripMenuItem1});
this.menuStrip1.Location = new System.Drawing.Point(0, 0);
this.menuStrip1.Name = "menuStrip1";
@ -225,18 +237,16 @@
this.toolStripMenuItem1.ForeColor = System.Drawing.Color.White;
this.toolStripMenuItem1.Name = "toolStripMenuItem1";
this.toolStripMenuItem1.Size = new System.Drawing.Size(75, 21);
this.toolStripMenuItem1.Text = "版本 0.3.4";
this.toolStripMenuItem1.Text = "版本 0.3.5";
this.toolStripMenuItem1.Click += new System.EventHandler(this.toolStripMenuItem1_Click);
//
// Other
// 商务合作ToolStripMenuItem
//
this.Other.Location = new System.Drawing.Point(4, 22);
this.Other.Name = "Other";
this.Other.Padding = new System.Windows.Forms.Padding(3);
this.Other.Size = new System.Drawing.Size(886, 448);
this.Other.TabIndex = 9;
this.Other.Text = "工具";
this.Other.UseVisualStyleBackColor = true;
this.ToolStripMenuItem.ForeColor = System.Drawing.Color.White;
this.ToolStripMenuItem.Name = "商务合作ToolStripMenuItem";
this.ToolStripMenuItem.Size = new System.Drawing.Size(68, 21);
this.ToolStripMenuItem.Text = "商务合作";
this.ToolStripMenuItem.Click += new System.EventHandler(this.cooperationToolStripMenuItem_Click);
//
// modBusTcpControl1
//
@ -289,5 +299,6 @@
private System.Windows.Forms.TabPage ModBusAscii;
private System.Windows.Forms.TabPage SiemensS7300;
private System.Windows.Forms.TabPage Other;
private System.Windows.Forms.ToolStripMenuItem ToolStripMenuItem;
}
}

View File

@ -235,6 +235,15 @@ namespace IoTClient.Tool
catch (Exception) { }
}
private void cooperationToolStripMenuItem_Click(object sender, EventArgs e)
{
try
{
Process.Start("http://wpa.qq.com/msgrd?v=3&uin=1150234111&site=qq&menu=yes");
}
catch (Exception) { }
}
private void toolStripMenuItem5_Click(object sender, EventArgs e)
{
try
@ -326,6 +335,6 @@ namespace IoTClient.Tool
if (File.Exists(filePath)) File.Delete(filePath);
}
}
}
}
}
}

View File

@ -5,7 +5,7 @@
/// <summary>
/// 当前版本
/// </summary>
public float CurrentVersion { get; set; } = 0.34f;
public float CurrentVersion { get; set; } = 0.35f;
/// <summary>
/// 忽略版本

View File

@ -121,43 +121,21 @@ namespace IoTClient.Clients.PLC
try
{
//兼容地址如VD5012中的D
if (address.Length >= 2 && !"0123456789".Contains(address[1].ToString()))
address = address.Remove(1, 1);
if (address.Length >= 2 && !"0123456789".Contains(address[1].ToString())) address = address.Remove(1, 1);
//发送读取信息
var arg = ConvertArg(address);
byte[] command;
if (isBit)
command = GetReadBitCommand(arg.TypeCode, arg.BeginAddress, arg.DbBlock);
command = GetReadBitCommand(arg.TypeCode, arg.BeginAddress, arg.DbBlock, length);
else
command = GetReadCommand(arg.TypeCode, arg.BeginAddress, arg.DbBlock, length);
result.Requst = string.Join(" ", command.Select(t => t.ToString("X2")));
//发送命令 并获取响应报文
var dataPackage = SendPackage(command);
var bufferLength = length == 8 ? 8 : 4;
byte[] temp = new byte[bufferLength];
byte[] response = new byte[bufferLength];
Array.Copy(dataPackage, dataPackage.Length - bufferLength, temp, 0, bufferLength);
switch (length)
{
case 8:
response[0] = temp[7];
response[1] = temp[6];
response[2] = temp[5];
response[3] = temp[4];
response[4] = temp[3];
response[5] = temp[2];
response[6] = temp[1];
response[7] = temp[0];
break;
default:
response[0] = temp[3];
response[1] = temp[2];
response[2] = temp[1];
response[3] = temp[0];
break;
}
byte[] responseData = new byte[length];
Array.Copy(dataPackage, dataPackage.Length - length, responseData, 0, length);
result.Response = string.Join(" ", dataPackage.Select(t => t.ToString("X2")));
result.Value = response;
result.Value = responseData.Reverse().ToArray();
}
catch (SocketException ex)
{
@ -195,12 +173,11 @@ namespace IoTClient.Clients.PLC
try
{
//兼容地址如VD5012中的D
if (address.Length >= 2 && !"0123456789".Contains(address[1].ToString()))
address = address.Remove(1, 1);
if (address.Length >= 2 && !"0123456789".Contains(address[1].ToString())) address = address.Remove(1, 1);
//发送读取信息
var arg = ConvertArg(address);
byte[] command = GetReadCommand(arg.TypeCode, arg.BeginAddress, arg.DbBlock, length);
result.Requst = string.Join(" ", command.Select(t => t.ToString("X2")));
result.Requst = string.Join(" ", command.Select(t => t.ToString("X2")));
var dataPackage = SendPackage(command);
byte[] requst = new byte[length];
Array.Copy(dataPackage, 25, requst, 0, length);
@ -239,7 +216,7 @@ namespace IoTClient.Clients.PLC
public Result<bool> ReadBoolean(string address)
{
//return BitConverter.ToBoolean(Read(address, 4, isBit: true), 0);
var readResut = Read(address, 4, isBit: true);
var readResut = Read(address, 1, isBit: true);
var result = new Result<bool>()
{
IsSucceed = readResut.IsSucceed,
@ -253,8 +230,13 @@ namespace IoTClient.Clients.PLC
return result;
}
/// <summary>
///
/// </summary>
/// <param name="address"></param>
/// <returns></returns>
public Result<byte> ReadByte(string address)
{
{
var readResut = Read(address, 1);
var result = new Result<byte>()
{
@ -483,6 +465,306 @@ namespace IoTClient.Clients.PLC
}
//return Encoding.ASCII.GetString(, 1, length[0]);
}
///// <summary>
///// 从批量读取的数据字节提取对应的地址数据
///// </summary>
///// <param name="beginAddress">批量读取的起始地址</param>
///// <param name="address">读取地址</param>
///// <param name="values">批量读取的值</param>
///// <returns></returns>
//public Result<bool> ReadBoolean(string beginAddress, string address, byte[] values)
//{
// if (!int.TryParse(address?.Trim(), out int addressInt) || !int.TryParse(beginAddress?.Trim(), out int beginAddressInt))
// throw new Exception($"只能是数字参数address{address} beginAddress{beginAddress}");
// try
// {
// var i = addressInt - beginAddressInt;
// var byteArry = values.Skip(i).Take(1).ToArray();
// return new Result<bool>
// {
// Value = BitConverter.ToBoolean(byteArry, 0)
// };
// }
// catch (Exception ex)
// {
// return new Result<bool>
// {
// IsSucceed = false,
// Err = ex.Message
// };
// }
//}
/// <summary>
/// 从批量读取的数据字节提取对应的地址数据
/// </summary>
/// <param name="beginAddress">批量读取的起始地址</param>
/// <param name="address">读取地址</param>
/// <param name="values">批量读取的值</param>
/// <returns></returns>
public Result<byte> ReadByte(string beginAddress, string address, byte[] values)
{
if (!int.TryParse(address?.Trim(), out int addressInt) || !int.TryParse(beginAddress?.Trim(), out int beginAddressInt))
throw new Exception($"只能是数字参数address{address} beginAddress{beginAddress}");
try
{
var i = addressInt - beginAddressInt;
return new Result<byte>
{
Value = values.Skip(i).Take(1).ToArray()[0]
};
}
catch (Exception ex)
{
return new Result<byte>
{
IsSucceed = false,
Err = ex.Message
};
}
}
/// <summary>
/// 从批量读取的数据字节提取对应的地址数据
/// </summary>
/// <param name="beginAddress">批量读取的起始地址</param>
/// <param name="address">读取地址</param>
/// <param name="values">批量读取的值</param>
/// <returns></returns>
public Result<short> ReadInt16(string beginAddress, string address, byte[] values)
{
if (!int.TryParse(address?.Trim(), out int addressInt) || !int.TryParse(beginAddress?.Trim(), out int beginAddressInt))
throw new Exception($"只能是数字参数address{address} beginAddress{beginAddress}");
try
{
var i = addressInt - beginAddressInt;
var byteArry = values.Skip(i).Take(2).Reverse().ToArray();
return new Result<short>
{
Value = BitConverter.ToInt16(byteArry, 0)
};
}
catch (Exception ex)
{
return new Result<short>
{
IsSucceed = false,
Err = ex.Message
};
}
}
/// <summary>
/// 从批量读取的数据字节提取对应的地址数据
/// </summary>
/// <param name="beginAddress">批量读取的起始地址</param>
/// <param name="address">读取地址</param>
/// <param name="values">批量读取的值</param>
/// <returns></returns>
public Result<ushort> ReadUInt16(string beginAddress, string address, byte[] values)
{
if (!int.TryParse(address?.Trim(), out int addressInt) || !int.TryParse(beginAddress?.Trim(), out int beginAddressInt))
throw new Exception($"只能是数字参数address{address} beginAddress{beginAddress}");
try
{
var i = addressInt - beginAddressInt;
var byteArry = values.Skip(i).Take(2).Reverse().ToArray();
return new Result<ushort>
{
Value = BitConverter.ToUInt16(byteArry, 0)
};
}
catch (Exception ex)
{
return new Result<ushort>
{
IsSucceed = false,
Err = ex.Message
};
}
}
/// <summary>
/// 从批量读取的数据字节提取对应的地址数据
/// </summary>
/// <param name="beginAddress">批量读取的起始地址</param>
/// <param name="address">读取地址</param>
/// <param name="values">批量读取的值</param>
/// <returns></returns>
public Result<int> ReadInt32(string beginAddress, string address, byte[] values)
{
if (!int.TryParse(address?.Trim(), out int addressInt) || !int.TryParse(beginAddress?.Trim(), out int beginAddressInt))
throw new Exception($"只能是数字参数address{address} beginAddress{beginAddress}");
try
{
var i = (addressInt - beginAddressInt) / 2;
var byteArry = values.Skip(i * 2).Take(2 * 2).Reverse().ToArray();
return new Result<int>
{
Value = BitConverter.ToInt32(byteArry, 0)
};
}
catch (Exception ex)
{
return new Result<int>
{
IsSucceed = false,
Err = ex.Message
};
}
}
/// <summary>
/// 从批量读取的数据字节提取对应的地址数据
/// </summary>
/// <param name="beginAddress">批量读取的起始地址</param>
/// <param name="address">读取地址</param>
/// <param name="values">批量读取的值</param>
/// <returns></returns>
public Result<uint> ReadUInt32(string beginAddress, string address, byte[] values)
{
if (!int.TryParse(address?.Trim(), out int addressInt) || !int.TryParse(beginAddress?.Trim(), out int beginAddressInt))
throw new Exception($"只能是数字参数address{address} beginAddress{beginAddress}");
try
{
var i = (addressInt - beginAddressInt) / 2;
var byteArry = values.Skip(i * 2).Take(2 * 2).Reverse().ToArray();
return new Result<uint>
{
Value = BitConverter.ToUInt32(byteArry, 0)
};
}
catch (Exception ex)
{
return new Result<uint>
{
IsSucceed = false,
Err = ex.Message
};
}
}
/// <summary>
/// 从批量读取的数据字节提取对应的地址数据
/// </summary>
/// <param name="beginAddress">批量读取的起始地址</param>
/// <param name="address">读取地址</param>
/// <param name="values">批量读取的值</param>
/// <returns></returns>
public Result<long> ReadInt64(string beginAddress, string address, byte[] values)
{
if (!int.TryParse(address?.Trim(), out int addressInt) || !int.TryParse(beginAddress?.Trim(), out int beginAddressInt))
throw new Exception($"只能是数字参数address{address} beginAddress{beginAddress}");
try
{
var i = (addressInt - beginAddressInt) / 4;
var byteArry = values.Skip(i * 4).Take(2 * 4).Reverse().ToArray();
return new Result<long>
{
Value = BitConverter.ToInt64(byteArry, 0)
};
}
catch (Exception ex)
{
return new Result<long>
{
IsSucceed = false,
Err = ex.Message
};
}
}
/// <summary>
/// 从批量读取的数据字节提取对应的地址数据
/// </summary>
/// <param name="beginAddress">批量读取的起始地址</param>
/// <param name="address">读取地址</param>
/// <param name="values">批量读取的值</param>
/// <returns></returns>
public Result<ulong> ReadUInt64(string beginAddress, string address, byte[] values)
{
if (!int.TryParse(address?.Trim(), out int addressInt) || !int.TryParse(beginAddress?.Trim(), out int beginAddressInt))
throw new Exception($"只能是数字参数address{address} beginAddress{beginAddress}");
try
{
var i = (addressInt - beginAddressInt) / 4;
var byteArry = values.Skip(i * 4).Take(2 * 4).Reverse().ToArray();
return new Result<ulong>
{
Value = BitConverter.ToUInt64(byteArry, 0)
};
}
catch (Exception ex)
{
return new Result<ulong>
{
IsSucceed = false,
Err = ex.Message
};
}
}
/// <summary>
/// 从批量读取的数据字节提取对应的地址数据
/// </summary>
/// <param name="beginAddress">批量读取的起始地址</param>
/// <param name="address">读取地址</param>
/// <param name="values">批量读取的值</param>
/// <returns></returns>
public Result<float> ReadFloat(string beginAddress, string address, byte[] values)
{
if (!int.TryParse(address?.Trim(), out int addressInt) || !int.TryParse(beginAddress?.Trim(), out int beginAddressInt))
throw new Exception($"只能是数字参数address{address} beginAddress{beginAddress}");
try
{
var i = (addressInt - beginAddressInt) / 2;
var byteArry = values.Skip(i * 2).Take(2 * 2).Reverse().ToArray();
return new Result<float>
{
Value = BitConverter.ToSingle(byteArry, 0)
};
}
catch (Exception ex)
{
return new Result<float>
{
IsSucceed = false,
Err = ex.Message
};
}
}
/// <summary>
/// 从批量读取的数据字节提取对应的地址数据
/// </summary>
/// <param name="beginAddress">批量读取的起始地址</param>
/// <param name="address">读取地址</param>
/// <param name="values">批量读取的值</param>
/// <returns></returns>
public Result<double> ReadDouble(string beginAddress, string address, byte[] values)
{
if (!int.TryParse(address?.Trim(), out int addressInt) || !int.TryParse(beginAddress?.Trim(), out int beginAddressInt))
throw new Exception($"只能是数字参数address{address} beginAddress{beginAddress}");
try
{
var i = (addressInt - beginAddressInt) / 4;
var byteArry = values.Skip(i * 4).Take(2 * 4).Reverse().ToArray();
return new Result<double>
{
Value = BitConverter.ToDouble(byteArry, 0)
};
}
catch (Exception ex)
{
return new Result<double>
{
IsSucceed = false,
Err = ex.Message
};
}
}
#endregion
#region Write
@ -584,7 +866,7 @@ namespace IoTClient.Clients.PLC
/// <returns></returns>
public Result Write(string address, byte value)
{
return Write(address, BitConverter.GetBytes(value));
return Write(address, new byte[1] { value });
}
/// <summary>
@ -764,23 +1046,23 @@ namespace IoTClient.Clients.PLC
command[3] = (byte)(command.Length % 256);//[2][3]整个读取请求长度为0x1F= 31
command[4] = 0x02;
command[5] = 0xF0;
command[6] = 0x80;
command[7] = 0x32;
command[6] = 0x80;//COTP
command[7] = 0x32;//协议ID
command[8] = 0x01;//1 客户端发送命令 3 服务器回复命令
command[9] = 0x00;
command[10] = 0x00;//[4]-[10]固定6个字节
command[11] = 0x00;
command[12] = 0x01;//[11][12]两个字节标识序列号回复报文相同位置和这个完全一样范围是0~65535
command[13] = 0x00;
command[14] = 0x0E;
command[14] = 0x0E;//parameter length[17]-[30]都为parameter刚好14也就是0x0E
command[15] = 0x00;
command[16] = 0x00;
command[16] = 0x00;//data length
command[17] = 0x04;//04读 05写
command[18] = 0x01;//读取数据块个数
command[19] = 0x12;
command[20] = 0x0A;
command[21] = 0x10;
command[22] = 0x02;
command[19] = 0x12;//variable specification
command[20] = 0x0A;//Length of following address specification
command[21] = 0x10;//Syntax Id: S7ANY
command[22] = 0x02;//Transport size: BYTE
command[23] = (byte)(length / 256);
command[24] = (byte)(length % 256);//[23][24]两个字节,访问数据的个数以byte为单位
command[25] = (byte)(dbAddress / 256);
@ -792,7 +1074,7 @@ namespace IoTClient.Clients.PLC
return command;
}
protected byte[] GetReadBitCommand(byte type, int beginAddress, ushort dbAddress)
protected byte[] GetReadBitCommand(byte type, int beginAddress, ushort dbAddress, ushort length = 1)
{
byte[] command = new byte[31];
command[0] = 0x03;
@ -809,7 +1091,7 @@ namespace IoTClient.Clients.PLC
command[11] = 0x00;
command[12] = 0x01;
command[13] = (byte)((command.Length - 17) / 256);
command[14] = (byte)((command.Length - 17) % 256);
command[14] = (byte)((command.Length - 17) % 256); //parameter length减17是因为从[17]到最后属于parameter
command[15] = 0x00;
command[16] = 0x00;
command[17] = 0x04;//04读 05写
@ -818,8 +1100,8 @@ namespace IoTClient.Clients.PLC
command[20] = 0x0A;
command[21] = 0x10;
command[22] = 0x01;
command[23] = 0x00;
command[24] = 0x01;
command[23] = (byte)(length / 256);
command[24] = (byte)(length % 256);
command[25] = (byte)(dbAddress / 256);
command[26] = (byte)(dbAddress % 256);//[25][26]DB块的编号
command[27] = type;//访问数据块的类型

View File

@ -1838,6 +1838,13 @@
<param name="address">地址</param>
<returns></returns>
</member>
<member name="M:IoTClient.Clients.PLC.SiemensClient.ReadByte(System.String)">
<summary>
</summary>
<param name="address"></param>
<returns></returns>
</member>
<member name="M:IoTClient.Clients.PLC.SiemensClient.ReadInt16(System.String)">
<summary>
读取Int16
@ -1901,6 +1908,87 @@
<param name="address">地址</param>
<returns></returns>
</member>
<member name="M:IoTClient.Clients.PLC.SiemensClient.ReadByte(System.String,System.String,System.Byte[])">
<summary>
从批量读取的数据字节提取对应的地址数据
</summary>
<param name="beginAddress">批量读取的起始地址</param>
<param name="address">读取地址</param>
<param name="values">批量读取的值</param>
<returns></returns>
</member>
<member name="M:IoTClient.Clients.PLC.SiemensClient.ReadInt16(System.String,System.String,System.Byte[])">
<summary>
从批量读取的数据字节提取对应的地址数据
</summary>
<param name="beginAddress">批量读取的起始地址</param>
<param name="address">读取地址</param>
<param name="values">批量读取的值</param>
<returns></returns>
</member>
<member name="M:IoTClient.Clients.PLC.SiemensClient.ReadUInt16(System.String,System.String,System.Byte[])">
<summary>
从批量读取的数据字节提取对应的地址数据
</summary>
<param name="beginAddress">批量读取的起始地址</param>
<param name="address">读取地址</param>
<param name="values">批量读取的值</param>
<returns></returns>
</member>
<member name="M:IoTClient.Clients.PLC.SiemensClient.ReadInt32(System.String,System.String,System.Byte[])">
<summary>
从批量读取的数据字节提取对应的地址数据
</summary>
<param name="beginAddress">批量读取的起始地址</param>
<param name="address">读取地址</param>
<param name="values">批量读取的值</param>
<returns></returns>
</member>
<member name="M:IoTClient.Clients.PLC.SiemensClient.ReadUInt32(System.String,System.String,System.Byte[])">
<summary>
从批量读取的数据字节提取对应的地址数据
</summary>
<param name="beginAddress">批量读取的起始地址</param>
<param name="address">读取地址</param>
<param name="values">批量读取的值</param>
<returns></returns>
</member>
<member name="M:IoTClient.Clients.PLC.SiemensClient.ReadInt64(System.String,System.String,System.Byte[])">
<summary>
从批量读取的数据字节提取对应的地址数据
</summary>
<param name="beginAddress">批量读取的起始地址</param>
<param name="address">读取地址</param>
<param name="values">批量读取的值</param>
<returns></returns>
</member>
<member name="M:IoTClient.Clients.PLC.SiemensClient.ReadUInt64(System.String,System.String,System.Byte[])">
<summary>
从批量读取的数据字节提取对应的地址数据
</summary>
<param name="beginAddress">批量读取的起始地址</param>
<param name="address">读取地址</param>
<param name="values">批量读取的值</param>
<returns></returns>
</member>
<member name="M:IoTClient.Clients.PLC.SiemensClient.ReadFloat(System.String,System.String,System.Byte[])">
<summary>
从批量读取的数据字节提取对应的地址数据
</summary>
<param name="beginAddress">批量读取的起始地址</param>
<param name="address">读取地址</param>
<param name="values">批量读取的值</param>
<returns></returns>
</member>
<member name="M:IoTClient.Clients.PLC.SiemensClient.ReadDouble(System.String,System.String,System.Byte[])">
<summary>
从批量读取的数据字节提取对应的地址数据
</summary>
<param name="beginAddress">批量读取的起始地址</param>
<param name="address">读取地址</param>
<param name="values">批量读取的值</param>
<returns></returns>
</member>
<member name="M:IoTClient.Clients.PLC.SiemensClient.Write(System.String,System.Boolean)">
<summary>
写入数据

View File

@ -9,11 +9,7 @@
/// <summary>
/// DB块编号
/// </summary>
public ushort DbBlock { get; set; }
///// <summary>
///// 读取的数据长度
///// </summary>
//public ushort Length { get; set; }
public ushort DbBlock { get; set; }
/// <summary>
/// 开始地址
/// </summary>

View File

@ -117,28 +117,32 @@ namespace IoTServer.Servers.PLC
continue;
}
var address = requetData[28] * 256 * 256 + requetData[29] * 256 + requetData[30];
var typeDB = requetData[27];
var stationNumberKey = $"s200-{typeDB}";
switch (requetData[17])
{
//读
case 4:
{
var value = dataPersist.Read(address);//TODO 数据存在 25、26
//读取数据长度
var readLength = requetData[23] * 256 + requetData[24];
var value = dataPersist.Read(stationNumberKey);//TODO 数据存在 25、26
var byteArray = JsonConvert.DeserializeObject<byte[]>(value) ?? new byte[65536];
//把存储的数据转为字节数组
var bytes = JsonConvert.DeserializeObject<byte[]>(value);
if (string.IsNullOrWhiteSpace(value))
bytes = BitConverter.GetBytes(0);
var dataContent = new byte[4 + bytes.Length];//可以从报文中获取Length
//var bytes = JsonConvert.DeserializeObject<byte[]>(value);
//if (string.IsNullOrWhiteSpace(value))
// bytes = BitConverter.GetBytes(0);
var dataContent = new byte[4 + readLength];//可以从报文中获取Length
DataConvert.StringToByteArray("FF 09 00 04").CopyTo(dataContent, 0);
dataContent[1] = bytes.Length == 1 ? (byte)0x03 : (byte)0x04;//04 byte(字节) 03bit
dataContent[2] = (byte)(bytes.Length / 256);
dataContent[3] = (byte)(bytes.Length % 256);
//dataContent[0] 固定
dataContent[1] = readLength == 1 ? (byte)0x03 : (byte)0x04;//04 byte(字节) 03bit
dataContent[2] = (byte)(readLength / 256);
dataContent[3] = (byte)(readLength % 256);
Buffer.BlockCopy(byteArray, address / 8, dataContent, 4, readLength);
//dataContent[2] dataContent[3] 后半截数据数组的Length
//dataContent[4]-[7] 返回给客户端的数据
byte[] responseData1 = new byte[21 + dataContent.Length];
DataConvert.StringToByteArray("03 00 00 1A 02 F0 80 32 03 00 00 00 01 00 02 00 00 00 00 04 01").CopyTo(responseData1, 0);
//responseData1[0] = 0x03;
//responseData1[1] = 0x00; //固定协议头
//responseData1[8] = 0x03;//1 客户端发送命令 3 服务器回复命令
responseData1[2] = (byte)(responseData1.Length / 256);
responseData1[3] = (byte)(responseData1.Length % 256);
@ -147,22 +151,24 @@ namespace IoTServer.Servers.PLC
responseData1[20] = requetData[18];
dataContent.CopyTo(responseData1, 21);
//当读取的是字符串的时候[25]存储的后面的数据长度参考SiemensClient的Write(string address, string value)方法。
Buffer.BlockCopy(bytes, 0, responseData1, responseData1.Length - bytes.Length, bytes.Length);
//Buffer.BlockCopy(bytes, 0, responseData1, responseData1.Length - bytes.Length, bytes.Length);
newSocket.Send(responseData1);
}
break;
//写
case 5:
{
var valueByte = new byte[requetData.Length - 35];
Buffer.BlockCopy(requetData, 35, valueByte, 0, valueByte.Length);
var value = new byte[requetData.Length - 35];
Buffer.BlockCopy(requetData, 35, value, 0, value.Length);
var byteArray = JsonConvert.DeserializeObject<byte[]>(dataPersist.Read(stationNumberKey)) ?? new byte[65536];
value.CopyTo(byteArray, address / 8);
//存储字节数据到内存
dataPersist.Write(address, JsonConvert.SerializeObject(valueByte));
dataPersist.Write(stationNumberKey, JsonConvert.SerializeObject(byteArray));
byte[] responseData1 = new byte[22];
DataConvert.StringToByteArray("03 00 00 16 02 F0 80 32 03 00 00 00 01 00 02 00 01 00 00 05 01 FF").CopyTo(responseData1, 0);
//responseData1[15] = (byte)(responseData1.Length / 256);
//responseData1[16] = (byte)(responseData1.Length % 256);
newSocket.Send(responseData1);
}
break;