From f8909c0d4b2496d7d4f370c41123d5d17119573d Mon Sep 17 00:00:00 2001 From: parallelbgls Date: Fri, 28 Apr 2017 17:17:59 +0800 Subject: [PATCH] 2017-04-28 update 1 Add combiner max limit. --- Modbus.Net/Modbus.Net.Modbus/ModbusMachine.cs | 8 +- .../Modbus.Net.Siemens/SiemensMachine.cs | 8 +- Modbus.Net/src/Base.Common/AddressCombiner.cs | 74 ++++++++++++++---- Tests/Modbus.Net.Tests/BaseTest.cs | 78 ++++++++++++++++++- 4 files changed, 143 insertions(+), 25 deletions(-) diff --git a/Modbus.Net/Modbus.Net.Modbus/ModbusMachine.cs b/Modbus.Net/Modbus.Net.Modbus/ModbusMachine.cs index 07ed8b9..450a12d 100644 --- a/Modbus.Net/Modbus.Net.Modbus/ModbusMachine.cs +++ b/Modbus.Net/Modbus.Net.Modbus/ModbusMachine.cs @@ -16,8 +16,8 @@ namespace Modbus.Net.Modbus { BaseUtility = new ModbusUtility(connectionType, connectionString, slaveAddress, masterAddress, endian); AddressFormater = new AddressFormaterModbus(); - AddressCombiner = new AddressCombinerContinus(AddressTranslator); - AddressCombinerSet = new AddressCombinerContinus(AddressTranslator); + AddressCombiner = new AddressCombinerContinus(AddressTranslator, 100); + AddressCombinerSet = new AddressCombinerContinus(AddressTranslator, 100); } public ModbusMachine(ModbusType connectionType, string connectionString, @@ -40,8 +40,8 @@ namespace Modbus.Net.Modbus { BaseUtility = new ModbusUtility(connectionType, connectionString, slaveAddress, masterAddress, endian); AddressFormater = new AddressFormaterModbus(); - AddressCombiner = new AddressCombinerContinus(AddressTranslator); - AddressCombinerSet = new AddressCombinerContinus(AddressTranslator); + AddressCombiner = new AddressCombinerContinus(AddressTranslator, 100); + AddressCombinerSet = new AddressCombinerContinus(AddressTranslator, 100); } public ModbusMachine(ModbusType connectionType, string connectionString, diff --git a/Modbus.Net/Modbus.Net.Siemens/SiemensMachine.cs b/Modbus.Net/Modbus.Net.Siemens/SiemensMachine.cs index 5c0e607..f91495c 100644 --- a/Modbus.Net/Modbus.Net.Siemens/SiemensMachine.cs +++ b/Modbus.Net/Modbus.Net.Siemens/SiemensMachine.cs @@ -15,8 +15,8 @@ namespace Modbus.Net.Siemens { BaseUtility = new SiemensUtility(connectionType, connectionString, model, slaveAddress, masterAddress); AddressFormater = new AddressFormaterSiemens(); - AddressCombiner = new AddressCombinerContinus(AddressTranslator); - AddressCombinerSet = new AddressCombinerContinus(AddressTranslator); + AddressCombiner = new AddressCombinerContinus(AddressTranslator, 100); + AddressCombinerSet = new AddressCombinerContinus(AddressTranslator, 100); } public SiemensMachine(SiemensType connectionType, string connectionString, SiemensMachineModel model, @@ -37,8 +37,8 @@ namespace Modbus.Net.Siemens { BaseUtility = new SiemensUtility(connectionType, connectionString, model, slaveAddress, masterAddress); AddressFormater = new AddressFormaterSiemens(); - AddressCombiner = new AddressCombinerContinus(AddressTranslator); - AddressCombinerSet = new AddressCombinerContinus(AddressTranslator); + AddressCombiner = new AddressCombinerContinus(AddressTranslator, 100); + AddressCombinerSet = new AddressCombinerContinus(AddressTranslator, 100); } public SiemensMachine(SiemensType connectionType, string connectionString, SiemensMachineModel model, diff --git a/Modbus.Net/src/Base.Common/AddressCombiner.cs b/Modbus.Net/src/Base.Common/AddressCombiner.cs index 3c7ef51..f60226a 100644 --- a/Modbus.Net/src/Base.Common/AddressCombiner.cs +++ b/Modbus.Net/src/Base.Common/AddressCombiner.cs @@ -29,7 +29,7 @@ namespace Modbus.Net /// public class AddressCombinerContinus : AddressCombinerContinus { - public AddressCombinerContinus(AddressTranslator addressTranslator) : base(addressTranslator) + public AddressCombinerContinus(AddressTranslator addressTranslator, int maxLength) : base(addressTranslator, maxLength) { } } @@ -39,9 +39,12 @@ namespace Modbus.Net /// public class AddressCombinerContinus : AddressCombiner where TKey : IEquatable { - public AddressCombinerContinus(AddressTranslator addressTranslator) + protected int MaxLength { get; set; } + + public AddressCombinerContinus(AddressTranslator addressTranslator, int maxLength) { AddressTranslator = addressTranslator; + MaxLength = maxLength; } protected AddressTranslator AddressTranslator { get; set; } @@ -158,7 +161,48 @@ namespace Modbus.Net OriginalAddresses = originalAddresses.ToList() }); } - return ans; + List> newAns = new List>(); + foreach (var communicationUnit in ans) + { + double oldByteCount = communicationUnit.GetCount * BigEndianValueHelper.Instance.ByteLength[communicationUnit.DataType.FullName]; + while (oldByteCount * BigEndianValueHelper.Instance.ByteLength[communicationUnit.DataType.FullName] > + MaxLength) + { + var newOriginalAddresses = new List>(); + var oldOriginalAddresses = communicationUnit.OriginalAddresses.ToList(); + var newByteCount = 0.0; + do + { + var currentAddressUnit = oldOriginalAddresses.First(); + newByteCount += BigEndianValueHelper.Instance.ByteLength[currentAddressUnit.DataType.FullName]; + if (newByteCount > MaxLength) break; + oldByteCount -= BigEndianValueHelper.Instance.ByteLength[currentAddressUnit.DataType.FullName]; + newOriginalAddresses.Add(currentAddressUnit); + oldOriginalAddresses.RemoveAt(0); + + } while (newByteCount < MaxLength); + var newCommunicationUnit = new CommunicationUnit + { + Area = communicationUnit.Area, + Address = communicationUnit.Address, + SubAddress = communicationUnit.SubAddress, + DataType = communicationUnit.DataType, + GetCount = + (int) + Math.Ceiling(newByteCount / + BigEndianValueHelper.Instance.ByteLength[communicationUnit.DataType.FullName]), + OriginalAddresses = newOriginalAddresses, + }; + + newAns.Add(newCommunicationUnit); + } + communicationUnit.GetCount = + (int) + Math.Ceiling(oldByteCount / + BigEndianValueHelper.Instance.ByteLength[communicationUnit.DataType.FullName]); + newAns.Add(communicationUnit); + } + return newAns; } } @@ -205,8 +249,8 @@ namespace Modbus.Net /// public class AddressCombinerNumericJump : AddressCombinerNumericJump { - public AddressCombinerNumericJump(int jumpByteCount, AddressTranslator addressTranslator) - : base(jumpByteCount, addressTranslator) + public AddressCombinerNumericJump(int jumpByteCount, int maxLength, AddressTranslator addressTranslator) + : base(jumpByteCount, maxLength, addressTranslator) { } } @@ -216,8 +260,8 @@ namespace Modbus.Net /// public class AddressCombinerNumericJump : AddressCombinerContinus where TKey : IEquatable { - public AddressCombinerNumericJump(int jumpByteCount, AddressTranslator addressTranslator) - : base(addressTranslator) + public AddressCombinerNumericJump(int jumpByteCount, int maxLength, AddressTranslator addressTranslator) + : base(addressTranslator, maxLength) { JumpNumber = jumpByteCount; } @@ -260,12 +304,14 @@ namespace Modbus.Net var jumpNumberInner = JumpNumber; foreach (var orderedGap in orderedGaps) { - jumpNumberInner -= orderedGap.GapNumber; - if (jumpNumberInner < 0) break; + if (orderedGap.GapNumber <= 0) continue; var nowAddress = orderedGap.EndUnit; var index = continusAddresses.IndexOf(nowAddress); index--; var preAddress = continusAddresses[index]; + if (nowAddress.GetCount*BigEndianValueHelper.Instance.ByteLength[nowAddress.DataType.FullName] + preAddress.GetCount*BigEndianValueHelper.Instance.ByteLength[preAddress.DataType.FullName] + orderedGap.GapNumber > MaxLength) continue; + jumpNumberInner -= orderedGap.GapNumber; + if (jumpNumberInner < 0) break; continusAddresses.RemoveAt(index); continusAddresses.RemoveAt(index); //合并两个已有的地址段,变为一个新的地址段 @@ -293,8 +339,8 @@ namespace Modbus.Net /// public class AddressCombinerPercentageJump : AddressCombinerPercentageJump { - public AddressCombinerPercentageJump(double percentage, AddressTranslator addressTranslator) - : base(percentage, addressTranslator) + public AddressCombinerPercentageJump(double percentage, int maxLength, AddressTranslator addressTranslator) + : base(percentage, maxLength, addressTranslator) { } } @@ -304,8 +350,8 @@ namespace Modbus.Net /// public class AddressCombinerPercentageJump : AddressCombinerContinus where TKey : IEquatable { - public AddressCombinerPercentageJump(double percentage, AddressTranslator addressTranslator) - : base(addressTranslator) + public AddressCombinerPercentageJump(double percentage, int maxLength, AddressTranslator addressTranslator) + : base(addressTranslator, maxLength) { if (percentage < 0) percentage = 0; Percentage = percentage; @@ -318,7 +364,7 @@ namespace Modbus.Net var addressUnits = addresses as IList> ?? addresses.ToList(); var count = addressUnits.Sum(address => BigEndianValueHelper.Instance.ByteLength[address.DataType.FullName]); return - new AddressCombinerNumericJump((int) (count*Percentage/100.0), AddressTranslator).Combine( + new AddressCombinerNumericJump((int) (count*Percentage/100.0), MaxLength, AddressTranslator).Combine( addressUnits); } } diff --git a/Tests/Modbus.Net.Tests/BaseTest.cs b/Tests/Modbus.Net.Tests/BaseTest.cs index 45f9b1a..c6b1249 100644 --- a/Tests/Modbus.Net.Tests/BaseTest.cs +++ b/Tests/Modbus.Net.Tests/BaseTest.cs @@ -151,7 +151,7 @@ namespace Modbus.Net.Tests [TestMethod] public void AddressCombinerContinusTest() { - var addressCombiner = new AddressCombinerContinus(new AddressTranslatorModbus()); + var addressCombiner = new AddressCombinerContinus(new AddressTranslatorModbus(), 100000); var combinedAddresses = addressCombiner.Combine(_addressUnits).ToArray(); Assert.AreEqual(combinedAddresses[0].Area, "3X"); Assert.AreEqual(combinedAddresses[0].Address, 1); @@ -176,6 +176,37 @@ namespace Modbus.Net.Tests Assert.AreEqual(combinedAddresses[6].GetCount, 2); } + [TestMethod] + public void AddressCombinerContinusLimitTest() + { + var addressCombiner = new AddressCombinerContinus(new AddressTranslatorModbus(), 4); + var combinedAddresses = addressCombiner.Combine(_addressUnits).ToArray(); + Assert.AreEqual(combinedAddresses[0].Area, "3X"); + Assert.AreEqual(combinedAddresses[0].Address, 1); + Assert.AreEqual(combinedAddresses[0].GetCount, 1); + Assert.AreEqual(combinedAddresses[1].Area, "3X"); + Assert.AreEqual(combinedAddresses[1].Address, 2); + Assert.AreEqual(combinedAddresses[1].GetCount, 4); + Assert.AreEqual(combinedAddresses[2].Area, "3X"); + Assert.AreEqual(combinedAddresses[2].Address, 2); + Assert.AreEqual(combinedAddresses[2].GetCount, 2); + Assert.AreEqual(combinedAddresses[3].Area, "3X"); + Assert.AreEqual(combinedAddresses[3].Address, 6); + Assert.AreEqual(combinedAddresses[3].GetCount, 2); + Assert.AreEqual(combinedAddresses[4].Area, "3X"); + Assert.AreEqual(combinedAddresses[4].Address, 9); + Assert.AreEqual(combinedAddresses[4].GetCount, 4); + Assert.AreEqual(combinedAddresses[5].Area, "3X"); + Assert.AreEqual(combinedAddresses[5].Address, 100); + Assert.AreEqual(combinedAddresses[5].GetCount, 2); + Assert.AreEqual(combinedAddresses[6].Area, "4X"); + Assert.AreEqual(combinedAddresses[6].Address, 1); + Assert.AreEqual(combinedAddresses[6].GetCount, 4); + Assert.AreEqual(combinedAddresses[7].Area, "4X"); + Assert.AreEqual(combinedAddresses[7].Address, 4); + Assert.AreEqual(combinedAddresses[7].GetCount, 2); + } + [TestMethod] public void AddressCombinerSingleTest() { @@ -203,7 +234,7 @@ namespace Modbus.Net.Tests [TestMethod] public void AddressCombinerNumericJumpTest() { - var addressCombiner = new AddressCombinerNumericJump(10, new AddressTranslatorModbus()); + var addressCombiner = new AddressCombinerNumericJump(10, 100000, new AddressTranslatorModbus()); var combinedAddresses = addressCombiner.Combine(_addressUnits).ToArray(); Assert.AreEqual(combinedAddresses[0].Area, "3X"); Assert.AreEqual(combinedAddresses[0].Address, 1); @@ -216,10 +247,29 @@ namespace Modbus.Net.Tests Assert.AreEqual(combinedAddresses[2].GetCount, 8); } + [TestMethod] + public void AddressCombinerNumericJumpLimitTest() + { + var addressCombiner = new AddressCombinerNumericJump(10, 10, new AddressTranslatorModbus()); + var combinedAddresses = addressCombiner.Combine(_addressUnits).ToArray(); + Assert.AreEqual(combinedAddresses[0].Area, "3X"); + Assert.AreEqual(combinedAddresses[0].Address, 1); + Assert.AreEqual(combinedAddresses[0].GetCount, 8); + Assert.AreEqual(combinedAddresses[1].Area, "3X"); + Assert.AreEqual(combinedAddresses[1].Address, 6); + Assert.AreEqual(combinedAddresses[1].GetCount, 10); + Assert.AreEqual(combinedAddresses[2].Area, "3X"); + Assert.AreEqual(combinedAddresses[2].Address, 100); + Assert.AreEqual(combinedAddresses[2].GetCount, 2); + Assert.AreEqual(combinedAddresses[3].Area, "4X"); + Assert.AreEqual(combinedAddresses[3].Address, 1); + Assert.AreEqual(combinedAddresses[3].GetCount, 8); + } + [TestMethod] public void AddressCombinerPercentageJumpTest() { - var addressCombiner = new AddressCombinerPercentageJump(30.0, new AddressTranslatorModbus()); + var addressCombiner = new AddressCombinerPercentageJump(30.0, 100000, new AddressTranslatorModbus()); var combinedAddresses = addressCombiner.Combine(_addressUnits).ToArray(); Assert.AreEqual(combinedAddresses[0].Area, "3X"); Assert.AreEqual(combinedAddresses[0].Address, 1); @@ -235,6 +285,28 @@ namespace Modbus.Net.Tests Assert.AreEqual(combinedAddresses[3].GetCount, 8); } + [TestMethod] + public void AddressCombinerPercentageJumpLimitTest() + { + var addressCombiner = new AddressCombinerPercentageJump(30.0, 10, new AddressTranslatorModbus()); + var combinedAddresses = addressCombiner.Combine(_addressUnits).ToArray(); + Assert.AreEqual(combinedAddresses[0].Area, "3X"); + Assert.AreEqual(combinedAddresses[0].Address, 1); + Assert.AreEqual(combinedAddresses[0].GetCount, 8); + Assert.AreEqual(combinedAddresses[1].Area, "3X"); + Assert.AreEqual(combinedAddresses[1].Address, 6); + Assert.AreEqual(combinedAddresses[1].GetCount, 2); + Assert.AreEqual(combinedAddresses[2].Area, "3X"); + Assert.AreEqual(combinedAddresses[2].Address, 9); + Assert.AreEqual(combinedAddresses[2].GetCount, 4); + Assert.AreEqual(combinedAddresses[3].Area, "3X"); + Assert.AreEqual(combinedAddresses[3].Address, 100); + Assert.AreEqual(combinedAddresses[3].GetCount, 2); + Assert.AreEqual(combinedAddresses[4].Area, "4X"); + Assert.AreEqual(combinedAddresses[4].Address, 1); + Assert.AreEqual(combinedAddresses[4].GetCount, 8); + } + [TestMethod] public void TaskManagerGetMachineTest() {