Stores the information requires to translate a string.
        /// <summary>
        /// Grants the lock.
        /// </summary>
        public void SetLock(ISystemContext context)
        {
            TranslationInfo state = new TranslationInfo(
                "LockConditionStateLocked",
                "en-US",
                BrowseNames.Locked);

            if (this.LockState.CurrentState != null)
            {
                this.LockState.CurrentState.Value = new LocalizedText(state);
                this.LockState.CurrentState.Id.Value = ExpandedNodeId.ToNodeId(ObjectIds.LockStateMachineType_Locked, context.NamespaceUris);
            }

            this.LockStateAsString.Value = state.Text;

            UpdateEffectiveState(context);
        }
        /// <summary>
        /// Activates the dialog.
        /// </summary>
        /// <param name="context">The system context.</param>
        public void Activate(ISystemContext context)
        {
            TranslationInfo state = new TranslationInfo(
                "ConditionStateDialogActive",
                "en-US",
                ConditionStateNames.Active);

            this.DialogState.Value = new LocalizedText(state);
            this.DialogState.Id.Value = true;

            if (this.DialogState.TransitionTime != null)
            {
                this.DialogState.TransitionTime.Value = DateTime.UtcNow;
            }

            UpdateEffectiveState(context);
        }
        /// <summary>
        /// Sets the response to the dialog.
        /// </summary>
        /// <param name="context">The system context.</param>
        /// <param name="response">The selected response.</param>
        public virtual void SetResponse(ISystemContext context, int response)
        {
            this.LastResponse.Value = response;

            TranslationInfo state = new TranslationInfo(
                "ConditionStateDialogInactive",
                "en-US",
                ConditionStateNames.Inactive);

            this.DialogState.Value = new LocalizedText(state);
            this.DialogState.Id.Value = false;

            if (this.DialogState.TransitionTime != null)
            {
                this.DialogState.TransitionTime.Value = DateTime.UtcNow;
            }

            UpdateEffectiveState(context);
        }
        /// <summary>
        /// Updates a transition event after the transition is complete.
        /// </summary>
        protected virtual void UpdateTransitionEvent(
            ISystemContext context,
            uint transitionId,
            uint causeId,
            TransitionEventState e)
        {
            TranslationInfo info = new TranslationInfo(
                "StateTransition",
                "en-US",
                "The {0} state machine moved to the {1} state.",
                this.GetDisplayPath(3, '.'),
                CurrentState.Value);

            e.Initialize(
                context,
                this,
                EventSeverity.Medium,
                new LocalizedText(info));

            e.SetChildValue(context, BrowseNames.FromState, LastState, false);
            e.SetChildValue(context, BrowseNames.ToState, CurrentState, false);
            e.SetChildValue(context, BrowseNames.Transition, LastTransition, false);
        }
Example #5
0
        /// <summary>
        /// Handles the OneShotShelve method.
        /// </summary>
        protected virtual ServiceResult OnOneShotShelve(
            ISystemContext context,
            MethodState method,
            IList <object> inputArguments,
            IList <object> outputArguments)
        {
            ServiceResult error = null;

            try
            {
                if (!this.EnabledState.Id.Value)
                {
                    return(error = StatusCodes.BadConditionDisabled);
                }

                if (!this.ShelvingState.IsCausePermitted(context, Methods.ShelvedStateMachineType_OneShotShelve, false))
                {
                    return(error = StatusCodes.BadConditionAlreadyShelved);
                }

                if (OnShelve == null)
                {
                    return(error = StatusCodes.BadNotSupported);
                }

                error = OnShelve(context, this, true, true, 0);

                // report a state change event.
                if (ServiceResult.IsGood(error))
                {
                    ReportStateChange(context, false);
                }
            }
            finally
            {
                if (this.AreEventsMonitored)
                {
                    AuditConditionShelvingEventState e = new AuditConditionShelvingEventState(null);

                    TranslationInfo info = new TranslationInfo(
                        "AuditConditionOneShotShelve",
                        "en-US",
                        "The OneShotShelve method was called.");

                    e.Initialize(
                        context,
                        this,
                        EventSeverity.Low,
                        new LocalizedText(info),
                        ServiceResult.IsGood(error),
                        DateTime.UtcNow);

                    e.SetChildValue(context, BrowseNames.SourceNode, NodeId, false);
                    e.SetChildValue(context, BrowseNames.SourceName, "Method/OneShotShelve", false);

                    e.SetChildValue(context, BrowseNames.MethodId, method.NodeId, false);
                    e.SetChildValue(context, BrowseNames.ShelvingTime, null, false);

                    ReportEvent(context, e);
                }
            }

            return(error);
        }
Example #6
0
        /// <summary>
        /// Handles the TimedShelve method.
        /// </summary>
        protected virtual ServiceResult OnTimedShelve(
            ISystemContext context,
            MethodState method,
            NodeId objectId,
            double shelvingTime)
        {
            ServiceResult error = null;

            try
            {
                if (!this.EnabledState.Id.Value)
                {
                    return(error = StatusCodes.BadConditionDisabled);
                }

                if (shelvingTime <= 0 || (this.MaxTimeShelved != null && shelvingTime > this.MaxTimeShelved.Value))
                {
                    return(error = StatusCodes.BadShelvingTimeOutOfRange);
                }

                if (!this.ShelvingState.IsCausePermitted(context, Methods.ShelvedStateMachineType_TimedShelve, false))
                {
                    return(error = StatusCodes.BadConditionAlreadyShelved);
                }

                if (OnShelve == null)
                {
                    return(error = StatusCodes.BadNotSupported);
                }

                error = OnShelve(context, this, true, false, shelvingTime);

                // report a state change event.
                if (ServiceResult.IsGood(error))
                {
                    ReportStateChange(context, false);
                }
            }
            finally
            {
                if (this.AreEventsMonitored)
                {
                    AuditConditionShelvingEventState e = new AuditConditionShelvingEventState(null);

                    TranslationInfo info = new TranslationInfo(
                        "AuditConditionTimedShelve",
                        "en-US",
                        "The TimedShelve method was called.");

                    e.Initialize(
                        context,
                        this,
                        EventSeverity.Low,
                        new LocalizedText(info),
                        ServiceResult.IsGood(error),
                        DateTime.UtcNow);

                    e.SourceName.Value = "Attribute/Call";

                    e.MethodId       = new PropertyState <NodeId>(e);
                    e.MethodId.Value = method.NodeId;

                    e.InputArguments       = new PropertyState <object[]>(e);
                    e.InputArguments.Value = new object[] { shelvingTime };

                    ReportEvent(context, e);
                }
            }

            return(error);
        }
        /// <summary>
        /// Creates a new instance of a ServiceResult
        /// </summary>
        public static ServiceResult Create(uint code, TranslationInfo translation)
        {
            if (translation == null)
            {
                return new ServiceResult(code);
            }

            return new ServiceResult(code, new LocalizedText(translation));
        }
