// This method uses Opc.Hda.Server class to read data // If OutWriter is specified, it is applied to data that were read. // In this case OPCHDAItemValues is NOT returned, to save memory. public bool Read(string strStartTime, string strEndTime, string[] Tagnames, int AggregateID, int MaxValues, int ResampleInterval, bool IncludeBounds, bool read_raw, OutputWriter OutWriter, out Opc.Hda.ItemValueCollection[] OPCHDAItemValues) { if ((Tagnames == null) || (Tagnames.Count() == 0)) { _trace.TraceEvent(TraceEventType.Error, 0, "HDAClient.Read: no tagnames to read"); OPCHDAItemValues = null; return(false); } if (!read_raw && !(SupportedAggregates.Any(a => a.ID == AggregateID))) { _trace.TraceEvent(TraceEventType.Error, 0, "HDAClient.Read: this aggregate is not supported"); OPCHDAItemValues = null; return(false); } var ItemIds = new Opc.ItemIdentifier[Tagnames.Count()]; for (int i = 0; i < Tagnames.Count(); i++) { ItemIds[i] = new Opc.ItemIdentifier(Tagnames[i]); } // When using Server.ReadProcessed instead of Trend.ReadProcessed, we have to manually Server.CreateItems before. // We also have to call ReleaseItems after use var ItemIDResults = _OPCServer.CreateItems(ItemIds); for (int i = 0; i < Tagnames.Count(); i++) { if (!ItemIDResults[i].ResultID.Succeeded()) { _trace.TraceEvent(TraceEventType.Error, 0, "Tag {0} from the read list is still not valid! Result_ID={1}", Tagnames[i], ItemIDResults[i].ResultID.ToString()); } } DateTime dtStartTime, dtEndTime; Opc.Hda.Time hdaStartTime, hdaEndTime; ConvertStrDatetimeToHDADatetime(strStartTime, out dtStartTime, out hdaStartTime); ConvertStrDatetimeToHDADatetime(strEndTime, out dtEndTime, out hdaEndTime); // Specified dtStartTime may be > than dtEndTime, this means that data should be returned in reverse order (see spec) int order = 1; if (dtStartTime > dtEndTime) { order = -1; } Opc.Hda.ItemValueCollection[] tmpOPCHDAItemValues = null; OPCHDAItemValues = null; try { if (read_raw) { if ((Status != null) && (MaxValues > Status.MaxReturnValues)) { _trace.TraceEvent(TraceEventType.Verbose, 0, "MaxValue was set to {0} (server cannot return more).", Status.MaxReturnValues); MaxValues = Status.MaxReturnValues; } tmpOPCHDAItemValues = _OPCServer.ReadRaw(hdaStartTime, hdaEndTime, MaxValues, IncludeBounds, ItemIDResults); if (OutWriter != null) { OutWriter.WriteHeader(tmpOPCHDAItemValues); OutWriter.Write(tmpOPCHDAItemValues); } else { OPCHDAItemValues = tmpOPCHDAItemValues; } } else // ReadProcessed { var Items = new Opc.Hda.Item[Tagnames.Count()]; for (int i = 0; i < Tagnames.Count(); i++) { Items[i] = new Opc.Hda.Item(ItemIDResults[i]); Items[i].AggregateID = AggregateID; } // Server returns data including start datetime, excluding last datetime: [dtStartPortion, dtEndPortion) DateTime dtStartPortion = dtStartTime; DateTime dtEndPortion; while (order * ((dtEndTime - dtStartPortion).TotalSeconds) > 0) { // is 32-bit int enough for Seconds? Yes, it's 68 years int numvalues = (int)Math.Abs((dtEndTime - dtStartPortion).TotalSeconds / ResampleInterval); if (numvalues > Status.MaxReturnValues) { dtEndPortion = dtStartPortion.AddSeconds(ResampleInterval * Status.MaxReturnValues * order); numvalues = Status.MaxReturnValues; } else { dtEndPortion = dtEndTime; } _trace.TraceEvent(TraceEventType.Verbose, 0, "Reading {0} values from {1} to {2}", numvalues, dtStartPortion.ToString(), dtEndPortion.ToString()); tmpOPCHDAItemValues = _OPCServer.ReadProcessed(new Opc.Hda.Time(dtStartPortion), new Opc.Hda.Time(dtEndPortion), ResampleInterval, Items); if (dtStartPortion.Equals(dtStartTime)) { // if it was a first call if (OutWriter != null) { OutWriter.WriteHeader(tmpOPCHDAItemValues); OutWriter.Write(tmpOPCHDAItemValues); } else { OPCHDAItemValues = tmpOPCHDAItemValues; } } else { if (OutWriter != null) { OutWriter.Write(tmpOPCHDAItemValues); } else { for (int i = 0; i < tmpOPCHDAItemValues.Count(); i++) { OPCHDAItemValues[i].AddRange(tmpOPCHDAItemValues[i]); } } } dtStartPortion = dtEndPortion; } } if (OPCHDAItemValues != null) { _trace.TraceEvent(TraceEventType.Verbose, 0, "Number of tags = OPCHDAItemValues.Count()={0}", OPCHDAItemValues.Count()); _trace.TraceEvent(TraceEventType.Verbose, 0, "Number of values for the first tag = OPCHDAItemValues[0].Count={0}", OPCHDAItemValues[0].Count); } return(true); } catch (Opc.ResultIDException e) { _trace.TraceEvent(TraceEventType.Error, 0, "Opc.ResultIDException:" + e.ToString()); // anyway, let's try to examine data if (tmpOPCHDAItemValues == null) { _trace.TraceEvent(TraceEventType.Error, 0, "tmpOPCHDAItemValues == null"); } else { foreach (Opc.Hda.ItemValueCollection item in tmpOPCHDAItemValues) { _trace.TraceEvent(TraceEventType.Error, 0, "For tag {0} the ResultID is {1}", item.ItemName, item.ResultID.ToString()); } } return(false); } catch (Exception e) { _trace.TraceEvent(TraceEventType.Error, 0, e.Message); _trace.TraceEvent(TraceEventType.Error, 0, e.GetType().ToString()); if (e.Data.Count > 0) { _trace.TraceEvent(TraceEventType.Verbose, 0, " Extra details:"); foreach (System.Collections.DictionaryEntry de in e.Data) { _trace.TraceEvent(TraceEventType.Verbose, 0, " Key: {0,-20} Value: {1}", "'" + de.Key.ToString() + "'", de.Value); } } return(false); } finally { _trace.TraceEvent(TraceEventType.Verbose, 0, "Releasing items."); _OPCServer.ReleaseItems(ItemIds); for (int i = 0; i < Tagnames.Count(); i++) { if (!ItemIDResults[i].ResultID.Succeeded()) { _trace.TraceEvent(TraceEventType.Error, 0, "Tag {0} couldn't be released! Result_ID={1}", Tagnames[i], ItemIDResults[i].ResultID.ToString()); } } if (OutWriter != null) { OutWriter.Close(); } } }
private void CreateSignalDict(Opc.Hda.Server Hda, List <string> tagsLst, string[] propID = null, string dtBegin = null, string dtEnd = null, bool restrict = false) { Dictionary = new Dictionary <string, Signal>(); DateTime dt1 = new DateTime(); DateTime dt2 = new DateTime(); var memRec = new OpcRecord(); if (dtBegin != null) { if (serverHda == null) { serverHda = Hda; } } for (int i = 0; i < tagsLst.Count; i++) { var signal = new Signal(serverDa, tagsLst[i], propID); if (dtBegin != null) { try { signal.ValueCollection = new List <OpcRecord>(); dt1 = System.Convert.ToDateTime(dtBegin); dt2 = DateTime.Today; DateTime lastdt = dt1; if (dtEnd == null) { dtEnd = dt2.AddDays(1).ToString(); } dt2 = System.Convert.ToDateTime(dtEnd); signal.DtBegin = dt1; signal.DtEnd = dt2; var identifiers = new ItemIdentifier[1]; identifiers[0] = new Opc.ItemIdentifier(tagsLst[i]); Opc.IdentifiedResult[] items = serverHda.CreateItems(identifiers); OpcRecord rec = null; bool exit = false; Opc.Hda.ItemValueCollection[] vForPrev = serverHda.ReadRaw(new Opc.Hda.Time(dt1), new Opc.Hda.Time(dt1.AddSeconds(1)), 0, true, items); signal.PrevValue = new OpcRecord(); if (vForPrev.Length > 0) { if (vForPrev[0].Count > 0) { signal.PrevValue.Value = vForPrev[0][0].Value; signal.PrevValue.Quality = vForPrev[0][0].Quality.GetCode(); signal.PrevValue.Timestamp = vForPrev[0][0].Timestamp.ToString(); } } Opc.Hda.ItemValueCollection[] vForNext = serverHda.ReadRaw(new Opc.Hda.Time(dt2.AddMilliseconds(-1)), new Opc.Hda.Time(dt2), 0, true, items); signal.NextValue = new OpcRecord(); if (vForNext.Length > 0) { if (vForNext[0].Count > 0) { signal.NextValue.Value = vForNext[0][vForNext[0].Count - 1].Value; signal.NextValue.Quality = vForNext[0][vForNext[0].Count - 1].Quality.GetCode(); signal.NextValue.Timestamp = vForNext[0][vForNext[0].Count - 1].Timestamp.ToString(); } } while (!exit) { Opc.Hda.ItemValueCollection[] values = serverHda.ReadRaw(new Opc.Hda.Time(lastdt), new Opc.Hda.Time(dt2), 0, false, items); for (int j = 0; j < values.Length; j++) { if (values[j].Count <= 1) { exit = true; } for (int k = 0; k < values[j].Count; k++) { rec = new OpcRecord(); if (signal.ValueType == "long") { if (values[j][k].Value != null) { rec.Value = System.Convert.ToInt64(values[j][k].Value.ToString()); } else { rec.Value = 0; } } if (signal.ValueType == "double") { if (values[j][k].Value != null) { rec.Value = System.Convert.ToDouble(values[j][k].Value.ToString()); } else { rec.Value = 0.0; } } if (signal.ValueType == "string") { if (values[j][k].Value != null) { rec.Value = values[j][k].Value.ToString(); } else { rec.Value = ""; } } if (signal.ValueType == "bool") { if (values[j][k].Value != null) { rec.Value = values[j][k].Value.ToString().ToLower().Trim() == "true"; } else { rec.Value = false; } } rec.Quality = values[j][k].Quality.GetCode(); rec.Timestamp = values[j][k].Timestamp.ToString(); rec.Value = values[j][k].Value; lastdt = values[j][k].Timestamp; if (values[j].Count > 1) { if (k == values[j].Count - 1 && values[j][k].Timestamp == values[j][k - 1].Timestamp) { lastdt = lastdt.AddMilliseconds(1); } } if (k != values[j].Count - 1) { if (restrict & signal.ValueCollection.Count > 0) { if ( System.Convert.ToDateTime( signal.ValueCollection[signal.ValueCollection.Count - 1].Timestamp) .ToString() == System.Convert.ToDateTime(rec.Timestamp).ToString() && rec.Quality >= 192) { signal.ValueCollection[signal.ValueCollection.Count - 1] = rec; } else { signal.ValueCollection.Add(rec); } } else { signal.ValueCollection.Add(rec); } } } } } if (restrict & signal.ValueCollection.Count > 0) { if ( System.Convert.ToDateTime( signal.ValueCollection[signal.ValueCollection.Count - 1].Timestamp).ToString() == System.Convert.ToDateTime(rec.Timestamp).ToString() && rec.Quality >= 192) { signal.ValueCollection[signal.ValueCollection.Count - 1] = rec; } else { signal.ValueCollection.Add(rec); } } else { signal.ValueCollection.Add(rec); } } catch (Exception) { MessageBox.Show(@"Отсутствует лицензия или проверьте подключения к серверу C:\Tag.ini", @"Ошибка подключения сервера", MessageBoxButton.OK, MessageBoxImage.Error); Environment.Exit(0); } } if (restrict) { if (signal.ValueCollection.Count > 0) { if (signal.ValueCollection[0] == null) { signal.ValueCollection.Remove(signal.ValueCollection[0]); } } var restrictLeft = new OpcRecord(); restrictLeft.Value = signal.PrevValue.Value; restrictLeft.Quality = signal.PrevValue.Quality; restrictLeft.Timestamp = dt1.ToString(); signal.ValueCollection.Insert(0, restrictLeft); var restrictRight = new OpcRecord(); restrictRight.Value = signal.ValueCollection[signal.ValueCollection.Count - 1].Value; restrictRight.Quality = signal.ValueCollection[signal.ValueCollection.Count - 1].Quality; restrictRight.Timestamp = dt2.ToString(); signal.ValueCollection.Add(restrictRight); } Dictionary.Add(tagsLst[i], signal); } }