diff --git a/IoTClient.Tests/Modbus_Tests/ModBusRtuClient_tests.cs b/IoTClient.Tests/Modbus_Tests/ModBusRtuClient_tests.cs
index e462315..c6e9041 100644
--- a/IoTClient.Tests/Modbus_Tests/ModBusRtuClient_tests.cs
+++ b/IoTClient.Tests/Modbus_Tests/ModBusRtuClient_tests.cs
@@ -14,7 +14,7 @@ namespace IoTClient.Tests.Modbus
byte stationNumber = 1;//站号
public ModbusRtuClient_tests()
{
- client = new ModbusRtuClient("COM3", 9600, 8, StopBits.One, Parity.None);
+ client = new ModbusRtuClient("COM2", 9600, 8, StopBits.One, Parity.None);
}
[Fact]
diff --git a/IoTClient.Tests/Modbus_Tests/ModBusTcpClient_tests.cs b/IoTClient.Tests/Modbus_Tests/ModBusTcpClient_tests.cs
index 58e94b0..a69c484 100644
--- a/IoTClient.Tests/Modbus_Tests/ModBusTcpClient_tests.cs
+++ b/IoTClient.Tests/Modbus_Tests/ModBusTcpClient_tests.cs
@@ -1,4 +1,5 @@
using IoTClient.Clients.Modbus;
+using IoTClient.Common.Helpers;
using IoTClient.Enums;
using IoTClient.Models;
using System;
@@ -22,9 +23,18 @@ namespace IoTClient.Tests.Modbus
client = new ModbusTcpClient(new IPEndPoint(ip, port));
}
+ public bool ShortToBit(int value, int index)
+ {
+ var binaryArray = DataConvert.IntToBinaryArray(value, 16);
+ var length = binaryArray.Length - 16;
+ return binaryArray[length + index].ToString() == "1";
+ }
+
[Fact]
public async Task 短连接自动开关()
{
+ var aa1 = client.ReadUInt16Bit("0.1").Value;
+
Random rnd = new Random((int)Stopwatch.GetTimestamp());
for (int i = 0; i < 10; i++)
{
@@ -129,7 +139,7 @@ namespace IoTClient.Tests.Modbus
[Fact]
public void 批量读取()
- {
+ {
var result1 = client.ReadInt16("12");
client.WarningLog = (msg, ex) =>
diff --git a/IoTClient.Tests/PLC_Tests/OmronFinsClient_Tests.cs b/IoTClient.Tests/PLC_Tests/OmronFinsClient_Tests.cs
index 3b18150..852e36a 100644
--- a/IoTClient.Tests/PLC_Tests/OmronFinsClient_Tests.cs
+++ b/IoTClient.Tests/PLC_Tests/OmronFinsClient_Tests.cs
@@ -24,6 +24,8 @@ namespace IoTClient.Tests.PLCTests
var reuslt = client.Open();
+ client.ReadInt16("D6402");
+
Random rnd = new Random((int)Stopwatch.GetTimestamp());
short short_number = (short)rnd.Next(short.MinValue, short.MaxValue);
@@ -37,6 +39,11 @@ namespace IoTClient.Tests.PLCTests
client.Write("D300", short_number);
client.Write("D301", short_number_1);
+ client.Write("D100", (short)100);
+
+ Assert.True(client.ReadInt16("D100").Value == 100);
+ Assert.True(client.ReadInt16("D300").Value == short_number);
+ Assert.True(client.ReadUInt16("D301").Value == short_number_1);
client.Write("D310", int_number);
client.Write("D312", int_number_1);
@@ -117,6 +124,11 @@ namespace IoTClient.Tests.PLCTests
Assert.True(Convert.ToUInt64(result.Value["D354"]) == Convert.ToUInt64(int_number_1));
Assert.True(Convert.ToDouble(result.Value["D358"]) == Convert.ToDouble(float_number));
+ client.Write("H400.15", false);
+ Assert.True(client.ReadBoolean("H400.15").Value == false);
+ client.Write("H400.15", true);
+ Assert.True(client.ReadBoolean("H400.15").Value == true);
+
client.Close();
}
diff --git a/IoTClient/Clients/Modbus/Base/ModbusSerialBase.cs b/IoTClient/Clients/Modbus/Base/ModbusSerialBase.cs
index eba65d1..fd13fbd 100644
--- a/IoTClient/Clients/Modbus/Base/ModbusSerialBase.cs
+++ b/IoTClient/Clients/Modbus/Base/ModbusSerialBase.cs
@@ -129,6 +129,38 @@ namespace IoTClient.Clients.Modbus
return result.EndTime();
}
+ ///
+ /// 按位的方式读取
+ ///
+ /// 寄存器地址:如1.00 ... 1.14、1.15
+ /// 站号
+ /// 功能码
+ /// 按位取值从左边开始取
+ ///
+ public Result ReadInt16Bit(string address, byte stationNumber = 1, byte functionCode = 3, bool left = true)
+ {
+ string[] adds = address.Split('.');
+ var readResut = Read(adds[0].Trim(), stationNumber, functionCode);
+ var result = new Result(readResut);
+ if (result.IsSucceed)
+ {
+ result.Value = BitConverter.ToInt16(readResut.Value, 0);
+ if (adds.Length >= 2)
+ {
+ var index = int.Parse(adds[1].Trim());
+ var binaryArray = DataConvert.IntToBinaryArray(result.Value, 16);
+ if (left)
+ {
+ var length = binaryArray.Length - 16;
+ result.Value = short.Parse(binaryArray[length + index].ToString());
+ }
+ else
+ result.Value = short.Parse(binaryArray[binaryArray.Length - 1 - index].ToString());
+ }
+ }
+ return result.EndTime();
+ }
+
///
/// 读取UInt16
///
@@ -145,6 +177,38 @@ namespace IoTClient.Clients.Modbus
return result.EndTime();
}
+ ///
+ /// 按位的方式读取
+ ///
+ /// 寄存器地址:如1.00 ... 1.14、1.15
+ /// 站号
+ /// 功能码
+ /// 按位取值从左边开始取
+ ///
+ public Result ReadUInt16Bit(string address, byte stationNumber = 1, byte functionCode = 3, bool left = true)
+ {
+ string[] adds = address.Split('.');
+ var readResut = Read(adds[0].Trim(), stationNumber, functionCode);
+ var result = new Result(readResut);
+ if (result.IsSucceed)
+ {
+ result.Value = BitConverter.ToUInt16(readResut.Value, 0);
+ if (adds.Length >= 2)
+ {
+ var index = int.Parse(adds[1].Trim());
+ var binaryArray = DataConvert.IntToBinaryArray(result.Value, 16);
+ if (left)
+ {
+ var length = binaryArray.Length - 16;
+ result.Value = ushort.Parse(binaryArray[length + index].ToString());
+ }
+ else
+ result.Value = ushort.Parse(binaryArray[binaryArray.Length - 1 - index].ToString());
+ }
+ }
+ return result.EndTime();
+ }
+
///
/// 读取Int32
///
diff --git a/IoTClient/Clients/Modbus/Interfaces/IModbusClient.cs b/IoTClient/Clients/Modbus/Interfaces/IModbusClient.cs
index df33d24..0369e6f 100644
--- a/IoTClient/Clients/Modbus/Interfaces/IModbusClient.cs
+++ b/IoTClient/Clients/Modbus/Interfaces/IModbusClient.cs
@@ -59,6 +59,16 @@ namespace IoTClient.Clients.Modbus
///
Result ReadInt16(string address, byte stationNumber = 1, byte functionCode = 3);
+ ///
+ /// 按位的方式读取
+ ///
+ /// 寄存器地址:如1.00 ... 1.14、1.15
+ /// 站号
+ /// 功能码
+ /// 按位取值从左边开始取
+ ///
+ Result ReadInt16Bit(string address, byte stationNumber = 1, byte functionCode = 3, bool left = true);
+
///
/// 从批量读取的数据字节提取对应的地址数据
///
@@ -86,6 +96,16 @@ namespace IoTClient.Clients.Modbus
///
Result ReadUInt16(string beginAddress, string address, byte[] values);
+ ///
+ /// 按位的方式读取
+ ///
+ /// 寄存器地址:如1.00 ... 1.14、1.15
+ /// 站号
+ /// 功能码
+ /// 按位取值从左边开始取
+ ///
+ Result ReadUInt16Bit(string address, byte stationNumber = 1, byte functionCode = 3, bool left = true);
+
///
/// 读取Int32
///
diff --git a/IoTClient/Clients/Modbus/ModbusRtuClient.cs b/IoTClient/Clients/Modbus/ModbusRtuClient.cs
index 57381c7..3b99bc1 100644
--- a/IoTClient/Clients/Modbus/ModbusRtuClient.cs
+++ b/IoTClient/Clients/Modbus/ModbusRtuClient.cs
@@ -65,6 +65,11 @@ namespace IoTClient.Clients.Modbus
result.Err = "响应结果CRC16验证失败";
//return result.EndTime();
}
+ else if (ModbusHelper.VerifyFunctionCode(functionCode, responsePackage[1]))
+ {
+ result.IsSucceed = false;
+ result.Err = ModbusHelper.ErrMsg(responsePackage[2]);
+ }
byte[] resultData = new byte[responsePackage.Length - 2 - 3];
Array.Copy(responsePackage, 3, resultData, 0, resultData.Length);
@@ -123,6 +128,11 @@ namespace IoTClient.Clients.Modbus
result.Err = "响应结果CRC16验证失败";
//return result.EndTime();
}
+ else if (ModbusHelper.VerifyFunctionCode(functionCode, responsePackage[1]))
+ {
+ result.IsSucceed = false;
+ result.Err = ModbusHelper.ErrMsg(responsePackage[2]);
+ }
byte[] resultBuffer = new byte[responsePackage.Length - 2];
Buffer.BlockCopy(responsePackage, 0, resultBuffer, 0, resultBuffer.Length);
result.Response = string.Join(" ", responsePackage.Select(t => t.ToString("X2")));
@@ -175,6 +185,11 @@ namespace IoTClient.Clients.Modbus
result.Err = "响应结果CRC16验证失败";
//return result.EndTime();
}
+ else if (ModbusHelper.VerifyFunctionCode(functionCode, responsePackage[1]))
+ {
+ result.IsSucceed = false;
+ result.Err = ModbusHelper.ErrMsg(responsePackage[2]);
+ }
byte[] resultBuffer = new byte[responsePackage.Length - 2];
Array.Copy(responsePackage, 0, resultBuffer, 0, resultBuffer.Length);
result.Response = string.Join(" ", responsePackage.Select(t => t.ToString("X2")));
diff --git a/IoTClient/Clients/Modbus/ModbusRtuOverTcpClient.cs b/IoTClient/Clients/Modbus/ModbusRtuOverTcpClient.cs
index 80718e2..fa95e9b 100644
--- a/IoTClient/Clients/Modbus/ModbusRtuOverTcpClient.cs
+++ b/IoTClient/Clients/Modbus/ModbusRtuOverTcpClient.cs
@@ -230,6 +230,38 @@ namespace IoTClient.Clients.Modbus
return result.EndTime();
}
+ ///
+ /// 按位的方式读取
+ ///
+ /// 寄存器地址:如1.00 ... 1.14、1.15
+ /// 站号
+ /// 功能码
+ /// 按位取值从左边开始取
+ ///
+ public Result ReadInt16Bit(string address, byte stationNumber = 1, byte functionCode = 3, bool left = true)
+ {
+ string[] adds = address.Split('.');
+ var readResut = Read(adds[0].Trim(), stationNumber, functionCode);
+ var result = new Result(readResut);
+ if (result.IsSucceed)
+ {
+ result.Value = BitConverter.ToInt16(readResut.Value, 0);
+ if (adds.Length >= 2)
+ {
+ var index = int.Parse(adds[1].Trim());
+ var binaryArray = DataConvert.IntToBinaryArray(result.Value, 16);
+ if (left)
+ {
+ var length = binaryArray.Length - 16;
+ result.Value = short.Parse(binaryArray[length + index].ToString());
+ }
+ else
+ result.Value = short.Parse(binaryArray[binaryArray.Length - 1 - index].ToString());
+ }
+ }
+ return result.EndTime();
+ }
+
///
/// 读取UInt16
///
@@ -246,6 +278,38 @@ namespace IoTClient.Clients.Modbus
return result.EndTime();
}
+ ///
+ /// 按位的方式读取
+ ///
+ /// 寄存器地址:如1.00 ... 1.14、1.15
+ /// 站号
+ /// 功能码
+ /// 按位取值从左边开始取
+ ///
+ public Result ReadUInt16Bit(string address, byte stationNumber = 1, byte functionCode = 3, bool left = true)
+ {
+ string[] adds = address.Split('.');
+ var readResut = Read(adds[0].Trim(), stationNumber, functionCode);
+ var result = new Result(readResut);
+ if (result.IsSucceed)
+ {
+ result.Value = BitConverter.ToUInt16(readResut.Value, 0);
+ if (adds.Length >= 2)
+ {
+ var index = int.Parse(adds[1].Trim());
+ var binaryArray = DataConvert.IntToBinaryArray(result.Value, 16);
+ if (left)
+ {
+ var length = binaryArray.Length - 16;
+ result.Value = ushort.Parse(binaryArray[length + index].ToString());
+ }
+ else
+ result.Value = ushort.Parse(binaryArray[binaryArray.Length - 1 - index].ToString());
+ }
+ }
+ return result.EndTime();
+ }
+
///
/// 读取Int32
///
diff --git a/IoTClient/Clients/Modbus/ModbusTcpClient.cs b/IoTClient/Clients/Modbus/ModbusTcpClient.cs
index d6cd1e4..e3c376a 100644
--- a/IoTClient/Clients/Modbus/ModbusTcpClient.cs
+++ b/IoTClient/Clients/Modbus/ModbusTcpClient.cs
@@ -183,6 +183,11 @@ namespace IoTClient.Clients.Modbus
result.Err = $"读取 地址:{address} 站号:{stationNumber} 功能码:{functionCode} 失败。响应结果校验失败";
socket?.SafeClose();
}
+ else if (ModbusHelper.VerifyFunctionCode(functionCode, dataPackage[7]))
+ {
+ result.IsSucceed = false;
+ result.Err = ModbusHelper.ErrMsg(dataPackage[8]);
+ }
}
catch (SocketException ex)
{
@@ -220,6 +225,38 @@ namespace IoTClient.Clients.Modbus
return result.EndTime();
}
+ ///
+ /// 按位的方式读取
+ ///
+ /// 寄存器地址:如1.00 ... 1.14、1.15
+ /// 站号
+ /// 功能码
+ /// 按位取值从左边开始取
+ ///
+ public Result ReadInt16Bit(string address, byte stationNumber = 1, byte functionCode = 3, bool left = true)
+ {
+ string[] adds = address.Split('.');
+ var readResut = Read(adds[0].Trim(), stationNumber, functionCode);
+ var result = new Result(readResut);
+ if (result.IsSucceed)
+ {
+ result.Value = BitConverter.ToInt16(readResut.Value, 0);
+ if (adds.Length >= 2)
+ {
+ var index = int.Parse(adds[1].Trim());
+ var binaryArray = DataConvert.IntToBinaryArray(result.Value, 16);
+ if (left)
+ {
+ var length = binaryArray.Length - 16;
+ result.Value = short.Parse(binaryArray[length + index].ToString());
+ }
+ else
+ result.Value = short.Parse(binaryArray[binaryArray.Length - 1 - index].ToString());
+ }
+ }
+ return result.EndTime();
+ }
+
///
/// 读取Int16类型数据
///
@@ -247,6 +284,38 @@ namespace IoTClient.Clients.Modbus
return result.EndTime();
}
+ ///
+ /// 按位的方式读取
+ ///
+ /// 寄存器地址:如1.00 ... 1.14、1.15
+ /// 站号
+ /// 功能码
+ /// 按位取值从左边开始取
+ ///
+ public Result ReadUInt16Bit(string address, byte stationNumber = 1, byte functionCode = 3, bool left = true)
+ {
+ string[] adds = address.Split('.');
+ var readResut = Read(adds[0].Trim(), stationNumber, functionCode);
+ var result = new Result(readResut);
+ if (result.IsSucceed)
+ {
+ result.Value = BitConverter.ToUInt16(readResut.Value, 0);
+ if (adds.Length >= 2)
+ {
+ var index = int.Parse(adds[1].Trim());
+ var binaryArray = DataConvert.IntToBinaryArray(result.Value, 16);
+ if (left)
+ {
+ var length = binaryArray.Length - 16;
+ result.Value = ushort.Parse(binaryArray[length + index].ToString());
+ }
+ else
+ result.Value = ushort.Parse(binaryArray[binaryArray.Length - 1 - index].ToString());
+ }
+ }
+ return result.EndTime();
+ }
+
///
/// 读取UInt16类型数据
///
@@ -1053,7 +1122,7 @@ namespace IoTClient.Clients.Modbus
result.IsSucceed = tempResult.IsSucceed;
result.Exception = tempResult.Exception;
result.ErrCode = tempResult.ErrCode;
- result.Err = $"读取 地址:{minAddress} 站号:{stationNumber} 功能码:{functionCode} 失败。{tempResult.Err}";
+ result.Err = tempResult.Err;// $"读取 地址:{minAddress} 站号:{stationNumber} 功能码:{functionCode} 失败。{tempResult.Err}";
result.AddErr2List();
return result.EndTime();
}
@@ -1146,6 +1215,11 @@ namespace IoTClient.Clients.Modbus
result.Err = "响应结果校验失败";
socket?.SafeClose();
}
+ else if (ModbusHelper.VerifyFunctionCode(functionCode, dataPackage[7]))
+ {
+ result.IsSucceed = false;
+ result.Err = ModbusHelper.ErrMsg(dataPackage[8]);
+ }
}
catch (SocketException ex)
{
@@ -1203,6 +1277,11 @@ namespace IoTClient.Clients.Modbus
result.Err = "响应结果校验失败";
socket?.SafeClose();
}
+ else if (ModbusHelper.VerifyFunctionCode(functionCode, dataPackage[7]))
+ {
+ result.IsSucceed = false;
+ result.Err = ModbusHelper.ErrMsg(dataPackage[8]);
+ }
}
catch (SocketException ex)
{
diff --git a/IoTClient/Clients/PLC/OmronFinsClient.cs b/IoTClient/Clients/PLC/OmronFinsClient.cs
index 2c61d3c..b31a0fc 100644
--- a/IoTClient/Clients/PLC/OmronFinsClient.cs
+++ b/IoTClient/Clients/PLC/OmronFinsClient.cs
@@ -221,7 +221,7 @@ namespace IoTClient.Clients.PLC
Array.Copy(dataPackage, dataPackage.Length - length, responseData, 0, length);
result.Response = string.Join(" ", dataPackage.Select(t => t.ToString("X2")));
if (setEndian)
- result.Value = responseData.ToArray().ByteFormatting(endianFormat, false);
+ result.Value = responseData.ToArray().ByteFormatting2(endianFormat, false);
else
result.Value = responseData.ToArray();
}
@@ -388,7 +388,7 @@ namespace IoTClient.Clients.PLC
{
var interval = (addressInt - startAddressInt) / 2;
var offset = (addressInt - startAddressInt) % 2 * 2;//取余 乘以2(每个地址16位,占两个字节)
- var byteArry = values.Skip(interval * 2 * 2 + offset).Take(2 * 2).ToArray().ByteFormatting(endianFormat, false);
+ var byteArry = values.Skip(interval * 2 * 2 + offset).Take(2 * 2).ToArray().ByteFormatting2(endianFormat, false);
return new Result
{
Value = BitConverter.ToInt32(byteArry, 0)
@@ -424,7 +424,7 @@ namespace IoTClient.Clients.PLC
{
var interval = (addressInt - startAddressInt) / 2;
var offset = (addressInt - startAddressInt) % 2 * 2;//取余 乘以2(每个地址16位,占两个字节)
- var byteArry = values.Skip(interval * 2 * 2 + offset).Take(2 * 2).ToArray().ByteFormatting(endianFormat, false);
+ var byteArry = values.Skip(interval * 2 * 2 + offset).Take(2 * 2).ToArray().ByteFormatting2(endianFormat, false);
return new Result
{
Value = BitConverter.ToUInt32(byteArry, 0)
@@ -460,7 +460,7 @@ namespace IoTClient.Clients.PLC
{
var interval = (addressInt - startAddressInt) / 4;
var offset = (addressInt - startAddressInt) % 4 * 2;
- var byteArry = values.Skip(interval * 2 * 4 + offset).Take(2 * 4).ToArray().ByteFormatting(endianFormat, false);
+ var byteArry = values.Skip(interval * 2 * 4 + offset).Take(2 * 4).ToArray().ByteFormatting2(endianFormat, false);
return new Result
{
Value = BitConverter.ToInt64(byteArry, 0)
@@ -496,7 +496,7 @@ namespace IoTClient.Clients.PLC
{
var interval = (addressInt - startAddressInt) / 4;
var offset = (addressInt - startAddressInt) % 4 * 2;
- var byteArry = values.Skip(interval * 2 * 4 + offset).Take(2 * 4).ToArray().ByteFormatting(endianFormat, false);
+ var byteArry = values.Skip(interval * 2 * 4 + offset).Take(2 * 4).ToArray().ByteFormatting2(endianFormat, false);
return new Result
{
Value = BitConverter.ToUInt64(byteArry, 0)
@@ -532,7 +532,7 @@ namespace IoTClient.Clients.PLC
{
var interval = (addressInt - beginAddressInt) / 2;
var offset = (addressInt - beginAddressInt) % 2 * 2;//取余 乘以2(每个地址16位,占两个字节)
- var byteArry = values.Skip(interval * 2 * 2 + offset).Take(2 * 2).ToArray().ByteFormatting(endianFormat, false);
+ var byteArry = values.Skip(interval * 2 * 2 + offset).Take(2 * 2).ToArray().ByteFormatting2(endianFormat, false);
return new Result
{
Value = BitConverter.ToSingle(byteArry, 0)
@@ -568,7 +568,7 @@ namespace IoTClient.Clients.PLC
{
var interval = (addressInt - beginAddressInt) / 4;
var offset = (addressInt - beginAddressInt) % 4 * 2;
- var byteArry = values.Skip(interval * 2 * 4 + offset).Take(2 * 4).ToArray().ByteFormatting(endianFormat, false);
+ var byteArry = values.Skip(interval * 2 * 4 + offset).Take(2 * 4).ToArray().ByteFormatting2(endianFormat, false);
return new Result
{
Value = BitConverter.ToDouble(byteArry, 0)
@@ -607,7 +607,7 @@ namespace IoTClient.Clients.PLC
Result result = new Result();
try
{
- data = data.Reverse().ToArray().ByteFormatting(endianFormat);
+ data = data.Reverse().ToArray().ByteFormatting2(endianFormat);
//发送写入信息
var arg = ConvertArg(address, isBit: isBit);
byte[] command = GetWriteCommand(arg, data);
@@ -842,7 +842,7 @@ namespace IoTClient.Clients.PLC
addressInfo.BitCode = 0x02;
addressInfo.WordCode = 0x82;
addressInfo.TypeChar = address.Substring(0, 1);
- addressInfo.BeginAddress = Convert.ToInt32(address.Substring(1));
+ addressInfo.BeginAddress = Convert.ToInt32(address.Substring(1).Split('.')[0]);
break;
}
case 'C'://CIO区
@@ -850,7 +850,7 @@ namespace IoTClient.Clients.PLC
addressInfo.BitCode = 0x30;
addressInfo.WordCode = 0xB0;
addressInfo.TypeChar = address.Substring(0, 1);
- addressInfo.BeginAddress = Convert.ToInt32(address.Substring(1));
+ addressInfo.BeginAddress = Convert.ToInt32(address.Substring(1).Split('.')[0]);
break;
}
case 'W'://WR区
@@ -858,7 +858,7 @@ namespace IoTClient.Clients.PLC
addressInfo.BitCode = 0x31;
addressInfo.WordCode = 0xB1;
addressInfo.TypeChar = address.Substring(0, 1);
- addressInfo.BeginAddress = Convert.ToInt32(address.Substring(1));
+ addressInfo.BeginAddress = Convert.ToInt32(address.Substring(1).Split('.')[0]);
break;
}
case 'H'://HR区
@@ -866,7 +866,7 @@ namespace IoTClient.Clients.PLC
addressInfo.BitCode = 0x32;
addressInfo.WordCode = 0xB2;
addressInfo.TypeChar = address.Substring(0, 1);
- addressInfo.BeginAddress = Convert.ToInt32(address.Substring(1));
+ addressInfo.BeginAddress = Convert.ToInt32(address.Substring(1).Split('.')[0]);
break;
}
case 'A'://AR区
@@ -874,7 +874,7 @@ namespace IoTClient.Clients.PLC
addressInfo.BitCode = 0x33;
addressInfo.WordCode = 0xB3;
addressInfo.TypeChar = address.Substring(0, 1);
- addressInfo.BeginAddress = Convert.ToInt32(address.Substring(1));
+ addressInfo.BeginAddress = Convert.ToInt32(address.Substring(1).Split('.')[0]);
break;
}
case 'E':
@@ -1070,9 +1070,11 @@ namespace IoTClient.Clients.PLC
switch (tempMax.DataTypeEnum)
{
case DataTypeEnum.Bool:
+ throw new Exception("暂时不支持Bool类型批量读取");
case DataTypeEnum.Byte:
- readLength = tempMax.BeginAddress + 1 - minAddress;
- break;
+ throw new Exception("暂时不支持Byte类型批量读取");
+ //readLength = tempMax.BeginAddress + 1 - minAddress;
+ //break;
case DataTypeEnum.Int16:
case DataTypeEnum.UInt16:
readLength = tempMax.BeginAddress * 2 + 2 - minAddress * 2;
diff --git a/IoTClient/Common/Helpers/DataConvert.cs b/IoTClient/Common/Helpers/DataConvert.cs
index efae6f2..39798aa 100644
--- a/IoTClient/Common/Helpers/DataConvert.cs
+++ b/IoTClient/Common/Helpers/DataConvert.cs
@@ -115,11 +115,12 @@ namespace IoTClient.Common.Helpers
/// Int转二进制
///
///
+ /// 补0长度
///
- public static string IntToBinaryArray(this int value)
+ public static string IntToBinaryArray(this int value, int minLength = 0)
{
//Convert.ToString(12,2); // 将12转为2进制字符串,结果 “1100”
- return Convert.ToString(value, 2);
+ return Convert.ToString(value, 2).PadLeft(minLength, '0');
}
///
diff --git a/IoTClient/Common/Helpers/EndianConversion.cs b/IoTClient/Common/Helpers/EndianConversion.cs
index 5e63584..bfcb2f3 100644
--- a/IoTClient/Common/Helpers/EndianConversion.cs
+++ b/IoTClient/Common/Helpers/EndianConversion.cs
@@ -116,5 +116,53 @@ namespace IoTClient.Common.Helpers
}
return buffer;
}
+
+ ///
+ /// 字节格式转换
+ ///
+ ///
+ ///
+ /// 是否经过了反转
+ ///
+ public static byte[] ByteFormatting2(this byte[] value, EndianFormat format = EndianFormat.ABCD, bool reverse = true)
+ {
+ if (!reverse)
+ {
+ switch (format)
+ {
+ case EndianFormat.ABCD:
+ format = EndianFormat.DCBA;
+ break;
+ case EndianFormat.BADC:
+ format = EndianFormat.CDAB;
+ break;
+ case EndianFormat.CDAB:
+ format = EndianFormat.BADC;
+ break;
+ case EndianFormat.DCBA:
+ format = EndianFormat.ABCD;
+ break;
+ }
+ }
+
+ byte[] buffer;
+ if (value.Length == 2)
+ {
+ buffer = new byte[2];
+ switch (format)
+ {
+ case EndianFormat.BADC:
+ buffer[0] = value[1];
+ buffer[1] = value[0];
+ break;
+ default:
+ buffer = value;
+ break;
+ }
+ }
+ else
+ return ByteFormatting(value, format, true);
+ return buffer;
+ }
}
}
diff --git a/IoTClient/Common/Helpers/ModbusHelper.cs b/IoTClient/Common/Helpers/ModbusHelper.cs
new file mode 100644
index 0000000..cd3f438
--- /dev/null
+++ b/IoTClient/Common/Helpers/ModbusHelper.cs
@@ -0,0 +1,62 @@
+using System;
+
+namespace IoTClient.Common.Helpers
+{
+ ///
+ /// 帮助类
+ ///
+ public class ModbusHelper
+ {
+ ///
+ /// 是否为异常功能码
+ ///
+ ///
+ ///
+ ///
+ public static bool VerifyFunctionCode(byte resultCode, byte responseCode)
+ {
+ return responseCode - resultCode == 128;
+ }
+
+ ///
+ /// 异常码描述
+ /// https://www.likecs.com/show-204655077.html?sc=5546
+ ///
+ ///
+ public static string ErrMsg(byte errCode)
+ {
+ var err = "未知异常";
+ switch (errCode)
+ {
+ case 0x01:
+ err = $"异常码{errCode}:⾮法功能";
+ break;
+ case 0x02:
+ err = $"异常码{errCode}:⾮法数据地址";
+ break;
+ case 0x03:
+ err = $"异常码{errCode}:⾮法数据值";
+ break;
+ case 0x04:
+ err = $"异常码{errCode}:从站设备故障";
+ break;
+ case 0x05:
+ err = $"异常码{errCode}:确认";
+ break;
+ case 0x06:
+ err = $"异常码{errCode}:从属设备忙";
+ break;
+ case 0x08:
+ err = $"异常码{errCode}:存储奇偶性差错";
+ break;
+ case 0x0A:
+ err = $"异常码{errCode}:不可⽤⽹关路径";
+ break;
+ case 0x0B:
+ err = $"异常码{errCode}:⽹关⽬标设备响应失败";
+ break;
+ }
+ return err;
+ }
+ }
+}
diff --git a/IoTClient/IoTClient.csproj b/IoTClient/IoTClient.csproj
index 9e91b80..8e719ea 100644
--- a/IoTClient/IoTClient.csproj
+++ b/IoTClient/IoTClient.csproj
@@ -12,7 +12,7 @@
Copyright (c) 2022 农码一生. All rights reserved.
git
https://github.com/zhaopeiym/IoTClient
- IoT,物联网,PLC,Modbus,Bacnet
+ Modbus,Bacnet,PLC,S7,ModbusTcp,三菱,西门子,欧姆龙,IoT,物联网,边缘计算
https://user-images.githubusercontent.com/5820324/66972725-12bccf80-f0c8-11e9-9468-3cfc57915dc9.png
diff --git a/IoTClient/IoTClient/IoTClient.xml b/IoTClient/IoTClient/IoTClient.xml
index a5d87c7..8c9ec10 100644
--- a/IoTClient/IoTClient/IoTClient.xml
+++ b/IoTClient/IoTClient/IoTClient.xml
@@ -53,6 +53,16 @@
功能码
+
+
+ 按位的方式读取
+
+ 寄存器地址:如1.00 ... 1.14、1.15
+ 站号
+ 功能码
+ 按位取值从左边开始取
+
+
读取UInt16
@@ -62,6 +72,16 @@
功能码
+
+
+ 按位的方式读取
+
+ 寄存器地址:如1.00 ... 1.14、1.15
+ 站号
+ 功能码
+ 按位取值从左边开始取
+
+
读取Int32
@@ -415,6 +435,16 @@
功能码
+
+
+ 按位的方式读取
+
+ 寄存器地址:如1.00 ... 1.14、1.15
+ 站号
+ 功能码
+ 按位取值从左边开始取
+
+
从批量读取的数据字节提取对应的地址数据
@@ -442,6 +472,16 @@
+
+
+ 按位的方式读取
+
+ 寄存器地址:如1.00 ... 1.14、1.15
+ 站号
+ 功能码
+ 按位取值从左边开始取
+
+
读取Int32
@@ -836,6 +876,16 @@
功能码
+
+
+ 按位的方式读取
+
+ 寄存器地址:如1.00 ... 1.14、1.15
+ 站号
+ 功能码
+ 按位取值从左边开始取
+
+
读取UInt16
@@ -845,6 +895,16 @@
功能码
+
+
+ 按位的方式读取
+
+ 寄存器地址:如1.00 ... 1.14、1.15
+ 站号
+ 功能码
+ 按位取值从左边开始取
+
+
读取Int32
@@ -1206,6 +1266,16 @@
功能码
+
+
+ 按位的方式读取
+
+ 寄存器地址:如1.00 ... 1.14、1.15
+ 站号
+ 功能码
+ 按位取值从左边开始取
+
+
@@ -1216,6 +1286,16 @@
功能码
+
+
+ 按位的方式读取
+
+ 寄存器地址:如1.00 ... 1.14、1.15
+ 站号
+ 功能码
+ 按位取值从左边开始取
+
+
读取UInt16类型数据
@@ -3286,11 +3366,12 @@
-
+
Int转二进制
+ 补0长度
@@ -3314,6 +3395,15 @@
是否经过了反转
+
+
+ 字节格式转换
+
+
+
+ 是否经过了反转
+
+
@@ -3348,6 +3438,26 @@
+
+
+ 帮助类
+
+
+
+
+ 是否为异常功能码
+
+
+
+
+
+
+
+ 异常码描述
+ https://www.likecs.com/show-204655077.html?sc=5546
+
+
+