private Dictionary <string, WorkingData> GetWorkingDataDictionary(OperationData operation, Catalog catalog)
        {
            Dictionary <string, WorkingData> workingDataDictionary = new Dictionary <string, WorkingData>();

            for (int i = 0; i <= operation.MaxDepth; i++)
            {
                IEnumerable <DeviceElementUse> deviceElementUses = operation.GetDeviceElementUses(i);
                foreach (DeviceElementUse deviceElementUse in deviceElementUses)
                {
                    DeviceElementConfiguration config = catalog.DeviceElementConfigurations.FirstOrDefault(c => c.Id.ReferenceId == deviceElementUse.DeviceConfigurationId);
                    string deviceName = deviceElementUse.Id.ReferenceId.ToString();
                    if (config != null)
                    {
                        deviceName = config.Id.ReferenceId + "_" + config.Description;
                    }

                    IEnumerable <WorkingData> workingDatas = deviceElementUse.GetWorkingDatas();
                    foreach (WorkingData workingData in workingDatas)
                    {
                        if (workingData.Representation != null)
                        {
                            string key = $"{deviceElementUse.Depth}.{deviceElementUse.Order}:__{deviceName}_{workingData.Representation.Code}";
                            if (!workingDataDictionary.ContainsKey(key))
                            {
                                workingDataDictionary.Add(key, workingData);
                            }
                        }
                    }
                }
            }
            return(workingDataDictionary);
        }
 public static DeviceElementConfiguration GetDeviceElementConfiguration(DeviceElement adaptDeviceElement, DeviceElementHierarchy isoHierarchy, AgGateway.ADAPT.ApplicationDataModel.ADM.Catalog catalog)
 {
     if (isoHierarchy.DeviceElement.DeviceElementType == ISOEnumerations.ISODeviceElementType.Connector ||
         isoHierarchy.DeviceElement.DeviceElementType == ISOEnumerations.ISODeviceElementType.Navigation)
     {
         //Data belongs to the parent device element from the ISO element referenced
         //Connector and Navigation data may be stored in Timelog data, but Connectors are not DeviceElements in ADAPT.  The data refers to the parent implement.
         DeviceElementConfiguration parentConfig = catalog.DeviceElementConfigurations.FirstOrDefault(c => c.DeviceElementId == adaptDeviceElement.ParentDeviceId);
         if (parentConfig == null)
         {
             DeviceElement parentElement = catalog.DeviceElements.Single(d => d.Id.ReferenceId == adaptDeviceElement.ParentDeviceId);
             parentConfig = AddDeviceElementConfiguration(parentElement, isoHierarchy.Parent, catalog);
         }
         return(parentConfig);
     }
     else
     {
         DeviceElementConfiguration deviceConfiguration = catalog.DeviceElementConfigurations.FirstOrDefault(c => c.DeviceElementId == adaptDeviceElement.Id.ReferenceId);
         if (deviceConfiguration == null)
         {
             deviceConfiguration = AddDeviceElementConfiguration(adaptDeviceElement, isoHierarchy, catalog);
         }
         return(deviceConfiguration);
     }
 }
Beispiel #3
0
        public static DeviceElementConfiguration GetDeviceElementConfiguration(DeviceElement adaptDeviceElement, DeviceElementHierarchy isoHierarchy, AgGateway.ADAPT.ApplicationDataModel.ADM.Catalog catalog)
        {
            if ((isoHierarchy.DeviceElement.DeviceElementType == ISOEnumerations.ISODeviceElementType.Bin &&
                 (isoHierarchy.Parent.DeviceElement.DeviceElementType == ISOEnumerations.ISODeviceElementType.Function ||
                  isoHierarchy.Parent.DeviceElement.DeviceElementType == ISOEnumerations.ISODeviceElementType.Device)) ||
                (isoHierarchy.DeviceElement.DeviceElementType == ISOEnumerations.ISODeviceElementType.Connector) ||
                (isoHierarchy.DeviceElement.DeviceElementType == ISOEnumerations.ISODeviceElementType.Navigation))
            {
                //Data belongs to the parent device element from the ISO element referenced

                //Bin children of functions or devices carry data that effectively belong to the parent device element in ISO.  See TC-GEO examples 5-8.
                //Find the parent DeviceElementUse and add the data to that object.
                //Per the TC-GEO spec: "The location of the Bin type device elements as children of the boom specifies that the products from these bins are all distributed through that boom."
                //-
                //Also, Connector and Navigation data may be stored in Timelog data, but Connectors are not DeviceElements in ADAPT.  The data refers to the parent implement.
                DeviceElementConfiguration parentConfig = catalog.DeviceElementConfigurations.FirstOrDefault(c => c.DeviceElementId == adaptDeviceElement.ParentDeviceId);
                if (parentConfig == null)
                {
                    DeviceElement parentElement = catalog.DeviceElements.Single(d => d.Id.ReferenceId == adaptDeviceElement.ParentDeviceId);
                    parentConfig = AddDeviceElementConfiguration(parentElement, isoHierarchy.Parent, catalog);
                }
                return(parentConfig);
            }
            else
            {
                DeviceElementConfiguration deviceConfiguration = catalog.DeviceElementConfigurations.FirstOrDefault(c => c.DeviceElementId == adaptDeviceElement.Id.ReferenceId);
                if (deviceConfiguration == null)
                {
                    deviceConfiguration = AddDeviceElementConfiguration(adaptDeviceElement, isoHierarchy, catalog);
                }
                return(deviceConfiguration);
            }
        }
Beispiel #4
0
        public ISOConnection ExportConnection(int loggedDataOrWorkItemID, EquipmentConfiguration adaptConnection)
        {
            ISOConnection isoConnection = new ISOConnection();

            //First Connector
            Connector connector1 = DataModel.Catalog.Connectors.FirstOrDefault(c => c.Id.ReferenceId == adaptConnection.Connector1Id);

            if (connector1 != null)
            {
                DeviceElementConfiguration config = DataModel.Catalog.DeviceElementConfigurations.FirstOrDefault(c => c.Id.ReferenceId == connector1.DeviceElementConfigurationId);
                if (config != null)
                {
                    string        isoDeviceElementID = TaskDataMapper.InstanceIDMap.GetISOID(config.DeviceElementId);
                    DeviceElement deviceElement      = DataModel.Catalog.DeviceElements.FirstOrDefault(d => d.Id.ReferenceId == config.DeviceElementId);
                    if (deviceElement != null)
                    {
                        string isoDeviceID = TaskDataMapper.InstanceIDMap.GetISOID(deviceElement.DeviceModelId);
                        if (!string.IsNullOrEmpty(isoDeviceElementID) && !string.IsNullOrEmpty(isoDeviceElementID))
                        {
                            isoConnection.DeviceIdRef_0        = isoDeviceID;
                            isoConnection.DeviceElementIdRef_0 = TaskDataMapper.InstanceIDMap.GetISOID(connector1.Id.ReferenceId); //We want to refer to the Connector DeviceElement, not its parent referred by the config element
                        }
                    }
                }
            }

            //Second Connector
            Connector connector2 = DataModel.Catalog.Connectors.FirstOrDefault(c => c.Id.ReferenceId == adaptConnection.Connector2Id);

            if (connector2 != null)
            {
                DeviceElementConfiguration config = DataModel.Catalog.DeviceElementConfigurations.FirstOrDefault(c => c.Id.ReferenceId == connector2.DeviceElementConfigurationId);
                if (config != null)
                {
                    string        isoDeviceElementID = TaskDataMapper.InstanceIDMap.GetISOID(config.DeviceElementId);
                    DeviceElement deviceElement      = DataModel.Catalog.DeviceElements.FirstOrDefault(d => d.Id.ReferenceId == config.DeviceElementId);
                    if (deviceElement != null)
                    {
                        string isoDeviceID = TaskDataMapper.InstanceIDMap.GetISOID(deviceElement.DeviceModelId);
                        if (!string.IsNullOrEmpty(isoDeviceElementID) && !string.IsNullOrEmpty(isoDeviceElementID))
                        {
                            isoConnection.DeviceIdRef_1        = isoDeviceID;
                            isoConnection.DeviceElementIdRef_1 = TaskDataMapper.InstanceIDMap.GetISOID(connector2.Id.ReferenceId);
                        }
                    }
                }
            }

            //DataLogTriggers
            if (adaptConnection.DataLogTriggers.Any())
            {
                string  taskID = TaskDataMapper.InstanceIDMap.GetISOID(loggedDataOrWorkItemID);
                ISOTask task   = TaskDataMapper.ISOTaskData.ChildElements.OfType <ISOTask>().First(t => t.TaskID == taskID);
                DataLogTriggerMapper dltMapper = new DataLogTriggerMapper(TaskDataMapper);
                task.DataLogTriggers = dltMapper.ExportDataLogTriggers(adaptConnection.DataLogTriggers).ToList();
            }

            return(isoConnection);
        }
