From c5e7f36e59a11c3c2b3f193a61f94b27d0bd62b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=BD=97=E5=9C=A3?= Date: Fri, 26 Aug 2016 16:02:06 +0800 Subject: [PATCH] Area Width Support (not complete) --- .../AddressTranslatorModbus.cs | 78 ++++++----- Modbus.Net/Modbus.Net.Modbus/ModbusMachine.cs | 4 +- .../AddressTranslatorSiemens.cs | 5 + .../Modbus.Net.Siemens/SiemensMachine.cs | 4 +- .../Modbus.Net.Siemens/SiemensProtocal.cs | 2 + .../SiemensStructDefinition.cs | 3 +- Modbus.Net/Modbus.Net/AddressCombiner.cs | 70 ++++++---- Modbus.Net/Modbus.Net/AddressTranslator.cs | 13 ++ Modbus.Net/Modbus.Net/BaseMachine.cs | 130 +++++++++--------- Modbus.Net/Modbus.Net/ValueHelper.cs | 101 ++++++++------ Modbus.Net/NA200H.UI.WPF/MainWindow.xaml.cs | 49 +++---- 11 files changed, 266 insertions(+), 193 deletions(-) diff --git a/Modbus.Net/Modbus.Net.Modbus/AddressTranslatorModbus.cs b/Modbus.Net/Modbus.Net.Modbus/AddressTranslatorModbus.cs index a4b5923..bb156bc 100644 --- a/Modbus.Net/Modbus.Net.Modbus/AddressTranslatorModbus.cs +++ b/Modbus.Net/Modbus.Net.Modbus/AddressTranslatorModbus.cs @@ -12,8 +12,8 @@ namespace Modbus.Net.Modbus public class AddressTranslatorNA200H : AddressTranslator { protected Dictionary TransDictionary; - protected Dictionary ReadFunctionCodeDictionary; - protected Dictionary WriteFunctionCodeDictionary; + protected Dictionary ReadFunctionCodeDictionary; + protected Dictionary WriteFunctionCodeDictionary; public AddressTranslatorNA200H() { @@ -30,27 +30,27 @@ namespace Modbus.Net.Modbus {"QW", 20000}, {"NW", 21000}, }; - ReadFunctionCodeDictionary = new Dictionary + ReadFunctionCodeDictionary = new Dictionary { - {"Q", (int)ModbusProtocalReadDataFunctionCode.ReadCoilStatus}, - {"M", (int)ModbusProtocalReadDataFunctionCode.ReadCoilStatus}, - {"N", (int)ModbusProtocalReadDataFunctionCode.ReadCoilStatus}, - {"I", (int)ModbusProtocalReadDataFunctionCode.ReadInputStatus}, - {"S", (int)ModbusProtocalReadDataFunctionCode.ReadInputStatus}, - {"IW", (int)ModbusProtocalReadDataFunctionCode.ReadInputRegister}, - {"SW", (int)ModbusProtocalReadDataFunctionCode.ReadInputRegister}, - {"MW", (int)ModbusProtocalReadDataFunctionCode.ReadHoldRegister}, - {"NW", (int)ModbusProtocalReadDataFunctionCode.ReadHoldRegister}, - {"QW", (int)ModbusProtocalReadDataFunctionCode.ReadHoldRegister}, + {"Q", new AreaOutputDef {Code = (int)ModbusProtocalReadDataFunctionCode.ReadCoilStatus, AreaWidth = 0.125}}, + {"M", new AreaOutputDef {Code = (int)ModbusProtocalReadDataFunctionCode.ReadCoilStatus, AreaWidth = 0.125}}, + {"N", new AreaOutputDef {Code = (int)ModbusProtocalReadDataFunctionCode.ReadCoilStatus, AreaWidth = 0.125}}, + {"I", new AreaOutputDef {Code = (int)ModbusProtocalReadDataFunctionCode.ReadInputStatus, AreaWidth = 0.125}}, + {"S", new AreaOutputDef {Code = (int)ModbusProtocalReadDataFunctionCode.ReadInputStatus, AreaWidth = 0.125}}, + {"IW", new AreaOutputDef {Code = (int)ModbusProtocalReadDataFunctionCode.ReadInputRegister, AreaWidth = 2}}, + {"SW", new AreaOutputDef {Code = (int)ModbusProtocalReadDataFunctionCode.ReadInputRegister, AreaWidth = 2}}, + {"MW", new AreaOutputDef {Code = (int)ModbusProtocalReadDataFunctionCode.ReadHoldRegister, AreaWidth = 2}}, + {"NW", new AreaOutputDef {Code = (int)ModbusProtocalReadDataFunctionCode.ReadHoldRegister, AreaWidth = 2}}, + {"QW", new AreaOutputDef {Code = (int)ModbusProtocalReadDataFunctionCode.ReadHoldRegister, AreaWidth = 2}}, }; - WriteFunctionCodeDictionary = new Dictionary + WriteFunctionCodeDictionary = new Dictionary { - {"Q", (int)ModbusProtocalWriteDataFunctionCode.WriteMultiCoil}, - {"M", (int)ModbusProtocalWriteDataFunctionCode.WriteMultiCoil}, - {"N", (int)ModbusProtocalWriteDataFunctionCode.WriteMultiCoil}, - {"MW", (int)ModbusProtocalWriteDataFunctionCode.WriteMultiRegister}, - {"NW", (int)ModbusProtocalWriteDataFunctionCode.WriteMultiRegister}, - {"QW", (int)ModbusProtocalWriteDataFunctionCode.WriteMultiRegister}, + {"Q", new AreaOutputDef {Code = (int)ModbusProtocalWriteDataFunctionCode.WriteMultiCoil, AreaWidth = 0.125}}, + {"M", new AreaOutputDef {Code = (int)ModbusProtocalWriteDataFunctionCode.WriteMultiCoil, AreaWidth = 0.125}}, + {"N", new AreaOutputDef {Code = (int)ModbusProtocalWriteDataFunctionCode.WriteMultiCoil, AreaWidth = 0.125}}, + {"MW", new AreaOutputDef {Code = (int)ModbusProtocalWriteDataFunctionCode.WriteMultiRegister, AreaWidth = 2}}, + {"NW", new AreaOutputDef {Code = (int)ModbusProtocalWriteDataFunctionCode.WriteMultiRegister, AreaWidth = 2}}, + {"QW", new AreaOutputDef {Code = (int)ModbusProtocalWriteDataFunctionCode.WriteMultiRegister, AreaWidth = 2}}, }; } @@ -63,15 +63,20 @@ namespace Modbus.Net.Modbus return isRead ? new AddressDef() { - Area = ReadFunctionCodeDictionary[head], + Area = ReadFunctionCodeDictionary[head].Code, Address = TransDictionary[head] + int.Parse(tail) - 1, } : new AddressDef() { - Area = WriteFunctionCodeDictionary[head], + Area = WriteFunctionCodeDictionary[head].Code, Address = TransDictionary[head] + int.Parse(tail) - 1, }; } + + public override double GetAreaByteLength(string area) + { + return ReadFunctionCodeDictionary[area].AreaWidth; + } } /// @@ -79,22 +84,22 @@ namespace Modbus.Net.Modbus /// public class AddressTranslatorModbus : AddressTranslator { - protected Dictionary ReadFunctionCodeDictionary; - protected Dictionary WriteFunctionCodeDictionary; + protected Dictionary ReadFunctionCodeDictionary; + protected Dictionary WriteFunctionCodeDictionary; public AddressTranslatorModbus() { - ReadFunctionCodeDictionary = new Dictionary + ReadFunctionCodeDictionary = new Dictionary { - {"0X", (int)ModbusProtocalReadDataFunctionCode.ReadCoilStatus}, - {"1X", (int)ModbusProtocalReadDataFunctionCode.ReadInputStatus}, - {"3X", (int)ModbusProtocalReadDataFunctionCode.ReadInputRegister}, - {"4X", (int)ModbusProtocalReadDataFunctionCode.ReadHoldRegister}, + {"0X", new AreaOutputDef {Code = (int)ModbusProtocalReadDataFunctionCode.ReadCoilStatus, AreaWidth = 0.125}}, + {"1X", new AreaOutputDef {Code = (int)ModbusProtocalReadDataFunctionCode.ReadInputStatus, AreaWidth = 0.125}}, + {"3X", new AreaOutputDef {Code = (int)ModbusProtocalReadDataFunctionCode.ReadInputRegister, AreaWidth = 2}}, + {"4X", new AreaOutputDef {Code = (int)ModbusProtocalReadDataFunctionCode.ReadHoldRegister, AreaWidth = 2}}, }; - WriteFunctionCodeDictionary = new Dictionary + WriteFunctionCodeDictionary = new Dictionary { - {"0X", (int)ModbusProtocalWriteDataFunctionCode.WriteMultiCoil}, - {"4X", (int)ModbusProtocalWriteDataFunctionCode.WriteMultiRegister}, + {"0X", new AreaOutputDef {Code = (int)ModbusProtocalWriteDataFunctionCode.WriteMultiCoil, AreaWidth = 0.125}}, + {"4X", new AreaOutputDef {Code = (int)ModbusProtocalWriteDataFunctionCode.WriteMultiRegister, AreaWidth = 2}}, }; } @@ -107,14 +112,19 @@ namespace Modbus.Net.Modbus return isRead ? new AddressDef() { - Area = ReadFunctionCodeDictionary[head], + Area = ReadFunctionCodeDictionary[head].Code, Address = int.Parse(tail) - 1, } : new AddressDef() { - Area = WriteFunctionCodeDictionary[head], + Area = WriteFunctionCodeDictionary[head].Code, Address = int.Parse(tail) - 1, }; } + + public override double GetAreaByteLength(string area) + { + return ReadFunctionCodeDictionary[area].AreaWidth; + } } } diff --git a/Modbus.Net/Modbus.Net.Modbus/ModbusMachine.cs b/Modbus.Net/Modbus.Net.Modbus/ModbusMachine.cs index c2fa8aa..fd68365 100644 --- a/Modbus.Net/Modbus.Net.Modbus/ModbusMachine.cs +++ b/Modbus.Net/Modbus.Net.Modbus/ModbusMachine.cs @@ -9,8 +9,8 @@ namespace Modbus.Net.Modbus { BaseUtility = new ModbusUtility(connectionType, connectionString); AddressFormater = new AddressFormaterModbus(); - AddressCombiner = new AddressCombinerContinus(); - AddressCombinerSet = new AddressCombinerContinus(); + AddressCombiner = new AddressCombinerContinus(AddressTranslator); + AddressCombinerSet = new AddressCombinerContinus(AddressTranslator); } public ModbusMachine(ModbusType connectionType, string connectionString, diff --git a/Modbus.Net/Modbus.Net.Siemens/AddressTranslatorSiemens.cs b/Modbus.Net/Modbus.Net.Siemens/AddressTranslatorSiemens.cs index cae1a48..970a4d0 100644 --- a/Modbus.Net/Modbus.Net.Siemens/AddressTranslatorSiemens.cs +++ b/Modbus.Net/Modbus.Net.Siemens/AddressTranslatorSiemens.cs @@ -78,5 +78,10 @@ namespace Modbus.Net.Siemens Address = int.Parse(tail) }; } + + public override double GetAreaByteLength(string area) + { + return 1; + } } } \ No newline at end of file diff --git a/Modbus.Net/Modbus.Net.Siemens/SiemensMachine.cs b/Modbus.Net/Modbus.Net.Siemens/SiemensMachine.cs index 042cd9a..d574c24 100644 --- a/Modbus.Net/Modbus.Net.Siemens/SiemensMachine.cs +++ b/Modbus.Net/Modbus.Net.Siemens/SiemensMachine.cs @@ -9,8 +9,8 @@ namespace Modbus.Net.Siemens { BaseUtility = new SiemensUtility(connectionType, connectionString, model); AddressFormater = new AddressFormaterSiemens(); - AddressCombiner = new AddressCombinerContinus(); - AddressCombinerSet = new AddressCombinerContinus(); + AddressCombiner = new AddressCombinerContinus(AddressTranslator); + AddressCombinerSet = new AddressCombinerContinus(AddressTranslator); } public SiemensMachine(SiemensType connectionType, string connectionString, SiemensMachineModel model, diff --git a/Modbus.Net/Modbus.Net.Siemens/SiemensProtocal.cs b/Modbus.Net/Modbus.Net.Siemens/SiemensProtocal.cs index 5a62444..da8a4d6 100644 --- a/Modbus.Net/Modbus.Net.Siemens/SiemensProtocal.cs +++ b/Modbus.Net/Modbus.Net.Siemens/SiemensProtocal.cs @@ -340,6 +340,7 @@ namespace Modbus.Net.Siemens } } + /* public class ReadTimeSiemensInputStruct : InputStruct { public ReadTimeSiemensInputStruct(ushort pduRef) @@ -415,6 +416,7 @@ namespace Modbus.Net.Siemens throw new NotImplementedException(); } } + */ public class SiemensProtocalErrorException : ProtocalErrorException { diff --git a/Modbus.Net/Modbus.Net.Siemens/SiemensStructDefinition.cs b/Modbus.Net/Modbus.Net.Siemens/SiemensStructDefinition.cs index 51fdb45..ecb45cb 100644 --- a/Modbus.Net/Modbus.Net.Siemens/SiemensStructDefinition.cs +++ b/Modbus.Net/Modbus.Net.Siemens/SiemensStructDefinition.cs @@ -1,4 +1,4 @@ -namespace Modbus.Net.Siemens +/*namespace Modbus.Net.Siemens { public struct TodClockStatus { @@ -88,3 +88,4 @@ public ushort TodValue { get; set; } } } +*/ \ No newline at end of file diff --git a/Modbus.Net/Modbus.Net/AddressCombiner.cs b/Modbus.Net/Modbus.Net/AddressCombiner.cs index df57a8a..011ed2f 100644 --- a/Modbus.Net/Modbus.Net/AddressCombiner.cs +++ b/Modbus.Net/Modbus.Net/AddressCombiner.cs @@ -22,6 +22,8 @@ namespace Modbus.Net /// public class AddressCombinerContinus : AddressCombiner { + protected AddressTranslator AddressTranslator { get; set; } + public override IEnumerable Combine(IEnumerable addresses) { var groupedAddresses = from address in addresses @@ -33,34 +35,44 @@ namespace Modbus.Net foreach (var groupedAddress in groupedAddresses) { string area = groupedAddress.Key; - int initNum = -1; - int preNum = -1; + double initNum = -1; + double preNum = -1; Type preType = null; - int getCount = 0; + double getCount = 0; + double byteCount = 0; + List originalAddresses = new List(); foreach (var address in groupedAddress.OrderBy(address => address.Address)) { if (initNum < 0) { - initNum = address.Address; - getCount = (int) BigEndianValueHelper.Instance.ByteLength[address.DataType.FullName]; + initNum = address.Address + (address.SubAddress + 1) * 0.125; + getCount = BigEndianValueHelper.Instance.ByteLength[address.DataType.FullName] / AddressTranslator.GetAreaByteLength(address.Area); + byteCount = BigEndianValueHelper.Instance.ByteLength[address.DataType.FullName]; + originalAddresses.Add(address); } else { - if (address.Address > preNum + BigEndianValueHelper.Instance.ByteLength[preType.FullName]) + if (address.Address > preNum + (int) (BigEndianValueHelper.Instance.ByteLength[preType.FullName] / AddressTranslator.GetAreaByteLength(address.Area))) { ans.Add(new CommunicationUnit() { Area = area, - Address = initNum, - GetCount = getCount, - DataType = typeof (byte) + Address = (int)Math.Floor(initNum), + GetCount = (int)Math.Ceiling(byteCount), + DataType = typeof (byte), + OriginalAddresses = originalAddresses.ToList(), }); initNum = address.Address; - getCount = (int) BigEndianValueHelper.Instance.ByteLength[address.DataType.FullName]; + getCount = BigEndianValueHelper.Instance.ByteLength[address.DataType.FullName] / AddressTranslator.GetAreaByteLength(address.Area); + byteCount = BigEndianValueHelper.Instance.ByteLength[address.DataType.FullName]; + originalAddresses.Clear(); + originalAddresses.Add(address); } else { - getCount += (int) BigEndianValueHelper.Instance.ByteLength[address.DataType.FullName]; + getCount += BigEndianValueHelper.Instance.ByteLength[address.DataType.FullName]/ AddressTranslator.GetAreaByteLength(address.Area); + byteCount += BigEndianValueHelper.Instance.ByteLength[address.DataType.FullName]; + originalAddresses.Add(address); } } preNum = address.Address; @@ -69,13 +81,19 @@ namespace Modbus.Net ans.Add(new CommunicationUnit() { Area = area, - Address = initNum, - GetCount = getCount, - DataType = typeof (byte) + Address = (int)Math.Floor(initNum), + GetCount = (int)Math.Ceiling(byteCount), + DataType = typeof (byte), + OriginalAddresses = originalAddresses.ToList() }); } return ans; } + + public AddressCombinerContinus(AddressTranslator addressTranslator) + { + AddressTranslator = addressTranslator; + } } public class AddressCombinerSingle : AddressCombiner @@ -90,7 +108,8 @@ namespace Modbus.Net Area = address.Area, Address = address.Address, DataType = address.DataType, - GetCount = 1 + GetCount = 1, + OriginalAddresses = new List() {address} }).ToList(); } } @@ -101,18 +120,18 @@ namespace Modbus.Net public int GapNumber { get; set; } } - public class AddressCombinerNumericJump : AddressCombiner + public class AddressCombinerNumericJump : AddressCombinerContinus { private int JumpNumber { get; } - public AddressCombinerNumericJump(int jumpNumber) + public AddressCombinerNumericJump(int jumpByteCount, AddressTranslator addressTranslator) : base(addressTranslator) { - JumpNumber = jumpNumber; + JumpNumber = jumpByteCount; } public override IEnumerable Combine(IEnumerable addresses) { - var continusAddresses = new AddressCombinerContinus().Combine(addresses).ToList(); + var continusAddresses = base.Combine(addresses).ToList(); List addressesGaps = new List(); CommunicationUnit preCommunicationUnit = null; foreach (var continusAddress in continusAddresses) @@ -127,7 +146,7 @@ namespace Modbus.Net var gap = new CommunicationUnitGap() { EndUnit = continusAddress, - GapNumber = continusAddress.Address - preCommunicationUnit.Address - (int)(preCommunicationUnit.GetCount * BigEndianValueHelper.Instance.ByteLength[preCommunicationUnit.DataType.FullName]) + GapNumber = (int)Math.Ceiling((continusAddress.Address - preCommunicationUnit.Address) * AddressTranslator.GetAreaByteLength(continusAddress.Area) - preCommunicationUnit.GetCount * BigEndianValueHelper.Instance.ByteLength[preCommunicationUnit.DataType.FullName]) }; addressesGaps.Add(gap); } @@ -155,7 +174,8 @@ namespace Modbus.Net orderedGap.GapNumber + (int) (nowAddress.GetCount*BigEndianValueHelper.Instance.ByteLength[nowAddress.DataType.FullName]), - DataType = typeof (byte) + DataType = typeof (byte), + OriginalAddresses = preAddress.OriginalAddresses.ToList().Union(nowAddress.OriginalAddresses) }; continusAddresses.Insert(index, newAddress); } @@ -163,13 +183,13 @@ namespace Modbus.Net } } - public class AddressCombinerPercentageJump : AddressCombiner + public class AddressCombinerPercentageJump : AddressCombinerContinus { private double Percentage { get; } - public AddressCombinerPercentageJump(double percentage) + public AddressCombinerPercentageJump(double percentage, AddressTranslator addressTranslator) :base (addressTranslator) { - if (percentage < 0 || percentage > 100) throw new ArgumentException(); + if (percentage < 0) percentage = 0; Percentage = percentage; } @@ -177,7 +197,7 @@ namespace Modbus.Net { var addressUnits = addresses as IList ?? addresses.ToList(); double count = addressUnits.Sum(address => BigEndianValueHelper.Instance.ByteLength[address.DataType.FullName]); - return new AddressCombinerNumericJump((int)(count * Percentage / 100.0)).Combine(addressUnits); + return new AddressCombinerNumericJump((int)(count * Percentage / 100.0), AddressTranslator).Combine(addressUnits); } } } diff --git a/Modbus.Net/Modbus.Net/AddressTranslator.cs b/Modbus.Net/Modbus.Net/AddressTranslator.cs index ce95ffa..a42ec12 100644 --- a/Modbus.Net/Modbus.Net/AddressTranslator.cs +++ b/Modbus.Net/Modbus.Net/AddressTranslator.cs @@ -9,6 +9,12 @@ namespace Modbus.Net public int Address { get; set; } } + public class AreaOutputDef + { + public int Code { get; set; } + public double AreaWidth { get; set; } + } + /// /// 地址翻译器 /// @@ -21,6 +27,8 @@ namespace Modbus.Net /// 是否为读取,是为读取,否为写入 /// Key为转换后的地址,Value为辅助码 public abstract AddressDef AddressTranslate(string address, bool isRead); + + public abstract double GetAreaByteLength(string area); } /// @@ -43,5 +51,10 @@ namespace Modbus.Net } throw new FormatException(); } + + public override double GetAreaByteLength(string area) + { + return 1; + } } } \ No newline at end of file diff --git a/Modbus.Net/Modbus.Net/BaseMachine.cs b/Modbus.Net/Modbus.Net/BaseMachine.cs index cb15a79..98201be 100644 --- a/Modbus.Net/Modbus.Net/BaseMachine.cs +++ b/Modbus.Net/Modbus.Net/BaseMachine.cs @@ -185,69 +185,61 @@ namespace Modbus.Net (int) Math.Ceiling(communicateAddress.GetCount * BigEndianValueHelper.Instance.ByteLength[ - communicateAddress.DataType.FullName])) return null; + communicateAddress.DataType.FullName])) + return null; } - - int pos = 0; - //解码数据 - while (pos < communicateAddress.GetCount) - { - //获取地址 - var address = - GetAddresses.SingleOrDefault( - p => p.Area == communicateAddress.Area && p.Address == pos + communicateAddress.Address); - if (address != null) - { - string key; - switch (getDataType) - { - case MachineGetDataType.CommunicationTag: - { - key = address.CommunicationTag; - break; - } - case MachineGetDataType.Address: - { - key = AddressFormater.FormatAddress(address.Area, address.Address); - break; - } - default: - { - key = address.CommunicationTag; - break; - } - } - if (datas == null) - { - ans.Add(key, new ReturnUnit + foreach (var address in communicateAddress.OriginalAddresses) + { + var localPos = ((address.Address - communicateAddress.Address)*8 + address.SubAddress)* + AddressTranslator.GetAreaByteLength(communicateAddress.Area)/8.0; + var localMainPos = (int) localPos; + var localSubPos = (int) ((localPos - localMainPos)*8); + + string key; + switch (getDataType) + { + case MachineGetDataType.CommunicationTag: { - PlcValue = null, - UnitExtend = address.UnitExtend - }); - pos += (int)ValueHelper.Instance.ByteLength[address.DataType.ToString()]; - } - else + key = address.CommunicationTag; + break; + } + case MachineGetDataType.Address: + { + key = AddressFormater.FormatAddress(address.Area, address.Address); + break; + } + default: + { + key = address.CommunicationTag; + break; + } + } + + if (datas == null) + { + ans.Add(key, new ReturnUnit { - //将获取的数据和对应的通讯标识对应 - ans.Add(key, - new ReturnUnit - { - PlcValue = - Double.Parse( - datasReturn.IsLittleEndian - ? ValueHelper.Instance.GetValue(datas, ref pos, address.DataType) - .ToString() - : BigEndianValueHelper.Instance.GetValue(datas, ref pos, - address.DataType) - .ToString())*address.Zoom, - UnitExtend = address.UnitExtend - }); - } + PlcValue = null, + UnitExtend = address.UnitExtend + }); } else { - pos++; + //将获取的数据和对应的通讯标识对应 + ans.Add(key, + new ReturnUnit + { + PlcValue = + Double.Parse( + datasReturn.IsLittleEndian + ? ValueHelper.Instance.GetValue(datas, ref localMainPos, ref localSubPos, address.DataType) + .ToString() + : BigEndianValueHelper.Instance.GetValue(datas, ref localMainPos, ref localSubPos, + address.DataType) + .ToString()) * address.Zoom, + UnitExtend = address.UnitExtend + }); } } } @@ -340,26 +332,28 @@ namespace Modbus.Net { List datasList = new List(); //需要设置的字节数,计数 - var setCount = (int) - Math.Ceiling(communicateAddress.GetCount* - BigEndianValueHelper.Instance.ByteLength[ - communicateAddress.DataType.FullName]); + var setCount = + communicateAddress.GetCount* + BigEndianValueHelper.Instance.ByteLength[communicateAddress.DataType.FullName]; //总数 var allBytes = setCount; //编码开始地址 var addressStart = AddressFormater.FormatAddress(communicateAddress.Area, communicateAddress.Address); - while (setCount > 0) + + while (setCount > 0.001) { + var localPos = (allBytes - setCount) / AddressTranslator.GetAreaByteLength(communicateAddress.Area); //编码当前地址 var address = AddressFormater.FormatAddress(communicateAddress.Area, - communicateAddress.Address + allBytes - setCount); + communicateAddress.Address + (int) localPos); //找到对应的描述地址 var addressUnit = GetAddresses.SingleOrDefault( p => p.Area == communicateAddress.Area && - p.Address == communicateAddress.Address + allBytes - setCount); + p.Address == communicateAddress.Address + (int) localPos && + p.SubAddress == (int) ((localPos - (int) localPos)/0.125)); //如果没有相应地址,跳过 if (addressUnit == null) continue; //获取写入类型 @@ -381,7 +375,7 @@ namespace Modbus.Net break; } } - setCount -= (int) BigEndianValueHelper.Instance.ByteLength[dataType.FullName]; + setCount -= BigEndianValueHelper.Instance.ByteLength[dataType.FullName]; } //写入数据 await BaseUtility.SetDatasAsync(2, 0, addressStart, datasList.ToArray()); @@ -469,6 +463,10 @@ namespace Modbus.Net /// 数据类型 /// public Type DataType { get; set; } + /// + /// 原始的地址 + /// + public IEnumerable OriginalAddresses { get; set; } } /// @@ -509,6 +507,10 @@ namespace Modbus.Net /// public int Address { get; set; } /// + /// bit位地址 + /// + public int SubAddress { get; set; } = 0; + /// /// 数据类型 /// public Type DataType { get; set; } diff --git a/Modbus.Net/Modbus.Net/ValueHelper.cs b/Modbus.Net/Modbus.Net/ValueHelper.cs index a59a4cc..88b5316 100644 --- a/Modbus.Net/Modbus.Net/ValueHelper.cs +++ b/Modbus.Net/Modbus.Net/ValueHelper.cs @@ -205,9 +205,10 @@ namespace Modbus.Net /// /// /// + /// /// /// - public virtual object GetValue(byte[] data, ref int pos, Type t) + public virtual object GetValue(byte[] data, ref int pos, ref int subPos, Type t) { switch (t.FullName) { @@ -256,6 +257,11 @@ namespace Modbus.Net byte value = _Instance.GetByte(data, ref pos); return value; } + case "System.Boolean": + { + bool value = Instance.GetBit(data, ref pos, ref subPos); + return value; + } default: { throw new NotImplementedException("没有实现除整数以外的其它转换方式"); @@ -399,6 +405,38 @@ namespace Modbus.Net return t; } + /// + /// 获取一个byte中相对应的bit数组展开中第n个位置中的bit元素。 + /// + /// byte数字 + /// bit数组中的对应位置 + /// 小数位 + /// 对应位置的bit元素 + public bool GetBit(byte number, ref int pos, ref int subPos) + { + if (subPos < 0 && subPos > 8) throw new IndexOutOfRangeException(); + int ans = number % 2; + int i = 7; + while (i >= subPos) + { + ans = number % 2; + number /= 2; + i--; + } + subPos += 1; + if (subPos >= 8) + { + pos++; + subPos = 0; + } + return ans > 0; + } + + public virtual bool GetBit(byte[] number, ref int pos, ref int subPos) + { + return GetBit(number[pos], ref pos, ref subPos); + } + /// /// 将待转换的对象数组转换为需要发送的byte数组 /// @@ -538,6 +576,13 @@ namespace Modbus.Net return ByteArrayToObjectArray(contents, new List>() {translateTypeAndCount}); } + public virtual T[] ByteArrayToDestinationArray(byte[] contents, int getCount) + { + var objectArray = _Instance.ByteArrayToObjectArray(contents, + new KeyValuePair(typeof (T), getCount)); + return _Instance.ObjectArrayToDestinationArray(objectArray); + } + /// /// 将byte数组转换为用户指定类型的数组,通过object数组的方式返回,用户需要再把object转换为自己需要的类型,或调用ObjectArrayToDestinationArray返回单一类型的目标数组。 /// @@ -652,41 +697,14 @@ namespace Modbus.Net return array; } - /// - /// 获取一个byte中相对应的bit数组展开中第n个位置中的bit元素。 - /// - /// byte数字 - /// bit数组中的对应位置 - /// 对应位置的bit元素 - public bool GetBit(byte number, ref int pos) - { - if (pos < 0 && pos > 8) throw new IndexOutOfRangeException(); - int ans = number % 2; - int i = 7; - while (i >= pos) - { - ans = number%2; - number /= 2; - i--; - } - pos += 1; - return ans > 0; - } - - public virtual bool GetBit(byte[] number, ref int pos) - { - var tpos = pos%8; - return GetBit(number[pos++/8], ref tpos); - } - /// /// 设置对应数字中相应位置的bit的值 /// /// byte数子 - /// 设置位置 + /// 设置位置 /// 设置bit大小,true为1,false为0 /// - public byte SetBit(byte number, int pos, bool setBit) + public byte SetBit(byte number, int subPos, bool setBit) { int creation = 0; if (setBit) @@ -694,7 +712,7 @@ namespace Modbus.Net for (int i = 0; i < 8; i++) { creation *= 2; - if (i == pos) creation++; + if (i == subPos) creation++; } return (byte) (number | creation); } @@ -703,17 +721,16 @@ namespace Modbus.Net for (int i = 0; i < 8; i++) { creation *= 2; - if (i != pos) creation++; + if (i != subPos) creation++; } return (byte) (number & creation); } } - public virtual ushort SetBit(byte[] number, int pos, bool setBit) + public virtual byte SetBit(byte[] number, int pos, int subPos, bool setBit) { - SetBit(number[pos / 8], pos % 8, setBit); - var tpos = 0; - return GetUShort(number, ref tpos); + SetBit(number[pos], subPos, setBit); + return GetByte(number, ref pos); } } @@ -836,10 +853,12 @@ namespace Modbus.Net return t; } - public override bool GetBit(byte[] number, ref int pos) + public override bool GetBit(byte[] number, ref int pos, ref int subPos) { - var tpos = pos % 8; - return base.GetBit(number[number.Length - 1 - (pos++ / 8)], ref tpos); + var tpos = 7 - subPos; + var bit = base.GetBit(number[pos], ref pos, ref tpos); + subPos = tpos - 7; + return bit; } public override bool[] GetBits(byte[] data, ref int pos) @@ -855,10 +874,10 @@ namespace Modbus.Net return t; } - public override ushort SetBit(byte[] number, int pos, bool setBit) + public override byte SetBit(byte[] number, int pos, int subPos, bool setBit) { Array.Reverse(number); - return base.SetBit(number, pos, setBit); + return base.SetBit(number, pos, subPos, setBit); } private Byte[] Reverse(Byte[] data) diff --git a/Modbus.Net/NA200H.UI.WPF/MainWindow.xaml.cs b/Modbus.Net/NA200H.UI.WPF/MainWindow.xaml.cs index 3ce6843..2e8fbb4 100644 --- a/Modbus.Net/NA200H.UI.WPF/MainWindow.xaml.cs +++ b/Modbus.Net/NA200H.UI.WPF/MainWindow.xaml.cs @@ -29,36 +29,37 @@ namespace NA200H.UI.WPF private void GetUtilityEnter() { - //utility = new ModbusUtility(ModbusType.Tcp, "192.168.3.12"); - //utility.AddressTranslator = new AddressTranslatorNA200H(); - //object[] getNum = utility.GetDatas(0x02, 0x00, "NW 1", new KeyValuePair(typeof(ushort), 4)); - utility = new SiemensUtility(SiemensType.Tcp, "192.168.3.11", SiemensMachineModel.S7_300); - utility.AddressTranslator = new AddressTranslatorSiemens(); - object[] getNum = utility.GetDatas(0x02, 0x00, "V 1", new KeyValuePair(typeof(ushort), 4)); + utility = new ModbusUtility(ModbusType.Tcp, "192.168.3.12"); + utility.AddressTranslator = new AddressTranslatorNA200H(); + object[] getNum = utility.GetDatas(0x02, 0x00, "NW 1", new KeyValuePair(typeof(ushort), 4)); + //utility = new SiemensUtility(SiemensType.Tcp, "192.168.3.11", SiemensMachineModel.S7_300); + //utility.AddressTranslator = new AddressTranslatorSiemens(); + //object[] getNum = utility.GetDatas(0x02, 0x00, "V 1", new KeyValuePair(typeof(ushort), 4)); ushort[] getNumUshorts = BigEndianValueHelper.Instance.ObjectArrayToDestinationArray(getNum); SetValue(getNumUshorts); } private void GetMachineEnter() { - //machine = new ModbusMachine(ModbusType.Tcp, "192.168.3.12", new List() - //{ - //new AddressUnit() {Id = 1, Area = "NW", Address = 1, CommunicationTag = "Add1", DataType = typeof(ushort), Zoom = 1, DecimalPos = 0}, - //new AddressUnit() {Id = 2, Area = "NW", Address = 3, CommunicationTag = "Add2", DataType = typeof(ushort), Zoom = 1, DecimalPos = 0}, - //new AddressUnit() {Id = 3, Area = "NW", Address = 5, CommunicationTag = "Add3", DataType = typeof(ushort), Zoom = 1, DecimalPos = 0}, - //new AddressUnit() {Id = 4, Area = "NW", Address = 7, CommunicationTag = "Ans", DataType = typeof(ushort), Zoom = 1, DecimalPos = 0} - //}); - //machine.AddressFormater = new AddressFormaterNA200H(); - //machine.AddressTranslator = new AddressTranslatorNA200H(); - //machine.AddressCombiner = new AddressCombinerContinus(); - machine = new SiemensMachine(SiemensType.Tcp, "192.168.3.11:102", SiemensMachineModel.S7_300, new List() + machine = new ModbusMachine(ModbusType.Tcp, "192.168.3.12", new List() { - new AddressUnit() {Id = "1", Area = "V", Address = 0, CommunicationTag = "Add1", DataType = typeof(ushort), Zoom = 1, DecimalPos = 0}, - new AddressUnit() {Id = "2", Area = "V", Address = 2, CommunicationTag = "Add2", DataType = typeof(ushort), Zoom = 1, DecimalPos = 0}, - new AddressUnit() {Id = "3", Area = "V", Address = 4, CommunicationTag = "Add3", DataType = typeof(ushort), Zoom = 1, DecimalPos = 0}, - new AddressUnit() {Id = "4", Area = "V", Address = 6, CommunicationTag = "Ans", DataType = typeof(ushort), Zoom = 1, DecimalPos = 0} + new AddressUnit() {Id = "1", Area = "MW", Address = 1, CommunicationTag = "Add1", DataType = typeof(ushort), Zoom = 1, DecimalPos = 0}, + new AddressUnit() {Id = "2", Area = "MW", Address = 2, CommunicationTag = "Add2", DataType = typeof(ushort), Zoom = 1, DecimalPos = 0}, + new AddressUnit() {Id = "3", Area = "MW", Address = 3, CommunicationTag = "Add3", DataType = typeof(ushort), Zoom = 1, DecimalPos = 0}, + new AddressUnit() {Id = "4", Area = "MW", Address = 4, CommunicationTag = "Ans", DataType = typeof(ushort), Zoom = 1, DecimalPos = 0}, }); - machine.AddressCombiner = new AddressCombinerContinus(); + machine.AddressFormater = new AddressFormaterNA200H(); + machine.AddressTranslator = new AddressTranslatorNA200H(); + machine.AddressCombiner = new AddressCombinerContinus(machine.AddressTranslator); + machine.AddressCombinerSet = new AddressCombinerContinus(machine.AddressTranslator); + //machine = new SiemensMachine(SiemensType.Tcp, "192.168.3.11:102", SiemensMachineModel.S7_300, new List() + //{ + //new AddressUnit() {Id = "1", Area = "V", Address = 0, CommunicationTag = "Add1", DataType = typeof(ushort), Zoom = 1, DecimalPos = 0}, + //new AddressUnit() {Id = "2", Area = "V", Address = 2, CommunicationTag = "Add2", DataType = typeof(ushort), Zoom = 1, DecimalPos = 0}, + //new AddressUnit() {Id = "3", Area = "V", Address = 4, CommunicationTag = "Add3", DataType = typeof(ushort), Zoom = 1, DecimalPos = 0}, + //new AddressUnit() {Id = "4", Area = "V", Address = 6, CommunicationTag = "Ans", DataType = typeof(ushort), Zoom = 1, DecimalPos = 0} + //}); + //machine.AddressCombiner = new AddressCombinerContinus(); var result = machine.GetDatas(MachineGetDataType.CommunicationTag); var resultFormat = BaseMachine.MapGetValuesToSetValues(result); SetValue(new ushort[4] {(ushort)resultFormat["Add1"], (ushort)resultFormat["Add2"], (ushort)resultFormat["Add3"], (ushort)resultFormat["Ans"]}); @@ -84,8 +85,8 @@ namespace NA200H.UI.WPF ushort.TryParse(Add1.Text, out add1); ushort.TryParse(Add2.Text, out add2); ushort.TryParse(Add3.Text, out add3); - //utility.SetDatas(0x02, 0x00, "NW 1", new object[] { add1, add2, add3 }); - utility.SetDatas(0x02, 0x00, "V 1", new object[] { add1, add2, add3 }); + utility.SetDatas(0x02, 0x00, "NW 1", new object[] { add1, add2, add3 }); + //utility.SetDatas(0x02, 0x00, "V 1", new object[] { add1, add2, add3 }); Thread.Sleep(100); GetUtilityEnter(); }