1
0
mirror of https://github.com/zhaopeiym/IoTClient synced 2025-10-19 22:14:31 +08:00
ModBusTcp 读写字符串
This commit is contained in:
BennyZhao 2021-05-06 11:12:19 +08:00
parent 79e5b1aee6
commit 5d313bf999
9 changed files with 93 additions and 110 deletions

View File

@ -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);
}
}

View File

@ -162,7 +162,7 @@ namespace IoTClient.Clients.Modbus
/// <param name="stationNumber"></param>
/// <param name="functionCode"></param>
/// <returns></returns>
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();

View File

@ -142,7 +142,7 @@ namespace IoTClient.Clients.Modbus
/// <param name="stationNumber"></param>
/// <param name="functionCode"></param>
/// <returns></returns>
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();

View File

@ -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);
}
/// <summary>
/// 读取字符串
/// </summary>
/// <param name="address">地址</param>
/// <param name="stationNumber">站号</param>
/// <param name="functionCode">功能码</param>
/// <param name="encoding">编码</param>
/// <param name="readLength">读取长度</param>
/// <returns></returns>
public Result<string> 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<string>()
{
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();
}
/// <summary>
/// 读取线圈类型数据
/// </summary>
@ -973,103 +1002,6 @@ namespace IoTClient.Clients.Modbus
return ReadDiscrete(beginAddress.ToString(), address.ToString(), values);
}
#region
///// <summary>
///// 分批读取【假的批量,内部实际还是循环读取】
///// </summary>
///// <param name="addresses">地址集合</param>
///// <param name="batchNumber">批量读取数量</param>
///// <returns></returns>
//public Result<Dictionary<string, object>> BatchRead(Dictionary<string, DataTypeEnum> addresses, int batchNumber = 19)
//{
// var result = new Result<Dictionary<string, object>>();
// result.Value = new Dictionary<string, object>();
// 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<Dictionary<string, object>> BatchRead(Dictionary<string, DataTypeEnum> addresses)
//{
// var result = new Result<Dictionary<string, object>>();
// result.Value = new Dictionary<string, object>();
// 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
/// <summary>
/// 分批读取(批量读取,内部进行批量计算读取)
/// </summary>
@ -1279,15 +1211,17 @@ namespace IoTClient.Clients.Modbus
/// <param name="values">批量读取的值</param>
/// <param name="stationNumber">站号</param>
/// <param name="functionCode">功能码</param>
/// <param name="byteFormatting">大小端设置</param>
/// <returns></returns>
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);
}
/// <summary>
/// 写字符串
/// </summary>
/// <param name="address">地址</param>
/// <param name="value">字符串值</param>
/// <param name="stationNumber">站号</param>
/// <param name="functionCode">功能码</param>
/// <param name="encoding">编码</param>
/// <returns></returns>
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

View File

@ -843,7 +843,7 @@ namespace IoTClient.Clients.Modbus
/// <param name="stationNumber"></param>
/// <param name="functionCode"></param>
/// <returns></returns>
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);
/// <summary>
/// 写入

View File

@ -251,7 +251,7 @@ namespace IoTClient.Clients.Modbus
/// <param name="stationNumber"></param>
/// <param name="functionCode"></param>
/// <returns></returns>
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);
/// <summary>
/// 写入

View File

@ -985,7 +985,7 @@ namespace IoTClient.Clients.Modbus
/// <param name="stationNumber"></param>
/// <param name="functionCode"></param>
/// <returns></returns>
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();

View File