Beispiel #5
0
        public List <DeviceElementUse> Map(ISOTime time, IEnumerable <ISOSpatialRow> isoRecords, int operationDataId, IEnumerable <string> isoDeviceElementIDs)
        {
            var sections = new List <DeviceElementUse>();

            foreach (string isoDeviceElementID in isoDeviceElementIDs)
            {
                DeviceElementHierarchy hierarchy = TaskDataMapper.DeviceElementHierarchies.GetRelevantHierarchy(isoDeviceElementID);
                if (hierarchy != null)
                {
                    DeviceElementUse   deviceElementUse = null;
                    List <WorkingData> workingDatas     = new List <WorkingData>();

                    //Get the relevant DeviceElementConfiguration
                    int           adaptDeviceElementId = TaskDataMapper.InstanceIDMap.GetADAPTID(isoDeviceElementID).Value;
                    DeviceElement adaptDeviceElement   = DataModel.Catalog.DeviceElements.SingleOrDefault(d => d.Id.ReferenceId == adaptDeviceElementId);
                    if (adaptDeviceElement != null)
                    {
                        DeviceElementConfiguration config = DeviceElementMapper.GetDeviceElementConfiguration(adaptDeviceElement, hierarchy, DataModel.Catalog);

                        int depth = hierarchy.Depth;
                        int order = hierarchy.Order;
                        if (config.DeviceElementId == adaptDeviceElement.ParentDeviceId)
                        {
                            //The configuration references the parent ISO element
                            depth = hierarchy.Parent.Depth;
                            order = hierarchy.Parent.Order;
                        }

                        //Read any spatially-listed widths/offsets on this data onto the DeviceElementConfiguration objects
                        hierarchy.SetWidthsAndOffsetsFromSpatialData(isoRecords, config, RepresentationMapper);

                        //Create the DeviceElementUse
                        deviceElementUse                       = new DeviceElementUse();
                        deviceElementUse.Depth                 = depth;
                        deviceElementUse.Order                 = order;
                        deviceElementUse.OperationDataId       = operationDataId;
                        deviceElementUse.DeviceConfigurationId = config.Id.ReferenceId;

                        //Add Working Data for any data on this device element
                        List <WorkingData> data = _workingDataMapper.Map(time, isoRecords, deviceElementUse, hierarchy, sections);
                        if (data.Any())
                        {
                            workingDatas.AddRange(data);
                        }

                        deviceElementUse.GetWorkingDatas = () => workingDatas;

                        if (!sections.Contains(deviceElementUse))
                        {
                            sections.Add(deviceElementUse);
                        }
                    }
                }
            }

            return(sections);
        }
Beispiel #6
0
        public IEnumerable <ISODataLogValue> ExportDataLogValues(List <WorkingData> workingDatas, List <DeviceElementUse> deviceElementUses)
        {
            if (workingDatas == null)
            {
                return(null);
            }

            List <ISODataLogValue> dlvs = new List <ISODataLogValue>();
            int i = 0;

            foreach (WorkingData workingData in workingDatas)
            {
                //DDI
                int?mappedDDI = RepresentationMapper.Map(workingData.Representation);
                var dlv       = new ISODataLogValue();
                if (mappedDDI != null)
                {
                    if (workingData.Representation != null && workingData.Representation.Code == "dtRecordingStatus" && workingData.DeviceElementUseId != 0)
                    {
                        dlv.ProcessDataDDI = 141.AsHexDDI(); //No support for exporting CondensedWorkState at this time
                    }
                    else
                    {
                        dlv.ProcessDataDDI = mappedDDI.Value.AsHexDDI();
                    }
                }
                else if (workingData.Representation.CodeSource == ApplicationDataModel.Representations.RepresentationCodeSourceEnum.ISO11783_DDI)
                {
                    dlv.ProcessDataDDI = workingData.Representation.Code;
                }

                //DeviceElementIdRef
                DeviceElementUse use = deviceElementUses.FirstOrDefault(d => d.Id.ReferenceId == workingData.DeviceElementUseId);
                if (use != null)
                {
                    DeviceElementConfiguration deviceElementConfiguration = DataModel.Catalog.DeviceElementConfigurations.FirstOrDefault(d => d.Id.ReferenceId == use.DeviceConfigurationId);
                    if (deviceElementConfiguration != null)
                    {
                        //This requires the Devices will have been mapped prior to the LoggedData
                        dlv.DeviceElementIdRef = TaskDataMapper.InstanceIDMap.GetISOID(deviceElementConfiguration.DeviceElementId);
                    }
                }

                if (dlv.ProcessDataDDI != null && dlv.DeviceElementIdRef != null)
                {
                    dlvs.Add(dlv);
                    _dataLogValueOrdersByWorkingDataID.Add(workingData.Id.ReferenceId, i++);
                }
            }
            return(dlvs);
        }
Beispiel #7
0
        private List <ISOTime> ExportSummary(Summary summary)
        {
            List <ISOTime> times = new List <ISOTime>();

            foreach (StampedMeteredValues values in summary.SummaryData)
            {
                ISOTime time = new ISOTime();
                time.Start = values.Stamp.TimeStamp1;
                time.Stop  = values.Stamp.TimeStamp2;
                if (values.Stamp.Duration.HasValue)
                {
                    time.Duration = (uint)values.Stamp.Duration.Value.TotalSeconds;
                }
                time.Type = values.Stamp.DateContext == DateContextEnum.ProposedStart ? ISOEnumerations.ISOTimeType.Planned : ISOEnumerations.ISOTimeType.Effective;

                foreach (MeteredValue value in values.Values)
                {
                    if (value.Value != null && value.Value is NumericRepresentationValue)
                    {
                        NumericRepresentationValue numericValue = value.Value as NumericRepresentationValue;
                        ISODataLogValue            dlv          = new ISODataLogValue();
                        int?ddi = RepresentationMapper.Map(numericValue.Representation);
                        if (ddi.HasValue)
                        {
                            dlv.ProcessDataDDI = ddi.Value.AsHexDDI();
                            DdiDefinition DdiDefinition = DDIs[ddi.Value];
                            dlv.ProcessDataValue = (int)(numericValue.Value.Value / (DdiDefinition.Resolution != 0 ? DdiDefinition.Resolution : 1d));
                        }
                        else
                        {
                            if (numericValue.Representation.CodeSource == RepresentationCodeSourceEnum.ISO11783_DDI)
                            {
                                dlv.ProcessDataDDI   = numericValue.Representation.Code;
                                dlv.ProcessDataValue = (int)numericValue.Value.Value;
                            }
                        }
                        if (value.DeviceConfigurationId.HasValue)
                        {
                            DeviceElementConfiguration config = DataModel.Catalog.DeviceElementConfigurations.FirstOrDefault(c => c.Id.ReferenceId == value.DeviceConfigurationId.Value);
                            if (config != null)
                            {
                                dlv.DeviceElementIdRef = TaskDataMapper.InstanceIDMap.GetISOID(config.DeviceElementId);
                            }
                        }
                        time.DataLogValues.Add(dlv);
                    }
                }
                times.Add(time);
            }
            return(times);
        }
