mirror of
https://github.com/zhaopeiym/IoTClient
synced 2025-10-19 22:14:31 +08:00
parent
79e5b1aee6
commit
5d313bf999
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
||||
|
|
|
|||
|
|
@ -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 获取命令
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
/// 写入
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
/// 写入
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
获取随机校验头
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user