Quantcast
Jump to content

Workout, a Tizen Sample App for Monitoring Health Sensors


Recommended Posts

Group%203528.png

The Workout app was created to show how to implement a fully working application that supports running on wearable devices with Tizen.

Workout is written in C# and uses the Xamarin.Forms and Tizen.CircularUI frameworks.

W-4.0-circle-x86-preview-2020-09-04-1513
Text
W-4.0-circle-x86-preview-2020-09-03-1342
Workout

Overview

This version of the application allows you to measure the following parameters while running:

  • Running time
  • Distance traveled
  • Heart rate
  • Pace
  • Present effort

In the summary of the training, the application also shows the most common range of effort.

Read more

In a series of blogs publishing this week, we will describe and show how key functionalities of the application are implemented, such as:

  • Distance traveled
  • Heart rate (intensity)
  • Workout summary

A detailed tutorial describing the application can be found on TizenSchool.org

W-4.0-circle-x86-preview-2020-09-03-1343
Distance
W-4.0-circle-x86-preview-2020-09-03-1338
Intensity

You can download and test the app from the link below:
https://github.com/Samsung/Tizen-CSharp-Samples/tree/master/Wearable/Workout

In the next release of the application, it will collect workout data and give an insight into the history. It will also allow you to edit user profile settings such as age or the distance measurement unit.

If you have an idea for functionality or have any comments about the application, let us know!

View the full blog at its source