Beispiel #8
0
        private MeteredValue GetSummaryMeteredValue(ISODataLogValue dlv)
        {
            if (dlv.ProcessDataDDI == null)
            {
                return(null);
            }
            int ddi = dlv.ProcessDataDDI.AsInt32DDI();

            int dataValue = 0;

            if (dlv.ProcessDataValue.HasValue)
            {
                dataValue = dlv.ProcessDataValue.Value;
            }

            var unitOfMeasure = RepresentationMapper.GetUnitForDdi(ddi);

            if (!DDIs.ContainsKey(ddi) || unitOfMeasure == null)
            {
                return(null);
            }

            DdiDefinition ddiDefintion = DDIs[ddi];

            int?deviceConfigurationID = null;
            int?deviceElementID       = TaskDataMapper.InstanceIDMap.GetADAPTID(dlv.DeviceElementIdRef);

            if (deviceElementID.HasValue)
            {
                //Since Device creation is on-demand, we need to call GetDeviceElementConfiguration here to ensure the relevant device is created if it hasn't been yet.
                var hierarchy          = TaskDataMapper?.DeviceElementHierarchies?.GetRelevantHierarchy(dlv.DeviceElementIdRef);
                var adaptDeviceElement = DataModel?.Catalog?.DeviceElements?.FirstOrDefault(d => d?.Id?.ReferenceId == deviceElementID.Value);
                if (hierarchy != null && adaptDeviceElement != null)
                {
                    DeviceElementConfiguration config = DeviceElementMapper.GetDeviceElementConfiguration(adaptDeviceElement, hierarchy, DataModel.Catalog);
                    if (config != null)
                    {
                        deviceConfigurationID = config.Id.ReferenceId;
                    }
                }
            }

            return(new MeteredValue
            {
                Value = new NumericRepresentationValue(RepresentationMapper.Map(ddi) as NumericRepresentation,
                                                       unitOfMeasure,
                                                       new NumericValue(unitOfMeasure, dataValue * ddiDefintion.Resolution)),
                DeviceConfigurationId = deviceConfigurationID
            });
        }
        private DeviceElementUse FindExistingDeviceElementUseForCondensedData(ISODeviceElement targetSection, List <DeviceElementUse> pendingDeviceElementUses)
        {
            DeviceElementUse existingDeviceElementUse = null;
            int?deviceElementID = TaskDataMapper.InstanceIDMap.GetADAPTID(targetSection.DeviceElementId);

            if (deviceElementID.HasValue)
            {
                DeviceElementConfiguration config = DataModel.Catalog.DeviceElementConfigurations.FirstOrDefault(d => d.DeviceElementId == deviceElementID.Value);
                if (config != null)
                {
                    existingDeviceElementUse = pendingDeviceElementUses.FirstOrDefault(p => p.DeviceConfigurationId == config.Id.ReferenceId);
                }
            }
            return(existingDeviceElementUse);
        }
        private void UpdateCondensedWorkingDatas(List <WorkingData> condensedWorkingDatas, ISODataLogValue dlv, DeviceElementUse deviceElementUse, List <DeviceElementUse> pendingDeviceElementUses, DeviceElementHierarchy isoDeviceElementHierarchy)
        {
            ISODeviceElement isoDeviceElement = TaskDataMapper.DeviceElementHierarchies.GetISODeviceElementFromID(dlv.DeviceElementIdRef);
            IEnumerable <ISODeviceElement> isoSectionElements = isoDeviceElement.ChildDeviceElements.Where(d => d.DeviceElementType == ISOEnumerations.ISODeviceElementType.Section);

            if (isoSectionElements.Count() > 0 && isoSectionElements.Count() <= condensedWorkingDatas.Count)
            {
                //We have found the expected number of sections in the DDOP
                List <ISODeviceElement> targetSections = isoSectionElements.ToList();

                //Update the DeviceElementReference on the Condensed WorkingDatas
                for (int i = 0; i < isoSectionElements.Count(); i++)
                {
                    WorkingData workingData = condensedWorkingDatas[i];

                    DeviceElementUse condensedDeviceElementUse = new DeviceElementUse();
                    condensedDeviceElementUse.OperationDataId = deviceElementUse.OperationDataId;

                    ISODeviceElement targetSection = targetSections[i];
                    int?deviceElementID            = TaskDataMapper.InstanceIDMap.GetADAPTID(targetSection.DeviceElementId);
                    if (deviceElementID.HasValue)
                    {
                        DeviceElement deviceElement = DataModel.Catalog.DeviceElements.SingleOrDefault(d => d.Id.ReferenceId == deviceElementID.Value);
                        if (deviceElement != null)
                        {
                            //Reference the device element in its hierarchy so that we can get the depth & order
                            DeviceElementHierarchy deviceElementInHierarchy = isoDeviceElementHierarchy.FromDeviceElementID(targetSection.DeviceElementId);

                            //Get the config id
                            DeviceElementConfiguration deviceElementConfig = DeviceElementMapper.GetDeviceElementConfiguration(deviceElement, deviceElementInHierarchy, DataModel.Catalog);
                            condensedDeviceElementUse.DeviceConfigurationId = deviceElementConfig.Id.ReferenceId;

                            //Set the depth & order
                            condensedDeviceElementUse.Depth = deviceElementInHierarchy.Depth;
                            condensedDeviceElementUse.Order = deviceElementInHierarchy.Order;
                        }
                    }

                    condensedDeviceElementUse.GetWorkingDatas = () => new List <WorkingData> {
                        workingData
                    };

                    workingData.DeviceElementUseId = condensedDeviceElementUse.Id.ReferenceId;

                    pendingDeviceElementUses.Add(condensedDeviceElementUse);
                }
            }
        }
