Example #1
0
        private async Task <ControlCompletionCheck> BeginControlAsync(SensingAgentState controlState, CancellationToken cancellationToken)
        {
            // this is a convenience method for beginning both active and opportunistic control. control state must be one of these two.
            if (controlState != SensingAgentState.ActiveControl && controlState != SensingAgentState.OpportunisticControl)
            {
                throw new Exception("Unrecognized control state:  " + controlState);
            }

            ControlCompletionCheck controlCompletionCheck = null;

            if (await TransitionToNewStateAsync(controlState, true, cancellationToken))
            {
                controlCompletionCheck = new ControlCompletionCheck(async controlCompletionCheckCancellationToken =>
                {
                    // the current check is called when a protocol is shutting down, and periodically while the
                    // protocol remains running. as long as the protocol is running and the observed data meet
                    // the control criterion, continue with sensing control; otherwise, end control and return
                    // to idle.
                    if (Protocol.State == ProtocolState.Running && ObservedDataMeetControlCriterion())
                    {
                        SensusServiceHelper.Logger.Log("Continuing sensing control in state:  " + StateDescription, LoggingLevel.Normal, GetType());
                    }
                    else
                    {
                        await ReturnToIdle(controlCompletionCheckCancellationToken);
                    }

                    return(State);
                }, ControlCompletionCheckInterval, "Sensus would like to measure your environment. Please open this notification.", "Measuring environment. You may close this alert.");

                SensusServiceHelper.Logger.Log("Established sensing control in state:  " + StateDescription, LoggingLevel.Normal, GetType());
            }

            return(controlCompletionCheck);
        }
Example #2
0
 public SensingAgentStateDatum(DateTimeOffset timestamp, SensingAgentState previousState, SensingAgentState currentState, string description)
     : base(timestamp)
 {
     PreviousState = previousState;
     CurrentState  = currentState;
     Description   = description;
 }
Example #3
0
        protected override async Task OnStateChangedAsync(SensingAgentState previousState, SensingAgentState currentState, CancellationToken cancellationToken)
        {
            await base.OnStateChangedAsync(previousState, currentState, cancellationToken);

            if (currentState == SensingAgentState.OpportunisticControl)
            {
                throw new Exception("Error, opportunistic control should be disabled for this agent");
            }

            var previousDesignDocumentState = ToDesignDocumentState(previousState);
            var currentDesignDocumentState  = ToDesignDocumentState(currentState);

            if (currentDesignDocumentState != previousDesignDocumentState)
            {
                var previousProbes = ToDesignDocumentProbes(previousDesignDocumentState).ToArray();
                var currentProbes  = ToDesignDocumentProbes(currentDesignDocumentState).ToArray();

                var probesToIgnore = previousProbes.Intersect(currentProbes).ToArray();
                var probesToStop   = previousProbes.Except(probesToIgnore).ToArray();
                var probesToStart  = currentProbes.Except(probesToIgnore).ToArray();

                foreach (var probe in probesToStop)
                {
                    await probe.StopAsync();
                }

                foreach (var probe in probesToStart)
                {
                    probe.MaxDataStoresPerSecond = ProbeHz;
                    await probe.StartAsync();
                }
            }
        }
        protected override async Task OnStateChangedAsync(SensingAgentState previousState, SensingAgentState currentState, CancellationToken cancellationToken)
        {
            await base.OnStateChangedAsync(previousState, currentState, cancellationToken);

            if (currentState == SensingAgentState.OpportunisticControl)
            {
                // keep device awake
                await SensusServiceHelper.KeepDeviceAwakeAsync();

                // increase sampling rate
                if (Protocol.TryGetProbe <ICompassDatum, IListeningProbe>(out IListeningProbe compassProbe))
                {
                    // increase sampling rate
                    compassProbe.MaxDataStoresPerSecond = 20;

                    // restart probe to take on new settings
                    await compassProbe.RestartAsync();
                }
            }
            else if (currentState == SensingAgentState.EndingControl)
            {
                if (Protocol.TryGetProbe <ICompassDatum, IListeningProbe>(out IListeningProbe compassProbe))
                {
                    // decrease sampling rate
                    compassProbe.MaxDataStoresPerSecond = 5;

                    // restart probe to take on original settings
                    await compassProbe.RestartAsync();
                }

                // let device sleep
                await SensusServiceHelper.LetDeviceSleepAsync();
            }
        }
Example #5
0
            public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
            {
                SensingAgentState state = (SensingAgentState)value;
                SensingAgentState label = (SensingAgentState)parameter;

                return(state == label ? Color.Green : Color.Gray);
            }
Example #6
0
 /// <summary>
 /// A function to map state to the constructs used/defined in the design document
 /// </summary>
 /// <param name="state">a sensing agent state</param>
 /// <returns>The state in terms of design document constructs</returns>
 private DesignDocumentState ToDesignDocumentState(SensingAgentState state)
 {
     if (state == SensingAgentState.ActiveObservation)
     {
         return(DesignDocumentState.ListeningWindow);
     }
     else if (state == SensingAgentState.ActiveControl)
     {
         return(DesignDocumentState.ActivePredictionWindow);
     }
     else
     {
         return(DesignDocumentState.InactivePredictionWindow);
     }
 }
