コード例 #1
0
        /// <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);
        }
コード例 #2
0
ファイル: BaseMachine.cs プロジェクト: cagnet/Modbus.Net
        /// <summary>
        ///     写入数据
        /// </summary>
        /// <param name="setDataType">写入类型</param>
        /// <param name="values">需要写入的数据字典,当写入类型为Address时,键为需要写入的地址,当写入类型为CommunicationTag时,键为需要写入的单元的描述</param>
        /// <returns>是否写入成功</returns>
        public async Task <bool> SetDatasAsync(MachineSetDataType setDataType, Dictionary <string, double> values)
        {
            try
            {
                //检测并连接设备
                if (!BaseUtility.IsConnected)
                {
                    await BaseUtility.ConnectAsync();
                }
                //如果设备无法连接,终止
                if (!BaseUtility.IsConnected)
                {
                    return(false);
                }
                var addresses = new List <AddressUnit>();
                //遍历每个要设置的值
                foreach (var value in values)
                {
                    //根据设置类型找到对应的地址描述
                    AddressUnit address = null;
                    switch (setDataType)
                    {
                    case MachineSetDataType.Address:
                    {
                        address =
                            GetAddresses.SingleOrDefault(
                                p =>
                                AddressFormater.FormatAddress(p.Area, p.Address, p.SubAddress) == value.Key ||
                                (p.DataType != typeof(bool) &&
                                 AddressFormater.FormatAddress(p.Area, p.Address) == value.Key));
                        break;
                    }

                    case MachineSetDataType.CommunicationTag:
                    {
                        address =
                            GetAddresses.SingleOrDefault(p => p.CommunicationTag == value.Key);
                        break;
                    }

                    case MachineSetDataType.Name:
                    {
                        address = GetAddresses.SingleOrDefault(p => p.Name == value.Key);
                        break;
                    }
                    }
                    //地址为空报错
                    if (address == null)
                    {
                        Console.WriteLine($"Machine {ConnectionToken} Address {value.Key} doesn't exist.");
                        continue;
                    }
                    //不能写报错
                    if (!address.CanWrite)
                    {
                        Console.WriteLine($"Machine {ConnectionToken} Address {value.Key} cannot write.");
                        continue;
                    }
                    addresses.Add(address);
                }
                //将地址编码成与实际设备通讯的地址
                var communcationUnits = AddressCombinerSet.Combine(addresses);
                //遍历每条通讯的连续地址
                foreach (var communicateAddress in communcationUnits)
                {
                    //编码开始地址
                    var addressStart = AddressFormater.FormatAddress(communicateAddress.Area,
                                                                     communicateAddress.Address);

                    var datasReturn = await BaseUtility.GetDatasAsync(
                        AddressFormater.FormatAddress(communicateAddress.Area, communicateAddress.Address, 0),
                        (int)
                        Math.Ceiling(communicateAddress.GetCount *
                                     BigEndianValueHelper.Instance.ByteLength[
                                         communicateAddress.DataType.FullName]));

                    var valueHelper = ValueHelper.GetInstance(BaseUtility.Endian);
                    //如果设备本身能获取到数据但是没有数据
                    var datas = datasReturn;

                    //如果没有数据,终止
                    if (datas == null || datas.Length <
                        (int)
                        Math.Ceiling(communicateAddress.GetCount *
                                     BigEndianValueHelper.Instance.ByteLength[
                                         communicateAddress.DataType.FullName]))
                    {
                        return(false);
                    }

                    foreach (var addressUnit in communicateAddress.OriginalAddresses)
                    {
                        //字节坐标地址
                        var byteCount =
                            AddressHelper.MapProtocalGetCountToAbstractByteCount(
                                addressUnit.Address - communicateAddress.Address +
                                addressUnit.SubAddress * 0.125 /
                                AddressTranslator.GetAreaByteLength(communicateAddress.Area),
                                AddressTranslator.GetAreaByteLength(communicateAddress.Area), 0);
                        //字节坐标主地址
                        var mainByteCount = (int)byteCount;
                        //字节坐标自地址
                        var localByteCount = (int)((byteCount - (int)byteCount) * 8);

                        //协议坐标地址
                        var localPos = byteCount / AddressTranslator.GetAreaByteLength(communicateAddress.Area);
                        //协议坐标子地址
                        var subPos =
                            (int)
                            ((localPos - (int)localPos) /
                             (0.125 / AddressTranslator.GetAreaByteLength(communicateAddress.Area)));
                        //协议主地址字符串
                        var address = AddressFormater.FormatAddress(communicateAddress.Area,
                                                                    communicateAddress.Address + (int)localPos, subPos);
                        //协议完整地址字符串
                        var address2 = subPos != 0
                            ? null
                            : AddressFormater.FormatAddress(communicateAddress.Area,
                                                            communicateAddress.Address + (int)localPos);
                        //获取写入类型
                        var dataType = addressUnit.DataType;
                        switch (setDataType)
                        {
                        case MachineSetDataType.Address:
                        {
                            //获取要写入的值
                            var value =
                                values.SingleOrDefault(
                                    p => p.Key == address || (address2 != null && p.Key == address2));
                            //将要写入的值加入队列
                            var data = Convert.ChangeType(value.Value / addressUnit.Zoom, dataType);

                            if (!valueHelper.SetValue(datas, mainByteCount, localByteCount, data))
                            {
                                return(false);
                            }
                            break;
                        }

                        case MachineSetDataType.CommunicationTag:
                        {
                            var value = values.SingleOrDefault(p => p.Key == addressUnit.CommunicationTag);
                            var data  = Convert.ChangeType(value.Value / addressUnit.Zoom, dataType);
                            if (!valueHelper.SetValue(datas, mainByteCount, localByteCount, data))
                            {
                                return(false);
                            }
                            break;
                        }

                        case MachineSetDataType.Name:
                        {
                            var value = values.SingleOrDefault(p => p.Key == addressUnit.Name);
                            var data  = Convert.ChangeType(value.Value / addressUnit.Zoom, dataType);
                            if (!valueHelper.SetValue(datas, mainByteCount, localByteCount, data))
                            {
                                return(false);
                            }
                            break;
                        }
                        }
                    }
                    //写入数据
                    await
                    BaseUtility.SetDatasAsync(addressStart,
                                              valueHelper.ByteArrayToObjectArray(datas,
                                                                                 new KeyValuePair <Type, int>(communicateAddress.DataType, communicateAddress.GetCount)));
                }
                //如果不保持连接,断开连接
                if (!KeepConnect)
                {
                    BaseUtility.Disconnect();
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(ConnectionToken + " " + e.Message);
                return(false);
            }
            return(true);
        }
コード例 #3
0
        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);
        }