Example #8
0
        /// <summary>
        /// Handles the TimedShelve method.
        /// </summary>
        protected virtual ServiceResult OnTimedShelve(
            ISystemContext context,
            MethodState method,
            NodeId objectId,
            double shelvingTime)
        {
            ServiceResult error = null;

            try
            {
                if (!this.EnabledState.Id.Value)
                {
                    return error = StatusCodes.BadConditionDisabled;
                }

                if (shelvingTime <= 0 || (this.MaxTimeShelved != null && shelvingTime > this.MaxTimeShelved.Value))
                {
                    return error = StatusCodes.BadShelvingTimeOutOfRange;
                }

                if (!this.ShelvingState.IsCausePermitted(context, Methods.ShelvedStateMachineType_TimedShelve, false))
                {
                    return error = StatusCodes.BadConditionAlreadyShelved;
                }

                if (OnShelve == null)
                {
                    return error = StatusCodes.BadNotSupported;
                }

                error = OnShelve(context, this, true, false, shelvingTime);

                // report a state change event.
                if (ServiceResult.IsGood(error))
                {
                    ReportStateChange(context, false);
                }
            }
            finally
            {
                if (this.AreEventsMonitored)
                {
                    AuditConditionShelvingEventState e = new AuditConditionShelvingEventState(null);

                    TranslationInfo info = new TranslationInfo(
                        "AuditConditionTimedShelve",
                        "en-US",
                        "The TimedShelve method was called.");

                    e.Initialize(
                        context,
                        this,
                        EventSeverity.Low,
                        new LocalizedText(info),
                        ServiceResult.IsGood(error),
                        DateTime.UtcNow);

                    e.SourceName.Value = "Attribute/Call";

                    e.MethodId = new PropertyState<NodeId>(e);
                    e.MethodId.Value = method.NodeId;

                    e.InputArguments = new PropertyState<object[]>(e);
                    e.InputArguments.Value = new object[] { shelvingTime };

                    ReportEvent(context, e);
                }
            }

            return error;
        }
        /// <summary>
        /// Updates the state.
        /// </summary>
        /// <param name="limit">The limit.</param>
        /// <param name="active">if set to <c>true</c> is the state is active.</param>
        private void UpdateState(TwoStateVariableState limit, bool active)
        {
            TranslationInfo state = null;

            if (active)
            {
                state = new TranslationInfo(
                     "ConditionStateActive",
                     "en-US",
                     ConditionStateNames.Active);
            }
            else
            {
                state = new TranslationInfo(
                     "ConditionStateInactive",
                     "en-US",
                     ConditionStateNames.Inactive);
            }

            limit.Value = new LocalizedText(state);
            limit.Id.Value = active;

            if (limit.TransitionTime != null)
            {
                limit.TransitionTime.Value = DateTime.UtcNow;
            }
        }
        /// <summary>
        /// Called when the Confirm method is called.
        /// </summary>
        /// <param name="context">The system context.</param>
        /// <param name="method">The method being called.</param>
        /// <param name="objectId">The id of the object.</param>
        /// <param name="eventId">The identifier for the event which is the target for the comment.</param>
        /// <param name="comment">The comment.</param>
        /// <returns>Any error.</returns>
        protected virtual ServiceResult OnConfirmCalled(
            ISystemContext context,
            MethodState method,
            NodeId objectId,
            byte[] eventId,
            LocalizedText comment)
        {
            ServiceResult error = ProcessBeforeConfirm(context, eventId, comment);

            if (ServiceResult.IsGood(error))
            {
                SetConfirmedState(context, true);
                SetComment(context, comment, GetCurrentUserId(context));
            }

            if (this.AreEventsMonitored)
            {
                // report a state change event.
                if (ServiceResult.IsGood(error))
                {
                    ReportStateChange(context, false);
                }

                // raise the audit event.
                AuditConditionConfirmEventState e = new AuditConditionConfirmEventState(null);

                TranslationInfo info = new TranslationInfo(
                    "AuditConditionConfirm",
                    "en-US",
                    "The Confirm method was called.");

                e.Initialize(
                    context,
                    this,
                    EventSeverity.Low,
                    new LocalizedText(info),
                    ServiceResult.IsGood(error),
                    DateTime.UtcNow);

                e.SourceName.Value = "Attribute/Call";

                e.MethodId = new PropertyState<NodeId>(e);
                e.MethodId.Value = method.NodeId;

                e.InputArguments = new PropertyState<object[]>(e);
                e.InputArguments.Value = new object[] { eventId, comment };

                ReportEvent(context, e);
            }

            return error;
        }
