[TASK] Initial commit with basic product setup
This commit is contained in:
@@ -0,0 +1,114 @@
|
||||
namespace Mapbox.Unity.Location
|
||||
{
|
||||
|
||||
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Globalization;
|
||||
using Mapbox.VectorTile.ExtensionMethods;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Base class for reading/writing location logs
|
||||
/// </summary>
|
||||
public abstract class LocationLogAbstractBase
|
||||
{
|
||||
|
||||
|
||||
public readonly string Delimiter = ";";
|
||||
protected readonly CultureInfo _invariantCulture = CultureInfo.InvariantCulture;
|
||||
|
||||
|
||||
public enum LogfileColumns
|
||||
{
|
||||
#if !ENABLE_WINMD_SUPPORT
|
||||
[Description("location service enabled")]
|
||||
#endif
|
||||
LocationServiceEnabled = 0,
|
||||
#if !ENABLE_WINMD_SUPPORT
|
||||
[Description("location service intializing")]
|
||||
#endif
|
||||
LocationServiceInitializing = 1,
|
||||
#if !ENABLE_WINMD_SUPPORT
|
||||
[Description("location updated")]
|
||||
#endif
|
||||
LocationUpdated = 2,
|
||||
#if !ENABLE_WINMD_SUPPORT
|
||||
[Description("userheading updated")]
|
||||
#endif
|
||||
UserHeadingUpdated = 3,
|
||||
#if !ENABLE_WINMD_SUPPORT
|
||||
[Description("location provider")]
|
||||
#endif
|
||||
LocationProvider = 4,
|
||||
#if !ENABLE_WINMD_SUPPORT
|
||||
[Description("location provider class")]
|
||||
#endif
|
||||
LocationProviderClass = 5,
|
||||
#if !ENABLE_WINMD_SUPPORT
|
||||
[Description("time device [utc]")]
|
||||
#endif
|
||||
UtcTimeDevice = 6,
|
||||
#if !ENABLE_WINMD_SUPPORT
|
||||
[Description("time location [utc]")]
|
||||
#endif
|
||||
UtcTimeOfLocation = 7,
|
||||
#if !ENABLE_WINMD_SUPPORT
|
||||
[Description("latitude")]
|
||||
#endif
|
||||
Latitude = 8,
|
||||
#if !ENABLE_WINMD_SUPPORT
|
||||
[Description("longitude")]
|
||||
#endif
|
||||
Longitude = 9,
|
||||
#if !ENABLE_WINMD_SUPPORT
|
||||
[Description("accuracy [m]")]
|
||||
#endif
|
||||
Accuracy = 10,
|
||||
#if !ENABLE_WINMD_SUPPORT
|
||||
[Description("user heading [°]")]
|
||||
#endif
|
||||
UserHeading = 11,
|
||||
#if !ENABLE_WINMD_SUPPORT
|
||||
[Description("device orientation [°]")]
|
||||
#endif
|
||||
DeviceOrientation = 12,
|
||||
#if !ENABLE_WINMD_SUPPORT
|
||||
[Description("speed [km/h]")]
|
||||
#endif
|
||||
Speed = 13,
|
||||
#if !ENABLE_WINMD_SUPPORT
|
||||
[Description("has gps fix")]
|
||||
#endif
|
||||
HasGpsFix = 14,
|
||||
#if !ENABLE_WINMD_SUPPORT
|
||||
[Description("satellites used")]
|
||||
#endif
|
||||
SatellitesUsed = 15,
|
||||
#if !ENABLE_WINMD_SUPPORT
|
||||
[Description("satellites in view")]
|
||||
#endif
|
||||
SatellitesInView = 16
|
||||
}
|
||||
|
||||
|
||||
public string[] HeaderNames
|
||||
{
|
||||
get
|
||||
{
|
||||
Type enumType = typeof(LogfileColumns);
|
||||
Array arrEnumVals = Enum.GetValues(enumType);
|
||||
string[] hdrs = new string[arrEnumVals.Length];
|
||||
for (int i = 0; i < arrEnumVals.Length; i++)
|
||||
{
|
||||
hdrs[i] = ((LogfileColumns)Enum.Parse(enumType, arrEnumVals.GetValue(i).ToString())).Description();
|
||||
|
||||
}
|
||||
return hdrs;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8837e931abc92c5488b8c41e1caa2e65
|
||||
timeCreated: 1526467177
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,166 @@
|
||||
namespace Mapbox.Unity.Location
|
||||
{
|
||||
|
||||
|
||||
using Mapbox.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using UnityEngine;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Parses location data and returns Location objects.
|
||||
/// </summary>
|
||||
public class LocationLogReader : LocationLogAbstractBase, IDisposable
|
||||
{
|
||||
|
||||
|
||||
public LocationLogReader(byte[] contents)
|
||||
{
|
||||
MemoryStream ms = new MemoryStream(contents);
|
||||
_textReader = new StreamReader(ms);
|
||||
}
|
||||
|
||||
|
||||
private bool _disposed;
|
||||
private TextReader _textReader;
|
||||
|
||||
|
||||
#region idisposable
|
||||
|
||||
|
||||
~LocationLogReader()
|
||||
{
|
||||
Dispose(false);
|
||||
}
|
||||
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
|
||||
protected virtual void Dispose(bool disposeManagedResources)
|
||||
{
|
||||
if (!_disposed)
|
||||
{
|
||||
if (disposeManagedResources)
|
||||
{
|
||||
if (null != _textReader)
|
||||
{
|
||||
#if !NETFX_CORE
|
||||
_textReader.Close();
|
||||
#endif
|
||||
_textReader.Dispose();
|
||||
_textReader = null;
|
||||
}
|
||||
}
|
||||
_disposed = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Returns 'Location' objects from the data passed in. Loops through the data.
|
||||
/// </summary>
|
||||
/// <returns>'Location' objects and loops through the data.</returns>
|
||||
public IEnumerator<Location> GetLocations()
|
||||
{
|
||||
|
||||
while (true)
|
||||
{
|
||||
string line = string.Empty;
|
||||
|
||||
while (1 == 1)
|
||||
{
|
||||
line = _textReader.ReadLine();
|
||||
// rewind if end of log (or last empty line) reached
|
||||
if (null == line || string.IsNullOrEmpty(line))
|
||||
{
|
||||
((StreamReader)_textReader).BaseStream.Position = 0;
|
||||
((StreamReader)_textReader).DiscardBufferedData();
|
||||
continue;
|
||||
}
|
||||
|
||||
// skip comments
|
||||
if (line.StartsWith("#")) { continue; } else { break; }
|
||||
}
|
||||
|
||||
string[] tokens = line.Split(Delimiter.ToCharArray());
|
||||
//simple safety net: check if number of columns matches
|
||||
if (tokens.Length != HeaderNames.Length)
|
||||
{
|
||||
Debug.LogError("unsupported log file");
|
||||
yield return new Location();
|
||||
}
|
||||
|
||||
Location location = new Location();
|
||||
|
||||
location.IsLocationServiceEnabled = bool.Parse(tokens[(int)LogfileColumns.LocationServiceEnabled]);
|
||||
location.IsLocationServiceInitializing = bool.Parse(tokens[(int)LogfileColumns.LocationServiceInitializing]);
|
||||
location.IsLocationUpdated = bool.Parse(tokens[(int)LogfileColumns.LocationUpdated]);
|
||||
location.IsUserHeadingUpdated = bool.Parse(tokens[(int)LogfileColumns.UserHeadingUpdated]);
|
||||
location.Provider = tokens[(int)LogfileColumns.LocationProvider];
|
||||
location.ProviderClass = tokens[(int)LogfileColumns.LocationProviderClass];
|
||||
|
||||
DateTime dtDevice;
|
||||
string dtDeviceTxt = tokens[(int)LogfileColumns.UtcTimeDevice];
|
||||
if (DateTime.TryParseExact(dtDeviceTxt, "yyyyMMdd-HHmmss.fff", _invariantCulture, DateTimeStyles.AssumeUniversal, out dtDevice))
|
||||
{
|
||||
location.TimestampDevice = UnixTimestampUtils.To(dtDevice);
|
||||
}
|
||||
|
||||
DateTime dtLocation;
|
||||
string dtLocationTxt = tokens[(int)LogfileColumns.UtcTimeOfLocation];
|
||||
if (DateTime.TryParseExact(dtLocationTxt, "yyyyMMdd-HHmmss.fff", _invariantCulture, DateTimeStyles.AssumeUniversal, out dtLocation))
|
||||
{
|
||||
location.Timestamp = UnixTimestampUtils.To(dtLocation);
|
||||
}
|
||||
|
||||
double lat;
|
||||
string latTxt = tokens[(int)LogfileColumns.Latitude];
|
||||
double lng;
|
||||
string lngTxt = tokens[(int)LogfileColumns.Longitude];
|
||||
if (
|
||||
!double.TryParse(latTxt, NumberStyles.Any, _invariantCulture, out lat)
|
||||
|| !double.TryParse(lngTxt, NumberStyles.Any, _invariantCulture, out lng)
|
||||
)
|
||||
{
|
||||
location.LatitudeLongitude = Vector2d.zero;
|
||||
}
|
||||
else
|
||||
{
|
||||
location.LatitudeLongitude = new Vector2d(lat, lng);
|
||||
}
|
||||
|
||||
|
||||
float accuracy;
|
||||
location.Accuracy = float.TryParse(tokens[(int)LogfileColumns.Accuracy], NumberStyles.Any, _invariantCulture, out accuracy) ? accuracy : 0;
|
||||
float userHeading;
|
||||
location.UserHeading = float.TryParse(tokens[(int)LogfileColumns.UserHeading], NumberStyles.Any, _invariantCulture, out userHeading) ? userHeading : 0;
|
||||
float deviceOrientation;
|
||||
location.DeviceOrientation = float.TryParse(tokens[(int)LogfileColumns.DeviceOrientation], NumberStyles.Any, _invariantCulture, out deviceOrientation) ? deviceOrientation : 0;
|
||||
float speed;
|
||||
location.SpeedMetersPerSecond = float.TryParse(tokens[(int)LogfileColumns.Speed], NumberStyles.Any, _invariantCulture, out speed) ? speed / 3.6f : (float?)null;
|
||||
bool hasGpsFix;
|
||||
location.HasGpsFix = bool.TryParse(tokens[(int)LogfileColumns.HasGpsFix], out hasGpsFix) ? hasGpsFix : (bool?)null;
|
||||
int satellitesUsed;
|
||||
location.SatellitesUsed = int.TryParse(tokens[(int)LogfileColumns.SatellitesUsed], out satellitesUsed) ? satellitesUsed : (int?)null;
|
||||
int satellitesInView;
|
||||
location.SatellitesInView = int.TryParse(tokens[(int)LogfileColumns.SatellitesInView], out satellitesInView) ? satellitesInView : (int?)null;
|
||||
|
||||
yield return location;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 31c75110fe6926946b6e5e098ec9562f
|
||||
timeCreated: 1526467150
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,132 @@
|
||||
namespace Mapbox.Unity.Location
|
||||
{
|
||||
|
||||
|
||||
using Mapbox.Utils;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Writes location data into Application.persistentDataPath
|
||||
/// </summary>
|
||||
public class LocationLogWriter : LocationLogAbstractBase, IDisposable
|
||||
{
|
||||
|
||||
|
||||
public LocationLogWriter()
|
||||
{
|
||||
string fileName = "MBX-location-log-" + DateTime.Now.ToString("yyyyMMdd-HHmmss") + ".txt";
|
||||
string persistentPath = Application.persistentDataPath;
|
||||
string fullFilePathAndName = Path.Combine(persistentPath, fileName);
|
||||
#if UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN || UNITY_WSA
|
||||
// use `GetFullPath` on that to sanitize the path: replaces `/` returned by `Application.persistentDataPath` with `\`
|
||||
fullFilePathAndName = Path.GetFullPath(fullFilePathAndName);
|
||||
#endif
|
||||
Debug.Log("starting new log file: " + fullFilePathAndName);
|
||||
|
||||
_fileStream = new FileStream(fullFilePathAndName, FileMode.Create, FileAccess.Write);
|
||||
_textWriter = new StreamWriter(_fileStream, new UTF8Encoding(false));
|
||||
_textWriter.WriteLine("#" + string.Join(Delimiter, HeaderNames));
|
||||
|
||||
}
|
||||
|
||||
|
||||
private bool _disposed;
|
||||
private FileStream _fileStream;
|
||||
private TextWriter _textWriter;
|
||||
private long _lineCount = 0;
|
||||
|
||||
|
||||
#region idisposable
|
||||
|
||||
|
||||
~LocationLogWriter()
|
||||
{
|
||||
Dispose(false);
|
||||
}
|
||||
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
|
||||
protected virtual void Dispose(bool disposeManagedResources)
|
||||
{
|
||||
if (!_disposed)
|
||||
{
|
||||
if (disposeManagedResources)
|
||||
{
|
||||
Debug.LogFormat("{0} locations logged", _lineCount);
|
||||
if (null != _textWriter)
|
||||
{
|
||||
_textWriter.Flush();
|
||||
_fileStream.Flush();
|
||||
#if !NETFX_CORE
|
||||
_textWriter.Close();
|
||||
#endif
|
||||
_textWriter.Dispose();
|
||||
_fileStream.Dispose();
|
||||
|
||||
_textWriter = null;
|
||||
_fileStream = null;
|
||||
}
|
||||
}
|
||||
_disposed = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
public void Write(Location location)
|
||||
{
|
||||
string[] lineTokens = new string[]
|
||||
{
|
||||
location.IsLocationServiceEnabled.ToString(),
|
||||
location.IsLocationServiceInitializing.ToString(),
|
||||
location.IsLocationUpdated.ToString(),
|
||||
location.IsUserHeadingUpdated.ToString(),
|
||||
location.Provider,
|
||||
LocationProviderFactory.Instance.DefaultLocationProvider.GetType().Name,
|
||||
DateTime.UtcNow.ToString("yyyyMMdd-HHmmss.fff"),
|
||||
UnixTimestampUtils.From(location.Timestamp).ToString("yyyyMMdd-HHmmss.fff"),
|
||||
string.Format(_invariantCulture, "{0:0.00000000}", location.LatitudeLongitude.x),
|
||||
string.Format(_invariantCulture, "{0:0.00000000}", location.LatitudeLongitude.y),
|
||||
string.Format(_invariantCulture, "{0:0.0}", location.Accuracy),
|
||||
string.Format(_invariantCulture, "{0:0.0}", location.UserHeading),
|
||||
string.Format(_invariantCulture, "{0:0.0}", location.DeviceOrientation),
|
||||
nullableAsStr<float>(location.SpeedKmPerHour, "{0:0.0}"),
|
||||
nullableAsStr<bool>(location.HasGpsFix, "{0}"),
|
||||
nullableAsStr<int>(location.SatellitesUsed, "{0}"),
|
||||
nullableAsStr<int>(location.SatellitesInView, "{0}")
|
||||
};
|
||||
|
||||
_lineCount++;
|
||||
string logMsg = string.Join(Delimiter, lineTokens);
|
||||
Debug.Log(logMsg);
|
||||
_textWriter.WriteLine(logMsg);
|
||||
_textWriter.Flush();
|
||||
}
|
||||
|
||||
|
||||
private string nullableAsStr<T>(T? val, string formatString = null) where T : struct
|
||||
{
|
||||
if (null == val && null == formatString) { return "[not supported by provider]"; }
|
||||
if (null == val && null != formatString) { return string.Format(_invariantCulture, formatString, "[not supported by provider]"); }
|
||||
if (null != val && null == formatString) { return val.Value.ToString(); }
|
||||
return string.Format(_invariantCulture, formatString, val);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2949fba833e7b6b45aca033b7289b971
|
||||
timeCreated: 1526467128
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user