Beispiel #11
0
        private MeteredValue GetSummaryMeteredValue(ISODataLogValue dlv)
        {
            if (dlv.ProcessDataDDI == null)
            {
                return(null);
            }
            int ddi = dlv.ProcessDataDDI.AsInt32DDI();

            int dataValue = 0;

            if (dlv.ProcessDataValue.HasValue)
            {
                dataValue = dlv.ProcessDataValue.Value;
            }

            var unitOfMeasure = RepresentationMapper.GetUnitForDdi(ddi);

            if (!DDIs.ContainsKey(ddi) || unitOfMeasure == null)
            {
                return(null);
            }

            DdiDefinition ddiDefintion = DDIs[ddi];

            int?deviceConfigurationID = null;
            int?deviceElementID       = TaskDataMapper.InstanceIDMap.GetADAPTID(dlv.DeviceElementIdRef);

            if (deviceElementID.HasValue)
            {
                DeviceElementConfiguration config = DataModel.Catalog.DeviceElementConfigurations.FirstOrDefault(c => c.DeviceElementId == deviceElementID.Value);
                if (config != null)
                {
                    deviceConfigurationID = config.Id.ReferenceId;
                }
            }

            return(new MeteredValue
            {
                Value = new NumericRepresentationValue(RepresentationMapper.Map(ddi) as NumericRepresentation,
                                                       unitOfMeasure,
                                                       new NumericValue(unitOfMeasure, dataValue * ddiDefintion.Resolution)),
                DeviceConfigurationId = deviceConfigurationID
            });
        }
        /// <summary>
        /// Adds a connector with a hitch at the given reference point, referencing the parent DeviceElement as the DeviceElementConfiguration
        /// </summary>
        /// <param name="rootDeviceHierarchy"></param>
        /// <param name="connectorDeviceElement"></param>
        /// <param name="deviceElement"></param>
        private void AddConnector(DeviceElementHierarchy rootDeviceHierarchy, ISODeviceElement connectorDeviceElement)
        {
            //Per the TC-GEO specification, the connector is always a child of the root device element.
            DeviceElementHierarchy hierarchy = rootDeviceHierarchy.FromDeviceElementID(connectorDeviceElement.DeviceElementId);

            if (hierarchy.Parent == rootDeviceHierarchy)
            {
                int?rootDeviceElementID = TaskDataMapper.InstanceIDMap.GetADAPTID(rootDeviceHierarchy.DeviceElement.DeviceElementId);
                if (rootDeviceElementID.HasValue)
                {
                    HitchPoint hitch = new HitchPoint();
                    hitch.ReferencePoint = new ReferencePoint()
                    {
                        XOffset = hierarchy.XOffsetRepresentation, YOffset = hierarchy.YOffsetRepresentation, ZOffset = hierarchy.ZOffsetRepresentation
                    };
                    hitch.HitchTypeEnum = HitchTypeEnum.Unkown;
                    DataModel.Catalog.HitchPoints.Add(hitch);

                    //Get the DeviceElementConfiguration for the root element in order that we may link the Connector to it.
                    DeviceElement root = DataModel.Catalog.DeviceElements.FirstOrDefault(d => d.Id.ReferenceId == rootDeviceElementID);
                    if (root != null)
                    {
                        DeviceElementConfiguration rootDeviceConfiguration = DeviceElementMapper.GetDeviceElementConfiguration(root, rootDeviceHierarchy, DataModel.Catalog);
                        if (rootDeviceConfiguration != null)
                        {
                            Connector connector = new Connector();
                            ImportIDs(connector.Id, hierarchy.DeviceElement.DeviceElementId);
                            connector.DeviceElementConfigurationId = rootDeviceConfiguration.Id.ReferenceId;
                            connector.HitchPointId = hitch.Id.ReferenceId;
                            DataModel.Catalog.Connectors.Add(connector);

                            //The ID mapping will link the ADAPT Connector to the ISO Device Element
                            TaskDataMapper.InstanceIDMap.Add(connector.Id.ReferenceId, connectorDeviceElement.DeviceElementId);
                        }
                    }
                }
            }
        }
Beispiel #13
0
        public static DeviceElementConfiguration GetDeviceElementConfiguration(DeviceElement adaptDeviceElement, DeviceElementHierarchy isoHierarchy, AgGateway.ADAPT.ApplicationDataModel.ADM.Catalog catalog)
        {
            if (isoHierarchy.DeviceElement.DeviceElementType == ISOEnumerations.ISODeviceElementType.Connector ||
                isoHierarchy.DeviceElement.DeviceElementType == ISOEnumerations.ISODeviceElementType.Navigation)
            {
                //Data belongs to the parent device element from the ISO element referenced
                //Connector and Navigation data may be stored in Timelog data, but Connectors are not DeviceElements in ADAPT.
                //The data refers to the parent implement, which must always be a Device DET per the ISO spec.  We map this to a Machine Config
                DeviceElement parent = catalog.DeviceElements.FirstOrDefault(d => d.Id.ReferenceId == adaptDeviceElement.ParentDeviceId);
                while (parent != null && parent.DeviceElementType != DeviceElementTypeEnum.Machine)
                {
                    parent = catalog.DeviceElements.FirstOrDefault(d => d.Id.ReferenceId == parent.ParentDeviceId);
                }

                if (parent == null)
                {
                    throw new ApplicationException($"Cannot identify Device for Navigation/Connector DeviceElement: {adaptDeviceElement.Description}.");
                }

                DeviceElementConfiguration parentConfig = catalog.DeviceElementConfigurations.FirstOrDefault(c => c.DeviceElementId == parent.Id.ReferenceId);
                if (parentConfig == null)
                {
                    DeviceElement parentElement = catalog.DeviceElements.Single(d => d.Id.ReferenceId == adaptDeviceElement.ParentDeviceId);
                    parentConfig = AddDeviceElementConfiguration(parentElement, isoHierarchy.Parent, catalog);
                }
                return(parentConfig);
            }
            else
            {
                DeviceElementConfiguration deviceConfiguration = catalog.DeviceElementConfigurations.FirstOrDefault(c => c.DeviceElementId == adaptDeviceElement.Id.ReferenceId);
                if (deviceConfiguration == null)
                {
                    deviceConfiguration = AddDeviceElementConfiguration(adaptDeviceElement, isoHierarchy, catalog);
                }
                return(deviceConfiguration);
            }
        }
        public void SetWidthsAndOffsetsFromSpatialData(IEnumerable <ISOSpatialRow> isoRecords, DeviceElementConfiguration config, RepresentationMapper representationMapper)
        {
            //Set values on this object and associated DeviceElementConfiguration
            if (Width == null)
            {
                Width = GetWidthFromSpatialData(isoRecords, DeviceElement.DeviceElementId, representationMapper);
            }

            if (config.Offsets == null)
            {
                config.Offsets = new List <NumericRepresentationValue>();
            }

            if (XOffset == null)
            {
                XOffset = GetXOffsetFromSpatialData(isoRecords, DeviceElement.DeviceElementId, representationMapper);
                if (XOffsetRepresentation != null)
                {
                    config.Offsets.Add(XOffsetRepresentation);
                }
            }

            if (YOffset == null)
            {
                YOffset = GetYOffsetFromSpatialData(isoRecords, DeviceElement.DeviceElementId, representationMapper);
                if (YOffsetRepresentation != null)
                {
                    config.Offsets.Add(YOffsetRepresentation);
                }
            }

            if (ZOffset == null)
            {
                ZOffset = GetZOffsetFromSpatialData(isoRecords, DeviceElement.DeviceElementId, representationMapper);
                if (ZOffsetRepresentation != null)
                {
                    config.Offsets.Add(ZOffsetRepresentation);
                }
            }

            //Update config values as appropriate
            if (this.DeviceElement.DeviceElementType == ISODeviceElementType.Navigation)
            {
                MachineConfiguration machineConfig = config as MachineConfiguration;
                if (machineConfig.GpsReceiverXOffset == null)
                {
                    machineConfig.GpsReceiverXOffset = XOffsetRepresentation;
                }
                if (machineConfig.GpsReceiverYOffset == null)
                {
                    machineConfig.GpsReceiverYOffset = YOffsetRepresentation;
                }
                if (machineConfig.GpsReceiverZOffset == null)
                {
                    machineConfig.GpsReceiverZOffset = ZOffsetRepresentation;
                }
            }
            else
            {
                if (config is SectionConfiguration)
                {
                    SectionConfiguration sectionConfig = config as SectionConfiguration;
                    if (sectionConfig.SectionWidth == null)
                    {
                        sectionConfig.SectionWidth = WidthRepresentation;
                    }
                    if (sectionConfig.InlineOffset == null)
                    {
                        sectionConfig.InlineOffset = XOffsetRepresentation;
                    }
                    if (sectionConfig.LateralOffset == null)
                    {
                        sectionConfig.LateralOffset = YOffsetRepresentation;
                    }
                }
                else if (config is ImplementConfiguration)
                {
                    ImplementConfiguration implementConfig = config as ImplementConfiguration;
                    if (implementConfig.Width == null)
                    {
                        implementConfig.Width = WidthRepresentation;
                    }
                }
            }
        }