Example #11
0
        /// <summary>
        /// Constructs an event and reports to the server.
        /// </summary>
        private void RaiseAuditUpdateMethodEvent(
            ISystemContext context,
            MethodState method,
            bool status,
            IList<object> inputArguments)
        {
            BaseObjectState parent = method.Parent as BaseObjectState;

            #region Task #D6 - Add Support for Notifiers
            // check if it is even necessary to produce an event.
            if (parent != null && !parent.AreEventsMonitored)
            {
                return;
            }
            #endregion

            // construct translation object with default text.
            TranslationInfo info = new TranslationInfo(
                "AuditUpdateMethodEvent",
                "en-US",
                "A method was called.");

            // intialize the event.
            AuditUpdateMethodEventState e = new AuditUpdateMethodEventState(null);

            e.Initialize(
                SystemContext,
                null,
                EventSeverity.Medium,
                new LocalizedText(info),
                true,
                DateTime.UtcNow);

            // fill in additional fields.
            e.SetChildValue(SystemContext, Opc.Ua.BrowseNames.SourceNode, method.Parent.NodeId, false);
            e.SetChildValue(SystemContext, Opc.Ua.BrowseNames.SourceName, "Attribute/Call", false);
            e.SetChildValue(SystemContext, Opc.Ua.BrowseNames.ServerId, context.ServerUris.GetString(0), false);
            e.SetChildValue(SystemContext, Opc.Ua.BrowseNames.ClientAuditEntryId, context.AuditEntryId, false);

            if (context.UserIdentity != null)
            {
                e.SetChildValue(SystemContext, Opc.Ua.BrowseNames.ClientUserId, context.UserIdentity.DisplayName, false);
            }

            e.SetChildValue(SystemContext, Opc.Ua.BrowseNames.MethodId, method.NodeId, false);

            // need to change data type.
            Variant[] values = new Variant[inputArguments.Count];

            for (int ii = 0; ii < values.Length; ii++)
            {
                values[ii] = new Variant(inputArguments[ii]);
            }

            e.SetChildValue(SystemContext, Opc.Ua.BrowseNames.InputArguments, values, false);

            #region Task #D6 - Add Support for Notifiers
            // report the event to the parent. let it propagate up the tree. 
            if (parent != null && parent.AreEventsMonitored)
            {
                parent.ReportEvent(context, e);
                return;
            }
            #endregion

            // report the event to the server object.
            Server.ReportEvent(e);
        }
        /// <summary>
        /// Called when the Confirm method is called.
        /// </summary>
        /// <param name="context">The system context.</param>
        /// <param name="method">The method being called.</param>
        /// <param name="objectId">The id of the object.</param>
        /// <param name="eventId">The identifier for the event which is the target for the comment.</param>
        /// <param name="comment">The comment.</param>
        /// <returns>Any error.</returns>
        protected virtual ServiceResult OnConfirmCalled(
            ISystemContext context,
            MethodState method,
            NodeId objectId,
            byte[] eventId,
            LocalizedText comment)
        {
            ServiceResult error = ProcessBeforeConfirm(context, eventId, comment);

            if (ServiceResult.IsGood(error))
            {
                AcknowledgeableConditionState branch = GetAcknowledgeableBranch(eventId);

                if (branch != null)
                {
                    branch.OnConfirmCalled(context, method, objectId, eventId, comment);
                    RemoveBranchEvent(eventId);
                }
                else
                {
                    SetConfirmedState(context, true);
                }

                // If this is a branch, the comment goes to both the branch and the original event
                if (CanSetComment(comment))
                {
                    SetComment(context, comment, GetCurrentUserId(context));
                }

                UpdateRetainState();
            }

            if (EventsMonitored())
            {
                // report a state change event.
                if (ServiceResult.IsGood(error))
                {
                    ReportStateChange(context, false);
                }

                // raise the audit event.
                AuditConditionConfirmEventState e = new AuditConditionConfirmEventState(null);

                TranslationInfo info = new TranslationInfo(
                    "AuditConditionConfirm",
                    "en-US",
                    "The Confirm method was called.");

                e.Initialize(
                    context,
                    this,
                    EventSeverity.Low,
                    new LocalizedText(info),
                    ServiceResult.IsGood(error),
                    DateTime.UtcNow);

                e.SetChildValue(context, BrowseNames.SourceNode, NodeId, false);
                e.SetChildValue(context, BrowseNames.SourceName, "Method/Confirm", false);

                e.SetChildValue(context, BrowseNames.MethodId, method.NodeId, false);
                e.SetChildValue(context, BrowseNames.InputArguments, new object[] { eventId, comment }, false);

                e.SetChildValue(context, BrowseNames.ConditionEventId, eventId, false);
                e.SetChildValue(context, BrowseNames.Comment, comment, false);

                ReportEvent(context, e);
            }

            return(error);
        }
Example #13
0
        /// <summary>
        /// Validates the password for a username token.
        /// </summary>
        private void VerifyPassword(string userName, string password)
        {
            if (String.IsNullOrEmpty(userName))
            {
                // an empty username is not accepted.
                throw ServiceResultException.Create(StatusCodes.BadIdentityTokenInvalid,
                    "Security token is not a valid username token. An empty username is not accepted.");
            }

            if (String.IsNullOrEmpty(password))
            {
                // an empty password is not accepted.
                throw ServiceResultException.Create(StatusCodes.BadIdentityTokenRejected,
                    "Security token is not a valid username token. An empty password is not accepted.");
            }

            if (!((userName == "user1" && password == "password") ||
                 (userName == "user2" && password == "password1")))
            {
                // construct translation object with default text.
                TranslationInfo info = new TranslationInfo(
                    "InvalidPassword",
                    "en-US",
                    "Invalid username or password.",
                    userName);

                // create an exception with a vendor defined sub-code.
                throw new ServiceResultException(new ServiceResult(
                    StatusCodes.BadUserAccessDenied,
                    "InvalidPassword",
                    "http://opcfoundation.org/UA/Sample/",
                    new LocalizedText(info)));
            }
        }
        /// <summary>
        /// Verifies that a certificate user token is trusted.
        /// </summary>
        private void VerifyCertificate(X509Certificate2 certificate)
        {
            try
            {
                CertificateValidator.Validate(certificate);

                // determine if self-signed.
                bool isSelfSigned = Utils.CompareDistinguishedName(certificate.Subject, certificate.Issuer);

                // do not allow self signed application certs as user token
                if (isSelfSigned && Utils.HasApplicationURN(certificate))
                {
                    throw new ServiceResultException(StatusCodes.BadCertificateUseNotAllowed);
                }
            }
            catch (Exception)
            {
                // construct translation object with default text.
                TranslationInfo info = new TranslationInfo(
                    "InvalidCertificate",
                    "en-US",
                    "'{0}' is not a trusted user certificate.",
                    certificate.Subject);

                // create an exception with a vendor defined sub-code.
                throw new ServiceResultException(new ServiceResult(
                    StatusCodes.BadIdentityTokenRejected,
                    "InvalidCertificate",
                    "http://opcfoundation.org/UA/Sample/",
                    new LocalizedText(info)));
            }
        }
        /// <summary>
        /// Called when the Respond method is called.
        /// </summary>
        /// <param name="context">The system context.</param>
        /// <param name="method">The method being called.</param>
        /// <param name="objectId">The id of the object.</param>
        /// <param name="selectedResponse">The selected response.</param>
        /// <returns>Any error.</returns>
        protected virtual ServiceResult OnRespondCalled(
            ISystemContext context,
            MethodState method,
            NodeId objectId,
            int selectedResponse)
        {
            ServiceResult error = null;

            try
            {
                if (!this.EnabledState.Id.Value)
                {
                    return error = StatusCodes.BadConditionDisabled;
                }

                if (!this.DialogState.Id.Value)
                {
                    return error = StatusCodes.BadDialogNotActive;
                }

                if (selectedResponse < 0 || selectedResponse >= this.ResponseOptionSet.Value.Length)
                {
                    return error = StatusCodes.BadDialogResponseInvalid;
                }

                if (OnRespond == null)
                {
                    return error = StatusCodes.BadNotSupported;
                }

                error = OnRespond(context, this, selectedResponse);

                // report a state change event.
                if (ServiceResult.IsGood(error))
                {
                    ReportStateChange(context, false);
                }
            }
            finally
            {
                if (this.AreEventsMonitored)
                {
                    AuditConditionRespondEventState e = new AuditConditionRespondEventState(null);

                    TranslationInfo info = new TranslationInfo(
                        "AuditConditionDialogResponse",
                        "en-US",
                        "The Respond method was called.");

                    e.Initialize(
                        context,
                        this,
                        EventSeverity.Low,
                        new LocalizedText(info),
                        ServiceResult.IsGood(error),
                        DateTime.UtcNow);

                    e.SourceName.Value = "Attribute/Call";

                    e.MethodId = new PropertyState<NodeId>(e);
                    e.MethodId.Value = method.NodeId;

                    e.InputArguments = new PropertyState<object[]>(e);
                    e.InputArguments.Value = new object[] { selectedResponse };

                    ReportEvent(context, e);
                }
            }

            return error;
        }
        /// <summary>
        /// Updates a transition event after the transition is complete.
        /// </summary>
        protected virtual void UpdateTransitionEvent(
            ISystemContext context,
            uint transitionId,
            uint causeId,
            TransitionEventState e)
        {            
            TranslationInfo info = new TranslationInfo(
                "StateTransition",
                "en-US",
                "The {0} state machine moved to the {1} state.",
                this.GetDisplayPath(3, '.'),
                CurrentState.Value);

            e.Initialize(
                context,
                this,
                EventSeverity.Medium,
                new LocalizedText(info));
        
            e.SetChildValue(context, BrowseNames.FromState, LastState, false);
            e.SetChildValue(context, BrowseNames.ToState, CurrentState, false);
            e.SetChildValue(context, BrowseNames.Transition, LastTransition, false);
        }
        /// <summary>
        /// Updates an audit event after the method is invoked.
        /// </summary>
        protected virtual void UpdateAuditEvent(
            ISystemContext context,
            MethodState causeMethod,
            uint causeId,
            AuditUpdateStateEventState e,
            ServiceResult result)
        {            
            TranslationInfo info = new TranslationInfo(
                "StateTransition",
                "en-US",
                "The {1} method called was on the {0} state machine.",
                this.GetDisplayPath(3, '.'),
                causeMethod.DisplayName);

            e.Initialize(
                context,
                this,
                EventSeverity.Medium,
                new LocalizedText(info),
                ServiceResult.IsGood(result),
                DateTime.UtcNow);
            
            e.MethodId = new PropertyState<NodeId>(e);
            e.MethodId.Value = causeMethod.NodeId;

            e.SetChildValue(context, BrowseNames.OldStateId, LastState, false);
            e.SetChildValue(context, BrowseNames.NewStateId, CurrentState, false);
        }