コード例 #4
0
ファイル: BaseMachine.cs プロジェクト: cagnet/Modbus.Net
        /// <summary>
        ///     读取数据
        /// </summary>
        /// <returns>从设备读取的数据</returns>
        public async Task <Dictionary <string, ReturnUnit> > GetDatasAsync(MachineGetDataType getDataType)
        {
            try
            {
                var ans = new Dictionary <string, ReturnUnit>();
                //检测并连接设备
                if (!BaseUtility.IsConnected)
                {
                    await BaseUtility.ConnectAsync();
                }
                //如果无法连接,终止
                if (!BaseUtility.IsConnected)
                {
                    return(null);
                }
                //遍历每一个实际向设备获取数据的连续地址
                foreach (var communicateAddress in CommunicateAddresses)
                {
                    //获取数据
                    var datas =
                        await
                        BaseUtility.GetDatasAsync(
                            AddressFormater.FormatAddress(communicateAddress.Area, communicateAddress.Address,
                                                          communicateAddress.SubAddress),
                            (int)
                            Math.Ceiling(communicateAddress.GetCount *
                                         BigEndianValueHelper.Instance.ByteLength[
                                             communicateAddress.DataType.FullName]));


                    //如果没有数据,终止
                    if (datas == null || (datas.Length != 0 && datas.Length <
                                          (int)
                                          Math.Ceiling(communicateAddress.GetCount *
                                                       BigEndianValueHelper.Instance.ByteLength[
                                                           communicateAddress.DataType.FullName])))
                    {
                        return(null);
                    }


                    foreach (var address in communicateAddress.OriginalAddresses)
                    {
                        //字节坐标的位置
                        var localPos = AddressHelper.MapProtocalCoordinateToAbstractCoordinate(address.Address,
                                                                                               communicateAddress.Address,
                                                                                               AddressTranslator.GetAreaByteLength(communicateAddress.Area)) +
                                       address.SubAddress * 0.125;
                        //字节坐标的主地址位置
                        var localMainPos = (int)localPos;
                        //字节坐标的子地址位置
                        var localSubPos = (int)((localPos - localMainPos) * 8);

                        //根据类型选择返回结果的键是通讯标识还是地址
                        string key;
                        switch (getDataType)
                        {
                        case MachineGetDataType.CommunicationTag:
                        {
                            key = address.CommunicationTag;
                            break;
                        }

                        case MachineGetDataType.Address:
                        {
                            key = AddressFormater.FormatAddress(address.Area, address.Address, address.SubAddress);
                            break;
                        }

                        case MachineGetDataType.Name:
                        {
                            key = address.Name;
                            break;
                        }

                        default:
                        {
                            key = address.CommunicationTag;
                            break;
                        }
                        }

                        //如果没有数据返回空
                        if (datas.Length == 0)
                        {
                            ans.Add(key, new ReturnUnit
                            {
                                PlcValue   = null,
                                UnitExtend = address.UnitExtend
                            });
                        }
                        else
                        {
                            //将获取的数据和对应的通讯标识对应
                            ans.Add(key,
                                    new ReturnUnit
                            {
                                PlcValue =
                                    Convert.ToDouble(
                                        ValueHelper.GetInstance(BaseUtility.Endian)
                                        .GetValue(datas, ref localMainPos, ref localSubPos,
                                                  address.DataType)) * address.Zoom,
                                UnitExtend = address.UnitExtend
                            });
                        }
                    }
                }
                //如果不保持连接,断开连接
                if (!KeepConnect)
                {
                    BaseUtility.Disconnect();
                }
                //返回数据
                if (ans.All(p => p.Value.PlcValue == null))
                {
                    ans = null;
                }
                ErrorCount = 0;
                return(ans);
            }
            catch (Exception e)
            {
                Console.WriteLine(ConnectionToken + " " + e.Message);
                ErrorCount++;
                if (ErrorCount >= _maxErrorCount)
                {
                    Disconnect();
                }
                return(null);
            }
        }
