// Process instance table after receiving Sample Data
        private List <Instance> ProcessInstances(MTConnectStreams.Document currentData, MTConnectStreams.Document sampleData)
        {
            var stpw = new System.Diagnostics.Stopwatch();

            stpw.Start();

            var result = new List <Instance>();

            Instance previousData = previousInstanceDataOld;

            if (currentData != null && sampleData != null)
            {
                if (sampleData.DeviceStreams != null && currentData.DeviceStreams != null)
                {
                    // Get all of the DataItems from the DeviceStream object
                    var dataItems = sampleData.DeviceStreams[0].DataItems;

                    // Convert the DataItems to a List of VariableData objects
                    List <VariableData> values = VariableData.Get(dataItems);

                    // Get List of Distinct Timestamps
                    IEnumerable <DateTime> timestamps = values.Select(x => x.Timestamp).Distinct();

                    // Sort timestamps by DateTime ASC
                    List <DateTime> sortedTimestamps = timestamps.ToList();
                    sortedTimestamps.Sort();

                    // Get List of Variables used
                    IEnumerable <string> usedVariables = values.Select(x => x.Id).Distinct();

                    var currentDataItems = currentData.DeviceStreams[0].DataItems;

                    foreach (DateTime timestamp in sortedTimestamps.ToList())
                    {
                        if (previousData == null || timestamp > previousData.Timestamp)
                        {
                            var data = new Instance();

                            // Preset previous values into new InstanceData object
                            if (previousData != null)
                            {
                                data = previousData;
                            }
                            // Fill unused variables with the values from the CurrentData object
                            else
                            {
                                FillInstanceDataWithCurrentData(usedVariables.ToList(), data, currentDataItems);
                            }

                            // Set timestamp for InstanceData object
                            data.Timestamp = timestamp;

                            data.AgentInstanceId = currentData.Header.InstanceId;

                            // Get List of Values at this timestamp
                            var valuesAtTimestamp = values.FindAll(x => x.Timestamp == timestamp);

                            foreach (var ivd in valuesAtTimestamp)
                            {
                                Instance.DataItemValue oldval = data.Values.Find(x => x.Id == ivd.Id);
                                // if value with id is already in data.values then overwrite the value
                                if (oldval != null)
                                {
                                    string s = null;
                                    if (ivd.Value != null)
                                    {
                                        s = ivd.Value.ToString();
                                    }

                                    oldval.Value           = s;
                                    oldval.ChangedSequence = ivd.Sequence;
                                }
                                // if not already in data.values then create new InstanceData.Value object and add it
                                else
                                {
                                    var newval = new Instance.DataItemValue();
                                    newval.Id              = ivd.Id;
                                    newval.Type            = ivd.Type;
                                    newval.SubType         = ivd.SubType;
                                    newval.ChangedSequence = ivd.Sequence;

                                    if (ivd.Value != null)
                                    {
                                        newval.Value = ivd.Value.ToString();
                                    }
                                    data.Values.Add(newval);
                                }

                                data.Sequence = ivd.Sequence;
                            }

                            previousData = data.Copy();

                            result.Add(data);
                        }
                    }
                }
            }
            else if (currentData != null)
            {
                Instance instanceData = ProcessInstance(currentData);

                if (previousData == null || instanceData.Timestamp > previousData.Timestamp)
                {
                    result.Add(instanceData);

                    previousData = instanceData.Copy();
                }
            }

            previousInstanceDataNew = previousData;

            return(result);
        }
        public static List<VariableData> Get(List<MTConnect.Application.Streams.DataItem> dataItems)
        {
            var result = new List<VariableData>();

            foreach (var item in dataItems)
            {
                var data = new VariableData();
                data.Id = item.DataItemId;

                data.Type = item.Type;
                data.SubType = item.SubType;

                if (item.Category == MTConnect.DataItemCategory.CONDITION)
                {
                    data.Value = ((MTConnect.Application.Streams.Condition)item).ConditionValue.ToString();
                }
                else data.Value = item.CDATA;

                data.Timestamp = item.Timestamp;
                data.Sequence = item.Sequence;

                result.Add(data);
            }

            // Sort List by timestamp ASC
            result.Sort((x, y) => x.Timestamp.Second.CompareTo(y.Timestamp.Second));

            return result;
        }