/// <summary> /// Called when activity changes /// </summary> /// <param name="sender">Sender object</param> /// <param name="args">Event arguments</param> public async void activityMonitor_ReadingChanged(IActivityMonitor sender, ActivityMonitorReading args) { await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => { this.ActivityEnum = args.Mode; }); }
/// <summary> /// Called when activity changes. /// </summary> /// <param name="sender">Sender object</param> /// <param name="args">Event arguments</param> private async void activityMonitor_ReadingChanged(IActivityMonitor sender, ActivityMonitorReading args) { if (ReadingChanged != null) { await Task.Run(() => { ReadingChanged(this, args.Mode); }); } }
/// <summary> /// Initializes activity monitor /// </summary> public async Task Initialize() { if (ActivityMonitorProperty == null) { if (await MapPage._instanceMap.CallSensorcoreApiAsync(async() => { ActivityMonitorProperty = await ActivityMonitor.GetDefaultAsync(); })) { Debug.WriteLine("ActivityMonitorSimulator initialized."); } if (ActivityMonitorProperty != null) { // Set activity observer ActivityMonitorProperty.ReadingChanged += activityMonitor_ReadingChanged; ActivityMonitorProperty.Enabled = true; // read current activity ActivityMonitorReading reading = null; if (await MapPage._instanceMap.CallSensorcoreApiAsync(async() => { reading = await ActivityMonitorProperty.GetCurrentReadingAsync(); })) { if (reading != null) { this.ActivityEnum = reading.Mode; } } } else { // nothing to do if we cannot use the API // in a real app do make an effort to make the user experience better return; } // Must call DeactivateAsync() when the application goes to background Window.Current.VisibilityChanged += async(sender, args) => { if (_activityMonitor != null) { await MapPage._instanceMap.CallSensorcoreApiAsync(async() => { if (!args.Visible) { await _activityMonitor.DeactivateAsync(); } else { await _activityMonitor.ActivateAsync(); } }); } }; } }
public static TimeSpan GetTimeSinceLastWalk(IEnumerable <ActivityMonitorReading> history, TimeSpan minimumMoveTime) { var prevTimestamp = new DateTimeOffset(); var lastMovedAt = new DateTimeOffset(); ActivityMonitorReading currentActivity = null; var historyList = history.ToList(); if (historyList.Count == 0) { return(TimeSpan.Zero); } foreach (var reading in historyList) { //The first value is actually the previous activity outside the time range if (prevTimestamp == new DateTimeOffset()) { prevTimestamp = reading.Timestamp; continue; } if ((reading.Mode == Activity.Moving || reading.Mode == Activity.Walking || reading.Mode == Activity.Running) && reading.Timestamp - prevTimestamp > minimumMoveTime) { lastMovedAt = reading.Timestamp; } prevTimestamp = reading.Timestamp; currentActivity = reading; } if (currentActivity != null && (currentActivity.Mode != Activity.Stationary)) { //the phone is sitting somewhere, or the person is currently moving return(TimeSpan.Zero); } return(DateTimeOffset.Now - lastMovedAt); }
/// <summary> /// Called when activity changes /// </summary> /// <param name="sender">Sender object</param> /// <param name="args">Event arguments</param> private async void activityMonitor_ReadingChanged( IActivityMonitor sender, ActivityMonitorReading args ) { await this.Dispatcher.RunAsync( CoreDispatcherPriority.Normal, () => { ActivityData.Instance().CurrentActivity = args.Mode; } ); }
/// <summary> /// Updates visualization /// </summary> private async Task UpdateScreenAsync() { // clear visual ActivityPanel.Children.Clear(); TimePanel.Children.Clear(); //update labels ZoomLabel.Text = "" + ZOOM_LEVELS[_currentZoomLevel] + " pixel(s)/minute"; DateLabel.Text = _iCurrentDate.ToString("dd/MM/yyyy", CultureInfo.InvariantCulture); //update date selected DateTime endDate = _iCurrentDate.AddDays(1); if (_iCurrentDate.Date == DateTime.Now.Date) { endDate = DateTime.Now; } // Add time labels and steps(walking+running) count for each hour for (int i = 0; i < 24; i++) { Grid timeBlock = new Grid(); StepCount stepCount = null; // getting steps count try { DateTime fromDate = _iCurrentDate + TimeSpan.FromHours(i); TimeSpan queryLength = TimeSpan.FromHours(1); if ((fromDate + queryLength) > endDate) { queryLength = endDate - fromDate; } stepCount = await _stepCounter.GetStepCountForRangeAsync(fromDate, queryLength); } catch (Exception) { } //updating steps count for each hour in visualizer TextBlock label = new TextBlock(); label.Height = ZOOM_LEVELS[_currentZoomLevel] * 60.0 * BASE_DRAW_SCALE; label.FontSize = 14.0; if (stepCount != null) { label.Text = String.Format( "{0:00}:00\n{1}/{2}", i, stepCount.WalkingStepCount, stepCount.RunningStepCount ); } else { label.Text = String.Format("{0:00}:00", i); } label.VerticalAlignment = Windows.UI.Xaml.VerticalAlignment.Top; timeBlock.Children.Add(label); //creating time(hour) intervel blocks Rectangle divider = new Rectangle(); divider.Width = 200.0; divider.Height = 0.5; divider.Fill = new SolidColorBrush(Colors.Gray); divider.VerticalAlignment = Windows.UI.Xaml.VerticalAlignment.Top; timeBlock.Children.Add(divider); TimePanel.Children.Add(timeBlock); } // Add activities for each hour in a day IList <ActivityMonitorReading> activities = null; if (await CallSenseApiAsync(async() => { activities = await _activityMonitor.GetActivityHistoryAsync(_iCurrentDate, endDate - _iCurrentDate); })) { if (activities.Count >= 2) { ActivityMonitorReading previousReading = activities[0]; // if first activity started few minutes after the day started then Add filler if needed if (previousReading.Timestamp > _iCurrentDate) { AppendActivityBarBlock(Colors.Transparent, previousReading.Timestamp - _iCurrentDate); } // Add activities for (int i = 1; i < activities.Count; i++) { ActivityMonitorReading reading = activities[i]; TimeSpan activityLength = reading.Timestamp - previousReading.Timestamp; // if first activity started before the day started then cut off any excess if (previousReading.Timestamp < _iCurrentDate) { activityLength -= (_iCurrentDate - previousReading.Timestamp); } AppendActivityBarBlock(ACTIVITY_COLORS[previousReading.Mode], activityLength); previousReading = reading; } // Show also current activity AppendActivityBarBlock(ACTIVITY_COLORS[previousReading.Mode], endDate - previousReading.Timestamp); } // Scroll to present/current time ActivityScroller.UpdateLayout(); double scrollTo = (ZOOM_LEVELS[_currentZoomLevel] * (endDate - _iCurrentDate).TotalMinutes * BASE_DRAW_SCALE) - 400.0; if (scrollTo < 0.0) { scrollTo = 0.0; } ActivityScroller.ChangeView(null, scrollTo, null); } else { MessageDialog dlg = new MessageDialog("Failed to fetch activities"); await dlg.ShowAsync(); } }
/// <summary> /// Populate the list of activities and durations to display in the UI /// </summary> private void QuantifyData() { if (_listData != null) { _listData.Clear(); } _listData = new List <MyQuantifiedData>(); if (!Windows.ApplicationModel.DesignMode.DesignModeEnabled) { List <string> _activitiesList = new List <string>(Enum.GetNames(typeof(Activity))); Dictionary <Activity, int> indexer = new Dictionary <Activity, int>(); TimeSpan[] _durations = new TimeSpan[_activitiesList.Count]; Activity[] values = (Activity[])Enum.GetValues(typeof(Activity)); for (int i = 0; i < values.Length; i++) { indexer.Add(values[i], i); } // there could be days with no data (e.g. of phone was turned off if (_historyData.Count > 0) { // first entry may be from previous time window, is there any data from current time window? bool hasDataInTimeWindow = false; // insert new fist entry, representing the last activity of the previous time window // this helps capture that activity's duration but only from the start of current time window ActivityMonitorReading first = _historyData[0]; if (first.Timestamp <= DateTime.Now.Date.AddDays(_timeWindowIndex)) { // create new "first" entry, with the same mode but timestamp set as 0:00h in current time window _historyData.Insert(1, new ActivityMonitorReading(first.Mode, DateTime.Now.Date.AddDays(_timeWindowIndex))); // remove previous entry _historyData.RemoveAt(0); hasDataInTimeWindow = _historyData.Count > 1; } else { // the first entry belongs to the current time window // there is no known activity before it hasDataInTimeWindow = true; } // if at least one activity is recorded in this time window if (hasDataInTimeWindow) { // insert a last activity, marking the begining of the next time window // this helps capturing the correct duration of the last activity stated in this time window ActivityMonitorReading last = _historyData.Last(); if (last.Timestamp < DateTime.Now.Date.AddDays(_timeWindowIndex + 1)) { // is this today's time window if (_timeWindowIndex == 0) { // last activity duration measured until this instant time _historyData.Add(new ActivityMonitorReading(last.Mode, DateTime.Now)); } else { // last activity measured until the begining of the next time index _historyData.Add(new ActivityMonitorReading(last.Mode, DateTime.Now.Date.AddDays(_timeWindowIndex + 1))); } } // calculate duration for each current activity by subtracting its timestamp from that of the next one for (int i = 0; i < _historyData.Count - 1; i++) { ActivityMonitorReading current = _historyData[i]; ActivityMonitorReading next = _historyData[i + 1]; _durations[indexer[current.Mode]] += next.Timestamp - current.Timestamp; } } } // populate the list to be displayed in the UI for (int i = 0; i < _activitiesList.Count; i++) { _listData.Add(new MyQuantifiedData(_activitiesList[i], _durations[i])); } } NotifyPropertyChanged("ListData"); }
/// <summary> /// Update Summary. /// </summary> /// <returns>Asynchronous task/returns> /// <param name="DayOffset">Day Offset</param> public async Task UpdateSummaryAsync(uint DayOffset) { // Read current activity ActivityMonitorReading reading = null; await CallSensorCoreApiAsync(async() => { reading = await _activityMonitor.GetCurrentReadingAsync(); }); if (reading != null) { ActivityData <Lumia.Sense.Activity> .Instance().CurrentActivity = reading.Mode; } // Fetch activity history for the day DateTime startDate = DateTime.Today.Subtract(TimeSpan.FromDays(DayOffset)); DateTime endDate = startDate + TimeSpan.FromDays(1); IList <ActivityMonitorReading> history = null; await CallSensorCoreApiAsync(async() => { history = await _activityMonitor.GetActivityHistoryAsync(startDate, TimeSpan.FromDays(1)); }); // Create a dictionary to store data Dictionary <Activity, TimeSpan> activitySummary = new Dictionary <Activity, TimeSpan>(); // Initialize timespan for all entries var activityTypes = Enum.GetValues(typeof(Activity)); foreach (var type in activityTypes) { activitySummary[(Activity)type] = TimeSpan.Zero; } // Update the timespan for all activities in the dictionary if (history.Count > 0) { Activity currentActivity = history[0].Mode; DateTime currentDate = history[0].Timestamp.DateTime; foreach (var item in history) { if (item.Timestamp >= startDate) { TimeSpan duration = TimeSpan.Zero; if (currentDate < startDate) { // If first activity of the day started already yesterday, set start time to midnight. currentDate = startDate; } if (item.Timestamp > endDate) { // If last activity extends over to next day, set end time to midnight. duration = endDate - currentDate; break; } else { duration = item.Timestamp - currentDate; } activitySummary[currentActivity] += duration; } currentActivity = item.Mode; currentDate = item.Timestamp.DateTime; } } // Prepare the summary to add it to data source List <ActivityDuration <Lumia.Sense.Activity> > historyList = new List <ActivityDuration <Lumia.Sense.Activity> >(); foreach (var activityType in activityTypes) { // For each entry in the summary add the type and duration to data source historyList.Add(new ActivityDuration <Lumia.Sense.Activity>((Activity)activityType, activitySummary[(Activity)activityType])); } // Update the singleton instance of the data source ActivityData <Lumia.Sense.Activity> .Instance().History = historyList; ActivityData <Lumia.Sense.Activity> .Instance().Date = startDate; }