コード例 #5
0
        public override IEnumerable <CommunicationUnit> Combine(IEnumerable <AddressUnit> addresses)
        {
            var continusAddresses = base.Combine(addresses).ToList();
            var addressesGaps     = new List <CommunicationUnitGap>();
            CommunicationUnit preCommunicationUnit = null;

            foreach (var continusAddress in continusAddresses)
            {
                if (preCommunicationUnit == null)
                {
                    preCommunicationUnit = continusAddress;
                    continue;
                }
                if (continusAddress.Area == preCommunicationUnit.Area)
                {
                    //计算间隔
                    var gap = new CommunicationUnitGap
                    {
                        EndUnit   = continusAddress,
                        GapNumber =
                            (int)
                            Math.Ceiling(AddressHelper.MapProtocalCoordinateToAbstractCoordinate(
                                             continusAddress.Address, preCommunicationUnit.Address,
                                             AddressTranslator.GetAreaByteLength(continusAddress.Area)) -
                                         preCommunicationUnit.GetCount *
                                         BigEndianValueHelper.Instance.ByteLength[
                                             preCommunicationUnit.DataType.FullName])
                    };
                    addressesGaps.Add(gap);
                }
                preCommunicationUnit = continusAddress;
            }
            //减去间隔
            var orderedGaps     = addressesGaps.OrderBy(p => p.GapNumber);
            var jumpNumberInner = JumpNumber;

            foreach (var orderedGap in orderedGaps)
            {
                jumpNumberInner -= orderedGap.GapNumber;
                if (jumpNumberInner < 0)
                {
                    break;
                }
                var nowAddress = orderedGap.EndUnit;
                var index      = continusAddresses.IndexOf(nowAddress);
                index--;
                var preAddress = continusAddresses[index];
                continusAddresses.RemoveAt(index);
                continusAddresses.RemoveAt(index);
                //合并两个已有的地址段,变为一个新的地址段
                var newAddress = new CommunicationUnit
                {
                    Area     = nowAddress.Area,
                    Address  = preAddress.Address,
                    GetCount =
                        (int)
                        (preAddress.GetCount * BigEndianValueHelper.Instance.ByteLength[preAddress.DataType.FullName]) +
                        orderedGap.GapNumber +
                        (int)
                        (nowAddress.GetCount * BigEndianValueHelper.Instance.ByteLength[nowAddress.DataType.FullName]),
                    DataType          = typeof(byte),
                    OriginalAddresses = preAddress.OriginalAddresses.ToList().Union(nowAddress.OriginalAddresses)
                };
                continusAddresses.Insert(index, newAddress);
            }
            return(continusAddresses);
        }