// This process watches (via change stream) for commands inserted to a commands collection // When the command is considered valid it is forwarded to the RTU static async void ProcessMongoCmd(JSONSCADAConfig jsConfig) { do { try { var Client = ConnectMongoClient(jsConfig); var DB = Client.GetDatabase(jsConfig.mongoDatabaseName); var collection = DB .GetCollection <rtCommand>(CommandsQueueCollectionName); bool isMongoLive = DB .RunCommandAsync((Command <BsonDocument>) "{ping:1}") .Wait(1000); if (!isMongoLive) { throw new Exception("Error on connection " + jsConfig.mongoConnectionString); } Log("MongoDB CMD CS - Start listening for commands via changestream..."); var filter = "{ operationType: 'insert' }"; var pipeline = new EmptyPipelineDefinition <ChangeStreamDocument <rtCommand > >().Match(filter); using (var cursor = await collection.WatchAsync(pipeline)) { await cursor .ForEachAsync(async change => { if (!Active) { return; } // process change event, only process inserts if ( change.OperationType == ChangeStreamOperationType.Insert ) { Log("MongoDB CMD CS - Looking for connection " + change .FullDocument .protocolSourceConnectionNumber + "..."); var found = false; foreach (OPCUA_connection srv in OPCUAconns ) { if ( srv.protocolConnectionNumber == change .FullDocument .protocolSourceConnectionNumber ) { found = true; int timeDif = DateTime .Now .ToLocalTime() .Subtract(change .FullDocument .timeTag .ToLocalTime( )) .Seconds; // test for command expired if (timeDif > 10) { // update as expired Log("MongoDB CMD CS - " + srv.name + " - " + " Address " + change .FullDocument .protocolSourceObjectAddress + " value " + change .FullDocument .value + " Expired, " + timeDif + " Seconds old"); var filter = new BsonDocument(new BsonDocument("_id", change .FullDocument .id)); var update = new BsonDocument("$set", new BsonDocument("cancelReason", "expired")); var result = await collection .UpdateOneAsync(filter, update); break; } if ( srv.connection.session.Connected && srv.commandsEnabled ) { WriteValueCollection nodesToWrite = new WriteValueCollection(); WriteValue WriteVal = new WriteValue(); WriteVal.NodeId = new NodeId(System .Convert .ToString(change.FullDocument.protocolSourceObjectAddress)); WriteVal.AttributeId = Attributes.Value; WriteVal.Value = new DataValue(); switch (change.FullDocument.protocolSourceASDU.ToString().ToLower()) { case "boolean": WriteVal.Value.Value = System.Convert.ToBoolean(System .Convert.ToDouble(change.FullDocument.value) != 0.0); break; case "sbyte": WriteVal.Value.Value = System .Convert .ToSByte(change.FullDocument.value); break; case "byte": WriteVal.Value.Value = System .Convert .ToByte(change.FullDocument.value); break; case "int16": WriteVal.Value.Value = System .Convert .ToInt16(change.FullDocument.value); break; case "uint16": WriteVal.Value.Value = System .Convert .ToUInt16(change.FullDocument.value); break; case "int32": WriteVal.Value.Value = System .Convert .ToInt16(change.FullDocument.value); break; case "uint32": WriteVal.Value.Value = System .Convert .ToUInt16(change.FullDocument.value); break; case "int64": WriteVal.Value.Value = System .Convert .ToInt16(change.FullDocument.value); break; case "uint64": WriteVal.Value.Value = System .Convert .ToUInt16(change.FullDocument.value); break; case "float": WriteVal.Value.Value = System .Convert .ToSingle(change.FullDocument.value); break; case "double": WriteVal.Value.Value = System .Convert .ToDouble(change.FullDocument.value); break; case "datetime": WriteVal.Value.Value = System .Convert .ToDateTime(change.FullDocument.value); break; case "string": WriteVal.Value.Value = System .Convert .ToString(change.FullDocument.value); break; } nodesToWrite.Add(WriteVal); // Write the node attributes StatusCodeCollection results = null; DiagnosticInfoCollection diagnosticInfos; Log("MongoDB CMD CS - " + srv.name + " - Writing node..."); // Call Write Service srv.connection.session.Write(null, nodesToWrite, out results, out diagnosticInfos); var okres = false; var resultDescription = ""; if (results.Count > 0) { resultDescription = results[0].ToString(); if (StatusCode.IsGood(results[0])) { okres = true; } } Log("MongoDB CMD CS - " + srv.name + " - " + " Address: " + change .FullDocument .protocolSourceObjectAddress + " - Command delivered - " + results[0].ToString()); // update as delivered var filter = new BsonDocument(new BsonDocument("_id", change .FullDocument .id)); var update = new BsonDocument { { "$set", new BsonDocument { { "delivered", true }, { "ack", okres }, { "ackTimeTag", new BsonDateTime(DateTime.Now) }, { "resultDescription", resultDescription } } } }; var result = await collection .UpdateOneAsync(filter, update); } else { // update as canceled (not connected) Log("MongoDB CMD CS - " + srv.name + " OA " + change .FullDocument .protocolSourceObjectAddress + " value " + change.FullDocument.value + ( srv.commandsEnabled ? " Not Connected" : " Commands Disabled" )); var filter = new BsonDocument(new BsonDocument("_id", change .FullDocument .id)); var update = new BsonDocument("$set", new BsonDocument("cancelReason", ( srv .commandsEnabled ? "not connected" : "commands disabled" ))); var result = await collection .UpdateOneAsync(filter, update); } break; } } if (!found) { // not for a connection managed by this driver instance, just ignore } } }); } } catch (Exception e) { Log("Exception MongoCmd"); Log(e); Log(e .ToString() .Substring(0, e.ToString().IndexOf(Environment.NewLine))); Thread.Sleep(3000); } }while (true); }
/// <summary> /// Calculates the Count aggregate for the timeslice. /// </summary> protected DataValue ComputeNumberOfTransitions(TimeSlice slice) { // get the values in the slice. List <DataValue> values = GetValues(slice); // check for empty slice. if (values == null) { return(GetNoDataValue(slice)); } // determine whether a transition occurs at the StartTime double lastValue = Double.NaN; if (slice.EarlyBound != null) { if (StatusCode.IsGood(slice.EarlyBound.Value.StatusCode)) { try { lastValue = CastToDouble(slice.EarlyBound.Value); } catch (Exception) { lastValue = Double.NaN; } } } // count the transitions. int count = 0; for (int ii = 0; ii < values.Count; ii++) { if (!IsGood(values[ii])) { continue; } double nextValue = 0; try { nextValue = CastToDouble(values[ii]); } catch (Exception) { continue; } if (!Double.IsNaN(lastValue)) { if (lastValue != nextValue) { count++; } } lastValue = nextValue; } // set the timestamp and status. DataValue value = new DataValue(); value.WrappedValue = new Variant(count, TypeInfo.Scalars.Int32); value.SourceTimestamp = GetTimestamp(slice); value.ServerTimestamp = GetTimestamp(slice); value.StatusCode = value.StatusCode.SetAggregateBits(AggregateBits.Calculated); value.StatusCode = GetValueBasedStatusCode(slice, values, value.StatusCode); // return result. return(value); }
/// <summary> /// Calculates the RegSlope, RegConst and RegStdDev aggregates for the timeslice. /// </summary> protected DataValue ComputeRegression(TimeSlice slice, int valueType) { // get the values in the slice. List <DataValue> values = GetValuesWithSimpleBounds(slice); // check for empty slice. if (values == null || values.Count == 0) { return(GetNoDataValue(slice)); } // get the regions. List <SubRegion> regions = GetRegionsInValueSet(values, false, true); List <double> xData = new List <double>(); List <double> yData = new List <double>(); double duration = 0; bool nonGoodDataExists = false; for (int ii = 0; ii < regions.Count; ii++) { if (StatusCode.IsGood(regions[ii].StatusCode)) { xData.Add(regions[ii].StartValue); yData.Add(duration); } else { nonGoodDataExists = true; } // normalize to seconds. duration += regions[ii].Duration / 1000.0; } // check if no good data. if (xData.Count == 0) { return(GetNoDataValue(slice)); } // compute the regression parameters. double regSlope = 0; double regConst = 0; double regStdDev = 0; if (xData.Count > 1) { double xAvg = 0; double yAvg = 0; double xxAgv = 0; double xyAvg = 0; for (int ii = 0; ii < xData.Count; ii++) { xAvg += xData[ii]; yAvg += yData[ii]; xxAgv += xData[ii] * xData[ii]; xyAvg += xData[ii] * yData[ii]; } xAvg /= xData.Count; yAvg /= xData.Count; xxAgv /= xData.Count; xyAvg /= xData.Count; regSlope = (xyAvg - xAvg * yAvg) / (xxAgv - xAvg * xAvg); regConst = yAvg - regSlope * xAvg; List <double> errors = new List <double>(); double eAvg = 0; for (int ii = 0; ii < xData.Count; ii++) { double error = yData[ii] - regConst - regSlope * xData[ii]; errors.Add(error); eAvg += error; } eAvg /= errors.Count; double variance = 0; for (int ii = 0; ii < errors.Count; ii++) { double error = errors[ii] - eAvg; variance += error * error; } variance /= errors.Count; regStdDev = Math.Sqrt(variance); } // select the result. double result = 0; switch (valueType) { case 1: { result = regSlope; break; } case 2: { result = regConst; break; } case 3: { result = regStdDev; break; } } // set the timestamp and status. DataValue value = new DataValue(); value.WrappedValue = new Variant(result, TypeInfo.Scalars.Double); value.SourceTimestamp = GetTimestamp(slice); value.ServerTimestamp = GetTimestamp(slice); if (nonGoodDataExists) { value.StatusCode = StatusCodes.UncertainDataSubNormal; } value.StatusCode = value.StatusCode.SetAggregateBits(AggregateBits.Calculated); // return result. return(value); }
/// <summary> /// Gets the result for the read operayoin. /// </summary> /// <param name="context">The context.</param> /// <param name="item">The item.</param> /// <param name="nodeToRead">The node to read.</param> /// <param name="value">The value.</param> /// <param name="diagnosticsMasks">The diagnostics masks.</param> /// <returns></returns> public ServiceResult GetResult( ISystemContext context, HdaItemState item, ReadValueId nodeToRead, DataValue value, DiagnosticsMasks diagnosticsMasks) { switch (nodeToRead.AttributeId) { case Attributes.Description: { string description = this.GetAttributeValue <string>(Constants.OPCHDA_DESCRIPTION, value, false); if (StatusCode.IsGood(value.StatusCode)) { value.Value = new LocalizedText(description); } break; } case Attributes.DataType: { short datatype = this.GetAttributeValue <short>(Constants.OPCHDA_DATA_TYPE, value, false); if (StatusCode.IsGood(value.StatusCode)) { value.Value = ComUtils.GetDataTypeId(datatype); } else { value.Value = DataTypeIds.BaseDataType; value.StatusCode = StatusCodes.GoodLocalOverride; } break; } case Attributes.ValueRank: { short datatype = this.GetAttributeValue <short>(Constants.OPCHDA_DATA_TYPE, value, false); if (StatusCode.IsGood(value.StatusCode)) { value.Value = ComUtils.GetValueRank(datatype); } else { value.Value = ValueRanks.Any; value.StatusCode = StatusCodes.GoodLocalOverride; } break; } case Attributes.Historizing: { bool archiving = this.GetAttributeValue <bool>(Constants.OPCHDA_ARCHIVING, value, false); if (StatusCode.IsGood(value.StatusCode)) { value.Value = archiving; } else { value.Value = false; value.StatusCode = StatusCodes.GoodLocalOverride; } break; } default: { return(StatusCodes.BadAttributeIdInvalid); } } // check if the attribute value is missing. if (value.StatusCode == StatusCodes.BadNotFound) { return(StatusCodes.BadAttributeIdInvalid); } return(ApplyIndexRangeAndDataEncoding(context, nodeToRead, value)); }
/// <summary> /// Updates the values with the current values read from the server. /// </summary> public void Read(params WriteValue[] nodesToWrite) { if (m_session == null) { throw new ServiceResultException(StatusCodes.BadNotConnected); } // build list of values to read. ReadValueIdCollection nodesToRead = new ReadValueIdCollection(); if (nodesToWrite == null || nodesToWrite.Length == 0) { foreach (DataGridViewRow row in ResultsDV.Rows) { DataRowView source = row.DataBoundItem as DataRowView; WriteValue value = (WriteValue)source.Row[0]; row.Selected = false; ReadValueId nodeToRead = new ReadValueId(); nodeToRead.NodeId = value.NodeId; nodeToRead.AttributeId = value.AttributeId; nodeToRead.IndexRange = value.IndexRange; nodeToRead.Handle = value; nodesToRead.Add(nodeToRead); } } else { foreach (WriteValue value in nodesToWrite) { ReadValueId nodeToRead = new ReadValueId(); nodeToRead.NodeId = value.NodeId; nodeToRead.AttributeId = value.AttributeId; nodeToRead.IndexRange = value.IndexRange; nodeToRead.Handle = value; nodesToRead.Add(nodeToRead); } } // read the values. DataValueCollection results = null; DiagnosticInfoCollection diagnosticInfos = null; m_session.Read( null, 0, TimestampsToReturn.Neither, nodesToRead, out results, out diagnosticInfos); ClientBase.ValidateResponse(results, nodesToRead); ClientBase.ValidateDiagnosticInfos(diagnosticInfos, nodesToRead); // add the results to the display. for (int ii = 0; ii < results.Count; ii++) { WriteValue nodeToWrite = nodesToRead[ii].Handle as WriteValue; DataRow row = nodeToWrite.Handle as DataRow; if (StatusCode.IsGood(results[ii].StatusCode)) { nodeToWrite.Value = results[ii]; UpdateRow(row, results[ii]); } } }
/// <summary> /// Updates the bounding values for the time slice. /// </summary> public override void UpdateBoundingValues(TimeSlice bucket, AggregateState state) { var EarlyBound = bucket.EarlyBound; var LateBound = bucket.LateBound; if (bucket.ExactMatch(state.LatestTimestamp) && StatusCode.IsGood(state.LatestStatus)) { EarlyBound.RawPoint = state.LatePoint ?? state.EarlyPoint; EarlyBound.DerivationType = BoundingValueType.Raw; } else { if (EarlyBound.DerivationType != BoundingValueType.Raw) { if (EarlyBound.EarlyPoint == null) { if ((state.EarlyPoint != null) && (state.EarlyPoint.SourceTimestamp < bucket.From)) { EarlyBound.EarlyPoint = state.EarlyPoint; } } if (EarlyBound.LatePoint == null) { if ((state.LatePoint != null) && (state.LatePoint.SourceTimestamp >= bucket.From)) { EarlyBound.CurrentBadPoints = new List <DataValue>(); foreach (var dv in state.CurrentBadPoints) { if (dv.SourceTimestamp < EarlyBound.Timestamp) { EarlyBound.CurrentBadPoints.Add(dv); } } EarlyBound.DerivationType = BoundingValueType.SteppedInterpolation; } } } if (state.HasTerminated && (state.LatePoint == null)) { EarlyBound.CurrentBadPoints = new List <DataValue>(); foreach (var dv in state.CurrentBadPoints) { if (dv.SourceTimestamp < EarlyBound.Timestamp) { EarlyBound.CurrentBadPoints.Add(dv); } } EarlyBound.DerivationType = BoundingValueType.SteppedExtrapolation; } } if (bucket.EndMatch(state.LatestTimestamp) && StatusCode.IsGood(state.LatestStatus)) { LateBound.RawPoint = state.LatePoint ?? state.EarlyPoint; LateBound.DerivationType = BoundingValueType.Raw; } else { if (LateBound.DerivationType != BoundingValueType.Raw) { if ((state.EarlyPoint != null) && (state.EarlyPoint.SourceTimestamp < bucket.To)) { LateBound.EarlyPoint = state.EarlyPoint; } if (LateBound.LatePoint == null) { if ((state.LatePoint != null) && (state.LatePoint.SourceTimestamp >= bucket.To)) { LateBound.CurrentBadPoints = new List <DataValue>(); foreach (var dv in state.CurrentBadPoints) { if (dv.SourceTimestamp < LateBound.Timestamp) { LateBound.CurrentBadPoints.Add(dv); } } LateBound.DerivationType = BoundingValueType.SteppedInterpolation; } } } if (state.HasTerminated && (state.LatePoint == null)) { LateBound.CurrentBadPoints = new List <DataValue>(); foreach (var dv in state.CurrentBadPoints) { if (dv.SourceTimestamp < LateBound.Timestamp) { LateBound.CurrentBadPoints.Add(dv); } } if (EarlyBound.PriorPoint == null) { EarlyBound.PriorPoint = state.PriorPoint; EarlyBound.PriorBadPoints = state.PriorBadPoints; EarlyBound.DerivationType = UseSlopedExtrapolation ? BoundingValueType.SlopedExtrapolation : BoundingValueType.SteppedExtrapolation; } LateBound.DerivationType = BoundingValueType.SteppedExtrapolation; } } }
/// <inheritdoc/> protected override async Task OnOpenAsync(CancellationToken token = default(CancellationToken)) { this.logger?.LogInformation($"Opening session channel with endpoint '{this.RemoteEndpoint.EndpointUrl}'."); this.logger?.LogInformation($"SecurityPolicy: '{this.RemoteEndpoint.SecurityPolicyUri}'."); this.logger?.LogInformation($"SecurityMode: '{this.RemoteEndpoint.SecurityMode}'."); this.logger?.LogInformation($"UserIdentity: '{this.UserIdentity}'."); await base.OnOpenAsync(token).ConfigureAwait(false); token.ThrowIfCancellationRequested(); // if SessionId is provided then we skip the CreateSessionRequest and go directly to (re)ActivateSession. // requires from previous Session: SessionId, AuthenticationToken, RemoteNonce if (this.SessionId == null) { var localNonce = this.GetNextNonce(NonceLength); var localCertificate = this.LocalCertificate; var createSessionRequest = new CreateSessionRequest { ClientDescription = this.LocalDescription, EndpointUrl = this.RemoteEndpoint.EndpointUrl, SessionName = this.LocalDescription.ApplicationName, ClientNonce = localNonce, ClientCertificate = localCertificate, RequestedSessionTimeout = this.options.SessionTimeout, MaxResponseMessageSize = this.RemoteMaxMessageSize }; var createSessionResponse = await this.CreateSessionAsync(createSessionRequest).ConfigureAwait(false); this.SessionId = createSessionResponse.SessionId; this.AuthenticationToken = createSessionResponse.AuthenticationToken; this.RemoteNonce = createSessionResponse.ServerNonce; // verify the server's certificate is the same as the certificate from the selected endpoint. if (this.RemoteEndpoint.ServerCertificate != null && !this.RemoteEndpoint.ServerCertificate.SequenceEqual(createSessionResponse.ServerCertificate)) { throw new ServiceResultException(StatusCodes.BadCertificateInvalid, "Server did not return the same certificate used to create the channel."); } // verify the server's signature. ISigner verifier = null; bool verified = false; switch (this.RemoteEndpoint.SecurityPolicyUri) { case SecurityPolicyUris.Basic128Rsa15: case SecurityPolicyUris.Basic256: verifier = SignerUtilities.GetSigner("SHA-1withRSA"); verifier.Init(false, this.RemotePublicKey); verifier.BlockUpdate(localCertificate, 0, localCertificate.Length); verifier.BlockUpdate(localNonce, 0, localNonce.Length); verified = verifier.VerifySignature(createSessionResponse.ServerSignature.Signature); break; case SecurityPolicyUris.Basic256Sha256: case SecurityPolicyUris.Aes128_Sha256_RsaOaep: verifier = SignerUtilities.GetSigner("SHA-256withRSA"); verifier.Init(false, this.RemotePublicKey); verifier.BlockUpdate(localCertificate, 0, localCertificate.Length); verifier.BlockUpdate(localNonce, 0, localNonce.Length); verified = verifier.VerifySignature(createSessionResponse.ServerSignature.Signature); break; case SecurityPolicyUris.Aes256_Sha256_RsaPss: verifier = SignerUtilities.GetSigner("SHA-256withRSAandMGF1"); verifier.Init(false, this.RemotePublicKey); verifier.BlockUpdate(localCertificate, 0, localCertificate.Length); verifier.BlockUpdate(localNonce, 0, localNonce.Length); verified = verifier.VerifySignature(createSessionResponse.ServerSignature.Signature); break; default: verified = true; break; } verifier = null; if (!verified) { throw new ServiceResultException(StatusCodes.BadApplicationSignatureInvalid, "Server did not provide a correct signature for the nonce data provided by the client."); } } // create client signature SignatureData clientSignature = null; ISigner signer = null; switch (this.RemoteEndpoint.SecurityPolicyUri) { case SecurityPolicyUris.Basic128Rsa15: case SecurityPolicyUris.Basic256: signer = SignerUtilities.GetSigner("SHA-1withRSA"); signer.Init(true, this.LocalPrivateKey); signer.BlockUpdate(this.RemoteEndpoint.ServerCertificate, 0, this.RemoteEndpoint.ServerCertificate.Length); signer.BlockUpdate(this.RemoteNonce, 0, this.RemoteNonce.Length); clientSignature = new SignatureData { Signature = signer.GenerateSignature(), Algorithm = RsaSha1Signature, }; break; case SecurityPolicyUris.Basic256Sha256: case SecurityPolicyUris.Aes128_Sha256_RsaOaep: signer = SignerUtilities.GetSigner("SHA-256withRSA"); signer.Init(true, this.LocalPrivateKey); signer.BlockUpdate(this.RemoteEndpoint.ServerCertificate, 0, this.RemoteEndpoint.ServerCertificate.Length); signer.BlockUpdate(this.RemoteNonce, 0, this.RemoteNonce.Length); clientSignature = new SignatureData { Signature = signer.GenerateSignature(), Algorithm = RsaSha256Signature, }; break; case SecurityPolicyUris.Aes256_Sha256_RsaPss: signer = SignerUtilities.GetSigner("SHA-256withRSAandMGF1"); signer.Init(true, this.LocalPrivateKey); signer.BlockUpdate(this.RemoteEndpoint.ServerCertificate, 0, this.RemoteEndpoint.ServerCertificate.Length); signer.BlockUpdate(this.RemoteNonce, 0, this.RemoteNonce.Length); clientSignature = new SignatureData { Signature = signer.GenerateSignature(), Algorithm = RsaPssSha256Signature, }; break; default: clientSignature = new SignatureData(); break; } signer = null; // supported UserIdentityToken types are AnonymousIdentityToken, UserNameIdentityToken, IssuedIdentityToken, X509IdentityToken UserIdentityToken identityToken = null; SignatureData tokenSignature = null; // if UserIdentity type is IssuedIdentity if (this.UserIdentity is IssuedIdentity) { var tokenPolicy = this.RemoteEndpoint.UserIdentityTokens.FirstOrDefault(t => t.TokenType == UserTokenType.IssuedToken); if (tokenPolicy == null) { throw new ServiceResultException(StatusCodes.BadIdentityTokenRejected); } var issuedIdentity = (IssuedIdentity)this.UserIdentity; int plainTextLength = issuedIdentity.TokenData.Length + this.RemoteNonce.Length; IBufferedCipher encryptor; byte[] cipherText; int pos; var secPolicyUri = tokenPolicy.SecurityPolicyUri ?? this.RemoteEndpoint.SecurityPolicyUri; switch (secPolicyUri) { case SecurityPolicyUris.Basic128Rsa15: encryptor = CipherUtilities.GetCipher("RSA//PKCS1Padding"); encryptor.Init(true, this.RemotePublicKey); cipherText = new byte[encryptor.GetOutputSize(4 + plainTextLength)]; pos = encryptor.ProcessBytes(BitConverter.GetBytes(plainTextLength), cipherText, 0); pos = encryptor.ProcessBytes(issuedIdentity.TokenData, cipherText, pos); pos = encryptor.DoFinal(this.RemoteNonce, cipherText, pos); identityToken = new IssuedIdentityToken { TokenData = cipherText, EncryptionAlgorithm = RsaV15KeyWrap, PolicyId = tokenPolicy.PolicyId }; break; case SecurityPolicyUris.Basic256: case SecurityPolicyUris.Basic256Sha256: case SecurityPolicyUris.Aes128_Sha256_RsaOaep: encryptor = CipherUtilities.GetCipher("RSA//OAEPPADDING"); encryptor.Init(true, this.RemotePublicKey); cipherText = new byte[encryptor.GetOutputSize(4 + plainTextLength)]; pos = encryptor.ProcessBytes(BitConverter.GetBytes(plainTextLength), cipherText, 0); pos = encryptor.ProcessBytes(issuedIdentity.TokenData, cipherText, pos); pos = encryptor.DoFinal(this.RemoteNonce, cipherText, pos); identityToken = new IssuedIdentityToken { TokenData = cipherText, EncryptionAlgorithm = RsaOaepKeyWrap, PolicyId = tokenPolicy.PolicyId }; break; case SecurityPolicyUris.Aes256_Sha256_RsaPss: encryptor = CipherUtilities.GetCipher("RSA//OAEPWITHSHA256ANDMGF1PADDING"); encryptor.Init(true, this.RemotePublicKey); cipherText = new byte[encryptor.GetOutputSize(4 + plainTextLength)]; pos = encryptor.ProcessBytes(BitConverter.GetBytes(plainTextLength), cipherText, 0); pos = encryptor.ProcessBytes(issuedIdentity.TokenData, cipherText, pos); pos = encryptor.DoFinal(this.RemoteNonce, cipherText, pos); identityToken = new IssuedIdentityToken { TokenData = cipherText, EncryptionAlgorithm = RsaOaepSha256KeyWrap, PolicyId = tokenPolicy.PolicyId }; break; default: identityToken = new IssuedIdentityToken { TokenData = issuedIdentity.TokenData, EncryptionAlgorithm = null, PolicyId = tokenPolicy.PolicyId }; break; } tokenSignature = new SignatureData(); encryptor = null; cipherText = null; } // if UserIdentity type is X509Identity else if (this.UserIdentity is X509Identity) { var tokenPolicy = this.RemoteEndpoint.UserIdentityTokens.FirstOrDefault(t => t.TokenType == UserTokenType.Certificate); if (tokenPolicy == null) { throw new ServiceResultException(StatusCodes.BadIdentityTokenRejected); } var x509Identity = (X509Identity)this.UserIdentity; identityToken = new X509IdentityToken { CertificateData = x509Identity.Certificate?.GetEncoded(), PolicyId = tokenPolicy.PolicyId }; var secPolicyUri = tokenPolicy.SecurityPolicyUri ?? this.RemoteEndpoint.SecurityPolicyUri; switch (secPolicyUri) { case SecurityPolicyUris.Basic128Rsa15: case SecurityPolicyUris.Basic256: signer = SignerUtilities.GetSigner("SHA-1withRSA"); signer.Init(true, x509Identity.PrivateKey); signer.BlockUpdate(this.RemoteEndpoint.ServerCertificate, 0, this.RemoteEndpoint.ServerCertificate.Length); signer.BlockUpdate(this.RemoteNonce, 0, this.RemoteNonce.Length); tokenSignature = new SignatureData { Signature = signer.GenerateSignature(), Algorithm = RsaSha1Signature, }; break; case SecurityPolicyUris.Basic256Sha256: case SecurityPolicyUris.Aes128_Sha256_RsaOaep: signer = SignerUtilities.GetSigner("SHA-256withRSA"); signer.Init(true, x509Identity.PrivateKey); signer.BlockUpdate(this.RemoteEndpoint.ServerCertificate, 0, this.RemoteEndpoint.ServerCertificate.Length); signer.BlockUpdate(this.RemoteNonce, 0, this.RemoteNonce.Length); tokenSignature = new SignatureData { Signature = signer.GenerateSignature(), Algorithm = RsaSha256Signature, }; break; case SecurityPolicyUris.Aes256_Sha256_RsaPss: signer = SignerUtilities.GetSigner("SHA-256withRSAandMGF1"); signer.Init(true, x509Identity.PrivateKey); signer.BlockUpdate(this.RemoteEndpoint.ServerCertificate, 0, this.RemoteEndpoint.ServerCertificate.Length); signer.BlockUpdate(this.RemoteNonce, 0, this.RemoteNonce.Length); tokenSignature = new SignatureData { Signature = signer.GenerateSignature(), Algorithm = RsaSha256Signature, }; break; default: tokenSignature = new SignatureData(); break; } signer = null; } // if UserIdentity type is UserNameIdentity else if (this.UserIdentity is UserNameIdentity) { var tokenPolicy = this.RemoteEndpoint.UserIdentityTokens.FirstOrDefault(t => t.TokenType == UserTokenType.UserName); if (tokenPolicy == null) { throw new ServiceResultException(StatusCodes.BadIdentityTokenRejected); } var userNameIdentity = (UserNameIdentity)this.UserIdentity; byte[] passwordBytes = userNameIdentity.Password != null?System.Text.Encoding.UTF8.GetBytes(userNameIdentity.Password) : new byte[0]; int plainTextLength = passwordBytes.Length + this.RemoteNonce.Length; IBufferedCipher encryptor; byte[] cipherText; int pos; var secPolicyUri = tokenPolicy.SecurityPolicyUri ?? this.RemoteEndpoint.SecurityPolicyUri; switch (secPolicyUri) { case SecurityPolicyUris.Basic128Rsa15: encryptor = CipherUtilities.GetCipher("RSA//PKCS1Padding"); encryptor.Init(true, this.RemotePublicKey); cipherText = new byte[encryptor.GetOutputSize(4 + plainTextLength)]; pos = encryptor.ProcessBytes(BitConverter.GetBytes(plainTextLength), cipherText, 0); pos = encryptor.ProcessBytes(passwordBytes, cipherText, pos); pos = encryptor.DoFinal(this.RemoteNonce, cipherText, pos); identityToken = new UserNameIdentityToken { UserName = userNameIdentity.UserName, Password = cipherText, EncryptionAlgorithm = RsaV15KeyWrap, PolicyId = tokenPolicy.PolicyId }; break; case SecurityPolicyUris.Basic256: case SecurityPolicyUris.Basic256Sha256: case SecurityPolicyUris.Aes128_Sha256_RsaOaep: encryptor = CipherUtilities.GetCipher("RSA//OAEPPADDING"); encryptor.Init(true, this.RemotePublicKey); cipherText = new byte[encryptor.GetOutputSize(4 + plainTextLength)]; pos = encryptor.ProcessBytes(BitConverter.GetBytes(plainTextLength), cipherText, 0); pos = encryptor.ProcessBytes(passwordBytes, cipherText, pos); pos = encryptor.DoFinal(this.RemoteNonce, cipherText, pos); identityToken = new UserNameIdentityToken { UserName = userNameIdentity.UserName, Password = cipherText, EncryptionAlgorithm = RsaOaepKeyWrap, PolicyId = tokenPolicy.PolicyId }; break; case SecurityPolicyUris.Aes256_Sha256_RsaPss: encryptor = CipherUtilities.GetCipher("RSA//OAEPWITHSHA256ANDMGF1PADDING"); encryptor.Init(true, this.RemotePublicKey); cipherText = new byte[encryptor.GetOutputSize(4 + plainTextLength)]; pos = encryptor.ProcessBytes(BitConverter.GetBytes(plainTextLength), cipherText, 0); pos = encryptor.ProcessBytes(passwordBytes, cipherText, pos); pos = encryptor.DoFinal(this.RemoteNonce, cipherText, pos); identityToken = new UserNameIdentityToken { UserName = userNameIdentity.UserName, Password = cipherText, EncryptionAlgorithm = RsaOaepSha256KeyWrap, PolicyId = tokenPolicy.PolicyId }; break; default: identityToken = new UserNameIdentityToken { UserName = userNameIdentity.UserName, Password = passwordBytes, EncryptionAlgorithm = null, PolicyId = tokenPolicy.PolicyId }; break; } tokenSignature = new SignatureData(); passwordBytes = null; encryptor = null; cipherText = null; } // if UserIdentity type is AnonymousIdentity or null else { var tokenPolicy = this.RemoteEndpoint.UserIdentityTokens.FirstOrDefault(t => t.TokenType == UserTokenType.Anonymous); if (tokenPolicy == null) { throw new ServiceResultException(StatusCodes.BadIdentityTokenRejected); } identityToken = new AnonymousIdentityToken { PolicyId = tokenPolicy.PolicyId }; tokenSignature = new SignatureData(); } var activateSessionRequest = new ActivateSessionRequest { ClientSignature = clientSignature, LocaleIds = new[] { CultureInfo.CurrentUICulture.TwoLetterISOLanguageName }, UserIdentityToken = identityToken, UserTokenSignature = tokenSignature }; var activateSessionResponse = await this.ActivateSessionAsync(activateSessionRequest).ConfigureAwait(false); this.RemoteNonce = activateSessionResponse.ServerNonce; // fetch namespace array, etc. var readValueIds = new ReadValueId[] { new ReadValueId { NodeId = NodeId.Parse(VariableIds.Server_NamespaceArray), AttributeId = AttributeIds.Value }, new ReadValueId { NodeId = NodeId.Parse(VariableIds.Server_ServerArray), AttributeId = AttributeIds.Value } }; var readRequest = new ReadRequest { NodesToRead = readValueIds }; var readResponse = await this.ReadAsync(readRequest).ConfigureAwait(false); if (readResponse.Results.Length == 2) { if (StatusCode.IsGood(readResponse.Results[0].StatusCode)) { this.NamespaceUris.Clear(); this.NamespaceUris.AddRange(readResponse.Results[0].GetValueOrDefault <string[]>()); } if (StatusCode.IsGood(readResponse.Results[1].StatusCode)) { this.ServerUris.Clear(); this.ServerUris.AddRange(readResponse.Results[1].GetValueOrDefault <string[]>()); } } // create the keep alive subscription. var subscriptionRequest = new CreateSubscriptionRequest { RequestedPublishingInterval = DefaultPublishingInterval, RequestedMaxKeepAliveCount = DefaultKeepaliveCount, RequestedLifetimeCount = DefaultKeepaliveCount * 3, PublishingEnabled = true, }; var subscriptionResponse = await this.CreateSubscriptionAsync(subscriptionRequest).ConfigureAwait(false); // link up the dataflow blocks var id = subscriptionResponse.SubscriptionId; var linkToken = this.LinkTo(this.actionBlock, pr => pr.SubscriptionId == id); // start publishing. this.stateMachineTask = Task.Run(() => this.StateMachineAsync(this.stateMachineCts.Token)); }
/// <summary> /// Reads and displays the new values. /// </summary> private void ReadAttributes() { // Prepare call to ClientAPI. int i = 0; foreach (ListViewItem item in this.listView.Items) { ReadValueIdCollection nodesToRead = new ReadValueIdCollection(); WriteValueInfo info = item.Tag as WriteValueInfo; // DataType nodesToRead.Add(new ReadValueId() { NodeId = info.NodeId, AttributeId = Attributes.DataType }); // ValueRank nodesToRead.Add(new ReadValueId() { NodeId = info.NodeId, AttributeId = Attributes.ValueRank }); // ArrayDimension nodesToRead.Add(new ReadValueId() { NodeId = info.NodeId, AttributeId = Attributes.ArrayDimensions }); // Call to ClientAPI. List <DataValue> readResults = new List <DataValue>(); try { readResults = m_Session.Read( nodesToRead, 0, TimestampsToReturn.Both, null); if (StatusCode.IsGood(readResults[0].StatusCode) && StatusCode.IsGood(readResults[1].StatusCode)) { // datatype info.DataType = TypeUtils.GetBuiltInType((NodeId)readResults[0].Value, m_Session.Cache); // value rank info.ValueRank = (int)readResults[1].Value; // array dimension if (info.ValueRank == ValueRanks.Scalar) { info.ArrayDimensions = null; info.AttributesRead = true; } else if (info.ValueRank == ValueRanks.OneDimension) { info.ArrayDimensions = readResults[1].Value as List <uint>; info.AttributesRead = true; } // can't handle else { info.Error = true; } } else { info.Error = true; } // Update status label. lblStatus.Text = "Reading attributes succeeded."; } catch (Exception e) { // Update status label. lblStatus.Text = "An exception occured while reading attributes: " + e.Message; } i++; } }
/// <summary> /// Reads the arguments for the method. /// </summary> private void ReadArguments(NodeId nodeId) { m_inputArguments = null; m_outputArguments = null; // build list of references to browse. BrowseDescriptionCollection nodesToBrowse = new BrowseDescriptionCollection(); BrowseDescription nodeToBrowse = new BrowseDescription(); nodeToBrowse.NodeId = nodeId; nodeToBrowse.BrowseDirection = BrowseDirection.Forward; nodeToBrowse.ReferenceTypeId = Opc.Ua.ReferenceTypeIds.HasProperty; nodeToBrowse.IncludeSubtypes = true; nodeToBrowse.NodeClassMask = (uint)NodeClass.Variable; nodeToBrowse.ResultMask = (uint)BrowseResultMask.BrowseName; nodesToBrowse.Add(nodeToBrowse); // find properties. ReferenceDescriptionCollection references = ClientUtils.Browse(m_session, null, nodesToBrowse, false); // build list of properties to read. ReadValueIdCollection nodesToRead = new ReadValueIdCollection(); for (int ii = 0; references != null && ii < references.Count; ii++) { ReferenceDescription reference = references[ii]; // ignore out of server references. if (reference.NodeId.IsAbsolute) { continue; } // ignore other properties. if (reference.BrowseName != Opc.Ua.BrowseNames.InputArguments && reference.BrowseName != Opc.Ua.BrowseNames.OutputArguments) { continue; } ReadValueId nodeToRead = new ReadValueId(); nodeToRead.NodeId = (NodeId)reference.NodeId; nodeToRead.AttributeId = Attributes.Value; nodeToRead.Handle = reference; nodesToRead.Add(nodeToRead); } // method has no arguments. if (nodesToRead.Count == 0) { return; } // read the arguments. DataValueCollection results = null; DiagnosticInfoCollection diagnosticInfos = null; m_session.Read( null, 0, TimestampsToReturn.Neither, nodesToRead, out results, out diagnosticInfos); ClientBase.ValidateResponse(results, nodesToRead); ClientBase.ValidateDiagnosticInfos(diagnosticInfos, nodesToRead); // save the results. for (int ii = 0; ii < results.Count; ii++) { ReferenceDescription reference = (ReferenceDescription)nodesToRead[ii].Handle; if (StatusCode.IsGood(results[ii].StatusCode)) { if (reference.BrowseName == Opc.Ua.BrowseNames.InputArguments) { m_inputArguments = (Argument[])ExtensionObject.ToArray(results[ii].GetValue <ExtensionObject[]>(null), typeof(Argument)); } if (reference.BrowseName == Opc.Ua.BrowseNames.OutputArguments) { m_outputArguments = (Argument[])ExtensionObject.ToArray(results[ii].GetValue <ExtensionObject[]>(null), typeof(Argument)); } } } // set default values for input arguments. if (m_inputArguments != null) { foreach (Argument argument in m_inputArguments) { argument.Value = TypeInfo.GetDefaultValue(argument.DataType, argument.ValueRank, m_session.TypeTree); } } }
/// <summary> /// Peridically checks the system state. /// </summary> private void OnCheckSystemStatus(object state) { #if CONDITION_SAMPLES lock (Lock) { try { // create the dialog. if (_dialog == null) { _dialog = new DialogConditionState(null); CreateNode( SystemContext, ExpandedNodeId.ToNodeId(ObjectIds.Data_Conditions, SystemContext.NamespaceUris), ReferenceTypeIds.HasComponent, new QualifiedName("ResetSystemDialog", _namespaceIndex), _dialog); _dialog.OnAfterResponse = OnDialogComplete; } StatusCode systemStatus = _system.SystemStatus; _systemStatusCondition.UpdateStatus(systemStatus); // cycle through different status codes in order to simulate a real system. if (StatusCode.IsGood(systemStatus)) { _systemStatusCondition.UpdateSeverity((ushort)EventSeverity.Low); _system.SystemStatus = StatusCodes.Uncertain; } else if (StatusCode.IsUncertain(systemStatus)) { _systemStatusCondition.UpdateSeverity((ushort)EventSeverity.Medium); _system.SystemStatus = StatusCodes.Bad; } else { _systemStatusCondition.UpdateSeverity((ushort)EventSeverity.High); _system.SystemStatus = StatusCodes.Good; } // request a reset if status is bad. if (StatusCode.IsBad(systemStatus)) { _dialog.RequestResponse( SystemContext, "Reset the test system?", (uint)(int)(DialogConditionChoice.Ok | DialogConditionChoice.Cancel), (ushort)EventSeverity.MediumHigh); } // report the event. TranslationInfo info = new TranslationInfo( "TestSystemStatusChange", "en-US", "The TestSystem status is now {0}.", systemStatus); _systemStatusCondition.ReportConditionChange( SystemContext, null, new LocalizedText(info), false); } catch (Exception e) { Utils.Trace(e, "Unexpected error monitoring system status."); } } #endif }
protected override async Task OnOpenAsync(CancellationToken token) { await base.OnOpenAsync(token).ConfigureAwait(false); token.ThrowIfCancellationRequested(); // if SessionId is provided then we skip the CreateSessionRequest and go directly to (re)ActivateSession. // requires from previous Session: SessionId, AuthenticationToken, RemoteNonce if (this.SessionId == null) { var localNonce = this.RemoteEndpoint.SecurityMode != MessageSecurityMode.None ? this.GetNextNonce() : null; var localCertificateBlob = this.RemoteEndpoint.SecurityMode != MessageSecurityMode.None ? this.LocalCertificate.RawData : null; var createSessionRequest = new CreateSessionRequest { ClientDescription = this.LocalDescription, EndpointUrl = this.RemoteEndpoint.EndpointUrl, SessionName = this.LocalDescription.ApplicationName, ClientNonce = localNonce, ClientCertificate = localCertificateBlob, RequestedSessionTimeout = this.SessionTimeout, MaxResponseMessageSize = this.RemoteMaxMessageSize }; var createSessionResponse = await this.CreateSessionAsync(createSessionRequest).ConfigureAwait(false); this.SessionId = createSessionResponse.SessionId; this.AuthenticationToken = createSessionResponse.AuthenticationToken; this.RemoteNonce = createSessionResponse.ServerNonce; // verify the server's certificate is the same as the certificate from the selected endpoint. if (this.RemoteEndpoint.ServerCertificate != null && !this.RemoteEndpoint.ServerCertificate.SequenceEqual(createSessionResponse.ServerCertificate)) { throw new ServiceResultException(StatusCodes.BadCertificateInvalid, "Server did not return the same certificate used to create the channel."); } // verify the server's signature. switch (this.RemoteEndpoint.SecurityPolicyUri) { case SecurityPolicyUris.Basic128Rsa15: case SecurityPolicyUris.Basic256: byte[] dataToVerify = Concat(localCertificateBlob, localNonce); if (!this.RemotePublicKey.VerifyData(dataToVerify, createSessionResponse.ServerSignature.Signature, HashAlgorithmName.SHA1, RSASignaturePadding.Pkcs1)) { throw new ServiceResultException(StatusCodes.BadApplicationSignatureInvalid, "Server did not provide a correct signature for the nonce data provided by the client."); } break; case SecurityPolicyUris.Basic256Sha256: byte[] dataToVerify256 = Concat(localCertificateBlob, localNonce); if (!this.RemotePublicKey.VerifyData(dataToVerify256, createSessionResponse.ServerSignature.Signature, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1)) { throw new ServiceResultException(StatusCodes.BadApplicationSignatureInvalid, "Server did not provide a correct signature for the nonce data provided by the client."); } break; default: break; } } // create client signature SignatureData clientSignature = null; switch (this.RemoteEndpoint.SecurityPolicyUri) { case SecurityPolicyUris.Basic128Rsa15: case SecurityPolicyUris.Basic256: byte[] dataToSign = Concat(this.RemoteEndpoint.ServerCertificate, this.RemoteNonce); clientSignature = new SignatureData { Signature = this.LocalPrivateKey.SignData(dataToSign, HashAlgorithmName.SHA1, RSASignaturePadding.Pkcs1), Algorithm = RsaSha1Signature, }; break; case SecurityPolicyUris.Basic256Sha256: byte[] dataToSign256 = Concat(this.RemoteEndpoint.ServerCertificate, this.RemoteNonce); clientSignature = new SignatureData { Signature = this.LocalPrivateKey.SignData(dataToSign256, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1), Algorithm = RsaSha256Signature, }; break; default: clientSignature = new SignatureData(); break; } // supported UserIdentityToken types are AnonymousIdentityToken, UserNameIdentityToken, IssuedIdentityToken, X509IdentityToken UserIdentityToken identityToken = null; SignatureData tokenSignature = null; // if UserIdentity type is IssuedIdentity if (this.UserIdentity is IssuedIdentity) { var tokenPolicy = this.RemoteEndpoint.UserIdentityTokens.FirstOrDefault(t => t.TokenType == UserTokenType.IssuedToken); if (tokenPolicy == null) { throw new ServiceResultException(StatusCodes.BadIdentityTokenRejected); } var issuedIdentity = (IssuedIdentity)this.UserIdentity; byte[] plainText = Concat(issuedIdentity.TokenData, this.RemoteNonce); var secPolicyUri = tokenPolicy.SecurityPolicyUri ?? this.RemoteEndpoint.SecurityPolicyUri; RSA asymRemoteEncryptionKey; switch (secPolicyUri) { case SecurityPolicyUris.Basic128Rsa15: asymRemoteEncryptionKey = this.RemoteCertificate.GetRSAPublicKey(); identityToken = new IssuedIdentityToken { TokenData = asymRemoteEncryptionKey.EncryptTokenData(plainText, secPolicyUri), EncryptionAlgorithm = RsaV15KeyWrap, PolicyId = tokenPolicy.PolicyId }; break; case SecurityPolicyUris.Basic256: case SecurityPolicyUris.Basic256Sha256: asymRemoteEncryptionKey = this.RemoteCertificate.GetRSAPublicKey(); identityToken = new IssuedIdentityToken { TokenData = asymRemoteEncryptionKey.EncryptTokenData(plainText, secPolicyUri), EncryptionAlgorithm = RsaOaepKeyWrap, PolicyId = tokenPolicy.PolicyId }; break; default: identityToken = new IssuedIdentityToken { TokenData = issuedIdentity.TokenData, EncryptionAlgorithm = null, PolicyId = tokenPolicy.PolicyId }; break; } tokenSignature = new SignatureData(); } // if UserIdentity type is X509Identity else if (this.UserIdentity is X509Identity) { var tokenPolicy = this.RemoteEndpoint.UserIdentityTokens.FirstOrDefault(t => t.TokenType == UserTokenType.Certificate); if (tokenPolicy == null) { throw new ServiceResultException(StatusCodes.BadIdentityTokenRejected); } var x509Identity = (X509Identity)this.UserIdentity; identityToken = new X509IdentityToken { CertificateData = x509Identity.Certificate?.RawData, PolicyId = tokenPolicy.PolicyId }; var secPolicyUri = tokenPolicy.SecurityPolicyUri ?? this.RemoteEndpoint.SecurityPolicyUri; switch (secPolicyUri) { case SecurityPolicyUris.Basic128Rsa15: case SecurityPolicyUris.Basic256: var asymSigningKey = x509Identity.Certificate?.GetRSAPrivateKey(); if (asymSigningKey != null) { byte[] dataToSign = Concat(this.RemoteEndpoint.ServerCertificate, this.RemoteNonce); tokenSignature = new SignatureData { Signature = asymSigningKey.SignData(dataToSign, HashAlgorithmName.SHA1, RSASignaturePadding.Pkcs1), Algorithm = RsaSha1Signature, }; break; } tokenSignature = new SignatureData(); break; case SecurityPolicyUris.Basic256Sha256: var asymSigningKey256 = x509Identity.Certificate?.GetRSAPrivateKey(); if (asymSigningKey256 != null) { byte[] dataToSign256 = Concat(this.RemoteEndpoint.ServerCertificate, this.RemoteNonce); tokenSignature = new SignatureData { Signature = asymSigningKey256.SignData(dataToSign256, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1), Algorithm = RsaSha256Signature, }; break; } tokenSignature = new SignatureData(); break; default: tokenSignature = new SignatureData(); break; } } // if UserIdentity type is UserNameIdentity else if (this.UserIdentity is UserNameIdentity) { var tokenPolicy = this.RemoteEndpoint.UserIdentityTokens.FirstOrDefault(t => t.TokenType == UserTokenType.UserName); if (tokenPolicy == null) { throw new ServiceResultException(StatusCodes.BadIdentityTokenRejected); } var userNameIdentity = (UserNameIdentity)this.UserIdentity; byte[] plainText = Concat(System.Text.Encoding.UTF8.GetBytes(userNameIdentity.Password), this.RemoteNonce); var secPolicyUri = tokenPolicy.SecurityPolicyUri ?? this.RemoteEndpoint.SecurityPolicyUri; RSA asymRemoteEncryptionKey; switch (secPolicyUri) { case SecurityPolicyUris.Basic128Rsa15: asymRemoteEncryptionKey = this.RemoteCertificate.GetRSAPublicKey(); identityToken = new UserNameIdentityToken { UserName = userNameIdentity.UserName, Password = asymRemoteEncryptionKey.EncryptTokenData(plainText, secPolicyUri), EncryptionAlgorithm = RsaV15KeyWrap, PolicyId = tokenPolicy.PolicyId }; break; case SecurityPolicyUris.Basic256: case SecurityPolicyUris.Basic256Sha256: asymRemoteEncryptionKey = this.RemoteCertificate.GetRSAPublicKey(); identityToken = new UserNameIdentityToken { UserName = userNameIdentity.UserName, Password = asymRemoteEncryptionKey.EncryptTokenData(plainText, secPolicyUri), EncryptionAlgorithm = RsaOaepKeyWrap, PolicyId = tokenPolicy.PolicyId }; break; default: identityToken = new UserNameIdentityToken { UserName = userNameIdentity.UserName, Password = System.Text.Encoding.UTF8.GetBytes(userNameIdentity.Password), EncryptionAlgorithm = null, PolicyId = tokenPolicy.PolicyId }; break; } tokenSignature = new SignatureData(); } // if UserIdentity type is AnonymousIdentity or null else { var tokenPolicy = this.RemoteEndpoint.UserIdentityTokens.FirstOrDefault(t => t.TokenType == UserTokenType.Anonymous); if (tokenPolicy == null) { throw new ServiceResultException(StatusCodes.BadIdentityTokenRejected); } identityToken = new AnonymousIdentityToken { PolicyId = tokenPolicy.PolicyId }; tokenSignature = new SignatureData(); } var activateSessionRequest = new ActivateSessionRequest { ClientSignature = clientSignature, LocaleIds = new[] { CultureInfo.CurrentUICulture.TwoLetterISOLanguageName }, UserIdentityToken = identityToken, UserTokenSignature = tokenSignature }; var activateSessionResponse = await this.ActivateSessionAsync(activateSessionRequest).ConfigureAwait(false); this.RemoteNonce = activateSessionResponse.ServerNonce; // fetch namespace array, etc. var readValueIds = new ReadValueId[] { new ReadValueId { NodeId = NodeId.Parse(VariableIds.Server_NamespaceArray), AttributeId = AttributeIds.Value }, new ReadValueId { NodeId = NodeId.Parse(VariableIds.Server_ServerArray), AttributeId = AttributeIds.Value } }; var readRequest = new ReadRequest { NodesToRead = readValueIds }; var readResponse = await this.ReadAsync(readRequest).ConfigureAwait(false); if (readResponse.Results.Length == 2) { if (StatusCode.IsGood(readResponse.Results[0].StatusCode)) { this.NamespaceUris.Clear(); this.NamespaceUris.AddRange(readResponse.Results[0].GetValueOrDefault <string[]>()); } if (StatusCode.IsGood(readResponse.Results[1].StatusCode)) { this.ServerUris.Clear(); this.ServerUris.AddRange(readResponse.Results[1].GetValueOrDefault <string[]>()); } } }
/// <inheritdoc/> public async Task <Session> GetOrCreateSessionAsync(ConnectionModel connection, bool createIfNotExists, uint statusCode = StatusCodes.Good) { // Find session and if not exists create var id = new ConnectionIdentifier(connection); SessionWrapper wrapper = null; await _lock.WaitAsync(); try { // try to get an existing session try { if (!_sessions.TryGetValue(id, out wrapper)) { if (!createIfNotExists) { return(null); } wrapper = new SessionWrapper() { MissedKeepAlives = 0, MaxKeepAlives = _clientConfig.MaxKeepAliveCount, State = SessionState.Init, Session = null, IdleCount = 0 }; _sessions.Add(id, wrapper); } switch (wrapper.State) { case SessionState.Reconnecting: case SessionState.Connecting: // nothing to do the consumer will either retry or handle the issue return(null); case SessionState.Running: if (StatusCode.IsGood(statusCode)) { return(wrapper.Session); } wrapper.State = SessionState.Reconnecting; break; case SessionState.Retry: wrapper.State = SessionState.Reconnecting; break; case SessionState.Init: case SessionState.Failed: wrapper.State = SessionState.Connecting; break; default: throw new InvalidOperationException($"Illegal SessionState ({wrapper.State})"); } } catch (Exception ex) { _logger.Error(ex, "Failed to get/create as session for Id {id}.", id); throw; } finally { _lock.Release(); } while (true) { switch (wrapper.State) { case SessionState.Reconnecting: // attempt to reactivate try { wrapper.MissedKeepAlives++; _logger.Information("Session '{name}' missed {keepAlives} keep alive(s) due to {status}." + " Awaiting for reconnect...", wrapper.Session.SessionName, wrapper.MissedKeepAlives, new StatusCode(statusCode)); wrapper.Session.Reconnect(); wrapper.State = SessionState.Running; wrapper.MissedKeepAlives = 0; return(wrapper.Session); } catch (Exception e) { if (e is ServiceResultException sre) { switch (sre.StatusCode) { case StatusCodes.BadNotConnected: case StatusCodes.BadNoCommunication: case StatusCodes.BadSessionNotActivated: case StatusCodes.BadServerHalted: case StatusCodes.BadServerNotConnected: _logger.Warning("Failed to reconnect session {sessionName}." + " Retry reconnection later.", wrapper.Session.SessionName); wrapper.State = SessionState.Retry; if (wrapper.MissedKeepAlives < wrapper.MaxKeepAlives) { return(null); } break; default: break; } } // cleanup the session _logger.Warning("Failed to reconnect session {sessionName} due to {exception}." + " Disposing and trying create new.", wrapper.Session.SessionName, e.Message); if (wrapper.Session.SubscriptionCount > 0) { foreach (var subscription in wrapper.Session.Subscriptions) { Try.Op(() => subscription.DeleteItems()); Try.Op(() => subscription.Delete(true)); } Try.Op(() => wrapper.Session.RemoveSubscriptions(wrapper.Session.Subscriptions)); } Try.Op(wrapper.Session.Close); Try.Op(wrapper.Session.Dispose); wrapper.Session = null; wrapper.MissedKeepAlives = 0; wrapper.State = SessionState.Connecting; } break; case SessionState.Connecting: if (wrapper.Session != null) { _logger.Warning("Session {sessionName} still attached to wrapper in {state}", wrapper.Session.SessionName, wrapper.State); Try.Op(wrapper.Session.Dispose); wrapper.Session = null; } var endpointUrlCandidates = id.Connection.Endpoint.Url.YieldReturn(); if (id.Connection.Endpoint.AlternativeUrls != null) { endpointUrlCandidates = endpointUrlCandidates.Concat( id.Connection.Endpoint.AlternativeUrls); } var exceptions = new List <Exception>(); foreach (var endpointUrl in endpointUrlCandidates) { try { var session = await CreateSessionAsync(endpointUrl, id); if (session != null) { _logger.Information("Connected on {endpointUrl}", endpointUrl); wrapper.Session = session; wrapper.State = SessionState.Running; return(wrapper.Session); } } catch (Exception ex) { _logger.Debug("Failed to connect on {endpointUrl}: {message} - try again...", endpointUrl, ex.Message); exceptions.Add(ex); } } throw new AggregateException(exceptions); default: throw new InvalidOperationException($"Invalid SessionState ({wrapper.State}) not handled."); } } } catch (ServiceResultException sre) { _logger.Warning("Failed to get or create session {id} due to {exception}.", id, sre.StatusCode.ToString()); } catch (AggregateException aex) { _logger.Warning("Failed to get or create session {id} due to {exception}.", id, aex.Message); } catch (Exception ex) { _logger.Error(ex, "Failed to get or create session."); } wrapper.State = SessionState.Failed; return(null); }
/// <summary> /// Formats a value for display in the control. /// </summary> private string GetValueText(object value) { // check for null. if (value == null) { return("(null)"); } // format bytes. byte[] bytes = value as byte[]; if (bytes != null) { StringBuilder buffer = new StringBuilder(); for (int ii = 0; ii < bytes.Length; ii++) { if (ii != 0 && ii % 16 == 0) { buffer.Append(" "); } buffer.AppendFormat("{0:X2} ", bytes[ii]); } return(buffer.ToString()); } // format xml element. XmlElement xml = value as XmlElement; if (xml != null) { // return the entire element if not expandable. if (!IsExpandableType(xml)) { return(xml.OuterXml); } // show only the start tag. string text = xml.OuterXml; int index = text.IndexOf('>'); if (index != -1) { text = text.Substring(0, index); } return(text); } // format array. Array array = value as Array; if (array != null) { if (array.Rank > 1) { int[] lenghts = new int[array.Rank]; for (int i = 0; i < array.Rank; ++i) { lenghts[i] = array.GetLength(i); } return(Utils.Format("{1}[{0}]", string.Join(",", lenghts), value.GetType().GetElementType().Name)); } else { return(Utils.Format("{1}[{0}]", array.Length, value.GetType().GetElementType().Name)); } } // format list. IList list = value as IList; if (list != null) { string type = value.GetType().Name; if (type.EndsWith("Collection")) { type = type.Substring(0, type.Length - "Collection".Length); } else { type = "Object"; } return(Utils.Format("{1}[{0}]", list.Count, type)); } // format encodeable object. IEncodeable encodeable = value as IEncodeable; if (encodeable != null) { return(encodeable.GetType().Name); } // format extension object. ExtensionObject extension = value as ExtensionObject; if (extension != null) { return(GetValueText(extension.Body)); } // check for event value. EventFieldList eventFields = value as EventFieldList; if (eventFields != null) { if (m_monitoredItem != null) { return(String.Format("{0}", m_monitoredItem.GetEventType(eventFields))); } return(eventFields.GetType().Name); } // check for data value. DataValue dataValue = value as DataValue; if (dataValue != null) { StringBuilder formattedValue = new StringBuilder(); if (!StatusCode.IsGood(dataValue.StatusCode)) { formattedValue.Append("["); formattedValue.AppendFormat("Q:{0}", dataValue.StatusCode); } DateTime now = DateTime.UtcNow; if ((dataValue != null) && ((dataValue.ServerTimestamp > now) || (dataValue.SourceTimestamp > now))) { if (formattedValue.ToString().Length > 0) { formattedValue.Append(", "); } else { formattedValue.Append("["); } formattedValue.Append("T:future"); } if (formattedValue.ToString().Length > 0) { formattedValue.Append("] "); } formattedValue.AppendFormat("{0}", dataValue.Value); return(formattedValue.ToString()); } // use default formatting. return(Utils.Format("{0}", value)); }
public async Task TransferSubscriptions() { // get or add application certificate. var localCertificate = this.localDescription.GetCertificate(); if (localCertificate == null) { throw new ServiceResultException(StatusCodes.BadSecurityChecksFailed, "Application certificate is missing."); } // discover available endpoints of server. var getEndpointsRequest = new GetEndpointsRequest { EndpointUrl = this.endpointUrl, ProfileUris = new[] { TransportProfileUris.UaTcpTransport } }; Console.WriteLine($"Discovering endpoints of '{getEndpointsRequest.EndpointUrl}'."); var getEndpointsResponse = await UaTcpDiscoveryClient.GetEndpointsAsync(getEndpointsRequest); var selectedEndpoint = getEndpointsResponse.Endpoints.OrderBy(e => e.SecurityLevel).Last(); IUserIdentity selectedUserIdentity = new UserNameIdentity("root", "secret"); var channel = new UaTcpSessionChannel( this.localDescription, localCertificate, selectedUserIdentity, selectedEndpoint); Console.WriteLine($"Creating session with endpoint '{channel.RemoteEndpoint.EndpointUrl}'."); Console.WriteLine($"SecurityPolicy: '{channel.RemoteEndpoint.SecurityPolicyUri}'."); Console.WriteLine($"SecurityMode: '{channel.RemoteEndpoint.SecurityMode}'."); await channel.OpenAsync(); Console.WriteLine($"Activated session '{channel.SessionId}'."); var req = new CreateSubscriptionRequest { RequestedPublishingInterval = 1000, RequestedMaxKeepAliveCount = 20, PublishingEnabled = true }; var res = await channel.CreateSubscriptionAsync(req); Console.WriteLine($"Created subscription '{res.SubscriptionId}'."); Console.WriteLine($"Aborting session '{channel.SessionId}'."); await channel.AbortAsync(); var channel2 = new UaTcpSessionChannel( this.localDescription, localCertificate, selectedUserIdentity, selectedEndpoint); await channel2.OpenAsync(); Console.WriteLine($"Activated session '{channel2.SessionId}'."); var req2 = new TransferSubscriptionsRequest { SubscriptionIds = new[] { res.SubscriptionId } }; var res2 = await channel2.TransferSubscriptionsAsync(req2); Console.WriteLine($"Transferred subscription result '{res2.Results[0].StatusCode}'."); Console.WriteLine($"Closing session '{channel2.SessionId}'."); await channel2.CloseAsync(); Assert.IsTrue(StatusCode.IsGood(res2.Results[0].StatusCode)); }
public async Task TransferSubscription() { var channel1 = new UaTcpSessionChannel( this.localDescription, this.certificateStore, new UserNameIdentity("root", "secret"), EndpointUrl, loggerFactory: this.loggerFactory); await channel1.OpenAsync(); Console.WriteLine($"Opened session with endpoint '{channel1.RemoteEndpoint.EndpointUrl}'."); Console.WriteLine($"SecurityPolicy: '{channel1.RemoteEndpoint.SecurityPolicyUri}'."); Console.WriteLine($"SecurityMode: '{channel1.RemoteEndpoint.SecurityMode}'."); Console.WriteLine($"Activated session '{channel1.SessionId}'."); // create the keep alive subscription. var subscriptionRequest = new CreateSubscriptionRequest { RequestedPublishingInterval = 1000f, RequestedMaxKeepAliveCount = 30, RequestedLifetimeCount = 30 * 3, PublishingEnabled = true, }; var subscriptionResponse = await channel1.CreateSubscriptionAsync(subscriptionRequest).ConfigureAwait(false); var id = subscriptionResponse.SubscriptionId; var token = channel1.Where(pr => pr.SubscriptionId == id).Subscribe(pr => { // loop thru all the data change notifications var dcns = pr.NotificationMessage.NotificationData.OfType <DataChangeNotification>(); foreach (var dcn in dcns) { foreach (var min in dcn.MonitoredItems) { Console.WriteLine($"channel: 1; sub: {pr.SubscriptionId}; handle: {min.ClientHandle}; value: {min.Value}"); } } }); var itemsRequest = new CreateMonitoredItemsRequest { SubscriptionId = id, ItemsToCreate = new MonitoredItemCreateRequest[] { new MonitoredItemCreateRequest { ItemToMonitor = new ReadValueId { NodeId = NodeId.Parse("i=2258"), AttributeId = AttributeIds.Value }, MonitoringMode = MonitoringMode.Reporting, RequestedParameters = new MonitoringParameters { ClientHandle = 12345, SamplingInterval = -1, QueueSize = 0, DiscardOldest = true } } }, }; var itemsResponse = await channel1.CreateMonitoredItemsAsync(itemsRequest); await Task.Delay(3000); var channel2 = new UaTcpSessionChannel( this.localDescription, this.certificateStore, new UserNameIdentity("root", "secret"), EndpointUrl); await channel2.OpenAsync(); var token2 = channel2.Where(pr => pr.SubscriptionId == id).Subscribe(pr => { // loop thru all the data change notifications var dcns = pr.NotificationMessage.NotificationData.OfType <DataChangeNotification>(); foreach (var dcn in dcns) { foreach (var min in dcn.MonitoredItems) { Console.WriteLine($"channel: 2; sub: {pr.SubscriptionId}; handle: {min.ClientHandle}; value: {min.Value}"); } } }); var transferRequest = new TransferSubscriptionsRequest { SubscriptionIds = new[] { id }, SendInitialValues = true }; var transferResult = await channel2.TransferSubscriptionsAsync(transferRequest); StatusCode.IsGood(transferResult.Results[0].StatusCode) .Should().BeTrue(); await Task.Delay(3000); Console.WriteLine($"Closing session '{channel1.SessionId}'."); await channel1.CloseAsync(); Console.WriteLine($"Closing session '{channel2.SessionId}'."); await channel2.CloseAsync(); }
/// <summary> /// Calculates the Delta aggregate for the timeslice. /// </summary> protected DataValue ComputeDelta(TimeSlice slice) { // get the values in the slice. List <DataValue> values = GetValues(slice); // check for empty slice. if (values == null || values.Count == 0) { return(GetNoDataValue(slice)); } // find start value. DataValue start = null; double startValue = 0; TypeInfo originalType = null; bool badDataSkipped = false; for (int ii = 0; ii < values.Count; ii++) { start = values[ii]; if (StatusCode.IsGood(start.StatusCode)) { try { startValue = CastToDouble(start); originalType = start.WrappedValue.TypeInfo; break; } catch (Exception) { startValue = Double.NaN; } } start = null; badDataSkipped = true; } // find end value. DataValue end = null; double endValue = 0; for (int ii = values.Count - 1; ii >= 0; ii--) { end = values[ii]; if (StatusCode.IsGood(end.StatusCode)) { try { endValue = CastToDouble(end); break; } catch (Exception) { endValue = Double.NaN; } break; } end = null; badDataSkipped = true; } // check if no good data. if (Double.IsNaN(startValue) || Double.IsNaN(endValue)) { return(GetNoDataValue(slice)); } DataValue value = new DataValue(); value.SourceTimestamp = GetTimestamp(slice); value.ServerTimestamp = GetTimestamp(slice); // set status code. if (badDataSkipped) { value.StatusCode = StatusCodes.UncertainDataSubNormal; } value.StatusCode = value.StatusCode.SetAggregateBits(AggregateBits.Calculated); // calculate delta. double delta = endValue - startValue; if (originalType != null && originalType.BuiltInType != BuiltInType.Double) { object delta2 = TypeInfo.Cast(delta, TypeInfo.Scalars.Double, originalType.BuiltInType); value.WrappedValue = new Variant(delta2, originalType); } else { value.WrappedValue = new Variant(delta, TypeInfo.Scalars.Double); } // return result. return(value); }
private async Task <bool> TryConnect() { if (connection != null) { return(true); } if (config == null || string.IsNullOrEmpty(config.Address)) { lastConnectErrMsg = "No address configured"; return(false); } try { if (certificateStore == null) { var pkiPath = Path.Combine( Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "ifakFAST.IO.OPC_UA", "pki"); Console.WriteLine($"Location of OPC UA certificate store: {pkiPath}"); certificateStore = new DirectoryStore(pkiPath, acceptAllRemoteCertificates: true, createLocalCertificateIfNotExist: true); certificateLocation = Path.Combine(pkiPath, "own", "certs"); } const string Config_Security = "Security"; string sec = "None"; if (config.Config.Any(nv => nv.Name == Config_Security)) { sec = config.Config.First(nv => nv.Name == Config_Security).Value; } var mapSecurityPolicies = new Dictionary <string, string>() { { "None", SecurityPolicyUris.None }, { "Basic128Rsa15", SecurityPolicyUris.Basic128Rsa15 }, { "Basic256", SecurityPolicyUris.Basic256 }, { "Https", SecurityPolicyUris.Https }, { "Basic256Sha256", SecurityPolicyUris.Basic256Sha256 }, { "Aes128_Sha256_RsaOaep", SecurityPolicyUris.Aes128_Sha256_RsaOaep }, { "Aes256_Sha256_RsaPss", SecurityPolicyUris.Aes256_Sha256_RsaPss }, }; if (!mapSecurityPolicies.ContainsKey(sec)) { string[] keys = mapSecurityPolicies.Keys.ToArray(); string strKeys = string.Join(", ", keys); throw new Exception($"Invalid value for config setting '{Config_Security}': {sec}. Expected any of: {strKeys}"); } var endpoint = new EndpointDescription { EndpointUrl = config.Address, SecurityPolicyUri = mapSecurityPolicies[sec], }; IUserIdentity identity = GetIdentity(); var channel = new UaTcpSessionChannel( localDescription: appDescription, certificateStore: certificateStore, userIdentity: identity, remoteEndpoint: endpoint); await channel.OpenAsync(); this.connection = channel; lastConnectErrMsg = ""; PrintLine($"Opened session with endpoint '{channel.RemoteEndpoint.EndpointUrl}'."); PrintLine($"SecurityPolicy: '{channel.RemoteEndpoint.SecurityPolicyUri}'."); PrintLine($"SecurityMode: '{channel.RemoteEndpoint.SecurityMode}'."); PrintLine($"UserIdentityToken: '{channel.UserIdentity}'."); ItemInfo[] nodesNeedingResolve = mapId2Info.Values.Where(n => n.Node == null).ToArray(); if (nodesNeedingResolve.Length > 0) { PrintLine($"Resolving node ids for {nodesNeedingResolve.Length} items..."); TranslateBrowsePathsToNodeIdsRequest req = new TranslateBrowsePathsToNodeIdsRequest() { BrowsePaths = nodesNeedingResolve.Select(n => new BrowsePath() { StartingNode = n.StartingNode, RelativePath = n.RelativePath }).ToArray() }; TranslateBrowsePathsToNodeIdsResponse resp = await connection.TranslateBrowsePathsToNodeIdsAsync(req); if (resp.Results == null || resp.Results.Length != nodesNeedingResolve.Length) { LogWarn("Mismatch", "TranslateBrowsePathsToNodeIds failed"); } else { for (int i = 0; i < resp.Results.Length; ++i) { BrowsePathResult?x = resp.Results[i]; if (x != null && StatusCode.IsGood(x.StatusCode) && x.Targets != null && x.Targets.Length > 0) { BrowsePathTarget?target = x.Targets[0]; if (target != null && target.TargetId != null) { NodeId id = target.TargetId.NodeId; nodesNeedingResolve[i].Node = id; PrintLine($"Resolved item '{nodesNeedingResolve[i].Name}' => {id}"); } else { PrintLine($"Could not resolve item '{nodesNeedingResolve[i].Name}': StatusCode: {x.StatusCode}"); } } else { string statusCode = x == null ? "?" : x.StatusCode.ToString(); PrintLine($"Could not resolve item '{nodesNeedingResolve[i].Name}': StatusCode: {statusCode}"); } } } } ReturnToNormal("OpenChannel", $"Connected to OPC UA server at {config.Address}"); return(true); } catch (Exception exp) { Exception baseExp = exp.GetBaseException() ?? exp; lastConnectErrMsg = baseExp.Message; LogWarn("OpenChannel", "Open channel error: " + baseExp.Message, dataItem: null, details: baseExp.StackTrace); await CloseChannel(); return(false); } }
/// <summary> /// Gets the result for the read operayoin. /// </summary> /// <param name="context">The context.</param> /// <param name="item">The item.</param> /// <param name="nodeToRead">The node to read.</param> /// <param name="value">The value.</param> /// <param name="diagnosticsMasks">The diagnostics masks.</param> /// <returns></returns> public ServiceResult GetResult( ISystemContext context, DaItemState item, ReadValueId nodeToRead, DataValue value, DiagnosticsMasks diagnosticsMasks) { if (nodeToRead.AttributeId == Attributes.Value) { ServiceResult result = GetItemValue(m_value, value, diagnosticsMasks); if (ServiceResult.IsBad(result)) { return(result); } return(ApplyIndexRangeAndDataEncoding(context, nodeToRead, value)); } switch (nodeToRead.AttributeId) { case Attributes.Description: { string description = this.GetPropertyValue <string>(Opc.Ua.Com.PropertyIds.Description, value, false); if (StatusCode.IsGood(value.StatusCode)) { value.Value = new LocalizedText(description); } break; } case Attributes.DataType: { short datatype = this.GetPropertyValue <short>(Opc.Ua.Com.PropertyIds.DataType, value, false); if (StatusCode.IsGood(value.StatusCode)) { value.Value = ComUtils.GetDataTypeId(datatype); } break; } case Attributes.ValueRank: { short datatype = this.GetPropertyValue <short>(Opc.Ua.Com.PropertyIds.DataType, value, false); if (StatusCode.IsGood(value.StatusCode)) { value.Value = ComUtils.GetValueRank(datatype); } break; } case Attributes.AccessLevel: case Attributes.UserAccessLevel: { int accessRights = this.GetPropertyValue <int>(Opc.Ua.Com.PropertyIds.AccessRights, value, false); if (StatusCode.IsGood(value.StatusCode)) { value.Value = (byte)accessRights; } break; } case Attributes.MinimumSamplingInterval: { float scanRate = this.GetPropertyValue <float>(Opc.Ua.Com.PropertyIds.ScanRate, value, false); if (StatusCode.IsGood(value.StatusCode)) { value.Value = (double)scanRate; } break; } default: { return(StatusCodes.BadAttributeIdInvalid); } } // check if the property value is missing. if (value.StatusCode == StatusCodes.BadNotFound) { return(StatusCodes.BadAttributeIdInvalid); } return(ApplyIndexRangeAndDataEncoding(context, nodeToRead, value)); }
/// <summary> /// Returns the next reference. /// </summary> /// <returns>The next reference that meets the browse criteria.</returns> public override IReference Next() { lock (DataLock) { IReference reference = null; // enumerate pre-defined references. // always call first to ensure any pushed-back references are returned first. reference = base.Next(); if (reference != null) { return(reference); } // don't start browsing huge number of references when only internal references are requested. if (InternalOnly) { return(null); } if (m_stage == Stage.Begin) { // construct request. BrowseDescription nodeToBrowse = new BrowseDescription(); NodeId startId = ObjectIds.ObjectsFolder; if (m_source != null) { startId = m_mapper.ToRemoteId(m_source.NodeId); } nodeToBrowse.NodeId = startId; nodeToBrowse.BrowseDirection = this.BrowseDirection; nodeToBrowse.ReferenceTypeId = this.ReferenceType; nodeToBrowse.IncludeSubtypes = this.IncludeSubtypes; nodeToBrowse.NodeClassMask = 0; nodeToBrowse.ResultMask = (uint)BrowseResultMask.All; BrowseDescriptionCollection nodesToBrowse = new BrowseDescriptionCollection(); nodesToBrowse.Add(nodeToBrowse); // start the browse operation. BrowseResultCollection results = null; DiagnosticInfoCollection diagnosticInfos = null; ResponseHeader responseHeader = m_client.Browse( null, null, 0, nodesToBrowse, out results, out diagnosticInfos); // these do sanity checks on the result - make sure response matched the request. ClientBase.ValidateResponse(results, nodesToBrowse); ClientBase.ValidateDiagnosticInfos(diagnosticInfos, nodesToBrowse); m_position = 0; m_references = null; m_continuationPoint = null; m_stage = Stage.References; // check status. if (StatusCode.IsGood(results[0].StatusCode)) { m_references = results[0].References; m_continuationPoint = results[0].ContinuationPoint; reference = NextChild(); if (reference != null) { return(reference); } } } if (m_stage == Stage.References) { reference = NextChild(); if (reference != null) { return(reference); } if (m_source == null && IsRequired(ReferenceTypes.HasNotifier, false)) { // construct request. BrowseDescription nodeToBrowse = new BrowseDescription(); nodeToBrowse.NodeId = ObjectIds.Server; nodeToBrowse.BrowseDirection = BrowseDirection.Forward; nodeToBrowse.ReferenceTypeId = ReferenceTypes.HasNotifier; nodeToBrowse.IncludeSubtypes = true; nodeToBrowse.NodeClassMask = 0; nodeToBrowse.ResultMask = (uint)BrowseResultMask.All; BrowseDescriptionCollection nodesToBrowse = new BrowseDescriptionCollection(); nodesToBrowse.Add(nodeToBrowse); // start the browse operation. BrowseResultCollection results = null; DiagnosticInfoCollection diagnosticInfos = null; ResponseHeader responseHeader = m_client.Browse( null, null, 0, nodesToBrowse, out results, out diagnosticInfos); // these do sanity checks on the result - make sure response matched the request. ClientBase.ValidateResponse(results, nodesToBrowse); ClientBase.ValidateDiagnosticInfos(diagnosticInfos, nodesToBrowse); m_position = 0; m_references = null; m_continuationPoint = null; m_stage = Stage.Notifiers; // check status. if (StatusCode.IsGood(results[0].StatusCode)) { m_references = results[0].References; m_continuationPoint = results[0].ContinuationPoint; } } m_stage = Stage.Notifiers; } if (m_stage == Stage.Notifiers) { reference = NextChild(); if (reference != null) { return(reference); } m_stage = Stage.Done; } // all done. return(null); } }
/// <summary> /// Gets the result for the read operation. /// </summary> /// <param name="context">The context.</param> /// <param name="property">The property.</param> /// <param name="nodeToRead">The node to read.</param> /// <param name="value">The value.</param> /// <param name="diagnosticsMasks">The diagnostics masks.</param> /// <returns></returns> public ServiceResult GetResult( ISystemContext context, PropertyState property, ReadValueId nodeToRead, DataValue value, DiagnosticsMasks diagnosticsMasks) { DaItemState item = property.Parent as DaItemState; if (item == null) { return(StatusCodes.BadNodeIdUnknown); } if (nodeToRead.AttributeId != Attributes.Value) { return(StatusCodes.BadAttributeIdInvalid); } switch (property.SymbolicName) { case Opc.Ua.BrowseNames.EURange: { double high = this.GetPropertyValue <double>(Opc.Ua.Com.PropertyIds.HighEU, value, true); if (StatusCode.IsBad(value.StatusCode)) { return(value.StatusCode); } double low = this.GetPropertyValue <double>(Opc.Ua.Com.PropertyIds.LowEU, value, true); if (StatusCode.IsBad(value.StatusCode)) { return(value.StatusCode); } value.Value = new Range(high, low); break; } case Opc.Ua.BrowseNames.InstrumentRange: { double high = this.GetPropertyValue <double>(Opc.Ua.Com.PropertyIds.HighIR, value, true); if (StatusCode.IsBad(value.StatusCode)) { return(value.StatusCode); } double low = this.GetPropertyValue <double>(Opc.Ua.Com.PropertyIds.LowIR, value, true); if (StatusCode.IsBad(value.StatusCode)) { return(value.StatusCode); } value.Value = new Range(high, low); break; } case Opc.Ua.BrowseNames.EngineeringUnits: { string units = this.GetPropertyValue <string>(Opc.Ua.Com.PropertyIds.EngineeringUnits, value, true); if (StatusCode.IsBad(value.StatusCode)) { return(value.StatusCode); } value.Value = new EUInformation(units, Namespaces.ComInterop); break; } case Opc.Ua.BrowseNames.EnumStrings: { string[] strings = this.GetPropertyValue <string[]>(Opc.Ua.Com.PropertyIds.EuInfo, value, true); if (StatusCode.IsBad(value.StatusCode)) { return(value.StatusCode); } if (strings != null) { LocalizedText[] texts = new LocalizedText[strings.Length]; for (int ii = 0; ii < texts.Length; ii++) { texts[ii] = new LocalizedText(strings[ii]); } value.Value = texts; } break; } case Opc.Ua.BrowseNames.LocalTime: { int timebias = this.GetPropertyValue <int>(Opc.Ua.Com.PropertyIds.TimeZone, value, true); if (StatusCode.IsBad(value.StatusCode)) { return(value.StatusCode); } TimeZoneDataType timeZone = new TimeZoneDataType(); timeZone.Offset = (short)timebias; timeZone.DaylightSavingInOffset = false; value.Value = timeZone; break; } case Opc.Ua.BrowseNames.TrueState: { string description = this.GetPropertyValue <string>(Opc.Ua.Com.PropertyIds.CloseLabel, value, false); if (StatusCode.IsGood(value.StatusCode)) { value.Value = new LocalizedText(description); } break; } case Opc.Ua.BrowseNames.FalseState: { string description = this.GetPropertyValue <string>(Opc.Ua.Com.PropertyIds.OpenLabel, value, false); if (StatusCode.IsGood(value.StatusCode)) { value.Value = new LocalizedText(description); } break; } default: { return(StatusCodes.BadAttributeIdInvalid); } } // check if the property value is missing. if (value.StatusCode == StatusCodes.BadNotFound) { return(StatusCodes.BadNodeIdUnknown); } return(ApplyIndexRangeAndDataEncoding(context, nodeToRead, value)); }
private void OnNotification(MonitoredItem item, MonitoredItemNotificationEventArgs e) { //MonitoredItemNotification notification = e.NotificationValue as MonitoredItemNotification; //Console.WriteLine("Notification Received for Variable \"{0}\" and Value = {1} type {2}.", item.DisplayName, notification.Value, notification.TypeId); foreach (var value in item.DequeueValues()) { if (value != null) { string tp = "unknown"; bool isArray = false; try { if (value.WrappedValue.TypeInfo != null) { tp = value.WrappedValue.TypeInfo.BuiltInType.ToString(); isArray = value.Value.GetType().ToString().Contains("[]"); // Log(conn_name + " - " + item.ResolvedNodeId + "TYPE: " + tp, LogLevelDetailed); } else { Log(conn_name + " - " + item.ResolvedNodeId + " TYPE: ?????", LogLevelDetailed); } Log(conn_name + " - " + item.ResolvedNodeId + " " + item.DisplayName + " " + value.Value + " " + value.SourceTimestamp + " " + value.StatusCode, LogLevelDetailed); if (value.Value != null) { Double dblValue = 0.0; string strValue = ""; try { if (tp == "Variant") { try { dblValue = System.Convert.ToDouble(value.Value); } catch { try { dblValue = System.Convert.ToInt64(value.Value); } catch { try { dblValue = System.Convert.ToInt32(value.Value); } catch { dblValue = 0; try { var opt = new JsonSerializerOptions { NumberHandling = JsonNumberHandling.AllowReadingFromString | JsonNumberHandling.WriteAsString }; strValue = JsonSerializer.Serialize(value.Value, opt); } catch { strValue = value.Value.ToString(); } } } } } else if (tp == "DateTime") { dblValue = ((DateTimeOffset)System.Convert.ToDateTime(value.Value)).ToUnixTimeMilliseconds(); strValue = System.Convert.ToDateTime(value.Value).ToString("o"); } else if (tp == "String" || tp == "ExtensionObject" || isArray) { dblValue = 0; strValue = System.Convert.ToString(value.Value); } else { try { dblValue = System.Convert.ToDouble(value.Value); strValue = value.Value.ToString(); } catch { dblValue = 0; strValue = value.Value.ToString(); } } } catch { dblValue = 0; strValue = value.Value.ToString(); } var options = new JsonSerializerOptions { NumberHandling = JsonNumberHandling.AllowReadingFromString | JsonNumberHandling.WriteAsString }; OPC_Value iv = new OPC_Value() { valueJson = JsonSerializer.Serialize(value, options), selfPublish = true, address = item.ResolvedNodeId.ToString(), asdu = tp, isDigital = true, value = dblValue, valueString = strValue, hasSourceTimestamp = value.SourceTimestamp != DateTime.MinValue, sourceTimestamp = value.SourceTimestamp, serverTimestamp = DateTime.Now, quality = StatusCode.IsGood(value.StatusCode), cot = 3, conn_number = conn_number, conn_name = conn_name, common_address = "", display_name = item.DisplayName }; OPCDataQueue.Enqueue(iv); } } catch (Exception excpt) { Log(conn_name + " - " + excpt.Message); Log(conn_name + " - " + "TYPE:" + tp); Log(conn_name + " - " + item.ResolvedNodeId + " " + item.DisplayName + " " + value.Value + " " + value.SourceTimestamp + " " + value.StatusCode); } } else { Log(conn_name + " - " + item.ResolvedNodeId + " " + item.DisplayName + " NULL VALUE!", LogLevelDetailed); } Thread.Yield(); Thread.Sleep(1); //if ((OPCDataQueue.Count % 50) == 0) //{ // await Task.Delay(200); //} } }
/// <summary> /// Reads the attributes, verifies the results and updates the nodes. /// </summary> private bool Read(ReadValueIdCollection nodesToRead) { bool success = true; DataValueCollection results; DiagnosticInfoCollection diagnosticInfos; RequestHeader requestHeader = new RequestHeader(); requestHeader.ReturnDiagnostics = 0; Session.Read( requestHeader, 0, TimestampsToReturn.Both, nodesToRead, out results, out diagnosticInfos); ClientBase.ValidateResponse(results, nodesToRead); ClientBase.ValidateDiagnosticInfos(diagnosticInfos, nodesToRead); // check diagnostics. if (diagnosticInfos != null && diagnosticInfos.Count > 0) { Log("Returned non-empty DiagnosticInfos array during Read."); return(false); } // check results. for (int ii = 0; ii < nodesToRead.Count; ii++) { ReadValueId request = nodesToRead[ii]; Node node = (Node)request.Handle; if (!VerifyTimestamps(node, request.AttributeId, TimestampsToReturn.Both, results[ii])) { success = false; continue; } if (request.IndexRange == null && request.DataEncoding == null) { if (StatusCode.IsBad(results[ii].StatusCode)) { if (!VerifyBadAttribute(node, request.AttributeId, results[ii].StatusCode)) { success = false; } continue; } if (!VerifyGoodAttribute(node, request.AttributeId, results[ii])) { success = false; continue; } } else if (request.IndexRange != null) { if (request.AttributeId != Attributes.Value || (node.NodeClass != NodeClass.Variable && node.NodeClass != NodeClass.VariableType)) { if (results[ii].StatusCode != StatusCodes.BadAttributeIdInvalid && results[ii].StatusCode != StatusCodes.BadIndexRangeInvalid) { Log( "IndexRange not valid for non-value attributes '{0}'. NodeId = {1}, Attribute = {2}, StatusCode = {3}", node, node.NodeId, Attributes.GetBrowseName(request.AttributeId), results[ii].StatusCode); success = false; break; } continue; } // check for variable types with no value. if (node.NodeClass == NodeClass.VariableType) { if (results[ii].StatusCode == StatusCodes.BadAttributeIdInvalid) { continue; } } // index range can be ignored if the value is null. if (StatusCode.IsGood(results[ii].StatusCode) && results[ii].Value == null) { continue; } // check for access errors. if (results[ii].StatusCode == StatusCodes.BadNotReadable || results[ii].StatusCode == StatusCodes.BadUserAccessDenied) { continue; } // check the result against the expected data type. IVariableBase variable = node as IVariableBase; BuiltInType type = TypeInfo.GetBuiltInType(variable.DataType, Session.TypeTree); if (variable.ValueRank == ValueRanks.Scalar) { if (!VerifyIndexRangeForScalar(variable, type, results[ii])) { success = false; break; } } else { if (!VerifyIndexRangeForArray(variable, type, request.IndexRange, results[ii])) { success = false; break; } } } if (request.DataEncoding != null) { if (request.AttributeId != Attributes.Value || (node.NodeClass != NodeClass.Variable && node.NodeClass != NodeClass.VariableType)) { if (results[ii].StatusCode != StatusCodes.BadAttributeIdInvalid && results[ii].StatusCode != StatusCodes.BadDataEncodingInvalid && results[ii].StatusCode != StatusCodes.BadDataEncodingUnsupported) { Log( "DataEncoding not valid for non-value attributes '{0}'. NodeId = {1}, Attribute = {2}, StatusCode = {3}", node, node.NodeId, Attributes.GetBrowseName(request.AttributeId), results[ii].StatusCode); success = false; break; } continue; } // check for variable types with no value. if (node.NodeClass == NodeClass.VariableType) { if (results[ii].StatusCode == StatusCodes.BadAttributeIdInvalid) { continue; } } // data encoding can be ignored if the value is null. if (StatusCode.IsGood(results[ii].StatusCode) && results[ii].Value == null) { continue; } // check for access errors. if (results[ii].StatusCode == StatusCodes.BadNotReadable || results[ii].StatusCode == StatusCodes.BadUserAccessDenied) { continue; } // check the result against the expected data type. IVariableBase variable = node as IVariableBase; BuiltInType type = TypeInfo.GetBuiltInType(variable.DataType, Session.TypeTree); if (type != BuiltInType.ExtensionObject) { if (!IsDaBadStatus(results[ii].StatusCode)) { if (results[ii].StatusCode != StatusCodes.BadDataEncodingInvalid && results[ii].StatusCode != StatusCodes.BadDataEncodingUnsupported) { Log( "Wrong error code when reading value with data encoding '{0}'. NodeId = {1}, Value = {2}, StatusCode = {3}", variable, variable.NodeId, variable.Value, results[ii].StatusCode); success = false; break; } } } else { if (!VerifyDataEncoding(variable, type, request.DataEncoding, results[ii])) { success = false; break; } } } } // check attribute consistency. if (success) { Node current = null; for (int ii = 0; ii < nodesToRead.Count; ii++) { if (Object.ReferenceEquals(current, nodesToRead[ii].Handle)) { continue; } current = (Node)nodesToRead[ii].Handle; if (!VerifyAttributeConsistency(current)) { success = false; continue; } } } return(success); }
/// <summary> /// Verifies that the timestamps match the requested filter. /// </summary> protected bool VerifyTimestamps( Node node, uint attributeId, TimestampsToReturn timestampsToReturn, DataValue value) { // check server timestamp. if (timestampsToReturn != TimestampsToReturn.Server && timestampsToReturn != TimestampsToReturn.Both) { if (value.ServerTimestamp != DateTime.MinValue || value.ServerPicoseconds != 0) { Log( "Unexpected ServerTimestamp returned during read for Node '{0}'. NodeId = {1}, Attribute = {2}, Timestamp = {3}, Picoseconds = {4}", node, node.NodeId, Attributes.GetBrowseName(attributeId), value.ServerTimestamp, value.ServerPicoseconds); return(false); } } if (timestampsToReturn == TimestampsToReturn.Server || timestampsToReturn == TimestampsToReturn.Both) { if (value.ServerTimestamp.AddHours(1) < DateTime.UtcNow || DateTime.UtcNow.AddHours(1) < value.ServerTimestamp) { Log( "Valid ServerTimestamp not returned during read for Node '{0}'. NodeId = {1}, Attribute = {2}, Timestamp = {3}, Picoseconds = {4}", node, node.NodeId, Attributes.GetBrowseName(attributeId), value.ServerTimestamp, value.ServerPicoseconds); return(false); } } // check source timestamp. if (timestampsToReturn != TimestampsToReturn.Source && timestampsToReturn != TimestampsToReturn.Both) { if (value.SourceTimestamp != DateTime.MinValue || value.SourcePicoseconds != 0) { Log( "Unexpected SourceTimestamp returned during read for Node '{0}'. NodeId = {1}, Attribute = {2}, Timestamp = {3}, Picoseconds = {4}", node, node.NodeId, Attributes.GetBrowseName(attributeId), value.SourceTimestamp, value.ServerPicoseconds); return(false); } } // check non-value attribute source timestamp. if (attributeId != Attributes.Value) { if (value.SourceTimestamp != DateTime.MinValue || value.SourcePicoseconds != 0) { Log( "Unexpected SourceTimestamp returned during non-value attribute for Node '{0}'. NodeId = {1}, Attribute = {2}, Timestamp = {3}, Picoseconds = {4}", node, node.NodeId, Attributes.GetBrowseName(attributeId), value.SourceTimestamp, value.ServerPicoseconds); return(false); } } else if (StatusCode.IsGood(value.StatusCode)) { if (timestampsToReturn == TimestampsToReturn.Source || timestampsToReturn == TimestampsToReturn.Both) { if (value.SourceTimestamp.AddYears(10) < DateTime.UtcNow || DateTime.UtcNow.AddHours(1) < value.SourceTimestamp) { Log( "Valid SourceTimestamp not returned during read for Node '{0}'. NodeId = {1}, Attribute = {2}, Timestamp = {3}, Picoseconds = {4}", node, node.NodeId, Attributes.GetBrowseName(attributeId), value.SourceTimestamp, value.SourcePicoseconds); return(false); } } } return(true); }
protected override bool RightStatusCode(DataValue dv) { return(StatusCode.IsGood(dv.StatusCode)); }
public bool WriteUDT(List <string> opcNodes, List <object> values, out List <bool> status) { bool ret = false; try { if (opcNodes.Count != values.Count) { throw new Exception("opcNodes.Count != values.Count"); } int count = opcNodes.Count; status = new List <bool>(count); List <Type> types = new List <Type>(count); List <NodeId> nodeIds = new List <NodeId>(count); DiagnosticInfoCollection diags; StatusCodeCollection statusCodes; WriteValueCollection writeValues = new WriteValueCollection(count); for (int i = 0; i < count; i++) { //Variant variant = new Variant(values[i]); Opc.Ua.ExpandedNodeId expNodeId = new Opc.Ua.ExpandedNodeId(opcNodes[i]); Opc.Ua.ExtensionObject extObj = new Opc.Ua.ExtensionObject(expNodeId, values[i]); DataValue dataVal = new DataValue(extObj); WriteValue writeVal = new WriteValue(); //writeVal. writeVal.Value = dataVal; writeVal.NodeId = new NodeId(opcNodes[i]); writeVal.AttributeId = Attributes.Value; writeValues.Add(writeVal); } ResponseHeader rh = session.Write(null, writeValues, out statusCodes, out diags); ret = StatusCode.IsGood(rh.ServiceResult.Code); for (int i = 0; i < count; i++) { //status[i] = StatusCode.IsGood(statusCodes[i]); status.Add(StatusCode.IsGood(statusCodes[i])); ret = ret & status[i]; } } catch (Exception ex) { ret = false; status = null; System.Diagnostics.Debug.WriteLine("Exception OpcUaClient::WriteValues " + ex.Message); } return(ret); }
public async Task ReadHistorical() { var channel = new UaTcpSessionChannel( this.localDescription, this.certificateStore, new AnonymousIdentity(), "opc.tcp://localhost:48010", loggerFactory: this.loggerFactory); await channel.OpenAsync(); Console.WriteLine($"Opened session with endpoint '{channel.RemoteEndpoint.EndpointUrl}'."); Console.WriteLine($"SecurityPolicy: '{channel.RemoteEndpoint.SecurityPolicyUri}'."); Console.WriteLine($"SecurityMode: '{channel.RemoteEndpoint.SecurityMode}'."); Console.WriteLine($"Activated session '{channel.SessionId}'."); var historyReadRequest = new HistoryReadRequest { HistoryReadDetails = new ReadRawModifiedDetails { StartTime = DateTime.UtcNow - TimeSpan.FromMinutes(10), EndTime = DateTime.UtcNow, ReturnBounds = true, IsReadModified = false }, NodesToRead = new[] { new HistoryReadValueId { NodeId = NodeId.Parse("ns=2;s=Demo.History.DoubleWithHistory") } }, }; var historyReadResponse = await channel.HistoryReadAsync(historyReadRequest); var result = historyReadResponse.Results[0]; StatusCode.IsGood(result.StatusCode) .Should().BeTrue(); Console.WriteLine($"HistoryRead response status code: {result.StatusCode}, HistoryData count: {((HistoryData)result.HistoryData).DataValues.Length}."); if (false) // UaCPPserver does not appear to store event history. { var historyReadRequest2 = new HistoryReadRequest { HistoryReadDetails = new ReadEventDetails { StartTime = DateTime.UtcNow - TimeSpan.FromMinutes(10), EndTime = DateTime.UtcNow, Filter = new EventFilter // Use EventHelper to select all the fields of AlarmCondition. { SelectClauses = EventHelper.GetSelectClauses <AlarmCondition>() } }, NodesToRead = new[] { new HistoryReadValueId { NodeId = NodeId.Parse("ns=2;s=Demo.History.DoubleWithHistory") } }, }; var historyReadResponse2 = await channel.HistoryReadAsync(historyReadRequest2); var result2 = historyReadResponse2.Results[0]; StatusCode.IsGood(result2.StatusCode) .Should().BeTrue(); Console.WriteLine($"HistoryRead response status code: {result2.StatusCode}, HistoryEvent count: {((HistoryEvent)result2.HistoryData).Events.Length}."); // Use EventHelper to create AlarmConditions from the HistoryEventFieldList var alarms = ((HistoryEvent)result2.HistoryData).Events.Select(e => EventHelper.Deserialize <AlarmCondition>(e.EventFields)); } Console.WriteLine($"Closing session '{channel.SessionId}'."); await channel.CloseAsync(); }
/// <summary> /// Calculates the DurationGood and DurationBad aggregates for the timeslice. /// </summary> protected DataValue ComputeWorstQuality(TimeSlice slice, bool includeBounds) { // get the values in the slice. List <DataValue> values = null; if (!includeBounds) { values = GetValues(slice); } else { values = GetValuesWithSimpleBounds(slice); } // check for empty slice. if (values == null || values.Count == 0) { return(GetNoDataValue(slice)); } // get the regions. List <SubRegion> regions = GetRegionsInValueSet(values, false, true); StatusCode worstQuality = StatusCodes.Good; int badQualityCount = 0; int uncertainQualityCount = 0; for (int ii = 0; ii < values.Count; ii++) { StatusCode quality = values[ii].StatusCode; if (StatusCode.IsBad(quality)) { badQualityCount++; if (StatusCode.IsNotBad(worstQuality)) { worstQuality = quality.CodeBits; } continue; } if (StatusCode.IsUncertain(quality)) { uncertainQualityCount++; if (StatusCode.IsGood(worstQuality)) { worstQuality = quality.CodeBits; } continue; } } // set the timestamp and status. DataValue value = new DataValue(); value.WrappedValue = new Variant(worstQuality, TypeInfo.Scalars.StatusCode); value.SourceTimestamp = GetTimestamp(slice); value.ServerTimestamp = GetTimestamp(slice); value.StatusCode = value.StatusCode.SetAggregateBits(AggregateBits.Calculated); if ((StatusCode.IsBad(worstQuality) && badQualityCount > 1) || (StatusCode.IsUncertain(worstQuality) && uncertainQualityCount > 1)) { value.StatusCode = value.StatusCode.SetAggregateBits(value.StatusCode.AggregateBits | AggregateBits.MultipleValues); } // return result. return(value); }
public async Task StackTest() { var channel = new UaTcpSessionChannel( this.localDescription, this.certificateStore, new AnonymousIdentity(), EndpointUrl, loggerFactory: this.loggerFactory); await channel.OpenAsync(); Console.WriteLine($"Opened session with endpoint '{channel.RemoteEndpoint.EndpointUrl}'."); Console.WriteLine($"SecurityPolicy: '{channel.RemoteEndpoint.SecurityPolicyUri}'."); Console.WriteLine($"SecurityMode: '{channel.RemoteEndpoint.SecurityMode}'."); Console.WriteLine($"Activated session '{channel.SessionId}'."); var readRequest = new ReadRequest { NodesToRead = new[] { new ReadValueId { AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Scalar.Boolean") }, new ReadValueId { AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Scalar.SByte") }, new ReadValueId { AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Scalar.Int16") }, new ReadValueId { AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Scalar.Int32") }, new ReadValueId { AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Scalar.Int64") }, new ReadValueId { AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Scalar.Byte") }, new ReadValueId { AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Scalar.UInt16") }, new ReadValueId { AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Scalar.UInt32") }, new ReadValueId { AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Scalar.UInt64") }, new ReadValueId { AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Scalar.Float") }, new ReadValueId { AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Scalar.Double") }, new ReadValueId { AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Scalar.String") }, new ReadValueId { AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Scalar.DateTime") }, new ReadValueId { AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Scalar.Guid") }, new ReadValueId { AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Scalar.ByteString") }, new ReadValueId { AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Scalar.XmlElement") }, new ReadValueId { AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Scalar.LocalizedText") }, new ReadValueId { AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Scalar.QualifiedName") }, new ReadValueId { AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Arrays.Boolean") }, new ReadValueId { AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Arrays.SByte") }, new ReadValueId { AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Arrays.Int16") }, new ReadValueId { AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Arrays.Int32") }, new ReadValueId { AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Arrays.Int64") }, new ReadValueId { AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Arrays.Byte") }, new ReadValueId { AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Arrays.UInt16") }, new ReadValueId { AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Arrays.UInt32") }, new ReadValueId { AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Arrays.UInt64") }, new ReadValueId { AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Arrays.Float") }, new ReadValueId { AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Arrays.Double") }, new ReadValueId { AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Arrays.String") }, new ReadValueId { AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Arrays.DateTime") }, new ReadValueId { AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Arrays.Guid") }, new ReadValueId { AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Arrays.ByteString") }, new ReadValueId { AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Arrays.XmlElement") }, new ReadValueId { AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Arrays.LocalizedText") }, new ReadValueId { AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("ns=2;s=Demo.Static.Arrays.QualifiedName") }, }, }; readRequest = new ReadRequest { NodesToRead = new[] { new ReadValueId { AttributeId = AttributeIds.Value, NodeId = NodeId.Parse("i=11494") }, }, }; var sw = new Stopwatch(); sw.Restart(); for (int i = 0; i < 1; i++) { var readResponse = await channel.ReadAsync(readRequest); foreach (var result in readResponse.Results) { StatusCode.IsGood(result.StatusCode) .Should().BeTrue(); var obj = result.GetValue(); } } sw.Stop(); Console.WriteLine($"{sw.ElapsedMilliseconds} ms"); Console.WriteLine($"Closing session '{channel.SessionId}'."); await channel.CloseAsync(); }
/// <summary> /// Calculates the StdDev, Variance, StdDev2 and Variance2 aggregates for the timeslice. /// </summary> protected DataValue ComputeStdDev(TimeSlice slice, bool includeBounds, int valueType) { // get the values in the slice. List <DataValue> values = null; if (includeBounds) { values = GetValuesWithSimpleBounds(slice); } else { values = GetValues(slice); } // check for empty slice. if (values == null || values.Count == 0) { return(GetNoDataValue(slice)); } // get the regions. List <SubRegion> regions = GetRegionsInValueSet(values, false, true); List <double> xData = new List <double>(); double average = 0; bool nonGoodDataExists = false; for (int ii = 0; ii < regions.Count; ii++) { if (StatusCode.IsGood(regions[ii].StatusCode)) { xData.Add(regions[ii].StartValue); average += regions[ii].StartValue; } else { nonGoodDataExists = true; } } // check if no good data. if (xData.Count == 0) { return(GetNoDataValue(slice)); } average /= xData.Count; // calculate variance. double variance = 0; for (int ii = 0; ii < xData.Count; ii++) { double error = xData[ii] - average; variance += error * error; } // use the sample variance if bounds are included. if (includeBounds) { variance /= (xData.Count + 1); } // use the population variance if bounds are not included. else { variance /= xData.Count; } // select the result. double result = 0; switch (valueType) { case 1: { result = Math.Sqrt(variance); break; } case 2: { result = variance; break; } } // set the timestamp and status. DataValue value = new DataValue(); value.WrappedValue = new Variant(result, TypeInfo.Scalars.Double); value.SourceTimestamp = GetTimestamp(slice); value.ServerTimestamp = GetTimestamp(slice); if (nonGoodDataExists) { value.StatusCode = StatusCodes.UncertainDataSubNormal; } value.StatusCode = value.StatusCode.SetAggregateBits(AggregateBits.Calculated); // return result. return(value); }
public ReadVarResponse(string Name, uint code) : base() { success = StatusCode.IsGood(code); name = Name; statusCode = new StatusCode(code); }