Exemplo n.º 1
0
        // 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);
        }
Exemplo n.º 4
0
        /// <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));
        }
Exemplo n.º 5
0
        /// <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;
                }
            }
        }
Exemplo n.º 7
0
        /// <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));
        }
Exemplo n.º 8
0
        /// <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++;
            }
        }
Exemplo n.º 9
0
        /// <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);
                }
            }
        }
Exemplo n.º 10
0
        /// <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
        }
Exemplo n.º 11
0
        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[]>());
                }
            }
        }
Exemplo n.º 12
0
        /// <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);
        }
Exemplo n.º 13
0
        /// <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));
        }
Exemplo n.º 14
0
        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);
        }
Exemplo n.º 17
0
        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);
            }
        }
Exemplo n.º 18
0
        /// <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));
        }
Exemplo n.º 19
0
        /// <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);
            }
        }
Exemplo n.º 20
0
        /// <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));
        }
Exemplo n.º 21
0
            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);
                    //}
                }
            }
Exemplo n.º 22
0
        /// <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);
        }
Exemplo n.º 23
0
        /// <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);
        }
Exemplo n.º 24
0
 protected override bool RightStatusCode(DataValue dv)
 {
     return(StatusCode.IsGood(dv.StatusCode));
 }
Exemplo n.º 25
0
        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();
        }
Exemplo n.º 27
0
        /// <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);
        }
Exemplo n.º 30
0
 public ReadVarResponse(string Name, uint code) : base()
 {
     success    = StatusCode.IsGood(code);
     name       = Name;
     statusCode = new StatusCode(code);
 }