@ -234,7 +234,7 @@
<param name="stationNumber"></param>
<param name="functionCode"></param>
</member>
<member name="M:IoTClient.Clients.Modbus.ModbusSerialBase.Write(System.String,System.Byte[],System.Byte,System.Byte)">
<member name="M:IoTClient.Clients.Modbus.ModbusSerialBase.Write(System.String,System.Byte[],System.Byte,System.Byte,System.Boolean)">
<summary>
写入
</summary>
@ -583,7 +583,7 @@
<param name="stationNumber"></param>
<param name="functionCode"></param>
</member>
<member name="M:IoTClient.Clients.Modbus.IModbusClient.Write(System.String,System.Byte[],System.Byte,System.Byte)">
<member name="M:IoTClient.Clients.Modbus.IModbusClient.Write(System.String,System.Byte[],System.Byte,System.Byte,System.Boolean)">
<summary>
写入
</summary>
@ -701,7 +701,7 @@
<param name="stationNumber"></param>
<param name="functionCode"></param>
</member>
<member name="M:IoTClient.Clients.Modbus.ModbusAsciiClient.Write(System.String,System.Byte[],System.Byte,System.Byte)">
<member name="M:IoTClient.Clients.Modbus.ModbusAsciiClient.Write(System.String,System.Byte[],System.Byte,System.Byte,System.Boolean)">
<summary>
写入
</summary>
@ -748,7 +748,7 @@
<param name="stationNumber"></param>
<param name="functionCode"></param>
</member>
<member name="M:IoTClient.Clients.Modbus.ModbusRtuClient.Write(System.String,System.Byte[],System.Byte,System.Byte)">
<member name="M:IoTClient.Clients.Modbus.ModbusRtuClient.Write(System.String,System.Byte[],System.Byte,System.Byte,System.Boolean)">
<summary>
写入
</summary>
@ -991,7 +991,7 @@
<param name="stationNumber"></param>
<param name="functionCode"></param>
</member>
<member name="M:IoTClient.Clients.Modbus.ModbusRtuOverTcpClient.Write(System.String,System.Byte[],System.Byte,System.Byte)">
<member name="M:IoTClient.Clients.Modbus.ModbusRtuOverTcpClient.Write(System.String,System.Byte[],System.Byte,System.Byte,System.Boolean)">
<summary>
写入
</summary>
@ -1291,6 +1291,17 @@
<param name="functionCode">功能码</param>
<returns></returns>
</member>
<member name="M:IoTClient.Clients.Modbus.ModbusTcpClient.ReadString(System.String,System.Byte,System.Byte,System.Text.Encoding,System.UInt16)">
<summary>
读取字符串
</summary>
<param name="address">地址</param>
<param name="stationNumber">站号</param>
<param name="functionCode">功能码</param>
<param name="encoding">编码</param>
<param name="readLength">编码</param>
<returns></returns>
</member>
<member name="M:IoTClient.Clients.Modbus.ModbusTcpClient.ReadCoil(System.String,System.Byte,System.Byte)">
<summary>
读取线圈类型数据
@ -1523,7 +1534,7 @@
<param name="stationNumber">站号</param>
<param name="functionCode">功能码</param>
</member>
<member name="M:IoTClient.Clients.Modbus.ModbusTcpClient.Write(System.String,System.Byte[],System.Byte,System.Byte)">
<member name="M:IoTClient.Clients.Modbus.ModbusTcpClient.Write(System.String,System.Byte[],System.Byte,System.Byte,System.Boolean)">
<summary>
写入
</summary>
@ -1531,6 +1542,7 @@
<param name="values">批量读取的值</param>
<param name="stationNumber">站号</param>
<param name="functionCode">功能码</param>
<param name="byteFormatting">大小端设置</param>
<returns></returns>
</member>
<member name="M:IoTClient.Clients.Modbus.ModbusTcpClient.Write(System.String,System.Int16,System.Byte,System.Byte)">
@ -1605,6 +1617,17 @@
<param name="stationNumber">站号</param>
<param name="functionCode">功能码</param>
</member>
<member name="M:IoTClient.Clients.Modbus.ModbusTcpClient.Write(System.String,System.String,System.Byte,System.Byte,System.Text.Encoding)">
<summary>
写字符串
</summary>
<param name="address">地址</param>
<param name="value">字符串值</param>
<param name="stationNumber">站号</param>
<param name="functionCode">功能码</param>
<param name="encoding">编码</param>
<returns></returns>
</member>
<member name="M:IoTClient.Clients.Modbus.ModbusTcpClient.GetCheckHead(System.Int32)">
<summary>
获取随机校验头

View File

@ -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();