Пример #1
0
        private static (ICollection <IPlcItem> ValidItems, ICollection <(IPlcItem FailedItem, string ErrorMessage)>) VerifyPlcItemResults(ICollection <ReadPlcItemWrapper> mapping, ICollection <AGL4.DATA_RW40> allAgLinkItems, bool transferData)
        {
            var validItems  = new List <IPlcItem>(mapping.Count);
            var failedItems = new List <(IPlcItem FailedItem, string ErrorMessage)>(0);            //! Assume that no errors occur to save memory.

            // Iterate each plc item and get the data for all AGLink items that where needed to handle it.
            foreach (var(plcItem, start, amount) in mapping)
            {
                // Get all ag link items of this plc item.
                var agLinkItems = allAgLinkItems.Skip(start).Take(amount).ToArray();

                // Check if any of those have failed.
                var itemResult = agLinkItems
                                 .Select(agLinkItem => agLinkItem.Result)
                                 .FirstOrDefault(resultCode => resultCode != 0)
                ;

                var result = AgLinkPlc.ConvertToAgLinkResult(itemResult);
                if (result != AgLinkResult.Success)
                {
                    failedItems.Add((plcItem, AgLinkPlc.ErrorMapping.GetErrorMessageForCode(itemResult)));
                }
                else
                {
                    validItems.Add(plcItem);
                    if (transferData)
                    {
                        var data = agLinkItems.SelectMany(agLinkItem => agLinkItem.B).ToArray();
                        AgLinkPlc.TransferValue(plcItem, data);
                    }
                }
            }

            return(validItems, failedItems);
        }
Пример #2
0
        private static (ICollection <ReadPlcItemWrapper> Mapping, AGL4.DATA_RW40[] AllAgLinkItems) CreateMappingAndAgLinkItems(ICollection <IPlcItem> plcItems, PlcItemUsageType usageType)
        {
            var mapping = plcItems
                          .Select(plcItem => new ReadPlcItemWrapper(plcItem))
                          .ToArray()
            ;

            // Create all needed AGLink items.
            //! Directly storing the AGLink items in the ReadPlcItemWrapper instance won't work, as AGL4.DATA_RW40 is a struct that would consequently be copied on assignment.
            //! Therefore the ReadPlcItemWrapper only contains the start position and the amount of items in the returned AGLink items array.
            var previousAmount = 0;
            var allAgLinkItems = mapping
                                 .SelectMany
                                 (
                readPlcItemWrapper =>
            {
                var agLinkItems = AgLinkPlc.CreateAgLinkItems(readPlcItemWrapper.PlcItem, usageType).ToArray();

                readPlcItemWrapper.Start  = (previousAmount += agLinkItems.Length) - 1;
                readPlcItemWrapper.Amount = agLinkItems.Length;

                return(agLinkItems);
            }
                                 )
                                 .ToArray()
            ;

            return(mapping, allAgLinkItems);
        }
Пример #3
0
        private async Task PerformWriteAsync(ICollection <IPlcItem> plcItems, CancellationToken cancellationToken)
        {
            const PlcItemUsageType usageType = PlcItemUsageType.Write;
            var underlyingPlc = AgLinkPlc.VerifyConnectivity(this, plcItems, usageType);

            // Create the mapping.
            var(mapping, allAgLinkItems) = AgLinkPlc.CreateMappingAndAgLinkItems(plcItems, usageType);

            // Write to the plc.
            var writeResult = await Task.Run(() => underlyingPlc.WriteMixEx(allAgLinkItems, allAgLinkItems.Length), cancellationToken);

            // Verify the total result.
            //! Ignore the total result and inspect the result of each item individually.
            var result = AgLinkPlc.ConvertToAgLinkResult(writeResult);

            //if (result != AgLinkResult.Success)
            //{
            //	var errorMessage = AgLinkPlc.ErrorMapping.GetErrorMessageForCode(writeResult);
            //	var items = plcItems.Select(item => (item, "General writing error.")).ToArray();
            //	throw new WritePlcException(new IPlcItem[0], items, $"Could not write any items to {this:LOG}. AGLink returned error code '{result}' ({errorMessage}).");
            //}

            // Verify the result of all items.
            var(validItems, failedItems) = AgLinkPlc.VerifyPlcItemResults(mapping, allAgLinkItems, false);
            if (failedItems.Any())
            {
                throw new WritePlcException(validItems, failedItems, $"Some of the items couldn't be written. See the '{nameof(ReadOrWritePlcException.FailedItems)}' property for further information.");
            }
        }
Пример #4
0
        private async Task PerformReadAsync(ICollection <IPlcItem> plcItems, CancellationToken cancellationToken)
        {
            const PlcItemUsageType usageType = PlcItemUsageType.Read;
            var underlyingPlc = AgLinkPlc.VerifyConnectivity(this, plcItems, usageType);

            // Create the mapping.
            var(mapping, allAgLinkItems) = AgLinkPlc.CreateMappingAndAgLinkItems(plcItems, usageType);

            // Read from the plc.
            //! The return value may be zero even if some or all of the items failed. To get the real result the 'Result' property of the AGLink item (AGL4.DATA_RW40.Result) must be checked.
            var readResult = await Task.Run(() => underlyingPlc.ReadMixEx(allAgLinkItems, allAgLinkItems.Length), cancellationToken);

            // Verify the total result.
            //! Ignore the total result and inspect the result of each item individually.
            var result = AgLinkPlc.ConvertToAgLinkResult(readResult);

            //if (result != AgLinkResult.Success)
            //{
            //	var errorMessage = AgLinkPlc.ErrorMapping.GetErrorMessageForCode(readResult);
            //	var items = plcItems.Select(item => (item, "General reading error.")).ToArray();
            //	throw new ReadPlcException(new IPlcItem[0], items, $"Could not read any items from {this:LOG}. AGLink returned error code '{result}' ({errorMessage}).");
            //}

            // Verify the result of all items and transfer the value.
            var(validItems, failedItems) = AgLinkPlc.VerifyPlcItemResults(mapping, allAgLinkItems, true);
            if (failedItems.Any())
            {
                throw new ReadPlcException(validItems, failedItems, $"Some of the items couldn't be read. See the '{nameof(ReadOrWritePlcException.FailedItems)}' property for further information.");
            }
        }
Пример #5
0
        private static IAGLink4 VerifyConnectivity(AgLinkPlc plc, ICollection <IPlcItem> plcItems, PlcItemUsageType usageType)
        {
            var underlyingPlc = plc.UnderlyingPlc;

            if (underlyingPlc is null)
            {
                var itemDescriptions = Plc.GetPlcItemDescription(plcItems);
                throw new NotConnectedPlcException($"Cannot {usageType.ToString().ToLower()} the plc items ({itemDescriptions}) because {plc:LOG} is not connected. All items will be put on hold.");
            }

            return(underlyingPlc);
        }