Example #18
0
        /// <summary>
        /// Validates the password for a username token.
        /// </summary>
        private void VerifyPassword(string userName, string password)
        {
            if (String.IsNullOrEmpty(password))
            {
                // specify arguments to use when formatting the lcoalized text,
                TranslationInfo info = new TranslationInfo(TutorialErrorCodes.InvalidPassword, userName);

                // create an error with a vendor defined sub-code and the translation info.
                ServiceResult error = new ServiceResult(
                    StatusCodes.BadIdentityTokenRejected,
                    TutorialErrorCodes.InvalidPassword,
                    new LocalizedText(info));

                // throw the exception.
                throw new ServiceResultException(error);
            }
        }
Example #19
0
        /// <summary>
        /// Called when the Respond method is called.
        /// </summary>
        /// <param name="context">The system context.</param>
        /// <param name="method">The method being called.</param>
        /// <param name="objectId">The id of the object.</param>
        /// <param name="selectedResponse">The selected response.</param>
        /// <returns>Any error.</returns>
        protected virtual ServiceResult OnRespondCalled(
            ISystemContext context,
            MethodState method,
            NodeId objectId,
            int selectedResponse)
        {
            ServiceResult error = null;

            try {
                if (!this.EnabledState.Id.Value)
                {
                    return(error = StatusCodes.BadConditionDisabled);
                }

                if (!this.DialogState.Id.Value)
                {
                    return(error = StatusCodes.BadDialogNotActive);
                }

                if (selectedResponse < 0 || selectedResponse >= this.ResponseOptionSet.Value.Length)
                {
                    return(error = StatusCodes.BadDialogResponseInvalid);
                }

                if (OnRespond == null)
                {
                    return(error = StatusCodes.BadNotSupported);
                }

                error = OnRespond(context, this, selectedResponse);

                // report a state change event.
                if (ServiceResult.IsGood(error))
                {
                    ReportStateChange(context, false);
                }
            } finally {
                if (this.AreEventsMonitored)
                {
                    AuditConditionRespondEventState e = new AuditConditionRespondEventState(null);

                    TranslationInfo info = new TranslationInfo(
                        "AuditConditionDialogResponse",
                        "en-US",
                        "The Respond method was called.");

                    e.Initialize(
                        context,
                        this,
                        EventSeverity.Low,
                        new LocalizedText(info),
                        ServiceResult.IsGood(error),
                        DateTime.UtcNow);

                    e.SourceName.Value = "Attribute/Call";

                    e.MethodId       = new PropertyState <NodeId>(e);
                    e.MethodId.Value = method.NodeId;

                    e.InputArguments       = new PropertyState <object[]>(e);
                    e.InputArguments.Value = new object[] { selectedResponse };

                    ReportEvent(context, e);
                }
            }

            return(error);
        }
Example #20
0
        /// <summary>
        /// Reads a lock object.
        /// </summary>
        public LockConditionState ReadLock(ISystemContext context, BaseObject source)
        {
            ushort namespaceIndex = (ushort)context.NamespaceUris.GetIndex(DsatsDemo.Namespaces.DsatsDemo);

            LockConditionState node = new LockConditionState(null);

            node.Create(
                context,
                new NodeId("Locks/" + source.BrowseName, namespaceIndex),
                new QualifiedName(source.BrowseName, namespaceIndex),
                null,
                true);

            if (source.DisplayName != null && source.DisplayName.Length > 0)
            {
                node.DisplayName = Import(source.DisplayName);
            }

            if (source.Description != null && source.Description.Length > 0)
            {
                node.Description = Import(source.Description);
            }

            node.SetEnableState(context, true);
            node.Unlock(context);

            node.ConditionName.Value = source.BrowseName;
            node.EventId.Value = Guid.NewGuid().ToByteArray();
            node.EventType.Value = node.TypeDefinitionId;
            node.SourceName.Value = BrowseNames.Rig;
            node.SourceNode.Value = new NodeId(Objects.Rig, namespaceIndex);
            node.Severity.Value = 100;
            node.Time.Value = DateTime.UtcNow;
            node.ReceiveTime.Value = DateTime.UtcNow;
            node.ConditionClassId.Value = Opc.Ua.ObjectTypeIds.BaseConditionClassType;
            node.ConditionClassName.Value = Opc.Ua.BrowseNames.BaseConditionClassType;
            node.Retain.Value = true;
            
            TranslationInfo state = new TranslationInfo(
                "LockConditionStateMessage",
                "en-US",
                "Lock object is now in the '{0}' state.",
                node.LockState.CurrentState);

            node.Message.Value = new Opc.Ua.LocalizedText(state);

            return node;
        }
        /// <summary>
        /// Updates the condition state after enabling.
        /// </summary>
        /// <param name="context">The system context.</param>
        protected virtual void UpdateStateAfterAcknowledge(ISystemContext context)
        {
            TranslationInfo state = new TranslationInfo(
                "ConditionStateAcknowledged",
                "en-US",
                ConditionStateNames.Acknowledged);

            this.AckedState.Value = new LocalizedText(state);
            this.AckedState.Id.Value = true;

            if (this.AckedState.TransitionTime != null)
            {
                this.AckedState.TransitionTime.Value = DateTime.UtcNow;
            }

            UpdateEffectiveState(context);
        }
