diff --git a/Sensus.Android/Probes/Movement/AndroidLocationFenceProbe.cs b/Sensus.Android/Probes/Movement/AndroidLocationFenceProbe.cs index 4d233dc33..b6108cdc5 100644 --- a/Sensus.Android/Probes/Movement/AndroidLocationFenceProbe.cs +++ b/Sensus.Android/Probes/Movement/AndroidLocationFenceProbe.cs @@ -22,6 +22,7 @@ using Android.Gms.Awareness.Snapshot; using Android.Gms.Awareness; using Android.Gms.Awareness.Fence; +using Plugin.Geolocator.Abstractions; namespace Sensus.Android.Probes.Movement { @@ -110,7 +111,7 @@ protected override void StartListening() // request a location to start location fencing RequestLocationSnapshotAsync(); } - + private global::Android.Locations.Location _lastPosition; private void RequestLocationSnapshotAsync() { Task.Run(async () => @@ -121,8 +122,10 @@ private void RequestLocationSnapshotAsync() ILocationResult locationResult = await Awareness.SnapshotApi.GetLocationAsync(AwarenessApiClient); global::Android.Locations.Location location = locationResult.Location; DateTimeOffset timestamp = new DateTimeOffset(1970, 1, 1, 0, 0, 0, new TimeSpan()).AddMilliseconds(location.Time); - StoreDatum(new LocationDatum(timestamp, location.HasAccuracy ? location.Accuracy : -1, location.Latitude, location.Longitude)); - + StoreDatum(new LocationDatum(timestamp, location.HasAccuracy ? location.Accuracy : -1, + new Position(location.Latitude, location.Longitude), + (_lastPosition != null ? new Position(_lastPosition.Latitude, _lastPosition.Longitude) : null))); + _lastPosition = location; // replace the previous location fence with one around the current location. additions and removals are handled // in the order specified below. FenceUpdateRequestBuilder locationFenceRequestBuilder = new FenceUpdateRequestBuilder(); diff --git a/Sensus.Shared.Tests/Sensus.Shared/DataStores/Local/FileLocalDataStoreTests.cs b/Sensus.Shared.Tests/Sensus.Shared/DataStores/Local/FileLocalDataStoreTests.cs index 2de3d28d3..d94e94596 100644 --- a/Sensus.Shared.Tests/Sensus.Shared/DataStores/Local/FileLocalDataStoreTests.cs +++ b/Sensus.Shared.Tests/Sensus.Shared/DataStores/Local/FileLocalDataStoreTests.cs @@ -27,6 +27,7 @@ using Sensus.Tests.Classes; using System.Linq; using ICSharpCode.SharpZipLib.Tar; +using Plugin.Geolocator.Abstractions; namespace Sensus.Tests.DataStores.Local { @@ -298,7 +299,7 @@ private List GenerateData() } else if (type == 1) { - d = new LocationDatum(DateTimeOffset.UtcNow, r.NextDouble(), r.NextDouble(), r.NextDouble()); + d = new LocationDatum(DateTimeOffset.UtcNow, r.NextDouble(), new Position(r.NextDouble(), r.NextDouble()), new Position(r.NextDouble(), r.NextDouble())); } else { diff --git a/Sensus.Shared.Tests/Sensus.Shared/DatumTests.cs b/Sensus.Shared.Tests/Sensus.Shared/DatumTests.cs index b3ddd9686..9a983ab71 100644 --- a/Sensus.Shared.Tests/Sensus.Shared/DatumTests.cs +++ b/Sensus.Shared.Tests/Sensus.Shared/DatumTests.cs @@ -14,6 +14,7 @@ using System; using NUnit.Framework; +using Plugin.Geolocator.Abstractions; using Sensus.Anonymization; using Sensus.Probes.Location; using Sensus.Probes.Movement; @@ -36,7 +37,7 @@ public void SerializeDeserializeTest() TestSensusServiceHelper service1 = new TestSensusServiceHelper(); SensusServiceHelper.Initialize(() => service1); - LocationDatum datum = new LocationDatum(DateTimeOffset.UtcNow, 0.5, 75.5, -35.5); + LocationDatum datum = new LocationDatum(DateTimeOffset.UtcNow, 0.5, new Position(75.5, -35.5), new Position(75.0, -35.0)); Protocol protocol = new Protocol("test"); AnonymizedJsonContractResolver anonymizer = new AnonymizedJsonContractResolver(protocol); @@ -52,6 +53,7 @@ public void SerializeDeserializeTest() Assert.AreEqual(datum.Longitude, deserializedDatum.Longitude); Assert.AreEqual(datum.ProtocolId, deserializedDatum.ProtocolId); Assert.AreEqual(datum.Timestamp, deserializedDatum.Timestamp); + Assert.AreEqual(datum.DistanceTraveled, datum.DistanceTraveled); } [Test] diff --git a/Sensus.Shared/Probes/Location/ListeningLocationProbe.cs b/Sensus.Shared/Probes/Location/ListeningLocationProbe.cs index 843049a07..62ea176a5 100644 --- a/Sensus.Shared/Probes/Location/ListeningLocationProbe.cs +++ b/Sensus.Shared/Probes/Location/ListeningLocationProbe.cs @@ -63,14 +63,17 @@ public sealed override Type DatumType { get { return typeof(LocationDatum); } } - + private Position _lastPosition; public ListeningLocationProbe() { _positionChangedHandler = (o, e) => { SensusServiceHelper.Get().Logger.Log("Received position change notification.", LoggingLevel.Verbose, GetType()); - StoreDatum(new LocationDatum(e.Position.Timestamp, e.Position.Accuracy, e.Position.Latitude, e.Position.Longitude)); + StoreDatum(new LocationDatum(e.Position.Timestamp, e.Position.Accuracy, + e.Position, + _lastPosition)); + _lastPosition = e.Position; }; } diff --git a/Sensus.Shared/Probes/Location/LocationDatum.cs b/Sensus.Shared/Probes/Location/LocationDatum.cs index e008af5c6..cdb763e4e 100644 --- a/Sensus.Shared/Probes/Location/LocationDatum.cs +++ b/Sensus.Shared/Probes/Location/LocationDatum.cs @@ -13,6 +13,7 @@ // limitations under the License. using System; +using Plugin.Geolocator.Abstractions; using Sensus.Anonymization; using Sensus.Anonymization.Anonymizers; using Sensus.Probes.User.Scripts.ProbeTriggerProperties; @@ -31,6 +32,8 @@ public class LocationDatum : ImpreciseDatum { private double _latitude; private double _longitude; + private double? _distanceTraveled; + /// /// Latitude coordinate, measured in decimal degrees north and south of the equator per the WGS 1984 datum. @@ -56,20 +59,33 @@ public double Longitude set { _longitude = value; } } + + /// + /// Distance Traveled in kilometers between the last location reading and this one. + /// + /// Distance traveled between the last location reading and this one in kilometers. + [DoubleProbeTriggerProperty] + [Anonymizable(null, new Type[] { typeof(DoubleRoundingTenthsAnonymizer), typeof(DoubleRoundingHundredthsAnonymizer), typeof(DoubleRoundingThousandthsAnonymizer) }, -1)] + public double? DistanceTraveled + { + get { return _distanceTraveled; } + set { _distanceTraveled = value; } + } + public override string DisplayDetail { - get { return Math.Round(_latitude, 2) + " (lat), " + Math.Round(_longitude, 2) + " (lon)"; } + get { return Math.Round(_latitude, 2) + " (lat), " + Math.Round(_longitude, 2) + " (lon), " + (_distanceTraveled.HasValue ? _distanceTraveled.Value.ToString() : "Not Set")+ " (distance KM)"; } } /// - /// Gets the string placeholder value, which is the [lat,lon] location. + /// Gets the string placeholder value, which is the [lat,lon, distance from last reading in kilometers] location. /// /// The string placeholder value. public override object StringPlaceholderValue { get { - return "[" + Math.Round(_latitude, 2) + "," + Math.Round(_longitude, 2) + "]"; + return "[" + Math.Round(_latitude, 2) + "," + Math.Round(_longitude, 2) + "," + _distanceTraveled.GetValueOrDefault().ToString() + "]"; } } @@ -78,18 +94,25 @@ public override object StringPlaceholderValue /// private LocationDatum() { } - public LocationDatum(DateTimeOffset timestamp, double accuracy, double latitude, double longitude) - : base(timestamp, accuracy) + + public LocationDatum(DateTimeOffset timestamp, double accuracy, Position currentPosition, Position lastPosition = null) + : base(timestamp, accuracy) { - _latitude = latitude; - _longitude = longitude; + _latitude = currentPosition.Latitude; + _longitude = currentPosition.Longitude; + //TODO: We might want to refactor this so it isn't calling the into the speed datum + if (lastPosition != null) + { + _distanceTraveled = Movement.SpeedDatum.CalculateDistanceKM(currentPosition, lastPosition); + } } public override string ToString() { return base.ToString() + Environment.NewLine + "Latitude: " + _latitude + Environment.NewLine + - "Longitude: " + _longitude; + "Longitude: " + _longitude + + "Distance Traveled (KM): " + (_distanceTraveled.HasValue ? _distanceTraveled.Value.ToString() : "Not Set"); } } } diff --git a/Sensus.Shared/Probes/Location/PollingLocationProbe.cs b/Sensus.Shared/Probes/Location/PollingLocationProbe.cs index 71a3a26c5..6a8de9f4b 100644 --- a/Sensus.Shared/Probes/Location/PollingLocationProbe.cs +++ b/Sensus.Shared/Probes/Location/PollingLocationProbe.cs @@ -57,7 +57,7 @@ protected override void Initialize() throw new Exception(error); } } - + private Position _lastPosition = null; protected sealed override IEnumerable Poll(CancellationToken cancellationToken) { Position currentPosition = GpsReceiver.Get().GetReading(cancellationToken, false); @@ -68,7 +68,11 @@ protected sealed override IEnumerable Poll(CancellationToken cancellation } else { - return new Datum[] { new LocationDatum(currentPosition.Timestamp, currentPosition.Accuracy, currentPosition.Latitude, currentPosition.Longitude) }; + var toReturn = new Datum[] { new LocationDatum(currentPosition.Timestamp, currentPosition.Accuracy, + currentPosition, + _lastPosition) }; + _lastPosition = currentPosition; + return toReturn; } }