Example #7
0
        protected override async Task OnStateChangedAsync(SensingAgentState previousState, SensingAgentState currentState, CancellationToken cancellationToken)
        {
            await base.OnStateChangedAsync(previousState, currentState, cancellationToken);

            List <ProtocolSetting> newSettings = new List <ProtocolSetting>();

            // first gather up settings to apply as a result of exiting the previous state

            if (previousState == SensingAgentState.ActiveObservation)
            {
                newSettings.AddRange(EndActiveObservationSettings);
            }

            // next gather up settings to apply as a result of entering the current state

            if (currentState == SensingAgentState.ActiveObservation)
            {
                newSettings.AddRange(BeginActiveObservationSettings);
            }
            else if (currentState == SensingAgentState.OpportunisticControl || currentState == SensingAgentState.ActiveControl)
            {
                // hang on to the begin-control statement. we need ensure that the
                // same statement used to begin control is also used to end it.
                _ongoingControlStatement = _statementToBeginControl;

                // reset the begin-control statement. we won't set it again until
                // control has ended and we've reset the ongoing control statement.
                _statementToBeginControl = null;

                // add the begin-control settings
                newSettings.AddRange(_ongoingControlStatement.BeginControlSettings);

                // update state description to include the ongoing-control statement
                StateDescription += ":  " + _ongoingControlStatement.Id;
            }
            else if (currentState == SensingAgentState.EndingControl)
            {
                newSettings.AddRange(_ongoingControlStatement.EndControlSettings);
                _ongoingControlStatement = null;
            }

            if (newSettings.Count > 0)
            {
                SensusServiceHelper.Logger.Log("Applying " + newSettings.Count + " protocol setting(s) for transition from " + previousState + " to " + currentState + ".", LoggingLevel.Normal, GetType());
                await(Protocol as Protocol).ApplySettingsAsync(newSettings, cancellationToken);
            }
        }
Example #8
0
        protected virtual Task OnStateChangedAsync(SensingAgentState previousState, SensingAgentState currentState, CancellationToken cancellationToken)
        {
            StateDescription = previousState + " --> " + currentState;

            return(Task.CompletedTask);
        }
Example #9
0
        /// <summary>
        /// The state machine for all <see cref="SensingAgent"/> classes.
        /// </summary>
        /// <returns><c>true</c>, if the <see cref="SensingAgent"/> transitioned into the new state, <c>false</c> otherwise. If the
        /// new state equals the current state, then <c>false</c> will be returned indicating no state change.</returns>
        /// <param name="newState">New state.</param>
        /// <param name="writeSensingAgentStateDatum">Whether to write a <see cref="ISensingAgentStateDatum"/> to the local data store
        /// to record the transition, if made.</param>
        /// <param name="cancellationToken">Cancellation token.</param>
        private async Task <bool> TransitionToNewStateAsync(SensingAgentState newState, bool writeSensingAgentStateDatum, CancellationToken cancellationToken)
        {
            bool stateChanged = false;
            SensingAgentState?previousState = null;

            lock (_stateLocker)
            {
                if (!_stateIsTransitioning && newState != State)
                {
                    bool transitionPermitted = false;

                    // the state machine...
                    if (State == SensingAgentState.Idle)
                    {
                        transitionPermitted = newState == SensingAgentState.OpportunisticObservation ||
                                              newState == SensingAgentState.ActiveObservation;
                    }
                    else if (State == SensingAgentState.OpportunisticObservation)
                    {
                        transitionPermitted = newState == SensingAgentState.Idle ||
                                              newState == SensingAgentState.OpportunisticControl;
                    }
                    else if (State == SensingAgentState.OpportunisticControl)
                    {
                        transitionPermitted = newState == SensingAgentState.EndingControl;
                    }
                    else if (State == SensingAgentState.ActiveObservation)
                    {
                        transitionPermitted = newState == SensingAgentState.Idle ||
                                              newState == SensingAgentState.ActiveControl;
                    }
                    else if (State == SensingAgentState.ActiveControl)
                    {
                        transitionPermitted = newState == SensingAgentState.EndingControl;
                    }
                    else if (State == SensingAgentState.EndingControl)
                    {
                        transitionPermitted = newState == SensingAgentState.Idle;
                    }

                    if (transitionPermitted)
                    {
                        previousState         = State;
                        State                 = newState;
                        stateChanged          = true;
                        _stateIsTransitioning = true;
                    }
                }
            }

            if (stateChanged)
            {
                // notify the concrete class. catch exceptions as we don't know who is implementing this method.
                try
                {
                    await OnStateChangedAsync(previousState.Value, State, cancellationToken);

                    if (writeSensingAgentStateDatum)
                    {
                        // record the state change within the protocol's local data store. this needs to come after the
                        // call to the concrete class implementation of OnStateChangedAsync, as the state description might
                        // be updated in that call, and we'd like to use the new description here.
                        Protocol.WriteSensingAgentStateDatum(previousState.Value, State, StateDescription, cancellationToken);
                    }
                }
                catch (Exception ex)
                {
                    SensusServiceHelper.Logger.Log("Exception while notifying concrete class of change from state " + previousState.Value + " to state " + State + ":  " + ex.Message, LoggingLevel.Normal, GetType());
                    throw ex;
                }
                finally
                {
                    _stateIsTransitioning = false;

                    FireStateChangedEvent();
                }
            }

            return(stateChanged);
        }