Example #22
0
        /// <summary>
        /// Sets the active state of the condition.
        /// </summary>
        /// <param name="context">The system context.</param>
        /// <param name="active">if set to <c>true</c> the condition is active.</param>
        public virtual void SetActiveState(
            ISystemContext context,
            bool active)
        {
            TranslationInfo state = null;

            if (active)
            {
                state = new TranslationInfo(
                     "ConditionStateActive",
                     "en-US",
                     ConditionStateNames.Active);
            }
            else
            {
                // update shelving state if one shot mode.
                if (this.ShelvingState != null)
                {
                    if (m_oneShot)
                    {
                        SetShelvingState(context, false, false, 0);
                    }
                }

                state = new TranslationInfo(
                     "ConditionStateInactive",
                     "en-US",
                     ConditionStateNames.Inactive);
            }

            this.ActiveState.Value = new LocalizedText(state);
            this.ActiveState.Id.Value = active;

            if (this.ActiveState.TransitionTime != null)
            {
                this.ActiveState.TransitionTime.Value = DateTime.UtcNow;
            }

            UpdateEffectiveState(context);
        }
        /// <summary>
        /// Updates the condition state after disabling.
        /// </summary>
        /// <param name="context">The system context.</param>
        protected virtual void UpdateStateAfterUnconfirm(ISystemContext context)
        {
            if (this.ConfirmedState != null)
            {
                TranslationInfo state = new TranslationInfo(
                    "ConditionStateUnconfirmed",
                    "en-US",
                    ConditionStateNames.Unconfirmed);

                this.ConfirmedState.Value = new LocalizedText(state);
                this.ConfirmedState.Id.Value = false;

                if (this.ConfirmedState.TransitionTime != null)
                {
                    this.ConfirmedState.TransitionTime.Value = DateTime.UtcNow;
                }

                UpdateEffectiveState(context);
            }
        }
        /// <summary>
        /// Handles the Disable method.
        /// </summary>
        protected virtual ServiceResult OnDisableCalled(
            ISystemContext context,
            MethodState method,
            IList<object> inputArguments,
            IList<object> outputArguments)
        {
            // check that method can be called.
            ServiceResult error = ProcessBeforeEnableDisable(context, false);

            if (ServiceResult.IsGood(error))
            {
                UpdateStateAfterDisable(context);
            }

            // raise the audit event.
            if (this.AreEventsMonitored)
            {
                // report a state change event.
                if (ServiceResult.IsGood(error))
                {
                    ReportStateChange(context, true);
                }

                // raise the audit event.
                AuditConditionEnableEventState e = new AuditConditionEnableEventState(null);

                TranslationInfo info = new TranslationInfo(
                    "AuditConditionEnable",
                    "en-US",
                    "The Disable method was called.");

                e.Initialize(
                    context,
                    this,
                    EventSeverity.Low,
                    new LocalizedText(info),
                    ServiceResult.IsGood(error),
                    DateTime.UtcNow);

                e.SourceName.Value = "Attribute/Call";

                e.MethodId = new PropertyState<NodeId>(e);
                e.MethodId.Value = method.NodeId;

                ReportEvent(context, e);
            }

            return error;
        }
        /// <summary>
        /// Peridically checks the system state.
        /// </summary>
        private void OnCheckSystemStatus(object state)
        {
            #if CONDITION_SAMPLES
            lock (Lock)
            {
                try
                {  
                    // create the dialog.
                    if (m_dialog == null)
                    {
                        m_dialog = new DialogConditionState(null);

                        CreateNode(
                            SystemContext,
                            ExpandedNodeId.ToNodeId(ObjectIds.Data_Conditions, SystemContext.NamespaceUris),
                            ReferenceTypeIds.HasComponent,
                            new QualifiedName("ResetSystemDialog", m_namespaceIndex),
                            m_dialog);

                        m_dialog.OnAfterResponse = OnDialogComplete;
                    }
        
                    StatusCode systemStatus = m_system.SystemStatus;
                    m_systemStatusCondition.UpdateStatus(systemStatus);

                    // cycle through different status codes in order to simulate a real system.
                    if (StatusCode.IsGood(systemStatus))
                    {
                        m_systemStatusCondition.UpdateSeverity((ushort)EventSeverity.Low);
                        m_system.SystemStatus = StatusCodes.Uncertain;
                    }
                    else if (StatusCode.IsUncertain(systemStatus))
                    {
                        m_systemStatusCondition.UpdateSeverity((ushort)EventSeverity.Medium);
                        m_system.SystemStatus = StatusCodes.Bad;
                    }
                    else
                    {
                        m_systemStatusCondition.UpdateSeverity((ushort)EventSeverity.High);
                        m_system.SystemStatus = StatusCodes.Good;
                    }

                    // request a reset if status is bad.
                    if (StatusCode.IsBad(systemStatus))
                    {
                        m_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);

                    m_systemStatusCondition.ReportConditionChange(
                        SystemContext,
                        null,
                        new LocalizedText(info),
                        false);
                }
                catch (Exception e)
                {
                    Utils.Trace(e, "Unexpected error monitoring system status.");
                }
            }
            #endif
        }    
