mirror of
https://github.com/zhaopeiym/IoTClient
synced 2025-10-19 22:14:31 +08:00
fixModbus fix
This commit is contained in:
parent
2303af0082
commit
6bf49e48bb
|
|
@ -5,6 +5,7 @@ using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
using System.Threading;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace IoTClient.Tests.PLCTests
|
namespace IoTClient.Tests.PLCTests
|
||||||
|
|
@ -36,7 +37,7 @@ namespace IoTClient.Tests.PLCTests
|
||||||
float float_number = int_number / 100;
|
float float_number = int_number / 100;
|
||||||
var bool_value = short_number % 2 == 1;
|
var bool_value = short_number % 2 == 1;
|
||||||
|
|
||||||
string value_string = "BennyZhao"+ float_number;
|
string value_string = "BennyZhao" + float_number;
|
||||||
|
|
||||||
client.Write("Q1.3", bool_value);
|
client.Write("Q1.3", bool_value);
|
||||||
Assert.True(client.ReadBoolean("Q1.3").Value == bool_value);
|
Assert.True(client.ReadBoolean("Q1.3").Value == bool_value);
|
||||||
|
|
@ -64,7 +65,7 @@ namespace IoTClient.Tests.PLCTests
|
||||||
Assert.True(client.ReadFloat("V200").Value == float_number);
|
Assert.True(client.ReadFloat("V200").Value == float_number);
|
||||||
client.Write("V300", Convert.ToDouble(float_number));
|
client.Write("V300", Convert.ToDouble(float_number));
|
||||||
Assert.True(client.ReadDouble("V300").Value == Convert.ToDouble(float_number));
|
Assert.True(client.ReadDouble("V300").Value == Convert.ToDouble(float_number));
|
||||||
|
|
||||||
client.Write("V2205", value_string);
|
client.Write("V2205", value_string);
|
||||||
Assert.True(client.ReadString("V2205").Value == value_string);
|
Assert.True(client.ReadString("V2205").Value == value_string);
|
||||||
}
|
}
|
||||||
|
|
@ -298,5 +299,21 @@ namespace IoTClient.Tests.PLCTests
|
||||||
var result2 = client.Write("DB1.434.0", false);
|
var result2 = client.Write("DB1.434.0", false);
|
||||||
client.Write("DB1.434.0", true);
|
client.Write("DB1.434.0", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void 定时更新()
|
||||||
|
{
|
||||||
|
client.ReadInt16("V100", (value,isSucceed,err) =>
|
||||||
|
{
|
||||||
|
Debug.WriteLine($"V100:{value} err:{err}");
|
||||||
|
});
|
||||||
|
|
||||||
|
client.ReadInt16("V102", (value, isSucceed, err) =>
|
||||||
|
{
|
||||||
|
Debug.WriteLine($"V102:{value} err:{err}");
|
||||||
|
});
|
||||||
|
|
||||||
|
Thread.Sleep(1000 * 30);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -688,7 +688,7 @@ namespace IoTClient.Clients.Modbus
|
||||||
var stationNumbers = addresses.Where(t => t.FunctionCode == functionCode).Select(t => t.StationNumber).Distinct();
|
var stationNumbers = addresses.Where(t => t.FunctionCode == functionCode).Select(t => t.StationNumber).Distinct();
|
||||||
foreach (var stationNumber in stationNumbers)
|
foreach (var stationNumber in stationNumbers)
|
||||||
{
|
{
|
||||||
var addressList = addresses.Where(t => t.FunctionCode == functionCode && t.StationNumber == t.StationNumber)
|
var addressList = addresses.Where(t => t.FunctionCode == functionCode && t.StationNumber == stationNumber)
|
||||||
.DistinctBy(t => t.Address)
|
.DistinctBy(t => t.Address)
|
||||||
.ToDictionary(t => t.Address, t => t.DataType);
|
.ToDictionary(t => t.Address, t => t.DataType);
|
||||||
var tempResult = BatchRead(addressList, stationNumber, functionCode);
|
var tempResult = BatchRead(addressList, stationNumber, functionCode);
|
||||||
|
|
|
||||||
|
|
@ -787,7 +787,7 @@ namespace IoTClient.Clients.Modbus
|
||||||
var stationNumbers = addresses.Where(t => t.FunctionCode == functionCode).Select(t => t.StationNumber).Distinct();
|
var stationNumbers = addresses.Where(t => t.FunctionCode == functionCode).Select(t => t.StationNumber).Distinct();
|
||||||
foreach (var stationNumber in stationNumbers)
|
foreach (var stationNumber in stationNumbers)
|
||||||
{
|
{
|
||||||
var addressList = addresses.Where(t => t.FunctionCode == functionCode && t.StationNumber == t.StationNumber)
|
var addressList = addresses.Where(t => t.FunctionCode == functionCode && t.StationNumber == stationNumber)
|
||||||
.DistinctBy(t => t.Address)
|
.DistinctBy(t => t.Address)
|
||||||
.ToDictionary(t => t.Address, t => t.DataType);
|
.ToDictionary(t => t.Address, t => t.DataType);
|
||||||
var tempResult = BatchRead(addressList, stationNumber, functionCode);
|
var tempResult = BatchRead(addressList, stationNumber, functionCode);
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,8 @@ using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace IoTClient.Clients.PLC
|
namespace IoTClient.Clients.PLC
|
||||||
{
|
{
|
||||||
|
|
@ -204,10 +206,9 @@ namespace IoTClient.Clients.PLC
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="address">地址</param>
|
/// <param name="address">地址</param>
|
||||||
/// <param name="length">读取长度</param>
|
/// <param name="length">读取长度</param>
|
||||||
/// <param name="isBit">是否Bit类型</param>
|
/// <param name="isBit">是否Bit类型</param>
|
||||||
/// <param name="setEndian">暂未使用</param>
|
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public Result<byte[]> Read(string address, ushort length, bool isBit = false, bool setEndian = true)
|
public Result<byte[]> Read(string address, ushort length, bool isBit = false)
|
||||||
{
|
{
|
||||||
if (!socket?.Connected ?? true)
|
if (!socket?.Connected ?? true)
|
||||||
{
|
{
|
||||||
|
|
@ -268,71 +269,6 @@ namespace IoTClient.Clients.PLC
|
||||||
return result.EndTime();
|
return result.EndTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 读取字符串
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="address">地址</param>
|
|
||||||
/// <param name="length">读取长度</param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public Result<byte[]> ReadString(string address, ushort length)
|
|
||||||
{
|
|
||||||
if (!socket?.Connected ?? true)
|
|
||||||
{
|
|
||||||
var connectResult = Connect();
|
|
||||||
if (!connectResult.IsSucceed)
|
|
||||||
{
|
|
||||||
return new Result<byte[]>(connectResult);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var result = new Result<byte[]>();
|
|
||||||
try
|
|
||||||
{
|
|
||||||
//发送读取信息
|
|
||||||
var arg = ConvertArg(address);
|
|
||||||
arg.ReadWriteLength = length;
|
|
||||||
byte[] command = GetReadCommand(arg);
|
|
||||||
result.Requst = string.Join(" ", command.Select(t => t.ToString("X2")));
|
|
||||||
var sendResult = SendPackage(command);
|
|
||||||
if (!sendResult.IsSucceed)
|
|
||||||
return result.SetErrInfo(sendResult).EndTime();
|
|
||||||
|
|
||||||
var dataPackage = sendResult.Value;
|
|
||||||
byte[] requst = new byte[length];
|
|
||||||
Array.Copy(dataPackage, 25, requst, 0, length);
|
|
||||||
result.Response = string.Join(" ", dataPackage.Select(t => t.ToString("X2")));
|
|
||||||
result.Value = requst;
|
|
||||||
}
|
|
||||||
catch (SocketException ex)
|
|
||||||
{
|
|
||||||
result.IsSucceed = false;
|
|
||||||
if (ex.SocketErrorCode == SocketError.TimedOut)
|
|
||||||
{
|
|
||||||
result.Err = "连接超时";
|
|
||||||
result.ErrList.Add("连接超时");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
result.Err = ex.Message;
|
|
||||||
result.Exception = ex;
|
|
||||||
result.ErrList.Add(ex.Message);
|
|
||||||
}
|
|
||||||
socket?.SafeClose();
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
result.IsSucceed = false;
|
|
||||||
result.Err = ex.Message;
|
|
||||||
result.Exception = ex;
|
|
||||||
result.ErrList.Add(ex.Message);
|
|
||||||
socket?.SafeClose();
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
if (isAutoOpen) Dispose();
|
|
||||||
}
|
|
||||||
return result.EndTime();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 分批读取,默认按19个地址打包读取
|
/// 分批读取,默认按19个地址打包读取
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -572,6 +508,31 @@ namespace IoTClient.Clients.PLC
|
||||||
return result.EndTime();
|
return result.EndTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 定时读取,回调更新
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="address"></param>
|
||||||
|
/// <param name="action"></param>
|
||||||
|
public void ReadInt16(string address, Action<short, bool, string> action)
|
||||||
|
{
|
||||||
|
Task.Run(() =>
|
||||||
|
{
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Thread.Sleep(400);
|
||||||
|
var value = ReadInt16(address);
|
||||||
|
action(value.Value, value.IsSucceed, value.Err);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
action(0, false, ex.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 读取Int16
|
/// 读取Int16
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -903,6 +864,70 @@ namespace IoTClient.Clients.PLC
|
||||||
//return Encoding.ASCII.GetString(, 1, length[0]);
|
//return Encoding.ASCII.GetString(, 1, length[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 读取字符串
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="address">地址</param>
|
||||||
|
/// <param name="length">读取长度</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public Result<byte[]> ReadString(string address, ushort length)
|
||||||
|
{
|
||||||
|
if (!socket?.Connected ?? true)
|
||||||
|
{
|
||||||
|
var connectResult = Connect();
|
||||||
|
if (!connectResult.IsSucceed)
|
||||||
|
{
|
||||||
|
return new Result<byte[]>(connectResult);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var result = new Result<byte[]>();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
//发送读取信息
|
||||||
|
var arg = ConvertArg(address);
|
||||||
|
arg.ReadWriteLength = length;
|
||||||
|
byte[] command = GetReadCommand(arg);
|
||||||
|
result.Requst = string.Join(" ", command.Select(t => t.ToString("X2")));
|
||||||
|
var sendResult = SendPackage(command);
|
||||||
|
if (!sendResult.IsSucceed)
|
||||||
|
return result.SetErrInfo(sendResult).EndTime();
|
||||||
|
|
||||||
|
var dataPackage = sendResult.Value;
|
||||||
|
byte[] requst = new byte[length];
|
||||||
|
Array.Copy(dataPackage, 25, requst, 0, length);
|
||||||
|
result.Response = string.Join(" ", dataPackage.Select(t => t.ToString("X2")));
|
||||||
|
result.Value = requst;
|
||||||
|
}
|
||||||
|
catch (SocketException ex)
|
||||||
|
{
|
||||||
|
result.IsSucceed = false;
|
||||||
|
if (ex.SocketErrorCode == SocketError.TimedOut)
|
||||||
|
{
|
||||||
|
result.Err = "连接超时";
|
||||||
|
result.ErrList.Add("连接超时");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result.Err = ex.Message;
|
||||||
|
result.Exception = ex;
|
||||||
|
result.ErrList.Add(ex.Message);
|
||||||
|
}
|
||||||
|
socket?.SafeClose();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
result.IsSucceed = false;
|
||||||
|
result.Err = ex.Message;
|
||||||
|
result.Exception = ex;
|
||||||
|
result.ErrList.Add(ex.Message);
|
||||||
|
socket?.SafeClose();
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
if (isAutoOpen) Dispose();
|
||||||
|
}
|
||||||
|
return result.EndTime();
|
||||||
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Write
|
#region Write
|
||||||
|
|
|
||||||
|
|
@ -60,7 +60,7 @@ namespace IoTClient.Interfaces
|
||||||
/// <param name="length"></param>
|
/// <param name="length"></param>
|
||||||
/// <param name="isBit"></param>
|
/// <param name="isBit"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Result<byte[]> Read(string address, ushort length, bool isBit = false, bool setEndian = true);
|
//Result<byte[]> Read(string address, ushort length, bool isBit = false, bool setEndian = true);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
///
|
||||||
|
|
@ -158,7 +158,7 @@ namespace IoTClient.Interfaces
|
||||||
/// <param name="data">值</param>
|
/// <param name="data">值</param>
|
||||||
/// <param name="isBit">值</param>
|
/// <param name="isBit">值</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Result Write(string address, byte[] data, bool isBit = false);
|
//Result Write(string address, byte[] data, bool isBit = false);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 写入数据
|
/// 写入数据
|
||||||
|
|
|
||||||
|
|
@ -1299,7 +1299,7 @@
|
||||||
<param name="stationNumber">站号</param>
|
<param name="stationNumber">站号</param>
|
||||||
<param name="functionCode">功能码</param>
|
<param name="functionCode">功能码</param>
|
||||||
<param name="encoding">编码</param>
|
<param name="encoding">编码</param>
|
||||||
<param name="readLength">编码</param>
|
<param name="readLength">读取长度</param>
|
||||||
<returns></returns>
|
<returns></returns>
|
||||||
</member>
|
</member>
|
||||||
<member name="M:IoTClient.Clients.Modbus.ModbusTcpClient.ReadCoil(System.String,System.Byte,System.Byte)">
|
<member name="M:IoTClient.Clients.Modbus.ModbusTcpClient.ReadCoil(System.String,System.Byte,System.Byte)">
|
||||||
|
|
@ -2570,22 +2570,13 @@
|
||||||
<param name="command"></param>
|
<param name="command"></param>
|
||||||
<returns></returns>
|
<returns></returns>
|
||||||
</member>
|
</member>
|
||||||
<member name="M:IoTClient.Clients.PLC.SiemensClient.Read(System.String,System.UInt16,System.Boolean,System.Boolean)">
|
<member name="M:IoTClient.Clients.PLC.SiemensClient.Read(System.String,System.UInt16,System.Boolean)">
|
||||||
<summary>
|
<summary>
|
||||||
读取字节数组
|
读取字节数组
|
||||||
</summary>
|
</summary>
|
||||||
<param name="address">地址</param>
|
<param name="address">地址</param>
|
||||||
<param name="length">读取长度</param>
|
<param name="length">读取长度</param>
|
||||||
<param name="isBit">是否Bit类型</param>
|
<param name="isBit">是否Bit类型</param>
|
||||||
<param name="setEndian">暂未使用</param>
|
|
||||||
<returns></returns>
|
|
||||||
</member>
|
|
||||||
<member name="M:IoTClient.Clients.PLC.SiemensClient.ReadString(System.String,System.UInt16)">
|
|
||||||
<summary>
|
|
||||||
读取字符串
|
|
||||||
</summary>
|
|
||||||
<param name="address">地址</param>
|
|
||||||
<param name="length">读取长度</param>
|
|
||||||
<returns></returns>
|
<returns></returns>
|
||||||
</member>
|
</member>
|
||||||
<member name="M:IoTClient.Clients.PLC.SiemensClient.BatchRead(System.Collections.Generic.Dictionary{System.String,IoTClient.Enums.DataTypeEnum},System.Int32)">
|
<member name="M:IoTClient.Clients.PLC.SiemensClient.BatchRead(System.Collections.Generic.Dictionary{System.String,IoTClient.Enums.DataTypeEnum},System.Int32)">
|
||||||
|
|
@ -2640,6 +2631,13 @@
|
||||||
<param name="address">地址</param>
|
<param name="address">地址</param>
|
||||||
<returns></returns>
|
<returns></returns>
|
||||||
</member>
|
</member>
|
||||||
|
<member name="M:IoTClient.Clients.PLC.SiemensClient.ReadInt16(System.String,System.Action{System.Int16,System.Boolean,System.String})">
|
||||||
|
<summary>
|
||||||
|
定时读取,回调更新
|
||||||
|
</summary>
|
||||||
|
<param name="address"></param>
|
||||||
|
<param name="action"></param>
|
||||||
|
</member>
|
||||||
<member name="M:IoTClient.Clients.PLC.SiemensClient.ReadInt16(System.String,System.UInt16)">
|
<member name="M:IoTClient.Clients.PLC.SiemensClient.ReadInt16(System.String,System.UInt16)">
|
||||||
<summary>
|
<summary>
|
||||||
读取Int16
|
读取Int16
|
||||||
|
|
@ -2760,6 +2758,14 @@
|
||||||
<param name="address">地址</param>
|
<param name="address">地址</param>
|
||||||
<returns></returns>
|
<returns></returns>
|
||||||
</member>
|
</member>
|
||||||
|
<member name="M:IoTClient.Clients.PLC.SiemensClient.ReadString(System.String,System.UInt16)">
|
||||||
|
<summary>
|
||||||
|
读取字符串
|
||||||
|
</summary>
|
||||||
|
<param name="address">地址</param>
|
||||||
|
<param name="length">读取长度</param>
|
||||||
|
<returns></returns>
|
||||||
|
</member>
|
||||||
<member name="M:IoTClient.Clients.PLC.SiemensClient.BatchWrite(System.Collections.Generic.Dictionary{System.String,System.Object})">
|
<member name="M:IoTClient.Clients.PLC.SiemensClient.BatchWrite(System.Collections.Generic.Dictionary{System.String,System.Object})">
|
||||||
<summary>
|
<summary>
|
||||||
批量写入
|
批量写入
|
||||||
|
|
@ -3428,15 +3434,6 @@
|
||||||
<param name="batchNumber">批量读取数量</param>
|
<param name="batchNumber">批量读取数量</param>
|
||||||
<returns></returns>
|
<returns></returns>
|
||||||
</member>
|
</member>
|
||||||
<member name="M:IoTClient.Interfaces.IEthernetClient.Read(System.String,System.UInt16,System.Boolean,System.Boolean)">
|
|
||||||
<summary>
|
|
||||||
读取数据
|
|
||||||
</summary>
|
|
||||||
<param name="address">地址</param>
|
|
||||||
<param name="length"></param>
|
|
||||||
<param name="isBit"></param>
|
|
||||||
<returns></returns>
|
|
||||||
</member>
|
|
||||||
<member name="M:IoTClient.Interfaces.IEthernetClient.ReadByte(System.String)">
|
<member name="M:IoTClient.Interfaces.IEthernetClient.ReadByte(System.String)">
|
||||||
<summary>
|
<summary>
|
||||||
|
|
||||||
|
|
@ -3522,15 +3519,6 @@
|
||||||
<param name="batchNumber">批量读取数量</param>
|
<param name="batchNumber">批量读取数量</param>
|
||||||
<returns></returns>
|
<returns></returns>
|
||||||
</member>
|
</member>
|
||||||
<member name="M:IoTClient.Interfaces.IEthernetClient.Write(System.String,System.Byte[],System.Boolean)">
|
|
||||||
<summary>
|
|
||||||
写入数据
|
|
||||||
</summary>
|
|
||||||
<param name="address">地址</param>
|
|
||||||
<param name="data">值</param>
|
|
||||||
<param name="isBit">值</param>
|
|
||||||
<returns></returns>
|
|
||||||
</member>
|
|
||||||
<member name="M:IoTClient.Interfaces.IEthernetClient.Write(System.String,System.Byte)">
|
<member name="M:IoTClient.Interfaces.IEthernetClient.Write(System.String,System.Byte)">
|
||||||
<summary>
|
<summary>
|
||||||
写入数据
|
写入数据
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user