Skip to content

Commit

Permalink
feat: Implemented Pedometer on iOS
Browse files Browse the repository at this point in the history
  • Loading branch information
MartinZikmund committed Apr 2, 2020
1 parent f78a38c commit 617dd49
Show file tree
Hide file tree
Showing 6 changed files with 228 additions and 0 deletions.
37 changes: 37 additions & 0 deletions src/Uno.UWP/Devices/Sensors/Helpers/SensorHelpers.iOS.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,49 @@ namespace Uno.Devices.Sensors.Helpers
{
internal static class SensorHelpers
{
private static readonly DateTimeOffset NSDateConversionStart =
new DateTimeOffset(2001, 1, 1, 0, 0, 0, TimeSpan.Zero);

public static DateTimeOffset TimestampToDateTimeOffset(double timestamp)
{
var bootTime = NSDate.FromTimeIntervalSinceNow(-NSProcessInfo.ProcessInfo.SystemUptime);
var date = (DateTime)bootTime.AddSeconds(timestamp);
return new DateTimeOffset(date);
}

public static DateTimeOffset NSDateToDateTimeOffset(NSDate nsDate)
{
if (nsDate == NSDate.DistantPast)
{
return DateTimeOffset.MinValue;
}
else if (nsDate == NSDate.DistantFuture)
{
return DateTimeOffset.MaxValue;
}

return NSDateConversionStart.AddSeconds(
nsDate.SecondsSinceReferenceDate);
}

public static NSDate DateTimeOffsetToNSDate(DateTimeOffset dateTimeOffset)
{
if (dateTimeOffset == DateTime.MinValue)
{
return NSDate.DistantPast;
}
else if (dateTimeOffset == DateTime.MaxValue)
{
return NSDate.DistantFuture;
}

var dateInSecondsFromStart = dateTimeOffset
.ToUniversalTime()
.Subtract(NSDateConversionStart.UtcDateTime);

return NSDate.FromTimeIntervalSinceReferenceDate(
dateInSecondsFromStart.TotalSeconds);
}
}
}
#endif
65 changes: 65 additions & 0 deletions src/Uno.UWP/Devices/Sensors/Pedometer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
using System;
using System.Threading.Tasks;
using Windows.Foundation;

namespace Windows.Devices.Sensors
{
public partial class Pedometer
{
private readonly static object _syncLock = new object();

private static Pedometer _instance;
private static bool _initializationAttempted;

private TypedEventHandler<Pedometer, PedometerReadingChangedEventArgs> _readingChanged;

public static IAsyncOperation<Pedometer> GetDefaultAsync()
{
if (_initializationAttempted)
{
return Task.FromResult(_instance).AsAsyncOperation();
}
lock (_syncLock)
{
if (!_initializationAttempted)
{
_instance = TryCreateInstance();
_initializationAttempted = true;
}
return Task.FromResult(_instance).AsAsyncOperation();
}
}

public event TypedEventHandler<Pedometer, PedometerReadingChangedEventArgs> ReadingChanged
{
add
{
lock (_syncLock)
{
var isFirstSubscriber = _readingChanged == null;
_readingChanged += value;
if (isFirstSubscriber)
{
StartReading();
}
}
}
remove
{
lock (_syncLock)
{
_readingChanged -= value;
if (_readingChanged == null)
{
StopReading();
}
}
}
}

private void OnReadingChanged(PedometerReading reading)
{
_readingChanged?.Invoke(this, new PedometerReadingChangedEventArgs(reading));
}
}
}
77 changes: 77 additions & 0 deletions src/Uno.UWP/Devices/Sensors/Pedometer.iOS.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
#if __IOS__
using System;
using System.Collections.Generic;
using System.Threading;
using CoreMotion;
using Foundation;
using Uno.Devices.Sensors.Helpers;

namespace Windows.Devices.Sensors
{
public partial class Pedometer
{
private readonly CMPedometer _pedometer;
private readonly EventWaitHandle _currentReadingWaiter =
new EventWaitHandle(false, EventResetMode.AutoReset);

private CMPedometerData _currentData = null;

private Pedometer(CMPedometer pedometer)
{
_pedometer = pedometer;
}

public static Pedometer TryCreateInstance()
{
if (CMPedometer.IsStepCountingAvailable)
{
return new Pedometer(new CMPedometer());
}
return null;
}

public IReadOnlyDictionary<PedometerStepKind, PedometerReading> GetCurrentReadings()
{
var readings = new Dictionary<PedometerStepKind, PedometerReading>();
_currentData = null;
_pedometer.QueryPedometerData(
NSDate.FromTimeIntervalSince1970(DateTimeOffset.Now.Subtract(DateTimeOffset.Now.TimeOfDay).ToUnixTimeSeconds()),
NSDate.FromTimeIntervalSince1970(DateTimeOffset.Now.ToUnixTimeSeconds()), HandlePedometerData);
_currentReadingWaiter.WaitOne();
var timeDifferenceInSeconds = TimeSpan.FromSeconds(
_currentData.EndDate.SecondsSinceReferenceDate -
_currentData.StartDate.SecondsSinceReferenceDate);
if (_currentData != null)
{
readings.Add(
PedometerStepKind.Unknown,
new PedometerReading(
_currentData.NumberOfSteps.Int32Value,
timeDifferenceInSeconds,
PedometerStepKind.Unknown,
SensorHelpers.NSDateToDateTimeOffset(_currentData.EndDate)));
}

return readings;
}

private void StartReading()
{
_pedometer.StartPedometerUpdates(
SensorHelpers.DateTimeOffsetToNSDate(DateTimeOffset.Now),
HandlePedometerData);
}

private void StopReading()
{
_pedometer.StopPedometerUpdates();
}

private void HandlePedometerData(CMPedometerData data, NSError err)
{
_currentData = data;
_currentReadingWaiter.Set();
}
}
}
#endif
27 changes: 27 additions & 0 deletions src/Uno.UWP/Devices/Sensors/PedometerReading.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
using System;

namespace Windows.Devices.Sensors
{
public partial class PedometerReading
{
internal PedometerReading(
int cumulativeSteps,
TimeSpan cumulativeStepsDuration,
PedometerStepKind stepKind,
DateTimeOffset timestamp)
{
CumulativeSteps = cumulativeSteps;
CumulativeStepsDuration = cumulativeStepsDuration;
StepKind = stepKind;
Timestamp = timestamp;
}

public int CumulativeSteps { get; }

public TimeSpan CumulativeStepsDuration { get; }

public PedometerStepKind StepKind { get; }

public DateTimeOffset Timestamp { get; }
}
}
13 changes: 13 additions & 0 deletions src/Uno.UWP/Devices/Sensors/PedometerReadingChangedEventArgs.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
namespace Windows.Devices.Sensors
{
public partial class PedometerReadingChangedEventArgs
{
internal PedometerReadingChangedEventArgs(
PedometerReading reading)
{
Reading = reading;
}

public PedometerReading Reading { get; }
}
}
9 changes: 9 additions & 0 deletions src/Uno.UWP/Devices/Sensors/PedometerStepKind.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace Windows.Devices.Sensors
{
public enum PedometerStepKind
{
Unknown,
Walking,
Running,
}
}

0 comments on commit 617dd49

Please sign in to comment.