Example #26
0
        /// <summary>
        /// Sets the limit state of the condition.
        /// </summary>
        /// <param name="context">The system context.</param>
        /// <param name="limit">The bit masks specifying the current state.</param>
        public virtual void SetLimitState(
            ISystemContext context,
            LimitAlarmStates limit)
        {
            if (this.HighState != null)
            {
                UpdateState(this.HighState, ((limit & LimitAlarmStates.High) != 0 || (limit & LimitAlarmStates.HighHigh) != 0));
            }

            if (this.HighHighState != null)
            {
                UpdateState(this.HighHighState, (limit & LimitAlarmStates.HighHigh) != 0);
            }

            if (this.LowState != null)
            {
                UpdateState(this.LowState, ((limit & LimitAlarmStates.Low) != 0 || (limit & LimitAlarmStates.LowLow) != 0));
            }

            if (this.LowLowState != null)
            {
                UpdateState(this.LowLowState, (limit & LimitAlarmStates.LowLow) != 0);
            }

            // select an appropriate effective display name for the active state.
            TranslationInfo displayName = null;

            if ((limit & LimitAlarmStates.HighHigh) != 0)
            {
                displayName = new TranslationInfo(
                    "ConditionStateHighHighActive",
                    "en-US",
                    ConditionStateNames.HighHighActive);
            }
            else if ((limit & LimitAlarmStates.LowLow) != 0)
            {
                displayName = new TranslationInfo(
                    "ConditionStateLowLowActive",
                    "en-US",
                    ConditionStateNames.LowLowActive);
            }
            else if ((limit & LimitAlarmStates.High) != 0)
            {
                displayName = new TranslationInfo(
                    "ConditionStateHighActive",
                    "en-US",
                    ConditionStateNames.HighActive);
            }
            else if ((limit & LimitAlarmStates.Low) != 0)
            {
                displayName = new TranslationInfo(
                    "ConditionStateLowActive",
                    "en-US",
                    ConditionStateNames.LowActive);
            }
            else
            {
                displayName = new TranslationInfo(
                    "ConditionStateInactive",
                    "en-US",
                    ConditionStateNames.Inactive);
            }

            // update the active superstae.
            SetActiveEffectiveSubState(context, new LocalizedText(displayName), DateTime.UtcNow);
            UpdateEffectiveState(context);
        }
        /// <summary>
        /// Does the simulation.
        /// </summary>
        /// <param name="state">The state.</param>
        private void DoSimulation(object state)
        {
            try
            {
                for (int ii = 1; ii < 3; ii++)
                {
                    // construct translation object with default text.
                    TranslationInfo info = new TranslationInfo(
                        "SystemCycleStarted",
                        "en-US",
                        "The system cycle '{0}' has started.",
                        ++m_cycleId);

                    // construct the event.
                    SystemCycleStartedEventState e = new SystemCycleStartedEventState(null);

                    e.Initialize(
                        SystemContext,
                        null,
                        (EventSeverity)ii,
                        new LocalizedText(info));

                    e.SetChildValue(SystemContext, Opc.Ua.BrowseNames.SourceName, "System", false);
                    e.SetChildValue(SystemContext, Opc.Ua.BrowseNames.SourceNode, Opc.Ua.ObjectIds.Server, false);
                    e.SetChildValue(SystemContext, new QualifiedName(BrowseNames.CycleId, NamespaceIndex), m_cycleId.ToString(), false);

                    CycleStepDataType step = new CycleStepDataType();
                    step.Name = "Step 1";
                    step.Duration = 1000;

                    e.SetChildValue(SystemContext, new QualifiedName(BrowseNames.CurrentStep, NamespaceIndex), step, false);
                    e.SetChildValue(SystemContext, new QualifiedName(BrowseNames.Steps, NamespaceIndex), new CycleStepDataType[] { step, step }, false);

                    Server.ReportEvent(e);
                }
            }
            catch (Exception e)
            {
                Utils.Trace(e, "Unexpected error during simulation.");
            }
        }
        public ServiceResult OnWriteValue(ISystemContext context, NodeState node, ref object value)
        {
            if (context.UserIdentity == null || context.UserIdentity.TokenType == UserTokenType.Anonymous)
            {
                TranslationInfo info = new TranslationInfo(
                    "BadUserAccessDenied",
                    "en-US",
                    "User cannot change value.");

                return new ServiceResult(StatusCodes.BadUserAccessDenied, new LocalizedText(info));
            }

            // attempt to update file system.
            try
            {
                string filePath = value as string;
                PropertyState<string> variable = node as PropertyState<string>;

                if (!String.IsNullOrEmpty(variable.Value))
                {
                    FileInfo file = new FileInfo(variable.Value);

                    if (file.Exists)
                    {
                        file.Delete();
                    }
                }

                if (!String.IsNullOrEmpty(filePath))
                {
                    FileInfo file = new FileInfo(filePath);

                    using (StreamWriter writer = file.CreateText())
                    {
                        writer.WriteLine(System.Security.Principal.WindowsIdentity.GetCurrent().Name);
                    }
                }

                value = filePath;
            }
            catch (Exception e)
            {
                return ServiceResult.Create(e, StatusCodes.BadUserAccessDenied, "Could not update file system.");
            }

            return ServiceResult.Good;
        }
Example #29
0
        /// <summary>
        /// Sets the suppressed state of the condition.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="suppressed">if set to <c>true</c> the condition is suppressed.</param>
        public virtual void SetSuppressedState(
            ISystemContext context,
            bool suppressed)
        {
            if (this.SuppressedState == null)
            {
                return;
            }

            TranslationInfo state = null;

            if (suppressed)
            {
                SuppressedOrShelved.Value = true;

                state = new TranslationInfo(
                     "ConditionStateSuppressed",
                     "en-US",
                     ConditionStateNames.Suppressed);
            }
            else
            {
                if (this.ShelvingState == null || this.ShelvingState.CurrentState.Id.Value == ObjectIds.ShelvedStateMachineType_Unshelved)
                {
                    SuppressedOrShelved.Value = false;
                }

                state = new TranslationInfo(
                     "ConditionStateUnsuppressed",
                     "en-US",
                     ConditionStateNames.Unsuppressed);
            }

            this.SuppressedState.Value = new LocalizedText(state);
            this.SuppressedState.Id.Value = suppressed;

            if (this.SuppressedState.TransitionTime != null)
            {
                this.SuppressedState.TransitionTime.Value = DateTime.UtcNow;
            }

            UpdateEffectiveState(context);
        }
        /// <summary>
        /// Handles the generate values method.
        /// </summary>
        protected virtual ServiceResult OnGenerateValues(
            ISystemContext context, 
            MethodState method,
            NodeId objectId,
            uint count)
        {
            ClearChangeMasks(context, true);

            if (AreEventsMonitored)
            {
                GenerateValuesEventState e = new GenerateValuesEventState(null);
                            
                TranslationInfo message = new TranslationInfo(
                    "GenerateValuesEventType",
                    "en-US",
                    "New values generated for test source '{0}'.",
                    this.DisplayName);
                
                e.Initialize(
                    context,
                    this,
                    EventSeverity.MediumLow,
                    new LocalizedText(message));

                e.Iterations = new PropertyState<uint>(e);
                e.Iterations.Value = count;

                e.NewValueCount = new PropertyState<uint>(e);
                e.NewValueCount.Value = 10;

                ReportEvent(context, e);
            }
            
            #if CONDITION_SAMPLES
            this.CycleComplete.RequestAcknowledgement(context, (ushort)EventSeverity.Low);
            #endif
            
            return ServiceResult.Good;
        }