Link to post
Share on other sites


Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Similar Topics

    • By STF News
      This is the final blog in a series to introduce the sample application Workout, a Tizen example for monitoring health sensors on a wearable device.
      The first blog, Workout -- A Tizen Sample App for Monitoring Health Sensors, presented the basic features of the application. The second blog, Adding Distance Traveled to the Tizen Workout Sample App, described how distance traveled is calculated. The third blog, Adding Heart Rate Summary to the Tizen Workout App, demonstrated how heart rate data is gathered.
      This blog describes how the application uses the Tizen.Wearable.CircularUI extension of the Xamarin.Forms framework. This extension provides a set of components customized for the wearable profile that makes development easier and efficient. It provides, among others, a CircleListView component, which is used on the summary view of the application. The list contains elements that differ from each other in terms of appearance. Apart from the different contents of the text, they allow you to:
      Use different icon images Set different positions of text elements on selected elements Use converters for selected list items Display the action button on selected elements of the list
      Time
      Distance
      Pace
      Intensity ItemSource
      The information about how the individual elements of the list should look like is provided by ItemSource, which is represented by the list of elements of the DetailsItemData class.
      Views/Workout/DetailsPageView.xaml
      <cui:CircleListView.ItemsSource> <x:Array Type="{x:Type models:DetailsItemData}"> <models:DetailsItemData Name="time" Value="{Binding ElapsedTime}" Icon="images/details_time_icon.png"> <models:DetailsItemData.ValueBounds> <Rectangle X=".5" Y="193" Width="-1" Height="-1" /> </models:DetailsItemData.ValueBounds> <models:DetailsItemData.NameBounds> <Rectangle X=".5" Y="245" Width="-1" Height="-1" /> </models:DetailsItemData.NameBounds> </models:DetailsItemData> <models:DetailsItemData Name="distance" Value="{Binding Distance}" Icon="images/details_distance_icon.png"> <models:DetailsItemData.ValueBounds> <Rectangle X=".5" Y="193" Width="-1" Height="-1" /> </models:DetailsItemData.ValueBounds> <models:DetailsItemData.NameBounds> <Rectangle X=".5" Y="245" Width="-1" Height="-1" /> </models:DetailsItemData.NameBounds> </models:DetailsItemData> <models:DetailsItemData Name="average pace" Value="{Binding AveragePace}" Icon="images/details_average_pace_icon.png"> <models:DetailsItemData.ValueBounds> <Rectangle X=".5" Y="193" Width="-1" Height="-1" /> </models:DetailsItemData.ValueBounds> <models:DetailsItemData.NameBounds> <Rectangle X=".5" Y="245" Width="-1" Height="-1" /> </models:DetailsItemData.NameBounds> </models:DetailsItemData> <models:DetailsItemData Name="intensity" Value="{Binding Intensity, Converter={StaticResource BpmRangeValueConverter}}" Icon="images/details_intensity_icon.png" IsActionButtonVisible="True"> <models:DetailsItemData.ValueBounds> <Rectangle X=".5" Y="172" Width="-1" Height="-1" /> </models:DetailsItemData.ValueBounds> <models:DetailsItemData.NameBounds> <Rectangle X=".5" Y="224" Width="-1" Height="-1" /> </models:DetailsItemData.NameBounds> </models:DetailsItemData> </x:Array> </cui:CircleListView.ItemsSource> Models/Workout/DetailsItemData.cs
      using Xamarin.Forms; namespace Workout.Models.Workout { /// <summary> /// Details item data class. /// Used as one element of the details page list. /// </summary> public class DetailsItemData : BindableObject { #region properties public static readonly BindableProperty ValueProperty = BindableProperty.Create("Value", typeof(string), typeof(DetailsItemData), default(string)); /// <summary> /// Workout detail name. /// </summary> public string Name { get; set; } /// <summary> /// Workout detail value. /// </summary> public string Value { get => (string)GetValue(ValueProperty); set => SetValue(ValueProperty, value); } /// <summary> /// Workout detail icon. /// </summary> public string Icon { get; set; } /// <summary> /// Item layout value bounds. /// </summary> public Rectangle ValueBounds { get; set; } /// <summary> /// Item layout name bounds. /// </summary> public Rectangle NameBounds { get; set; } /// <summary> /// Workout detail action button visibility flag. /// </summary> public bool IsActionButtonVisible { get; set; } #endregion } } ItemTemplate
      The values provided by ItemSource are used in ItemTemplate.
      Views/Workout/DetailsPageView.xaml
      <cui:CircleListView.ItemTemplate> <DataTemplate> <ViewCell> <AbsoluteLayout HeightRequest="360" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand"> <Image AbsoluteLayout.LayoutFlags="XProportional" AbsoluteLayout.LayoutBounds=".5, 74, AutoSize, AutoSize"> <Image.Source> <FileImageSource File="{Binding Icon}" /> </Image.Source> </Image> <Label Text="{Binding Value}" FontSize="{StaticResource FontSizeM}" TextColor="#FFF" AbsoluteLayout.LayoutFlags="XProportional" AbsoluteLayout.LayoutBounds="{Binding ValueBounds}"> </Label> <Label Text="{Binding Name}" FontSize="{StaticResource FontSizeXXS}" FontAttributes="Bold" TextColor="#AAFFCC" AbsoluteLayout.LayoutFlags="XProportional" AbsoluteLayout.LayoutBounds="{Binding NameBounds}"> </Label> <Button AbsoluteLayout.LayoutFlags="All" AbsoluteLayout.LayoutBounds="0, 1, 1, .25" Text="OK" TextColor="#1B1B7D" BackgroundColor="#AAFFCC" Command="{Binding BindingContext.FinishCommand, Source={x:Reference listView}}" IsVisible="{Binding IsActionButtonVisible}" tizen:VisualElement.Style="bottom" /> </AbsoluteLayout> </ViewCell> </DataTemplate> </cui:CircleListView.ItemTemplate> The values modify the content in each ViewCell element accordingly, so that:
      The Name and Value properties set the values of the Text property of the selected Label elements The NameBounds and ValueBounds properties set the LayoutBounds property of absolutely positioned Label elements The Icon property sets the Source property of the Image elements responsible for displaying the item icon The IsActionButtonVisible property sets the IsVisible property of Button elements, making them visible when the given value is True Read More
      To learn more about the implementation of CircleListView in the Workout application, please see this tutorial.
      Thank you for reading the tutorials about the Workout app. For more information about this app and developing for the Tizen platform, please visit developer.tizen.org.
      View the full blog at its source
    • By STF News
      This is the third blog in a series to introduce the sample application Workout, a Tizen example for monitoring health sensors on a wearable device.
      The first blog, Workout -- A Tizen Sample App for Monitoring Health Sensors, presented the basic features of the application. The second blog, Adding Distance Traveled to the Tizen Workout Sample App, described how distance traveled is calculated.
      In this blog, I will demonstrate another key feature of the app, Heart Rate Measurement (HRM), which shows the most recent heart rate intensity.

      Implementation
      To start collecting data from the HRM sensor, first start Tizen.Sensor.HeartRateMonitor from TizenFX API.
      HeartRateMonitorService.cs
      public void Init() { try { _hrm = new HRM { Interval = 1000, PausePolicy = SensorPausePolicy.None }; _hrm.DataUpdated += OnDataUpdated; } catch (Exception) { NotSupported?.Invoke(this, EventArgs.Empty); } } Initiating HRM in this way invokes DataUpdated every one second and the sensor is not stopped even when the application is sent to the background. The data from the event is handled by the OnDataUpdated handler, which invokes the event with the single bpm value.
      This event is listened to by the OnServiceDataUpdated handler in the HeartRateMonitorModel, where all information related to heart rate is calculated:
      HeartRateMonitorModel.cs
      private void OnServiceDataUpdated(object sender, int bpm) { double normalizedBpm = Math.Clamp((bpm - _minBpm) / (double)(_maxBpm - _minBpm), 0, 1); int bpmRange = bpm < _minBpm ? 0 : Math.Min((int)((normalizedBpm * (_bpmRanges - 1)) + 1), _bpmRanges - 1); if (!_isMeasurementPaused) { _bpmRangeOccurrences[bpmRange]++; } Updated?.Invoke(this, new HeartRateMonitorUpdatedEventArgs(new HeartRateMonitorData { Bpm = bpm, BpmRange = bpmRange, BpmRangeOccurrences = _bpmRangeOccurrences, NormalizedBpm = normalizedBpm })); } However, let's start with the values that are used in the above method:
      _maxBpm - this value is calculated during the class instantiation according to the formula: 220 - user age
      _minBpm - this is half the value of _maxBpm
      _minBpm and _maxBpm is used to calculate normalizedBpm, a value ranging from 0 to 1.
      Next, the bpmRange to which the current HRM service value belongs is calculated: For bpm below _minBpm, bpmRange is set to 0. For bpm greater than or equal to _minBpm, bpmRange is set to either (_normalizedBpm * (_bpmRanges -1) + 1) or (_bpmRanges - 1), whichever value is smaller.
      This calculated pulse interval is used as a position in an array, whose value is increased by 1. To obtain the most common pulse interval, find the index with the highest value associated with it.
      DetailsPageViewModel.cs
      Intensity = Array.LastIndexOf(bpmRangeOccurrences, bpmRangeOccurrences.Max()).ToString(); To display the range indication, Intensity is delivered to XAML and converted into text using a converter.
      DetailsPageView.xaml.cs
      <models:DetailsItemData Name="intensity" Value="{Binding Intensity, Converter={StaticResource BpmRangeValueConverter}}" Icon="images/details_intensity_icon.png" IsActionButtonVisible="True"> Read more
      To learn more about the implementation of the HRM sensor and the use of the data in the Workout app, see this tutorial
      In the final blog of this series, you'll learn how CircleListView is used in the app.
      View the full blog at its source
    • By STF News
      This is the second blog in a series to introduce the sample application Workout, a Tizen example for monitoring health sensors on a wearable device.
      The previous blog, Workout -- A Tizen Sample App for Monitoring Health Sensors, introduced the sample application, Workout, for runners who own a wearable device. In this blog, I will describe how one of the key features, traveled distance, is calculated.

      Implementation
      To calculate the traveled distance, the application uses the LocationService class providing location-related GPS data. This service uses the Tizen.Location API to initialize the GPS receiver:
      Services/LocationService.cs
      /// <summary> /// Initializes LocationService class instance. /// </summary> private LocationService() { _locator = new Locator(LocationType.Hybrid) { Interval = _gpsCallbackInterval }; AttachEvents(); } The API is also used to set the change handlers:
      Services/LocationService.cs
      /// <summary> /// Sets service listeners. /// </summary> private void AttachEvents() { _locator.ServiceStateChanged += (sender, args) => ServiceStateChanged?.Invoke(this, args.ServiceState); _locator.LocationChanged += (sender, args) => LocationChanged?.Invoke(this, args.Location); _locator.SettingChanged += (sender, args) => SettingChanged?.Invoke(this, args.IsEnabled); } Every time the location changes, the LocationChanged event is invoked with the new location.
      This event has an attached listener in LocationModel which receives the new location object. The new location is used to calculate the distance to the previous location and stored in a _locationData object:
      Models/LocationModel.cs
      _locationData.Distance += location.GetDistanceTo(_lastLocation) / SettingsService.Instance.Distance.UnitToKmRatio; The new location data is passed to MainModel, where all workout data are gathered and processed before being sent to viewModels.
      The entire flow of location data and other workout data is described in detail at tizenschool.org
      In the next blog in this series, I will discuss how data is gathered from the heart rate monitor.
      View the full blog at its source
×
×
  • Create New...