Beispiel #15
0
        public List <DeviceElementUse> Map(ISOTime time,
                                           IEnumerable <ISOSpatialRow> isoRecords,
                                           int operationDataId,
                                           IEnumerable <string> isoDeviceElementIDs,
                                           Dictionary <string, List <ISOProductAllocation> > isoProductAllocations)
        {
            var sections = new List <DeviceElementUse>();

            foreach (string isoDeviceElementID in isoDeviceElementIDs)
            {
                DeviceElementHierarchy hierarchy = TaskDataMapper.DeviceElementHierarchies.GetRelevantHierarchy(isoDeviceElementID);
                if (hierarchy != null)
                {
                    DeviceElementUse   deviceElementUse = null;
                    List <WorkingData> workingDatas     = new List <WorkingData>();

                    //Get the relevant DeviceElementConfiguration
                    int           adaptDeviceElementId = TaskDataMapper.InstanceIDMap.GetADAPTID(isoDeviceElementID).Value;
                    DeviceElement adaptDeviceElement   = DataModel.Catalog.DeviceElements.SingleOrDefault(d => d.Id.ReferenceId == adaptDeviceElementId);
                    if (adaptDeviceElement != null)
                    {
                        DeviceElementConfiguration config = DeviceElementMapper.GetDeviceElementConfiguration(adaptDeviceElement, hierarchy, DataModel.Catalog);

                        int depth = hierarchy.Depth;
                        int order = hierarchy.Order;
                        if (config.DeviceElementId == adaptDeviceElement.ParentDeviceId)
                        {
                            //The configuration references the parent ISO element
                            depth = hierarchy.Parent.Depth;
                            order = hierarchy.Parent.Order;
                        }

                        //Read any spatially-listed widths/offsets on this data onto the DeviceElementConfiguration objects
                        hierarchy.SetWidthsAndOffsetsFromSpatialData(time, isoRecords, config, RepresentationMapper);

                        deviceElementUse = sections.FirstOrDefault(d => d.DeviceConfigurationId == config.Id.ReferenceId);
                        if (deviceElementUse == null)
                        {
                            //Create the DeviceElementUse
                            deviceElementUse                       = new DeviceElementUse();
                            deviceElementUse.Depth                 = depth;
                            deviceElementUse.Order                 = order;
                            deviceElementUse.OperationDataId       = operationDataId;
                            deviceElementUse.DeviceConfigurationId = config.Id.ReferenceId;

                            //Add Working Data for any data on this device element
                            List <WorkingData> data = _workingDataMapper.Map(time, isoRecords, deviceElementUse, hierarchy, sections, isoProductAllocations);
                            if (data.Any())
                            {
                                workingDatas.AddRange(data);
                            }
                        }
                        else
                        {
                            workingDatas = deviceElementUse.GetWorkingDatas().ToList();

                            //Add Additional Working Data
                            List <WorkingData> data = _workingDataMapper.Map(time, isoRecords, deviceElementUse, hierarchy, sections, isoProductAllocations);
                            if (data.Any())
                            {
                                workingDatas.AddRange(data);
                            }
                        }

                        deviceElementUse.GetWorkingDatas = () => workingDatas;

                        if (!sections.Contains(deviceElementUse))
                        {
                            sections.Add(deviceElementUse);
                        }
                    }
                    else if (hierarchy.DeviceElement.DeviceElementType == ISOEnumerations.ISODeviceElementType.Connector)
                    {
                        int?connectorID = TaskDataMapper.InstanceIDMap.GetADAPTID(hierarchy.DeviceElement.DeviceElementId).Value;
                        if (connectorID.HasValue)
                        {
                            Connector adaptConnector = DataModel.Catalog.Connectors.FirstOrDefault(c => c.Id.ReferenceId == connectorID.Value);
                            if (adaptConnector != null)
                            {
                                HitchPoint hitch = DataModel.Catalog.HitchPoints.FirstOrDefault(h => h.Id.ReferenceId == adaptConnector.HitchPointId);
                                if (hitch != null)
                                {
                                    hierarchy.SetHitchOffsetsFromSpatialData(time, isoRecords, hitch, RepresentationMapper);
                                }
                            }
                        }
                    }
                }
            }

            return(sections);
        }
        public static void DescribeSpatialData(Catalog catalog, LoggedData loggedData)
        {
            //Coincident Operations
            DescribeCoincidentOperations(loggedData);

            Console.WriteLine();
            Console.WriteLine("-----------------------");
            Console.WriteLine("Spatial Data");
            Console.WriteLine("-----------------------");
            Console.WriteLine();

            foreach (OperationData operationData in loggedData.OperationData)
            {
                //1.  Create some collections for tracking high-level/header information on the implement devices and sensors.
                List <WorkingData>    operationDataWorkingDatas       = new List <WorkingData>();
                Dictionary <int, int> useToDeviceConfigurationMapping = new Dictionary <int, int>();

                //ADAPT models spatial data in multiple depths according to a virtual hierarchy describing the data as it relates to the physical layout of the implement.
                //In the 2020 implementation,
                //  depth 0 refers to a single device representing the entire width of the implement and any sensors reporting data across the implement.
                //  depth 1 generally refers to row-by-row data, where multiple DeviceElements representing individual rows contain one or more sensors
                //  depth 2 is present on planting data where there are multiple varieties configured in specific parts of the implement.  In that case
                //depth 1 contains a description of the varieties
                //depth 2 contains the row-level data
                for (int depth = 0; depth <= operationData.MaxDepth; depth++)  //MaxDepth defines the maximum depth of data on an OperationData
                {
                    //A DeviceElementUse is an instance of a DeviceElement/DeviceElementConfiguration within a specific OperationData.
                    //It contains the collection of all data elements (WorkingData objects) reported on that DeviceElement during the Operation.
                    IEnumerable <DeviceElementUse> deviceElementUses = operationData.GetDeviceElementUses(depth);
                    foreach (DeviceElementUse deviceElementUse in deviceElementUses)
                    {
                        //Track the DeviceConfiguration that this DeviceElementUse relates to for reconciling data values to implement offsets for precise location
                        useToDeviceConfigurationMapping.Add(deviceElementUse.Id.ReferenceId, deviceElementUse.DeviceConfigurationId);

                        //A WorkingData is essentially a Sensor.   It is the definition of some object that will report data per spatial point.
                        //List all such sensors on this DeviceElementUse within this Operation
                        IEnumerable <WorkingData> workingDatas = deviceElementUse.GetWorkingDatas();

                        //Track these in the comprehensive list
                        operationDataWorkingDatas.AddRange(workingDatas);
                    }
                }

                //2. Illustrate any multivariety data present here.
                //If an OperationData from the 2020 plugin contains a maxdepth of 2, then level 1 describes parts of the planter with specific varieties
                if (operationData.OperationType == OperationTypeEnum.SowingAndPlanting &&
                    operationData.MaxDepth == 2)
                {
                    //------------------
                    //Split Planter data
                    //-------------------
                    Console.WriteLine($"OperationData {operationData.Id.ReferenceId} is planter data containing multiple varieties assigned to specific rows:");
                    IEnumerable <DeviceElementUse> levelOneDeviceElementUses = operationData.GetDeviceElementUses(1);
                    foreach (DeviceElementUse use in levelOneDeviceElementUses)
                    {
                        //Retrieve the DeviceElementConfiguration object that matches the DeviceElementUse on this specific operation
                        DeviceElementConfiguration deviceElementConfig = catalog.DeviceElementConfigurations.First(d => d.Id.ReferenceId == use.DeviceConfigurationId);

                        //We've named the Level 1 device elements with the varieties in this situation
                        Console.WriteLine(deviceElementConfig.Description);

                        //All rows planting that variety will be children of this device element,
                        //and the level 1 DeviceElementUse will have a WorkingData called "vrProductIndex" that will map to the variety
                    }
                    Console.WriteLine();
                }
                else if (operationData.OperationType == OperationTypeEnum.SowingAndPlanting &&
                         operationData.MaxDepth == 1 &&
                         operationDataWorkingDatas.Select(w => w.Representation.Code).Any(c => c == "vrProductIndex"))
                {
                    //------------------------------------------------------
                    //vSetSelect & mSet data (variable multi-hybrid planting)
                    //------------------------------------------------------
                    Console.WriteLine($"OperationData {operationData.Id.ReferenceId} is planter data containing multiple varieties dynamically assigned to each row.");

                    //Make a dictionary of product names
                    Dictionary <int, string> productNames = new Dictionary <int, string>();
                    foreach (int productID in operationData.ProductIds)
                    {
                        List <DeviceElementUse> productDeviceElementUses = new List <DeviceElementUse>();
                        Product product = catalog.Products.First(p => p.Id.ReferenceId == productID);
                        productNames.Add(productID, product.Description);
                    }

                    Console.WriteLine($"The following varieties are planted at various points in the field: {string.Join(", ", productNames.Values)}");

                    SpatialRecord firstPoint = operationData.GetSpatialRecords().First();
                    Console.WriteLine("For example, on the first point...");

                    //Examine the content of each DeviceElementUse at the row level with a product index working data
                    foreach (DeviceElementUse deviceElementUse in operationData.GetDeviceElementUses(1)) //1 is the row level where OperationData.MaxDepth == 1.
                    {
                        foreach (WorkingData productIndexWorkingData in deviceElementUse.GetWorkingDatas().Where(w => w.Representation.Code == "vrProductIndex"))
                        {
                            NumericRepresentationValue productValue = firstPoint.GetMeterValue(productIndexWorkingData) as NumericRepresentationValue;
                            int productIndex = (int)productValue.Value.Value;
                            DeviceElementConfiguration deviceElementConfiguration = catalog.DeviceElementConfigurations.First(d => d.Id.ReferenceId == deviceElementUse.DeviceConfigurationId);
                            Console.WriteLine($"{deviceElementConfiguration.Description} planted {productNames[productIndex]}.");
                        }
                    }

                    Console.WriteLine();
                }


                //3. Read the point-by-point data
                //With the data definition of the OperationData now in-hand, we can iterate the collection of physical points on the field to read the data.
                //Rather than writing out each data value to the screen, we will assemble them into collections to summarize after iterating all data
                Dictionary <WorkingData, List <object> > operationSpatialDataValues = new Dictionary <WorkingData, List <object> >();
                Dictionary <WorkingData, string>         numericDataUnitsOfMeasure  = new Dictionary <WorkingData, string>();

                //Similarly, we will track the geospatial envelope of the data to illustrate lat/lon data present
                double maxLat = Double.MinValue;
                double minLat = Double.MaxValue;
                double maxLon = Double.MinValue;
                double minLon = Double.MaxValue;

                Console.WriteLine("Reading point-by-point data...");
                Console.WriteLine();

                //IMPORTANT
                //To effectively manage memory usage, avoid invoking the iterator multiple times or iterate the entire list in a Linq expression.
                //The linq expressions below do not necessarily take this advice as the focus here is illustrative.
                foreach (SpatialRecord spatialRecord in operationData.GetSpatialRecords())
                {
                    //2020 data will always be in point form
                    Point point = spatialRecord.Geometry as Point;

                    //Track the lat/lon to illustrate the envelope of the dataset
                    double latitude  = point.Y;
                    double longitude = point.X;
                    if (latitude < minLat)
                    {
                        minLat = latitude;
                    }
                    if (latitude > maxLat)
                    {
                        maxLat = latitude;
                    }
                    if (longitude < minLon)
                    {
                        minLon = longitude;
                    }
                    if (longitude > maxLon)
                    {
                        maxLon = longitude;
                    }

                    //Examine the actual data on the points
                    foreach (WorkingData operationWorkingData in operationDataWorkingDatas)
                    {
                        //Create a List for data values on the first encounter with this WorkingData
                        if (!operationSpatialDataValues.ContainsKey(operationWorkingData))
                        {
                            operationSpatialDataValues.Add(operationWorkingData, new List <object>());
                        }

                        //---------------
                        //Representations
                        //---------------
                        //ADAPT publishes standard representations that often equate to ISO11783-11 Data Dictionary Identifiers (DDIs)
                        //These representations define a common type of agricultural measurement.
                        //Where Precision Planting has implemented representations that are not published with ADAPT, they are marked as UserDefined
                        //and the Name describes what each is.

                        //--------------------
                        //RepresentationValues
                        //--------------------
                        //A Representation Value is a complex type that allows the value to
                        //be augmented the full representation, the unit of measure and other data.

                        RepresentationValue representationValue = spatialRecord.GetMeterValue(operationWorkingData);

                        //Values reported may be of type Numeric or Enumerated
                        if (representationValue is NumericRepresentationValue)
                        {
                            NumericRepresentationValue numericRepresentationValue = representationValue as NumericRepresentationValue;
                            operationSpatialDataValues[operationWorkingData].Add(numericRepresentationValue.Value.Value); //Value is a double

                            //--------------------
                            //Units of Measure
                            //--------------------
                            //Store the UOM on the first encounter
                            if (!numericDataUnitsOfMeasure.ContainsKey(operationWorkingData))
                            {
                                numericDataUnitsOfMeasure.Add(operationWorkingData, numericRepresentationValue.Value.UnitOfMeasure.Code);

                                //ADAPT units of measure are documented in the Resources/UnitSystem.xml that is installed in any ADAPT project
                                //They take the form of unitCode[postive exponent]unitcode[negative exponent]
                                //Where the exponents allow for complex units.   E.g.s,
                                //lb = pounds
                                //ac = acres
                                //lb1ac-1 = pounds per acre
                                //mm3m-2 = cubic millimeters per square meter
                            }
                        }
                        else if (representationValue is EnumeratedValue)
                        {
                            EnumeratedValue enumeratedValue = representationValue as EnumeratedValue;
                            operationSpatialDataValues[operationWorkingData].Add(enumeratedValue.Value.Value); //Value is a string
                        }
                    }
                }

                Console.WriteLine();
                Console.WriteLine("-----------------------");
                Console.WriteLine($"{Enum.GetName(typeof(OperationTypeEnum), operationData.OperationType)} data");
                Console.WriteLine("-----------------------");
                Console.WriteLine();

                Console.WriteLine($"Data logged within envelope bounded by {minLat},{minLon} and {maxLat},{maxLon}.");
                Console.WriteLine();

                foreach (WorkingData workingData in operationSpatialDataValues.Keys)
                {
                    //We can obtain a reference to the part of the machine that logged the data via the DeviceConfigurationId property.
                    DeviceElementConfiguration deviceElementConfig = catalog.DeviceElementConfigurations.FirstOrDefault(d => d.Id.ReferenceId == useToDeviceConfigurationMapping[workingData.DeviceElementUseId]);
                    string deviceElementName = deviceElementConfig.Description;

                    if (operationSpatialDataValues[workingData].Any())
                    {
                        if (workingData is NumericWorkingData)
                        {
                            double max     = operationSpatialDataValues[workingData].Cast <double>().Max();
                            double average = operationSpatialDataValues[workingData].Cast <double>().Average();
                            double min     = operationSpatialDataValues[workingData].Cast <double>().Min();
                            string uom     = numericDataUnitsOfMeasure[workingData];
                            Console.WriteLine($"Numeric Working Data {deviceElementConfig.Description}-{workingData.Representation.Description} had a minimum value of {min}, and average of {average} and a maximum value of {max} {uom}.");
                            Console.WriteLine();
                        }
                        else if (workingData is EnumeratedWorkingData)
                        {
                            EnumeratedWorkingData    enumeratedWorkingData    = workingData as EnumeratedWorkingData;
                            EnumeratedRepresentation enumeratedRepresentation = enumeratedWorkingData.Representation as EnumeratedRepresentation;
                            IEnumerable <string>     enumerationValues        = enumeratedRepresentation.EnumeratedMembers.Select(e => e.Value);

                            foreach (string enumerationValue in enumerationValues)
                            {
                                int count = operationSpatialDataValues[workingData].Cast <string>().Count(v => v == enumerationValue);
                                Console.WriteLine($"Enumerated Working Data {deviceElementConfig.Description}-{workingData.Representation.Description} had {count} values of {enumerationValue}.");
                                Console.WriteLine();
                            }
                        }
                    }
                }
            }
        }
        private void UpdateCondensedWorkingDatas(List <ISOEnumeratedMeter> condensedWorkingDatas, ISODataLogValue dlv, DeviceElementUse deviceElementUse, List <DeviceElementUse> pendingDeviceElementUses, DeviceHierarchyElement isoDeviceElementHierarchy)
        {
            ISODeviceElement        isoDeviceElement   = TaskDataMapper.DeviceElementHierarchies.GetISODeviceElementFromID(dlv.DeviceElementIdRef);
            List <ISODeviceElement> isoSectionElements = isoDeviceElement.ChildDeviceElements.Where(d => d.DeviceElementType == ISOEnumerations.ISODeviceElementType.Section).ToList();

            foreach (var subElement in isoDeviceElement.ChildDeviceElements)
            {
                //This handles cases where the condensed workstate is reported on a top-level boom with sub-booms in the hierarchy above the sections (e.g., ISO 11783-10:2015(E) Figure F.35)
                isoSectionElements.AddRange(subElement.ChildDeviceElements.Where(d => d.DeviceElementType == ISOEnumerations.ISODeviceElementType.Section).ToList());
            }
            //We have some sections in the DDOP
            if (isoSectionElements.Count > 0)
            {
                //Update the DeviceElementReference on the Condensed WorkingDatas
                foreach (var workingData in condensedWorkingDatas)
                {
                    if (workingData.SectionIndex - 1 >= isoSectionElements.Count)
                    {
                        break;
                    }
                    ISODeviceElement targetSection = isoSectionElements[workingData.SectionIndex - 1];

                    DeviceElementUse condensedDeviceElementUse = FindExistingDeviceElementUseForCondensedData(targetSection, pendingDeviceElementUses);
                    if (condensedDeviceElementUse == null)
                    {
                        //Make a new DeviceElementUse
                        condensedDeviceElementUse = new DeviceElementUse();
                        condensedDeviceElementUse.OperationDataId = deviceElementUse.OperationDataId;

                        int?deviceElementID = TaskDataMapper.InstanceIDMap.GetADAPTID(targetSection.DeviceElementId);
                        if (deviceElementID.HasValue)
                        {
                            DeviceElement deviceElement = DataModel.Catalog.DeviceElements.SingleOrDefault(d => d.Id.ReferenceId == deviceElementID.Value);
                            if (deviceElement != null)
                            {
                                //Reference the device element in its hierarchy so that we can get the depth & order
                                DeviceHierarchyElement deviceElementInHierarchy = isoDeviceElementHierarchy.FromDeviceElementID(targetSection.DeviceElementId);

                                //Get the config id
                                DeviceElementConfiguration deviceElementConfig = DeviceElementMapper.GetDeviceElementConfiguration(deviceElement, deviceElementInHierarchy, DataModel.Catalog);
                                condensedDeviceElementUse.DeviceConfigurationId = deviceElementConfig.Id.ReferenceId;

                                //Set the depth & order
                                condensedDeviceElementUse.Depth = deviceElementInHierarchy.Depth;
                                condensedDeviceElementUse.Order = deviceElementInHierarchy.Order;
                            }
                        }

                        condensedDeviceElementUse.GetWorkingDatas = () => new List <WorkingData> {
                            workingData
                        };

                        workingData.DeviceElementUseId = condensedDeviceElementUse.Id.ReferenceId;

                        pendingDeviceElementUses.Add(condensedDeviceElementUse);
                    }
                    else
                    {
                        //Use the existing DeviceElementUse
                        List <WorkingData>        data = new List <WorkingData>();
                        IEnumerable <WorkingData> existingWorkingDatas = condensedDeviceElementUse.GetWorkingDatas();
                        if (existingWorkingDatas != null)
                        {
                            data.AddRange(existingWorkingDatas.ToList());  //Add the preexisting
                        }
                        data.Add(workingData);
                        condensedDeviceElementUse.GetWorkingDatas = () => data;
                    }
                }
            }
        }