Example #31
0
        /// <summary>
        /// Handles the Unshelve method.
        /// </summary>
        protected virtual ServiceResult OnUnshelve(
            ISystemContext context,
            MethodState method,
            IList<object> inputArguments,
            IList<object> outputArguments)
        {
            ServiceResult error = null;

            try
            {
                if (!this.EnabledState.Id.Value)
                {
                    return error = StatusCodes.BadConditionDisabled;
                }

                if (!this.ShelvingState.IsCausePermitted(context, Methods.ShelvedStateMachineType_Unshelve, false))
                {
                    return error = StatusCodes.BadConditionNotShelved;
                }

                if (OnShelve == null)
                {
                    return error = StatusCodes.BadNotSupported;
                }

                error = OnShelve(context, this, false, false, 0);

                // report a state change event.
                if (ServiceResult.IsGood(error))
                {
                    ReportStateChange(context, false);
                }
            }
            finally
            {
                // raise the audit event.
                if (this.AreEventsMonitored)
                {
                    AuditConditionShelvingEventState e = new AuditConditionShelvingEventState(null);

                    TranslationInfo info = new TranslationInfo(
                        "AuditConditionUnshelve",
                        "en-US",
                        "The Unshelve method was called.");

                    e.Initialize(
                        context,
                        this,
                        EventSeverity.Low,
                        new LocalizedText(info),
                        ServiceResult.IsGood(error),
                        DateTime.UtcNow);

                    e.SourceName.Value = "Attribute/Call";

                    e.MethodId = new PropertyState<NodeId>(e);
                    e.MethodId.Value = method.NodeId;

                    ReportEvent(context, e);
                }
            }

            return error;
        }
        /// <summary>
        /// Verifies that a certificate user token is trusted.
        /// </summary>
        private void VerifyCertificate(X509Certificate2 certificate)
        {
            try
            {
                m_certificateValidator.Validate(certificate);
            }
            catch (Exception e)
            {
                // construct translation object with default text.
                TranslationInfo info = new TranslationInfo(
                    "InvalidCertificate",
                    "en-US",
                    "'{0}' is not a trusted user certificate.",
                    certificate.Subject);

                // create an exception with a vendor defined sub-code.
                throw new ServiceResultException(new ServiceResult(
                    e,
                    StatusCodes.BadIdentityTokenRejected,
                    "InvalidCertificate",
                    Namespaces.UserAuthentication,
                    new LocalizedText(info)));
            }
        }
        /// <summary>
        /// Sets the limit state of the condition.
        /// </summary>
        /// <param name="context">The system context.</param>
        /// <param name="limit">The bit masks specifying the current state.</param>
        public virtual void SetLimitState(
            ISystemContext context,
            LimitAlarmStates limit)
        {
            if (this.HighState != null)
            {
                UpdateState(this.HighState, ((limit & LimitAlarmStates.High) != 0 || (limit & LimitAlarmStates.HighHigh) != 0));
            }

            if (this.HighHighState != null)
            {
                UpdateState(this.HighHighState, (limit & LimitAlarmStates.HighHigh) != 0);
            }

            if (this.LowState != null)
            {
                UpdateState(this.LowState, ((limit & LimitAlarmStates.Low) != 0 || (limit & LimitAlarmStates.LowLow) != 0));
            }

            if (this.LowLowState != null)
            {
                UpdateState(this.LowLowState, (limit & LimitAlarmStates.LowLow) != 0);
            }

            // select an appropriate effective display name for the active state.
            TranslationInfo displayName = null;

            if ((limit & LimitAlarmStates.HighHigh) != 0)
            {
                displayName = new TranslationInfo(
                     "ConditionStateHighHighActive",
                     "en-US",
                     ConditionStateNames.HighHighActive);
            }
            else if ((limit & LimitAlarmStates.LowLow) != 0)
            {
                displayName = new TranslationInfo(
                     "ConditionStateLowLowActive",
                     "en-US",
                     ConditionStateNames.LowLowActive);
            }
            else if ((limit & LimitAlarmStates.High) != 0)
            {
                displayName = new TranslationInfo(
                     "ConditionStateHighActive",
                     "en-US",
                     ConditionStateNames.HighActive);
            }
            else if ((limit & LimitAlarmStates.Low) != 0)
            {
                displayName = new TranslationInfo(
                     "ConditionStateLowActive",
                     "en-US",
                     ConditionStateNames.LowActive);
            }
            else
            {
                displayName = new TranslationInfo(
                     "ConditionStateInactive",
                     "en-US",
                     ConditionStateNames.Inactive);
            }

            // update the active superstae.
            SetActiveEffectiveSubState(context, new LocalizedText(displayName), DateTime.UtcNow);
            UpdateEffectiveState(context);
        }
        /// <summary>
        /// Validates a Kerberos WSS user token.
        /// </summary>
        private SecurityToken ParseAndVerifyKerberosToken(byte[] tokenData)
        {
            XmlDocument document = new XmlDocument();
            XmlNodeReader reader = null;

            try
            {
                document.InnerXml = new UTF8Encoding().GetString(tokenData).Trim();
                reader = new XmlNodeReader(document.DocumentElement);

                SecurityToken securityToken = new WSSecurityTokenSerializer().ReadToken(reader, null);
                System.IdentityModel.Tokens.KerberosReceiverSecurityToken receiver = securityToken as KerberosReceiverSecurityToken;

                KerberosSecurityTokenAuthenticator authenticator = new KerberosSecurityTokenAuthenticator();

                if (authenticator.CanValidateToken(receiver))
                {
                    authenticator.ValidateToken(receiver);
                }

                return securityToken;
            }
            catch (Exception e)
            {
                // construct translation object with default text.
                TranslationInfo info = new TranslationInfo(
                    "InvalidKerberosToken",
                    "en-US",
                    "'{0}' is not a valid Kerberos token.",
                    document.DocumentElement.LocalName);

                // create an exception with a vendor defined sub-code.
                throw new ServiceResultException(new ServiceResult(
                    e,
                    StatusCodes.BadIdentityTokenRejected,
                    "InvalidKerberosToken",
                    Namespaces.UserAuthentication,
                    new LocalizedText(info)));
            }
            finally
            {
                if (reader != null)
                {
                    reader.Close();
                }
            }
        }
