void StartMonitoring() { foreach (var item in MonitoredMeasurements) { var nodeId = OpcUaHelper.FindNode(item.Path, ObjectIds.ObjectsFolder, l_session); var sub = new Subscription { PublishingInterval = item.MonitorResolution, PublishingEnabled = true, LifetimeCount = 0, KeepAliveCount = 0, DisplayName = item.Path, Priority = byte.MaxValue }; MonitoredItem monitoredItem = new MonitoredItem() { StartNodeId = nodeId, AttributeId = Attributes.Value, DisplayName = item.Name, SamplingInterval = item.MonitorResolution }; sub.AddItem(monitoredItem); l_session.AddSubscription(sub); sub.Create(); sub.ApplyChanges(); monitoredItem.Notification += (monitored, args) => { var p = (MonitoredItemNotification)args.NotificationValue; MonitorData(item, p.Value); }; } }
void ReadMeasurement(PolledMeasurement measurement) { OpcMetric metric = new OpcMetric(); metric.Measurement = (MeasurementDto)measurement; if (!l_session.Connected) { l_logger.ErrorFormat(string.Format("Server not connected. Cannot read path {0}.", measurement.Name)); throw new Exception(string.Format("Server not connected. Cannot read path {0}.", measurement.Name)); } var nodesToRead = OpcUaHelper.GetReadValueIdCollection(measurement.Path, l_session); DataValueCollection results; DiagnosticInfoCollection diag; l_session.Read( requestHeader: null, maxAge: 0, timestampsToReturn: TimestampsToReturn.Neither, nodesToRead: nodesToRead, results: out results, diagnosticInfos: out diag); var val = results[0]; metric.OpcValue = val.Value; metric.Opcstatus = val.StatusCode.ToString(); if (OpcHelper.QualifyMetric(ref metric, l_cache)) { l_cache[metric.Measurement.Name] = metric.OpcValue; l_metricCollection.Add(metric); } }
//bool QualifyMetric(ref OpcMetric metric) //{ // if (PointHasGoodOrDifferentBadStatus(metric)) // { // if (!l_cache.ContainsKey(metric.Measurement.Name)) // { // l_cache.Add(metric.Measurement.Name, metric.OpcValue); // metric.Measurement.LastOpcstatus = metric.Opcstatus; // metric.Measurement.LastValue = metric.OpcValue; // } // else // { // object lastvalue; // l_cache.TryGetValue(metric.Measurement.Name, out lastvalue); // metric.Measurement.LastValue = lastvalue; // } // if (!PointIsValid(metric) || !PointMatchesType(metric)) // { // // Set de default value for the type specified // l_logger.ErrorFormat("Invalid point: measurement.name<{0}>, measurement.path<{1}>, metric.value<{2}>", metric.Measurement.Name, metric.Measurement.Path, metric.OpcValue.ToString()); // switch (metric.Measurement.DataType) // { // case "number": // metric.OpcValue = 0; // break; // case "boolean": // metric.OpcValue = false; // break; // case "string": // metric.OpcValue = ""; // break; // default: // l_logger.Error("No valid datatype, ignoring point"); // break; // } // return false; // } // } // // Check for deadband // if (PointIsWithinDeadband(metric)) return false; // if (!PointMatchesType(metric)) // { // l_logger.ErrorFormat("Invalid type returned from OPC. Ignoring point {0}", metric.Measurement.Name); // return false; // } // return true; //} //bool PointMatchesType(OpcMetric metric) //{ // var match = (metric.OpcValue.IsNumber() && metric.Measurement.DataType == "number") // || metric.OpcValue.IsBoolean() && metric.Measurement.DataType == "boolean" // || metric.OpcValue.IsString() && metric.Measurement.DataType == "string"; // if (!match) // { // //log here // } // return match; //} //bool PointIsValid(OpcMetric p) //{ // // check if the value is a type that we can handle (number or a bool). // return (p.OpcValue != null && (p.OpcValue.IsBoolean() || p.OpcValue.IsNumber())) || p.OpcValue.IsString(); //} //bool PointHasGoodOrDifferentBadStatus(OpcMetric p) //{ // var curr = p.Opcstatus; // var prev = p.Measurement.LastOpcstatus; // if (curr == "Good" || curr != prev) return true; // return false; //} //bool PointIsWithinDeadband(OpcMetric metric) //{ // // some vars for shorter statements later on. // var curr = metric.OpcValue; // var prev = metric.Measurement.LastValue; // var dba = metric.Measurement.DeadbandAbsolute; // var dbr = metric.Measurement.DeadbandRelative; // // return early if the type of the previous value is not the same as the current. // // this will also return when this is the first value and prev is still undefined. // if (curr.GetType() != prev.GetType()) return false; // // calculate deadbands based on value type. For numbers, make the // // calculations for both absolute and relative if they are set. For bool, // // just check if a deadband has been set and if the value has changed. // if (curr.IsNumber()) // { // if (dba > 0 && Math.Abs(Convert.ToDecimal(curr) - Convert.ToDecimal(prev)) < dba) // { // return true; // } // if (dbr > 0 && Math.Abs(Convert.ToDecimal(curr) - Convert.ToDecimal(prev)) < Math.Abs(Convert.ToDecimal(prev)) * dbr) // { // // console.log("New value is within relative deadband.", p); // return true; // } // } // else if (curr.IsBoolean()) // { // if (dba > 0 && prev == curr) // // console.log("New value is within bool deadband.", p); // return true; // } // else if (curr.IsString()) // return true; // return false; //} #endregion #region methods private Session InitializeSession(Uri url, X509Certificate2 applicationCertificate = null) { var certificateValidator = new CertificateValidator(); certificateValidator.CertificateValidation += (sender, eventArgs) => { if (ServiceResult.IsGood(eventArgs.Error)) { eventArgs.Accept = true; } else if ((eventArgs.Error.StatusCode.Code == StatusCodes.BadCertificateUntrusted) && true) // AutoAcceptUntrustedCertificates = true; { eventArgs.Accept = true; } else { throw new Exception(string.Format("Failed to validate certificate with error code {0}: {1}, statusCode: {2}", eventArgs.Error.Code, eventArgs.Error.AdditionalInfo, eventArgs.Error.StatusCode)); } }; // Build the application configuration var appInstance = new ApplicationInstance { ApplicationType = ApplicationType.Client, ConfigSectionName = "Odenwald", ApplicationConfiguration = new ApplicationConfiguration { ApplicationUri = url.ToString(), ApplicationName = "Odenwald", ApplicationType = ApplicationType.Client, CertificateValidator = certificateValidator, ServerConfiguration = new ServerConfiguration { MaxSubscriptionCount = 100, MaxMessageQueueSize = 10, MaxNotificationQueueSize = 100, MaxPublishRequestCount = 20 }, SecurityConfiguration = new SecurityConfiguration { AutoAcceptUntrustedCertificates = true }, TransportQuotas = new TransportQuotas { OperationTimeout = 600000, MaxStringLength = 1048576, MaxByteStringLength = 1048576, MaxArrayLength = 65535, MaxMessageSize = 4194304, MaxBufferSize = 65535, ChannelLifetime = 600000, SecurityTokenLifetime = 3600000 }, ClientConfiguration = new ClientConfiguration { DefaultSessionTimeout = 60000, MinSubscriptionLifetime = 10000 }, DisableHiResClock = true } }; // Assign a application certificate (when specified) if (applicationCertificate != null) { appInstance.ApplicationConfiguration.SecurityConfiguration.ApplicationCertificate = new CertificateIdentifier(applicationCertificate); } // Find the endpoint to be used var endpoints = OpcUaHelper.SelectEndpoint(url, false);//UseMessageSecurity = false; // Create the OPC session: var session = Session.Create( configuration: appInstance.ApplicationConfiguration, endpoint: new ConfiguredEndpoint( collection: null, description: endpoints, configuration: EndpointConfiguration.Create(applicationConfiguration: appInstance.ApplicationConfiguration)), updateBeforeConnect: false, checkDomain: false, sessionName: "Odenwald", sessionTimeout: 60000U, identity: null, preferredLocales: new string[] { }); return(session); }