diff --git a/IoTClient.Tests/Modbus_Tests/ModBusTcpClient_tests.cs b/IoTClient.Tests/Modbus_Tests/ModBusTcpClient_tests.cs
index 95d33b1..6e732bd 100644
--- a/IoTClient.Tests/Modbus_Tests/ModBusTcpClient_tests.cs
+++ b/IoTClient.Tests/Modbus_Tests/ModBusTcpClient_tests.cs
@@ -5,6 +5,7 @@ using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Net;
+using System.Text;
using System.Threading.Tasks;
using Xunit;
@@ -37,6 +38,7 @@ namespace IoTClient.Tests.Modbus
float float_number = rnd.Next(int.MinValue, int.MaxValue) / 100;
double double_number = (double)rnd.Next(int.MinValue, int.MaxValue) / 100;
bool coil = int_number % 2 == 0;
+ string orderCode = "WX8200611002" + short_number;
#endregion
//写入地址:0 值为:short_number 站号:stationNumber 功能码:默认16(也可以自己传入对应的功能码)
@@ -51,6 +53,8 @@ namespace IoTClient.Tests.Modbus
client.Write("32", coil, stationNumber, 5);
+ client.Write("100", orderCode, stationNumber);
+
//写入可能有一定的延时,500毫秒后检验
await Task.Delay(500);
@@ -66,6 +70,8 @@ namespace IoTClient.Tests.Modbus
Assert.True(client.ReadDouble("28", stationNumber, 3).Value == double_number);
Assert.True(client.ReadCoil("32", stationNumber, 1).Value == coil);
+
+ Assert.True(client.ReadString("100", stationNumber, readLength: (ushort)orderCode.Length).Value == orderCode);
}
}
diff --git a/IoTClient/Clients/ModBus/ModBusAsciiClient.cs b/IoTClient/Clients/ModBus/ModBusAsciiClient.cs
index 3a60851..e2f8fd9 100644
--- a/IoTClient/Clients/ModBus/ModBusAsciiClient.cs
+++ b/IoTClient/Clients/ModBus/ModBusAsciiClient.cs
@@ -162,7 +162,7 @@ namespace IoTClient.Clients.Modbus
///
///
///
- public override Result Write(string address, byte[] values, byte stationNumber = 1, byte functionCode = 16)
+ public override Result Write(string address, byte[] values, byte stationNumber = 1, byte functionCode = 16, bool byteFormatting = true)
{
if (isAutoOpen) Connect();
diff --git a/IoTClient/Clients/ModBus/ModBusRtuClient.cs b/IoTClient/Clients/ModBus/ModBusRtuClient.cs
index 51114b4..4225bc8 100644
--- a/IoTClient/Clients/ModBus/ModBusRtuClient.cs
+++ b/IoTClient/Clients/ModBus/ModBusRtuClient.cs
@@ -142,7 +142,7 @@ namespace IoTClient.Clients.Modbus
///
///
///
- public override Result Write(string address, byte[] values, byte stationNumber = 1, byte functionCode = 16)
+ public override Result Write(string address, byte[] values, byte stationNumber = 1, byte functionCode = 16, bool byteFormatting = true)
{
if (isAutoOpen) Connect();
diff --git a/IoTClient/Clients/ModBus/ModBusTcpClient.cs b/IoTClient/Clients/ModBus/ModBusTcpClient.cs
index 70d993e..a5895a2 100644
--- a/IoTClient/Clients/ModBus/ModBusTcpClient.cs
+++ b/IoTClient/Clients/ModBus/ModBusTcpClient.cs
@@ -6,6 +6,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
+using System.Text;
namespace IoTClient.Clients.Modbus
{
@@ -469,6 +470,34 @@ namespace IoTClient.Clients.Modbus
return ReadDouble(address.ToString(), stationNumber, functionCode);
}
+ ///
+ /// 读取字符串
+ ///
+ /// 地址
+ /// 站号
+ /// 功能码
+ /// 编码
+ /// 读取长度
+ ///
+ public Result ReadString(string address, byte stationNumber = 1, byte functionCode = 3, Encoding encoding = null, ushort readLength = 10)
+ {
+ if (encoding == null) encoding = Encoding.ASCII;
+
+ readLength = (ushort)Math.Ceiling((float)readLength / 2);
+ var readResut = Read(address, stationNumber, functionCode, readLength: readLength, byteFormatting: false);
+ var result = new Result()
+ {
+ IsSucceed = readResut.IsSucceed,
+ Err = readResut.Err,
+ ErrList = readResut.ErrList,
+ Requst = readResut.Requst,
+ Response = readResut.Response,
+ };
+ if (result.IsSucceed)
+ result.Value = encoding.GetString(readResut.Value.Reverse().ToArray())?.Replace("\0", "");
+ return result.EndTime();
+ }
+
///
/// 读取线圈类型数据
///
@@ -973,103 +1002,6 @@ namespace IoTClient.Clients.Modbus
return ReadDiscrete(beginAddress.ToString(), address.ToString(), values);
}
- #region 假的批量 注释
- /////
- ///// 分批读取【假的批量,内部实际还是循环读取】
- /////
- ///// 地址集合
- ///// 批量读取数量
- /////
- //public Result> BatchRead(Dictionary addresses, int batchNumber = 19)
- //{
- // var result = new Result>();
- // result.Value = new Dictionary();
-
- // var batchCount = Math.Ceiling((float)addresses.Count / batchNumber);
- // for (int i = 0; i < batchCount; i++)
- // {
- // var tempAddresses = addresses.Skip(i * batchNumber).Take(batchNumber).ToDictionary(t => t.Key, t => t.Value);
- // var tempResult = BatchRead(tempAddresses);
- // if (tempResult.IsSucceed)
- // {
- // foreach (var item in tempResult.Value)
- // {
- // result.Value.Add(item.Key, item.Value);
- // }
- // }
- // else
- // {
- // result.IsSucceed = false;
- // result.Err = tempResult.Err;
- // }
- // }
- // return result.EndTime();
- //}
-
- //private Result> BatchRead(Dictionary addresses)
- //{
- // var result = new Result>();
- // result.Value = new Dictionary();
- // try
- // {
- // foreach (var item in addresses)
- // {
- // var richText = item.Key.Split('_');
- // if (richText.Length < 2)
- // continue; //必须传入站号
- // var stationNumber = byte.Parse(richText[0]);
- // var addresse = richText[1];
- // var functionCode = richText.Length >= 3 ? byte.Parse(richText[2]) : (byte)3;
- // object value;
- // switch (item.Value)
- // {
- // case DataTypeEnum.Bool:
- // value = ReadDiscrete(addresse, stationNumber, functionCode).Value;
- // break;
- // //case DataTypeEnum.Byte:
- // // value = readResut[0];
- // // break;
- // case DataTypeEnum.Int16:
- // value = ReadInt16(addresse, stationNumber, functionCode).Value;
- // break;
- // case DataTypeEnum.UInt16:
- // value = ReadUInt16(addresse, stationNumber, functionCode).Value;
- // break;
- // case DataTypeEnum.Int32:
- // value = ReadInt32(addresse, stationNumber, functionCode).Value;
- // break;
- // case DataTypeEnum.UInt32:
- // value = ReadUInt32(addresse, stationNumber, functionCode).Value;
- // break;
- // case DataTypeEnum.Int64:
- // value = ReadInt64(addresse, stationNumber, functionCode).Value;
- // break;
- // case DataTypeEnum.UInt64:
- // value = ReadUInt64(addresse, stationNumber, functionCode).Value;
- // break;
- // case DataTypeEnum.Float:
- // value = ReadFloat(addresse, stationNumber, functionCode).Value;
- // break;
- // case DataTypeEnum.Double:
- // value = ReadDouble(addresse, stationNumber, functionCode).Value;
- // break;
- // default:
- // throw new Exception($"未定义数据类型:{item.Value}");
- // }
- // result.Value.Add(item.Key, value);
- // }
- // }
- // catch (Exception ex)
- // {
- // result.IsSucceed = false;
- // result.Err = ex.Message;
- // result.Exception = ex;
- // result.ErrList.Add(ex.Message);
- // }
- // return result.EndTime();
- //}
- #endregion
-
///
/// 分批读取(批量读取,内部进行批量计算读取)
///
@@ -1279,15 +1211,17 @@ namespace IoTClient.Clients.Modbus
/// 批量读取的值
/// 站号
/// 功能码
+ /// 大小端设置
///
- public Result Write(string address, byte[] values, byte stationNumber = 1, byte functionCode = 16)
+ public Result Write(string address, byte[] values, byte stationNumber = 1, byte functionCode = 16, bool byteFormatting = true)
{
if (!socket?.Connected ?? true) Connect();
var result = new Result();
try
{
- values = values.ByteFormatting(format);
+ if (byteFormatting)
+ values = values.ByteFormatting(format);
var chenkHead = GetCheckHead(functionCode);
var command = GetWriteCommand(address, values, stationNumber, functionCode, chenkHead);
result.Requst = string.Join(" ", command.Select(t => t.ToString("X2")));
@@ -1426,6 +1360,24 @@ namespace IoTClient.Clients.Modbus
var values = BitConverter.GetBytes(value).Reverse().ToArray();
return Write(address, values, stationNumber, functionCode);
}
+
+ ///
+ /// 写字符串
+ ///
+ /// 地址
+ /// 字符串值
+ /// 站号
+ /// 功能码
+ /// 编码
+ ///
+ public Result Write(string address, string value, byte stationNumber = 1, byte functionCode = 16, Encoding encoding = null)
+ {
+ if (encoding == null) encoding = Encoding.ASCII;
+ if (value.Length % 2 == 1)
+ value = value + "\0";
+ var values = encoding.GetBytes(value);
+ return Write(address, values, stationNumber, functionCode, false);
+ }
#endregion
#region 获取命令
diff --git a/IoTClient/Clients/Modbus/Base/ModbusSerialBase.cs b/IoTClient/Clients/Modbus/Base/ModbusSerialBase.cs
index c396e90..d26464f 100644
--- a/IoTClient/Clients/Modbus/Base/ModbusSerialBase.cs
+++ b/IoTClient/Clients/Modbus/Base/ModbusSerialBase.cs
@@ -843,7 +843,7 @@ namespace IoTClient.Clients.Modbus
///
///
///
- public abstract Result Write(string address, byte[] values, byte stationNumber = 1, byte functionCode = 16);
+ public abstract Result Write(string address, byte[] values, byte stationNumber = 1, byte functionCode = 16, bool byteFormatting = true);
///
/// 写入
diff --git a/IoTClient/Clients/Modbus/Interfaces/IModbusClient.cs b/IoTClient/Clients/Modbus/Interfaces/IModbusClient.cs
index 5b77696..a30f9ea 100644
--- a/IoTClient/Clients/Modbus/Interfaces/IModbusClient.cs
+++ b/IoTClient/Clients/Modbus/Interfaces/IModbusClient.cs
@@ -251,7 +251,7 @@ namespace IoTClient.Clients.Modbus
///
///
///
- Result Write(string address, byte[] values, byte stationNumber = 1, byte functionCode = 16);
+ Result Write(string address, byte[] values, byte stationNumber = 1, byte functionCode = 16, bool byteFormatting = true);
///
/// 写入
diff --git a/IoTClient/Clients/Modbus/ModbusRtuOverTcpClient.cs b/IoTClient/Clients/Modbus/ModbusRtuOverTcpClient.cs
index 81f8b82..5f8c3d9 100644
--- a/IoTClient/Clients/Modbus/ModbusRtuOverTcpClient.cs
+++ b/IoTClient/Clients/Modbus/ModbusRtuOverTcpClient.cs
@@ -985,7 +985,7 @@ namespace IoTClient.Clients.Modbus
///
///
///
- public Result Write(string address, byte[] values, byte stationNumber = 1, byte functionCode = 16)
+ public Result Write(string address, byte[] values, byte stationNumber = 1, byte functionCode = 16, bool byteFormatting = true)
{
if (isAutoOpen) Connect();
diff --git a/IoTClient/IoTClient/IoTClient.xml b/IoTClient/IoTClient/IoTClient.xml
index ffd58f1..b0419a7 100644
--- a/IoTClient/IoTClient/IoTClient.xml
+++ b/IoTClient/IoTClient/IoTClient.xml
@@ -234,7 +234,7 @@
-
+
写入
@@ -583,7 +583,7 @@
-
+
写入
@@ -701,7 +701,7 @@
-
+
写入
@@ -748,7 +748,7 @@
-
+
写入
@@ -991,7 +991,7 @@
-
+
写入
@@ -1291,6 +1291,17 @@
功能码
+
+
+ 读取字符串
+
+ 地址
+ 站号
+ 功能码
+ 编码
+ 编码
+
+
读取线圈类型数据
@@ -1523,7 +1534,7 @@
站号
功能码
-
+
写入
@@ -1531,6 +1542,7 @@
批量读取的值
站号
功能码
+ 大小端设置
@@ -1605,6 +1617,17 @@
站号
功能码
+
+
+ 写字符串
+
+ 地址
+ 字符串值
+ 站号
+ 功能码
+ 编码
+
+
获取随机校验头
diff --git a/README.md b/README.md
index 802accb..4612a90 100644
--- a/README.md
+++ b/README.md
@@ -34,6 +34,7 @@ client.Write("20", (ulong)33, 2, 16); //写入ulong类型数值
client.Write("24", (float)33, 2, 16); //写入float类型数值
client.Write("28", (double)33, 2, 16); //写入double类型数值
client.Write("32", true, 2, 5); //写入线圈类型值
+client.Write("100", "orderCode", stationNumber); //写入字符串
//3、读操作 - 参数依次是:地址 、站号 、功能码
var value = client.ReadInt16("4", 2, 3).Value;
@@ -49,6 +50,7 @@ client.ReadFloat("24", stationNumber, 3); //float类型数据读取
client.ReadDouble("28", stationNumber, 3); //double类型数据读取
client.ReadCoil("32", stationNumber, 1); //线圈类型数据读取
client.ReadDiscrete("32", stationNumber, 2);//离散类型数据读取
+client.ReadString("100", stationNumber,10); //读取字符串
//4、如果没有主动Open,则会每次读写操作的时候自动打开自动和关闭连接,这样会使读写效率大大减低。所以建议手动Open和Close。
client.Open();