Example #35
0
        /// <summary>
        /// Handles the Unshelve method.
        /// </summary>
        protected virtual ServiceResult OnUnshelve(
            ISystemContext context,
            MethodState method,
            IList <object> inputArguments,
            IList <object> outputArguments)
        {
            ServiceResult error = null;

            try
            {
                if (!this.EnabledState.Id.Value)
                {
                    return(error = StatusCodes.BadConditionDisabled);
                }

                if (!this.ShelvingState.IsCausePermitted(context, Methods.ShelvedStateMachineType_Unshelve, false))
                {
                    return(error = StatusCodes.BadConditionNotShelved);
                }

                if (OnShelve == null)
                {
                    return(error = StatusCodes.BadNotSupported);
                }

                error = OnShelve(context, this, false, false, 0);

                // report a state change event.
                if (ServiceResult.IsGood(error))
                {
                    ReportStateChange(context, false);
                }
            }
            finally
            {
                // raise the audit event.
                if (this.AreEventsMonitored)
                {
                    AuditConditionShelvingEventState e = new AuditConditionShelvingEventState(null);

                    TranslationInfo info = new TranslationInfo(
                        "AuditConditionUnshelve",
                        "en-US",
                        "The Unshelve method was called.");

                    e.Initialize(
                        context,
                        this,
                        EventSeverity.Low,
                        new LocalizedText(info),
                        ServiceResult.IsGood(error),
                        DateTime.UtcNow);

                    e.SourceName.Value = "Attribute/Call";

                    e.MethodId       = new PropertyState <NodeId>(e);
                    e.MethodId.Value = method.NodeId;

                    ReportEvent(context, e);
                }
            }

            return(error);
        }
        /// <summary>
        /// This method is called at the being of the thread that processes a request.
        /// </summary>
        protected override OperationContext ValidateRequest(RequestHeader requestHeader, RequestType requestType)
        {
            OperationContext context = base.ValidateRequest(requestHeader, requestType);

            if (requestType == RequestType.Write)
            {
                // reject all writes if no user provided.
                if (context.UserIdentity.TokenType == UserTokenType.Anonymous)
                {
                    // construct translation object with default text.
                    TranslationInfo info = new TranslationInfo(
                        "NoWriteAllowed",
                        "en-US",
                        "Must provide a valid windows user before calling write.");

                    // create an exception with a vendor defined sub-code.
                    throw new ServiceResultException(new ServiceResult(
                        StatusCodes.BadUserAccessDenied,
                        "NoWriteAllowed",
                        Namespaces.UserAuthentication,
                        new LocalizedText(info)));
                }

                SecurityToken securityToken = context.UserIdentity.GetSecurityToken();

                // check for a kerberso token.
                KerberosReceiverSecurityToken kerberosToken = securityToken as KerberosReceiverSecurityToken;

                if (kerberosToken != null)
                {
                    ImpersonationContext impersonationContext = new ImpersonationContext();
                    impersonationContext.Context = kerberosToken.WindowsIdentity.Impersonate();

                    lock (this.m_lock)
                    {
                        m_contexts.Add(context.RequestId, impersonationContext);
                    }
                }

                // check for a user name token.
                UserNameSecurityToken userNameToken = securityToken as UserNameSecurityToken;

                if (userNameToken != null)
                {
                    LogonUser(context, userNameToken);
                }
            }

            return context;
        }
        /// <summary>
        /// Creates a new instance of a ServiceResult
        /// </summary>
        public static ServiceResult Create(Exception e, TranslationInfo translation, uint defaultCode)
        {
            // replace the default code with the one from the exception.
            ServiceResultException sre = e as ServiceResultException;
            
            if (sre != null)
            {
                defaultCode = sre.StatusCode;
            }

            if (translation == null)
            {
                return new ServiceResult(e, defaultCode);
            }

            return new ServiceResult(defaultCode, new LocalizedText(translation), e);
        }
        /// <summary>
        /// Called when the Acknowledge method is called.
        /// </summary>
        /// <param name="context">The system context.</param>
        /// <param name="method">The method being called.</param>
        /// <param name="objectId">The id of the object.</param>
        /// <param name="eventId">The identifier for the event which is the target for the comment.</param>
        /// <param name="comment">The comment.</param>
        /// <returns>Any error.</returns>
        protected virtual ServiceResult OnAcknowledgeCalled(
            ISystemContext context,
            MethodState method,
            NodeId objectId,
            byte[] eventId,
            LocalizedText comment)
        {
            ServiceResult error = ProcessBeforeAcknowledge(context, eventId, comment);

            if (ServiceResult.IsGood(error))
            {
                AcknowledgeableConditionState branch = GetAcknowledgeableBranch(eventId);

                if (branch != null)
                {
                    branch.OnAcknowledgeCalled(context, method, objectId, eventId, comment);

                    if (SupportsConfirm())
                    {
                        ReplaceBranchEvent(eventId, branch);
                    }
                    else
                    {
                        RemoveBranchEvent(eventId);
                    }
                }
                else
                {
                    SetAcknowledgedState(context, true);

                    if (SupportsConfirm())
                    {
                        SetConfirmedState(context, false);
                    }
                }

                // If this is a branch, the comment goes to both the branch and the original event
                if (CanSetComment(comment))
                {
                    SetComment(context, comment, GetCurrentUserId(context));
                }

                UpdateRetainState();
            }

            if (EventsMonitored())
            {
                // report a state change event.
                if (ServiceResult.IsGood(error))
                {
                    ReportStateChange(context, false);
                }

                // raise the audit event.
                AuditConditionAcknowledgeEventState e = new AuditConditionAcknowledgeEventState(null);

                TranslationInfo info = new TranslationInfo(
                    "AuditConditionAcknowledge",
                    "en-US",
                    "The Acknowledge method was called.");

                e.Initialize(
                    context,
                    this,
                    EventSeverity.Low,
                    new LocalizedText(info),
                    ServiceResult.IsGood(error),
                    DateTime.UtcNow);

                e.SourceName.Value = "Attribute/Call";

                e.MethodId       = new PropertyState <NodeId>(e);
                e.MethodId.Value = method.NodeId;

                e.InputArguments       = new PropertyState <object[]>(e);
                e.InputArguments.Value = new object[] { eventId, comment };

                ReportEvent(context, e);
            }

            return(error);
        }