/// <summary> /// 组合地址 /// </summary> /// <param name="addresses">需要组合的地址</param> /// <returns>组合后的地址</returns> public override IEnumerable <CommunicationUnit <TKey> > Combine(IEnumerable <AddressUnit <TKey> > addresses) { var groupedAddresses = from address in addresses orderby AddressHelper.GetProtocalCoordinate(address.Address, address.SubAddress, AddressTranslator.GetAreaByteLength(address.Area)) group address by address.Area into grouped select grouped; var ans = new List <CommunicationUnit <TKey> >(); foreach (var groupedAddress in groupedAddresses) { var area = groupedAddress.Key; double initNum = -1; double preNum = -1; Type preType = null; var originalAddresses = new List <AddressUnit <TKey> >(); var orderedAddresses = groupedAddress.OrderBy( address => AddressHelper.GetProtocalCoordinate(address.Address, address.SubAddress, AddressTranslator.GetAreaByteLength(address.Area))); foreach (var address in orderedAddresses) { if (initNum < 0) { initNum = AddressHelper.GetProtocalCoordinate(address.Address, address.SubAddress, AddressTranslator.GetAreaByteLength(address.Area)); originalAddresses.Add(address); } else { if (AddressHelper.GetProtocalCoordinate(address.Address, address.SubAddress, AddressTranslator.GetAreaByteLength(address.Area)) < AddressHelper.GetProtocalCoordinateNextPosition(preNum, preType, AddressTranslator.GetAreaByteLength(address.Area))) { originalAddresses.Add(address); //如果当前地址的末尾被记录,表示地址被记录的地址域覆盖,这个地址没有记录的必要 if (AddressHelper.GetProtocalCoordinateNextPosition( AddressHelper.GetProtocalCoordinate(address.Address, address.SubAddress, AddressTranslator.GetAreaByteLength(address.Area)), address.DataType, AddressTranslator.GetAreaByteLength(address.Area)) <= AddressHelper.GetProtocalCoordinateNextPosition(preNum, preType, AddressTranslator.GetAreaByteLength(address.Area))) { continue; } } else if (AddressHelper.GetProtocalCoordinate(address.Address, address.SubAddress, AddressTranslator.GetAreaByteLength(address.Area)) > AddressHelper.GetProtocalCoordinateNextPosition(preNum, preType, AddressTranslator.GetAreaByteLength(address.Area))) { ans.Add(new CommunicationUnit <TKey> { Area = area, Address = (int)Math.Floor(initNum), GetCount = (int) Math.Ceiling( AddressHelper.MapProtocalGetCountToAbstractByteCount( preNum - (int)Math.Floor(initNum), AddressTranslator.GetAreaByteLength(address.Area), BigEndianValueHelper.Instance.ByteLength[preType.FullName])), DataType = typeof(byte), OriginalAddresses = originalAddresses.ToList() }); initNum = address.Address; originalAddresses.Clear(); originalAddresses.Add(address); } else { //地址连续,压入当前记录的结果 originalAddresses.Add(address); } } //把当前地址变为上一个地址 preNum = AddressHelper.GetProtocalCoordinate(address.Address, address.SubAddress, AddressTranslator.GetAreaByteLength(address.Area)); preType = address.DataType; } //最后一个地址域压入返回结果 ans.Add(new CommunicationUnit <TKey> { Area = area, Address = (int)Math.Floor(initNum), GetCount = (int) Math.Ceiling( AddressHelper.MapProtocalGetCountToAbstractByteCount( preNum - (int)Math.Floor(initNum), AddressTranslator.GetAreaByteLength(area), BigEndianValueHelper.Instance.ByteLength[preType.FullName])), DataType = typeof(byte), OriginalAddresses = originalAddresses.ToList() }); } var newAns = new List <CommunicationUnit <TKey> >(); foreach (var communicationUnit in ans) { var oldByteCount = communicationUnit.GetCount * BigEndianValueHelper.Instance.ByteLength[communicationUnit.DataType.FullName]; while (oldByteCount * BigEndianValueHelper.Instance.ByteLength[communicationUnit.DataType.FullName] > MaxLength) { var newOriginalAddresses = new List <AddressUnit <TKey> >(); 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 <TKey> { 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); }
public override IEnumerable <CommunicationUnit> Combine(IEnumerable <AddressUnit> addresses) { //按从小到大的顺序对地址进行排序 var groupedAddresses = from address in addresses orderby AddressHelper.GetProtocalCoordinate(address.Address, address.SubAddress, AddressTranslator.GetAreaByteLength(address.Area)) group address by address.Area into grouped select grouped; var ans = new List <CommunicationUnit>(); foreach (var groupedAddress in groupedAddresses) { var area = groupedAddress.Key; //初始地址 double initNum = -1; //上一个地址 double preNum = -1; //上一个地址类型 Type preType = null; //记录一个地址组合当中的所有原始地址 var originalAddresses = new List <AddressUnit>(); //对组合内地址从小到大进行排序 var orderedAddresses = groupedAddress.OrderBy( address => AddressHelper.GetProtocalCoordinate(address.Address, address.SubAddress, AddressTranslator.GetAreaByteLength(address.Area))); foreach (var address in orderedAddresses) { //第一次进入时直接压入地址 if (initNum < 0) { initNum = AddressHelper.GetProtocalCoordinate(address.Address, address.SubAddress, AddressTranslator.GetAreaByteLength(address.Area)); originalAddresses.Add(address); } else { //如果当前地址小于已经记录的地址域,表示这个地址的开始已经记录过了 if (AddressHelper.GetProtocalCoordinate(address.Address, address.SubAddress, AddressTranslator.GetAreaByteLength(address.Area)) < AddressHelper.GetProtocalCoordinateNextPosition(preNum, preType, AddressTranslator.GetAreaByteLength(address.Area))) { originalAddresses.Add(address); //如果当前地址的末尾被记录,表示地址被记录的地址域覆盖,这个地址没有记录的必要 if (AddressHelper.GetProtocalCoordinateNextPosition( AddressHelper.GetProtocalCoordinate(address.Address, address.SubAddress, AddressTranslator.GetAreaByteLength(address.Area)), address.DataType, AddressTranslator.GetAreaByteLength(address.Area)) <= AddressHelper.GetProtocalCoordinateNextPosition(preNum, preType, AddressTranslator.GetAreaByteLength(address.Area))) { continue; } } //如果当前地址大于记录的地址域的开头,则表示地址已经不连续了 else if (AddressHelper.GetProtocalCoordinate(address.Address, address.SubAddress, AddressTranslator.GetAreaByteLength(address.Area)) > AddressHelper.GetProtocalCoordinateNextPosition(preNum, preType, AddressTranslator.GetAreaByteLength(address.Area))) { //上一个地址域压入返回结果,并把当前记录的结果清空。 ans.Add(new CommunicationUnit { Area = area, Address = (int)Math.Floor(initNum), GetCount = (int) Math.Ceiling( AddressHelper.MapProtocalGetCountToAbstractByteCount( preNum - (int)Math.Floor(initNum), AddressTranslator.GetAreaByteLength(address.Area), BigEndianValueHelper.Instance.ByteLength[preType.FullName])), DataType = typeof(byte), OriginalAddresses = originalAddresses.ToList() }); initNum = address.Address; originalAddresses.Clear(); originalAddresses.Add(address); } else { //地址连续,压入当前记录的结果 originalAddresses.Add(address); } } //把当前地址变为上一个地址 preNum = AddressHelper.GetProtocalCoordinate(address.Address, address.SubAddress, AddressTranslator.GetAreaByteLength(address.Area)); preType = address.DataType; } //最后一个地址域压入返回结果 ans.Add(new CommunicationUnit { Area = area, Address = (int)Math.Floor(initNum), GetCount = (int) Math.Ceiling( AddressHelper.MapProtocalGetCountToAbstractByteCount( preNum - (int)Math.Floor(initNum), AddressTranslator.GetAreaByteLength(area), BigEndianValueHelper.Instance.ByteLength[preType.FullName])), DataType = typeof(byte), OriginalAddresses = originalAddresses.ToList() }); } return(ans); }