Beispiel #18
0
        public List <DeviceElementUse> Map(ISOTime time,
                                           IEnumerable <ISOSpatialRow> isoRecords,
                                           int operationDataId,
                                           IEnumerable <string> isoDeviceElementIDs,
                                           Dictionary <string, List <ISOProductAllocation> > isoProductAllocations)
        {
            var sections = new List <DeviceElementUse>();

            foreach (string isoDeviceElementID in isoDeviceElementIDs)
            {
                DeviceHierarchyElement hierarchyElement = TaskDataMapper.DeviceElementHierarchies.GetMatchingElement(isoDeviceElementID);
                if (hierarchyElement != null)
                {
                    DeviceElementUse   deviceElementUse = null;
                    List <WorkingData> workingDatas     = new List <WorkingData>();

                    //Get the relevant DeviceElementConfiguration
                    int           adaptDeviceElementId = TaskDataMapper.InstanceIDMap.GetADAPTID(isoDeviceElementID).Value;
                    DeviceElement adaptDeviceElement   = DataModel.Catalog.DeviceElements.SingleOrDefault(d => d.Id.ReferenceId == adaptDeviceElementId);
                    if (adaptDeviceElement != null)
                    {
                        DeviceElementConfiguration config = DeviceElementMapper.GetDeviceElementConfiguration(adaptDeviceElement, hierarchyElement, DataModel.Catalog);

                        int depth = hierarchyElement.Depth;
                        int order = hierarchyElement.Order;
                        if (config.DeviceElementId == adaptDeviceElement.ParentDeviceId)
                        {
                            //The configuration references the parent ISO element
                            depth = hierarchyElement.Parent.Depth;
                            order = hierarchyElement.Parent.Order;
                        }

                        deviceElementUse = sections.FirstOrDefault(d => d.DeviceConfigurationId == config.Id.ReferenceId);
                        if (deviceElementUse == null)
                        {
                            //Create the DeviceElementUse
                            deviceElementUse                       = new DeviceElementUse();
                            deviceElementUse.Depth                 = depth;
                            deviceElementUse.Order                 = order;
                            deviceElementUse.OperationDataId       = operationDataId;
                            deviceElementUse.DeviceConfigurationId = config.Id.ReferenceId;

                            //Add Working Data for any data on this device element
                            List <WorkingData> data = _workingDataMapper.Map(time, isoRecords, deviceElementUse, hierarchyElement, sections, isoProductAllocations);
                            if (data.Any())
                            {
                                workingDatas.AddRange(data);
                            }
                        }
                        else
                        {
                            workingDatas = deviceElementUse.GetWorkingDatas().ToList();

                            //Add Additional Working Data
                            List <WorkingData> data = _workingDataMapper.Map(time, isoRecords, deviceElementUse, hierarchyElement, sections, isoProductAllocations);
                            if (data.Any())
                            {
                                workingDatas.AddRange(data);
                            }
                        }

                        deviceElementUse.GetWorkingDatas = () => workingDatas;

                        if (!sections.Contains(deviceElementUse))
                        {
                            sections.Add(deviceElementUse);
                        }
                    }
                }
            }

            return(sections);
        }
        public static void DescribeImplement(Catalog catalog, LoggedData loggedData)
        {
            Console.WriteLine();
            Console.WriteLine("-----------------------");
            Console.WriteLine("Equipment Configuration");
            Console.WriteLine("-----------------------");
            Console.WriteLine();


            //A LoggedData will have a single EquipmentConfigurationGroup that contains any EquipmentConfigurations in the file
            EquipmentConfigurationGroup equipConfigGroup = loggedData.EquipmentConfigurationGroup;

            //The configuration of the equipment can vary by each region, although it is likely that the equipment configuration remains consistent across many regions
            //Any distinct configurations represented in the field operation will be EquipmentConfigurations within this group
            List <EquipmentConfiguration> distinctConfigurations = equipConfigGroup.EquipmentConfigurations;

            Console.WriteLine($"Field operation has {distinctConfigurations.Count} distinct equipment configuration(s).");
            Console.WriteLine();

            //While a single OperationData object supports a list of EquipmentConfigurations, the 2020 plugin will always reference a single EquipmentConfiguration on any one OperationData.
            //This allows the consumer to predictively map data based a known equipment definition for that data.

            //Going deeper on the first OperationData
            Console.WriteLine("The first region and OperationData within the field operation has this configuration:");
            EquipmentConfiguration equipConfig = distinctConfigurations.SingleOrDefault(c => c.Id.ReferenceId == loggedData.OperationData.First().EquipmentConfigurationIds.Single());

            //The equipment configuration maps to 2 connectors, explaining what machinery was hitched together
            Connector connector1 = catalog.Connectors.SingleOrDefault(c => c.Id.ReferenceId == equipConfig.Connector1Id);
            Connector connector2 = catalog.Connectors.SingleOrDefault(c => c.Id.ReferenceId == equipConfig.Connector2Id);

            //Each connector contains two pieces of information, the DeviceElementConfiguration that connector/hitch is a part of, and metadata on a specific hitch point.
            DeviceElementConfiguration deviceElementConfiguration1 = catalog.DeviceElementConfigurations.SingleOrDefault(c => c.Id.ReferenceId == connector1.DeviceElementConfigurationId);
            HitchPoint hitchPoint1 = catalog.HitchPoints.SingleOrDefault(h => h.Id.ReferenceId == connector1.HitchPointId);

            DeviceElementConfiguration deviceElementConfiguration2 = catalog.DeviceElementConfigurations.SingleOrDefault(c => c.Id.ReferenceId == connector2.DeviceElementConfigurationId);
            HitchPoint hitchPoint2 = catalog.HitchPoints.SingleOrDefault(h => h.Id.ReferenceId == connector2.HitchPointId);

            //DeviceElementConfigurations are a polymorphic object within ADAPT.
            //A DeviceElementConfiguration may be of type
            //  MachineConfiguration (describing a tractor/vehicle)
            //  ImplementConfiguration (describing an entire implement)
            //  SectionConfiguration (describing a subsection or individual row of an implement)

            //DeviceElementConfigurations are part of a 3-object hierarchy that describes a piece of equipment
            //1. DeviceModel - A high-level description of the equipment: brand, manufacturer, description.   Any single piece of equipment has only 1 device model.
            //2. DeviceElement -A hierarchical descripion part of the equipment: brand, manufacturer, description, and type of element (section, machine, implement, etc.).
            //                  A DeviceElement maps to a single DeviceModel, and may be a parent and/or child of other DeviceElements.
            //                  E.g., each section is a child of the root implement DeviceElement
            //3. DeviceElementConfigurations - The DeviceElementConfiguration is an extension of the DeviceElement, each mapping to a single DeviceElement,
            //                                  but having specific phyproperties such as width and offsets.

            //The 2020 equipment configuration will always have a Machine/Vehicle as the Connector1 and an Implement as the Connector2.
            MachineConfiguration   vehicleConfiguration   = deviceElementConfiguration1 as MachineConfiguration;
            ImplementConfiguration implementConfiguration = deviceElementConfiguration2 as ImplementConfiguration;

            HitchPoint vehicleHitch   = hitchPoint1;
            HitchPoint implementHitch = hitchPoint2;

            //The DeviceElements expose the hierarchy between parts of the equipment
            Console.WriteLine();
            Console.WriteLine("Vehicle DeviceElement Hierarchy:");
            DeviceElement vehicleDeviceElement = catalog.DeviceElements.SingleOrDefault(d => d.Id.ReferenceId == vehicleConfiguration.DeviceElementId);

            DescribeDeviceHierarchy(catalog, vehicleDeviceElement, 0, new List <DeviceElement>());

            Console.WriteLine();
            Console.WriteLine("Implement DeviceElement Hierarchy:");
            List <DeviceElement> implementChildElements = new List <DeviceElement>();
            DeviceElement        implementDeviceElement = catalog.DeviceElements.SingleOrDefault(d => d.Id.ReferenceId == implementConfiguration.DeviceElementId);

            DescribeDeviceHierarchy(catalog, implementDeviceElement, 0, implementChildElements);

            Console.WriteLine();


            Console.WriteLine();
            Console.WriteLine("-----------------------");
            Console.WriteLine("Implement Width Values");
            Console.WriteLine("-----------------------");
            Console.WriteLine();

            //The Implement and Section DeviceElementConfigurations carry width information.
            Console.WriteLine($"The {implementConfiguration.Description} is {implementConfiguration.PhysicalWidth.Value.Value} {implementConfiguration.PhysicalWidth.Value.UnitOfMeasure.Code} wide.");
            foreach (DeviceElement childElement in implementChildElements)
            {
                DeviceElementConfiguration deviceElementConfiguration = catalog.DeviceElementConfigurations.SingleOrDefault(c => c.DeviceElementId == childElement.Id.ReferenceId);
                if (deviceElementConfiguration != null)
                {
                    SectionConfiguration sectionConfiguration = deviceElementConfiguration as SectionConfiguration;
                    if (sectionConfiguration != null)
                    {
                        Console.WriteLine($"{sectionConfiguration.Description} is {sectionConfiguration.SectionWidth.Value.Value} {sectionConfiguration.SectionWidth.Value.UnitOfMeasure.Code} wide.");
                    }
                }
            }


            Console.WriteLine();
            Console.WriteLine("-----------------------");
            Console.WriteLine("Equipment Offset Values");
            Console.WriteLine("-----------------------");
            Console.WriteLine();

            //Various offset values describe where each device element is located vs. other elements via data on the device element configuration

            //Vehicle GPS Receiver
            DescribeOffset("GPS Receiver", vehicleConfiguration.GpsReceiverXOffset, vehicleConfiguration.GpsReceiverYOffset, "tractor reference point (center of rear axle)");

            //Tractor hitch offset
            DescribeOffset("vehicle hitch point", vehicleHitch.ReferencePoint.XOffset, vehicleHitch.ReferencePoint.YOffset, "tractor reference point (center of rear axle)");

            //Implement hitch offset
            DescribeOffset("implement hitch point", implementHitch.ReferencePoint.XOffset, implementHitch.ReferencePoint.YOffset, "implement reference point (center of implement)");

            //Implmement control point offset (inverse of the prior)
            DescribeOffset("implement control point offset", implementConfiguration.ControlPoint.XOffset, implementConfiguration.ControlPoint.YOffset, "tractor hitch point");

            //Section offsets (measured to center of each section)
            foreach (DeviceElement childElement in implementChildElements)
            {
                DeviceElementConfiguration deviceElementConfiguration = catalog.DeviceElementConfigurations.SingleOrDefault(c => c.DeviceElementId == childElement.Id.ReferenceId);
                if (deviceElementConfiguration != null)
                {
                    SectionConfiguration sectionConfiguration = deviceElementConfiguration as SectionConfiguration;
                    if (sectionConfiguration != null)
                    {
                        DescribeOffset($"{childElement.Description} offset", sectionConfiguration.InlineOffset, sectionConfiguration.LateralOffset, "tractor hitch point");
                    }
                }
            }
        }