private void StreamsDocumentReceived(MTConnectStreams.Document document) { log.Trace("MTConnect Streams Document Received @ " + DateTime.Now.ToString("o")); UpdateConnectedStatus(true); if (!document.DeviceStreams.IsNullOrEmpty()) { var samples = new List <TrakHound.Api.v2.Data.Sample>(); var deviceStream = document.DeviceStreams[0]; foreach (var dataItem in deviceStream.DataItems) { samples.Add(Create(_deviceId, document.Header.InstanceId, dataItem)); } // Get Availability if (!string.IsNullOrEmpty(availabilityId)) { var avail = deviceStream.DataItems.Find(o => o.DataItemId == availabilityId); if (avail != null) { UpdateAvailableStatus(avail.CDATA == "AVAILABLE"); } } if (samples.Count > 0) { SamplesReceived?.Invoke(this, samples); } } }
private void Client_CurrentReceived(MTConnectStreams.Document document) { if (document == null || document.DeviceStreams == null || document.DeviceStreams.Count < 1) { return; } foreach (MTConnectStreams.DeviceStream ds in document.DeviceStreams) { // 通过对 Name 的调整(去掉 di,ev,sp, cd)进行验证后,发现 DataItems 中包含了 Event 、 Samples、Conditions // ComponentStreams 比较杂,好像什么都包含,就不在这里验证了。 // 因此在这里只保留了对 DataItems 的读取。 string namePrefix = ds.Uuid + ":" + ds.Name + ":"; if (ds.DataItems != null && ds.DataItems.Count > 0) { foreach (MTConnect.MTConnectStreams.DataItem di in ds.DataItems) { try { SimpleHttpHelper.GetInstance() //.RequestURL("http://127.0.0.1:15031/monitor/data_pack/put", //.RequestURL("http://192.168.123.248:15031/monitor/data_pack/put", .RequestURL(MonitorAddress, "p=" + ds.Name + "&n=" + di.Name + "&v=" + di.CDATA); } catch (Exception ex) { logger.Warn(ex.Message, ex); } } } } }
private static DateTime GetTimestampFromCurrent(Value value, MTConnectStreams.Document currentData) { var result = DateTime.MinValue; var dataItems = currentData.DeviceStreams[0].DataItems; foreach (var trigger in value.Triggers) { var timestamp = GetTimestampFromTrigger(trigger, dataItems); if (timestamp > result) { result = timestamp; } } foreach (var multitrigger in value.MultiTriggers) { foreach (var trigger in multitrigger.Triggers) { var timestamp = GetTimestampFromTrigger(trigger, dataItems); if (timestamp > result) { result = timestamp; } } } return(result); }
private static bool ProcessCollected(Snapshot snapshot, MTConnectStreams.Document currentData) { bool result = false; if (currentData.DeviceStreams != null) { var dataItems = currentData.DeviceStreams[0].DataItems; bool found = false; // Seach Conditions found = ProcessCollectedCondtion(snapshot, dataItems); // Search Events if (!found) { found = ProcessCollectedEvent(snapshot, dataItems); } // Search Samples if (!found) { found = ProcessCollectedSample(snapshot, dataItems); } result = found; } return(result); }
public void Update_Sample(MTConnectStreams.Document returnData) { List <Instance> instances = ProcessInstances(currentData, returnData); bufferedInstances.AddRange(instances); previousInstanceDataOld = previousInstanceDataNew; }
void StreamsSuccessful(MTConnectStreams.Document document) { foreach (var deviceStream in document.DeviceStreams) { foreach (var dataItem in deviceStream.DataItems) { Console.WriteLine(dataItem.DataItemId + " = " + dataItem.CDATA); } } }
private void SendSampleData(MTConnectStreams.Document returnData, DeviceConfiguration config) { var data = new EventData(this); data.Id = "MTCONNECT_SAMPLE"; data.Data01 = config; data.Data02 = returnData; SendData?.Invoke(data); }
private void dispatcherTimer_Tick(object sender, EventArgs e) { MTConnectStreams.Document Newcurrent = null; //make sure "current" has data document to avoid error while (Newcurrent == null) { Newcurrent = now.Execute(); } //give new Current Data to current-variable current = Newcurrent; //get new Axis Data, A,C-Angle and X,Y,Z-Position var NewRotaryA = current.DeviceStreams[0].DataItems.Find(o => o.DataItemId == "GFAgie01-A_2").CDATA; var NewRotaryC = current.DeviceStreams[0].DataItems.Find(o => o.DataItemId == "GFAgie01-C_2").CDATA; var NewLinearX = current.DeviceStreams[0].DataItems.Find(o => o.DataItemId == "GFAgie01-X_2").CDATA; var NewLinearY = current.DeviceStreams[0].DataItems.Find(o => o.DataItemId == "GFAgie01-Y_2").CDATA; var NewLinearZ = current.DeviceStreams[0].DataItems.Find(o => o.DataItemId == "GFAgie01-Z_2").CDATA; //Set new current data to _current and it will fire the OnPropertyChanged Event, so update the UI _current = current; //compare the New Data with older one, when new data is larger, it will replace the old data //and it will fire the OnPropertyChanged Event, so update the UI //New Data shouldn't equal to UNAVAILABLE when executing compare function if (Math.Abs(double.Parse(NewRotaryA)) > Math.Abs(double.Parse(_maxRotaryA[0])) && NewRotaryA != "UNAVAILABLE") { _maxRotaryA[0] = NewRotaryA; } if (Math.Abs(double.Parse(NewRotaryC)) > Math.Abs(double.Parse(_maxRotaryC[0])) && NewRotaryC != "UNAVAILABLE") { _maxRotaryC[0] = NewRotaryC; } if (Math.Abs(double.Parse(NewLinearX)) > Math.Abs(double.Parse(_maxLinearX[0])) && NewLinearX != "UNAVAILABLE") { _maxLinearX[0] = NewLinearX; } if (Math.Abs(double.Parse(NewLinearY)) > Math.Abs(double.Parse(_maxLinearY[0])) && NewLinearY != "UNAVAILABLE") { _maxLinearY[0] = NewLinearY; } if (Math.Abs(double.Parse(NewLinearZ)) > Math.Abs(double.Parse(_maxLinearZ[0])) && NewLinearZ != "UNAVAILABLE") { _maxLinearZ[0] = NewLinearZ; } //Add new data as XML data from path AddXmlData(_current, path); //read data from XML and show to UI ReadXML(path); }
private MTConnectStreams.Document GetCurrent(Data.AgentInfo config) { MTConnectStreams.Document result = null; string address = config.Address; int port = config.Port; string deviceName = config.DeviceName; //// Set Proxy Settings //var proxy = new HTTP.ProxySettings(); //proxy.Address = config.ProxyAddress; //proxy.Port = config.ProxyPort; DateTime requestTimestamp = DateTime.Now; // Create Agent Url var protocol = "http://"; var adr = address; if (adr.IndexOf(protocol) >= 0) { adr = adr.Substring(protocol.Length); } else { adr = protocol + adr; } var url = adr; if (port > 0 && port != 80) { url += ":" + port; } // Send Probe Request var current = new MTConnect.Clients.Current(url, deviceName); result = current.Execute(); if (result != null) { if (verbose) { logger.Info("Current Successful : " + url + " @ " + requestTimestamp.ToString("o") + " : " + result.Header.LastSequence); } } else { logger.Info("Current Error : " + url + " @ " + requestTimestamp.ToString("o") + " : Retrying in " + (config.Heartbeat / 1000) + " sec.."); } return(result); }
// Process InstanceData after receiving Current Data public static Instance ProcessInstance(MTConnectStreams.Document currentData) { var result = new Instance();; result.Timestamp = currentData.Header.CreationTime; // Agent.MTConnect.org only outputs to the nearest second (not fractional seconds), check if issue with Open Source Agent result.AgentInstanceId = currentData.Header.InstanceId; result.Sequence = currentData.Header.LastSequence; var dataItems = currentData.DeviceStreams[0].DataItems; FillInstanceDataWithCurrentData(new List <string>(), result, dataItems); return(result); }
private void RunRequests(DeviceConfiguration config) { var ac = config.Agent; if (ac != null) { // Run a Probe request and get the returned data if (probeData == null) { probeData = GetProbe(ac); // Send the Probe data to other plugins SendProbeData(probeData, config); } if (probeData != null) { // Run a Current request and get the returned data currentData = GetCurrent(ac); if (currentData != null && currentData.Header != null) { // Send the Current data to other plugins SendCurrentData(currentData, config); //Run a Sample request and get the returned data var sampleData = GetSample(currentData.Header, ac, config); //Send the Sample data to other plugins if (sampleData != null) { SendSampleData(sampleData, config); } UpdateAgentData(currentData.Header.InstanceId, currentData.Header.LastSequence); } else { probeData = null; SendAvailability(false, ac.Heartbeat, config); } } else { SendAvailability(false, ac.Heartbeat, config); } } }
public static void ProcessList(MTConnectStreams.Document current, List <StatusInfo> infos) { if (current.DeviceStreams != null && current.DeviceStreams.Count > 0) { var device = current.DeviceStreams[0]; foreach (var item in device.DataItems) { ProcessDataItem(item, infos); } foreach (var componentStream in device.ComponentStreams) { ProcessComponentStream(componentStream, infos); } } }
private static List <string> GetDataItemIds(MTConnectStreams.Document returnData) { var result = new List <string>(); var dataItems = returnData.DeviceStreams[0].DataItems; // Conditions ------------------------------------------------------------------------- foreach (var dataItem in dataItems.FindAll(x => x.Category == MTConnect.DataItemCategory.CONDITION)) { string name = dataItem.DataItemId.ToUpper(); if (!result.Contains(name)) { result.Add(name); } } // ------------------------------------------------------------------------------------ // Events ----------------------------------------------------------------------------- foreach (var dataItem in dataItems.FindAll(x => x.Category == MTConnect.DataItemCategory.EVENT)) { string name = dataItem.DataItemId.ToUpper(); if (!result.Contains(name)) { result.Add(name); } } // ------------------------------------------------------------------------------------ // Samples ---------------------------------------------------------------------------- foreach (var dataItem in dataItems.FindAll(x => x.Category == MTConnect.DataItemCategory.SAMPLE)) { string name = dataItem.DataItemId.ToUpper(); if (!result.Contains(name)) { result.Add(name); } } // ------------------------------------------------------------------------------------ return(result); }
public void Update_Current(MTConnectStreams.Document returnData) { currentData = returnData; Instance instance = ProcessInstance(returnData); previousInstanceDataOld = previousInstanceDataNew; var cid = new CurrentInstance(); cid.CurrentData = returnData; cid.Instance = instance; var instances = new List <Instance>(); if (bufferedInstances != null && bufferedInstances.Count > 0) { instances.AddRange(bufferedInstances); } // Only return new instances instances = instances.FindAll(o => o.Timestamp > lastTimestamp); // Sort instances ASC by timestamp instances = instances.OrderBy(o => o.Timestamp).ToList(); // update lastTimestamp if (instances.Count > 0) { lastTimestamp = instances[instances.Count - 1].Timestamp; } // Clear the send buffer bufferedInstances.Clear(); bufferedInstances.Add(instance); SendCurrentInstanceData(configuration, cid); SendInstanceData(configuration, instances); }
private MTConnectStreams.Document GetSample(MTConnect.Headers.MTConnectStreamsHeader header, Data.AgentInfo ac, DeviceConfiguration config) { MTConnectStreams.Document result = null; string address = ac.Address; int port = ac.Port; string deviceName = ac.DeviceName; //// Set Proxy Settings //var proxy = new HTTP.ProxySettings(); //proxy.Address = ac.ProxyAddress; //proxy.Port = ac.ProxyPort; SampleInfo info = GetSampleInfo(header, config); if (info != null) { if (info.Count > 0) { DateTime requestTimestamp = DateTime.Now; // Create Agent Url var protocol = "http://"; var adr = address; if (adr.IndexOf(protocol) >= 0) { adr = adr.Substring(protocol.Length); } else { adr = protocol + adr; } var url = adr; if (port > 0 && port != 80) { url += ":" + port; } // Send Probe Request var sample = new MTConnect.Clients.Sample(url, deviceName); sample.From = info.From; sample.Count = info.Count; result = sample.Execute(); if (result != null) { UpdateAgentData(header.InstanceId, info.From + info.Count); if (verbose) { logger.Info("Sample Successful : " + url + " @ " + requestTimestamp.ToString("o")); } } else { logger.Info("Sample Error : " + url + " @ " + requestTimestamp.ToString("o")); } } else { UpdateAgentData(header.InstanceId, header.LastSequence); } } return(result); }
/// <summary> /// it setup the MTConnectClient and get data from CurrentStream /// it also setup the timer, for data update and add XML data /// </summary> public void Start() { // The base address for the MTConnect Agent string baseUrl = "https://smstestbed.nist.gov/vds/"; // Create a new MTConnectClient using the baseUrl client = new MTConnectClient(baseUrl); // Subscribe to the Event handlers to receive the MTConnect documents client.ProbeReceived += DevicesSuccessful; client.CurrentReceived += StreamsSuccessful; client.SampleReceived += StreamsSuccessful; // Start the MTConnectClient client.Start(); now = new Current(baseUrl); //make sure _current has data document to avoid the error from finding DataItems. while (current == null) { current = now.Execute(); } //set the first data, which can be showed to UI and later compared with new data. RotaryA[0] = current.DeviceStreams[0].DataItems.Find(o => o.DataItemId == "GFAgie01-A_2").CDATA; _maxRotaryA[0] = current.DeviceStreams[0].DataItems.Find(o => o.DataItemId == "GFAgie01-A_2").CDATA; RotaryC[0] = current.DeviceStreams[0].DataItems.Find(o => o.DataItemId == "GFAgie01-C_2").CDATA; _maxRotaryC[0] = current.DeviceStreams[0].DataItems.Find(o => o.DataItemId == "GFAgie01-C_2").CDATA; LinearX[0] = current.DeviceStreams[0].DataItems.Find(o => o.DataItemId == "GFAgie01-X_2").CDATA; _maxLinearX[0] = current.DeviceStreams[0].DataItems.Find(o => o.DataItemId == "GFAgie01-X_2").CDATA; LinearY[0] = current.DeviceStreams[0].DataItems.Find(o => o.DataItemId == "GFAgie01-Y_2").CDATA; _maxLinearY[0] = current.DeviceStreams[0].DataItems.Find(o => o.DataItemId == "GFAgie01-Y_2").CDATA; LinearZ[0] = current.DeviceStreams[0].DataItems.Find(o => o.DataItemId == "GFAgie01-Z_2").CDATA; _maxLinearZ[0] = current.DeviceStreams[0].DataItems.Find(o => o.DataItemId == "GFAgie01-Z_2").CDATA; //for the simulated device , set the first data Avail[0] = FirstDevice .Element("DeviceStream") .Elements("Events") .Where(x => x.Attribute("name").Value == "Availability").Descendants().ElementAt(_indexXml).Value; RotaryA[1] = FirstDevice .Element("DeviceStream") .Elements("ComponentStream") .Where(x => x.Attribute("name").Value == "Rotary(A)").Descendants().ElementAt(_indexXml).Value; _maxRotaryA[1] = FirstDevice .Element("DeviceStream") .Elements("ComponentStream") .Where(x => x.Attribute("name").Value == "Rotary(A)").Descendants().ElementAt(_indexXml).Value; RotaryC[1] = FirstDevice .Element("DeviceStream") .Elements("ComponentStream") .Where(x => x.Attribute("name").Value == "Rotary(C)").Descendants().ElementAt(_indexXml).Value; _maxRotaryC[1] = FirstDevice .Element("DeviceStream") .Elements("ComponentStream") .Where(x => x.Attribute("name").Value == "Rotary(C)").Descendants().ElementAt(_indexXml).Value; LinearX[1] = FirstDevice .Element("DeviceStream") .Elements("ComponentStream") .Where(x => x.Attribute("name").Value == "Linear(X)").Descendants().ElementAt(_indexXml).Value; LinearY[1] = FirstDevice .Element("DeviceStream") .Elements("ComponentStream") .Where(x => x.Attribute("name").Value == "Linear(Y)").Descendants().ElementAt(_indexXml).Value; LinearZ[1] = FirstDevice .Element("DeviceStream") .Elements("ComponentStream") .Where(x => x.Attribute("name").Value == "Linear(Z)").Descendants().ElementAt(_indexXml).Value; _maxLinearX[1] = FirstDevice .Element("DeviceStream") .Elements("ComponentStream") .Where(x => x.Attribute("name").Value == "Linear(X)").Descendants().ElementAt(_indexXml).Value; _maxLinearY[1] = FirstDevice .Element("DeviceStream") .Elements("ComponentStream") .Where(x => x.Attribute("name").Value == "Linear(Y)").Descendants().ElementAt(_indexXml).Value; _maxLinearZ[1] = FirstDevice .Element("DeviceStream") .Elements("ComponentStream") .Where(x => x.Attribute("name").Value == "Linear(Z)").Descendants().ElementAt(_indexXml).Value; //set the first data as Maximum Data, bound to UI //_maxRotaryA = RotaryA; //_maxRotaryC = RotaryC; //_maxLinearX = LinearX; //_maxLinearY = LinearY; //_maxLinearZ = LinearZ; //for simulated device, bound to UI _Avail = Avail; //request new data by 3 sec by using DispatcherTimer //it will update the current data //it contains functions, which will set the Maximum Date //it will add the newest data to XML-data DispatcherTimer dispatcherTimer = new DispatcherTimer(); dispatcherTimer.Tick += new EventHandler(dispatcherTimer_Tick); dispatcherTimer.Interval = new TimeSpan(0, 0, 3); dispatcherTimer.Start(); }
/// <summary> /// Add new XML data to the existed XML-Schema /// </summary> /// <param name="document">it contains the newest data</param> /// <param name="Xmlpath">the position where XML Data will be saved</param> public void AddXmlData(MTConnectStreams.Document document, string Xmlpath) { //find and save DataItem from document as variable var avail = document.DeviceStreams[0].DataItems.Find(o => o.DataItemId == "GFAgie01-dtop_1"); var RotaryA = document.DeviceStreams[0].DataItems.Find(o => o.DataItemId == "GFAgie01-A_2"); var RotaryC = document.DeviceStreams[0].DataItems.Find(o => o.DataItemId == "GFAgie01-C_2"); var LinearX = document.DeviceStreams[0].DataItems.Find(o => o.DataItemId == "GFAgie01-X_2"); var LinearY = document.DeviceStreams[0].DataItems.Find(o => o.DataItemId == "GFAgie01-Y_2"); var LinearZ = document.DeviceStreams[0].DataItems.Find(o => o.DataItemId == "GFAgie01-Z_2"); //Load XML datai from path XDocument XmlData = XDocument.Load(Xmlpath); //Add "Availability" Live Data in XML-Schema XmlData.Element("DeviceStream") .Elements("Events") .Where(x => x.Attribute("name").Value == "Availability").LastOrDefault() .Add( new XElement("Availability", new XAttribute("timestamp", avail.Timestamp), new XAttribute("name", avail.Name), avail.CDATA)); //Add "Angle(A)" Live Data in XML-Schema XmlData.Element("DeviceStream") .Elements("ComponentStream") .Where(x => x.Attribute("name").Value == "Rotary(A)").LastOrDefault() .Add( new XElement("Angle", new XAttribute("timestamp", RotaryA.Timestamp), new XAttribute("name", RotaryA.Name), RotaryA.CDATA)); //Add "Angle(C)" Live Data in XML-Schema XmlData.Element("DeviceStream") .Elements("ComponentStream") .Where(x => x.Attribute("name").Value == "Rotary(C)").LastOrDefault() .Add( new XElement("Angle", new XAttribute("timestamp", RotaryC.Timestamp), new XAttribute("name", RotaryC.Name), RotaryC.CDATA)); //Add "Position(X)" Live Data in XML-Schema XmlData.Element("DeviceStream") .Elements("ComponentStream") .Where(x => x.Attribute("name").Value == "Linear(X)").LastOrDefault() .Add( new XElement("Position", new XAttribute("timestamp", LinearX.Timestamp), new XAttribute("name", LinearX.Name), LinearX.CDATA)); //Add "Position(Y)" Live Data in XML-Schema XmlData.Element("DeviceStream") .Elements("ComponentStream") .Where(x => x.Attribute("name").Value == "Linear(Y)").LastOrDefault() .Add( new XElement("Position", new XAttribute("timestamp", LinearY.Timestamp), new XAttribute("name", LinearY.Name), LinearY.CDATA)); //Add "Position(Z)" Live Data in XML-Schema XmlData.Element("DeviceStream") .Elements("ComponentStream") .Where(x => x.Attribute("name").Value == "Linear(Z)").LastOrDefault() .Add( new XElement("Position", new XAttribute("timestamp", LinearZ.Timestamp), new XAttribute("name", LinearZ.Name), LinearZ.CDATA)); //save XML data to XML path XmlData.Save(Xmlpath); }
private void Client_CurrentReceived(MTConnectStreams.Document document) { if (document == null || document.DeviceStreams == null || document.DeviceStreams.Count < 1) { return; } LinkedList <Poco> pocos = new LinkedList <Poco>(); foreach (MTConnectStreams.DeviceStream ds in document.DeviceStreams) { // 通过对 Name 的调整(去掉 di,ev,sp, cd)进行验证后,发现 DataItems 中包含了 Event 、 Samples、Conditions // ComponentStreams 比较杂,好像什么都包含,就不在这里验证了。 // 因此在这里只保留了对 DataItems 的读取。 string namePrefix = ds.Uuid + ":" + ds.Name + ":"; if (ds.DataItems != null && ds.DataItems.Count > 0) { foreach (MTConnect.MTConnectStreams.DataItem di in ds.DataItems) { pocos.AddLast(new Poco() { Device = namePrefix, Category = di.Category.ToString(), Sequence = di.Sequence.ToString(), SubType = di.SubType, DataItemId = di.DataItemId, Name = di.Name, Timestamp = di.Timestamp.ToString("yyyy-MM-dd HH:mm:ss:fff"), Value = di.CDATA }); PushToMonitorService ptms = PushToMonitorService.getInstance(); if (ptms != null) { ptms.push(di.DataItemId + "_" + di.Name, di.Timestamp, di.CDATA); } } } // 经验证,这个节点特别像他的父节点,什么都包含。 //if (ds.ComponentStreams != null && ds.ComponentStreams.Count > 0) //{ // foreach (MTConnect.MTConnectStreams.ComponentStream cs in ds.ComponentStreams) // { // pocos.AddLast(new Poco() // { // Name = namePrefix + cs.ComponentId + ":" + cs.Name + "-cs", // Timestamp = cs.Samples .Timestamp.ToString("yyyy-MM-dd HH:mm:ss"), // Value = di.CDATA // }); // } //} //if (ds.Samples != null && ds.Samples.Count > 0) //{ // foreach (MTConnectStreams.Sample sp in ds.Samples) // { // pocos.AddLast(new Poco() // { // Name = namePrefix + sp.DataItemId + ":" + sp.Name + "-sp", // Timestamp = sp.Timestamp.ToString("yyyy-MM-dd HH:mm:ss"), // Value = sp.CDATA // }); // } //} //if (ds.Events != null && ds.Events.Count > 0) //{ // foreach (MTConnectStreams.Event ev in ds.Events) // { // pocos.AddLast(new Poco() // { // Name = namePrefix + ev.DataItemId + ":" + ev.Name + "-di", // Timestamp = ev.Timestamp.ToString("yyyy-MM-dd HH:mm:ss"), // Value = ev.CDATA // }); // } //} //if (ds.Conditions != null && ds.Conditions.Count > 0) //{ // foreach (MTConnect.MTConnectStreams.Condition di in ds.Conditions) // { // pocos.AddLast(new Poco() // { // Name = namePrefix + di.DataItemId + ":" + di.Name + "-cd", // Timestamp = di.Timestamp.ToString("yyyy-MM-dd HH:mm:ss"), // Value = di.CDATA // }); // } //} } putToLV(pocos.ToArray()); }
private static void ProcessGenerated(Snapshot snapshot, GeneratedEvents.Configuration gec, Instance currentInstanceData, MTConnectStreams.Document currentData) { var e = gec.Events.Find(x => x.Name.ToLower() == snapshot.Link.ToLower()); if (e != null) { Return returnValue = e.Process(currentInstanceData); if (snapshot.Value != returnValue.Value) { if (returnValue != null) { var value = e.Values.Find(x => x.Result.NumVal == returnValue.NumVal); if (value != null) { snapshot.PreviousTimestamp = GetTimestampFromCurrent(value, currentData); } } snapshot.PreviousValue = snapshot.Value; snapshot.Value = returnValue.Value; } snapshot.Timestamp = returnValue.TimeStamp; } }
// 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); }