Skip to content

Commit

Permalink
Adding GPSDataCreator
Browse files Browse the repository at this point in the history
  • Loading branch information
Didosa committed Jan 7, 2022
1 parent 68f88fc commit e1f6305
Show file tree
Hide file tree
Showing 11 changed files with 326 additions and 36 deletions.
4 changes: 4 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[*.cs]

# CS8603: Possible null reference return.
dotnet_diagnostic.CS8603.severity = none
22 changes: 22 additions & 0 deletions GPSDataCreator/GPSDataCreator.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<LangVersion>latest</LangVersion>
<ImplicitUsings>disable</ImplicitUsings>
<Nullable>enable</Nullable>
<DisableImplicitNamespaceImports>true</DisableImplicitNamespaceImports>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="System.Configuration.ConfigurationManager" Version="6.0.0" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\PiLotAPIProxy\PiLotAPIProxy.csproj" />
<ProjectReference Include="..\PiLotModel\PiLotModel.csproj" />
<ProjectReference Include="..\PiLotUtils\PiLotUtils.csproj" />
</ItemGroup>

</Project>
171 changes: 171 additions & 0 deletions GPSDataCreator/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
using System;
using System.Configuration;
using System.Threading.Tasks;
using PiLot.APIProxy;
using PiLot.Model.Nav;
using PiLot.Utils.DateAndTime;

namespace PiLot.GPSDataCreator {

/// <summary>
/// Helper Program to generate GPS Data on a test system, so that
/// position and movement can be simulated.
/// </summary>
public class Program {

private static LatLon? position; // the current position
private static Double speed = 0; // m/s
private static Double course = 0; // course in degrees from north
private static Int64 boatTimeOffset = 60 * 60 * 1000; // 1 hours in milliseconds
private static PositionProxy positionProxy = null;

public static async Task Main(String[] args) {
position = await DefineStartPositionAsync();
Console.WriteLine($"Starting at {position}");
InitializeProxy();
MoveAsync();
WatchKeys();
}

/// <summary>
/// Sets up the proxy uses to save data to the api. Requires the values
/// for localAPI, username and password being set in app.config.
/// </summary>
private static void InitializeProxy() {
String apiUrl = ConfigurationManager.AppSettings["localAPI"];
String username = ConfigurationManager.AppSettings["username"];
String password = ConfigurationManager.AppSettings["password"];
LoginHelper loginHelper = new LoginHelper(apiUrl, username, password);
positionProxy = new PositionProxy(apiUrl, loginHelper);
}

/// <summary>
/// Defines the start position by either taking the last position within the
/// last few days or by manually entering latitude and longitude
/// </summary>
/// <returns>A LatLng, not null</returns>
private async static Task<LatLon> DefineStartPositionAsync() {
LatLon result = null;
Console.WriteLine("Loading latest position to continue");
LatLon startPosition = await LoadLatestPosistionAsync();
if (startPosition != null) {
Console.WriteLine($"Last position was lat {startPosition.Latitude}, lon {startPosition.Longitude}");
Console.WriteLine("Press y to use this position");
if(Console.ReadLine() == "y") {
result = startPosition;
}
}
if(result == null) {
Double? lat = null;
Double? lon = null;
String? entry;
Double test;
while (lat == null) {
Console.Write("Enter latitude: ");
entry = Console.ReadLine();
if(Double.TryParse(entry, out test)) {
lat = ((test + 90) % 180) - 90;
} else {
Console.WriteLine("Invalid latitude");
}
}
while (lon == null) {
Console.Write("Enter longitude: ");
entry = Console.ReadLine();
if (Double.TryParse(entry, out test)) {
lon = ((test + 180) % 360) - 180;
} else {
Console.WriteLine("Invalid latitude");
}
}
result = new LatLon(lat.Value, lon.Value);
}
return result;
}

/// <summary>
/// This moves the position every second, based on the current
/// speed and direction
/// </summary>
private async static Task MoveAsync() {
Int64 utcTime = 0;
Int64 boatTime = 0;
while (true) {
await Task.Delay(1000);
position.MoveBy(speed, course);
utcTime = DateTimeHelper.ToJSTime(DateTime.UtcNow);
boatTime = utcTime + boatTimeOffset;
GpsRecord record = new GpsRecord();
record.UTC = utcTime;
record.Latitude = position.Latitude;
record.Longitude = position.Longitude;
SendPositionAsync(record);
}
}

/// <summary>
/// This watches the keys. The arrow keys change heading and speed,
/// esc steps out of the loop and thus ends the program.
/// </summary>
private static void WatchKeys() {
Console.WriteLine("Hit esc to stop");
do {
if (Console.KeyAvailable) {
ConsoleKeyInfo key = Console.ReadKey(true);
if (key.Key == ConsoleKey.Escape) {
break;
} else {
switch (key.Key) {
case ConsoleKey.RightArrow:
course = (course + 5 + 360) % 360;
break;
case ConsoleKey.LeftArrow:
course = (course - 5 + 360) % 360;
break;
case ConsoleKey.UpArrow:
speed += 0.5;
break;
case ConsoleKey.DownArrow:
speed = Math.Max(0, speed - 0.5);
break;
}
Console.WriteLine(String.Format($"COG: {course:000}°, SOG: {speed}"));
}
}

} while (true);
}

/// <summary>
/// This tries to load the latest position by reading the track from the
/// last seven days.
/// </summary>
private async static Task<LatLon> LoadLatestPosistionAsync() {
LatLon result = null;
String url = ConfigurationManager.AppSettings["localAPI"];
TrackProxy trackProxy = new TrackProxy(url, null);
Int64 utcNow = DateTimeHelper.JSNow;
Int64 start = utcNow - (7 * 24 * 3600 * 1000); // 7 days
ProxyResult<Track> proxyResult = await trackProxy.GetTrackAsync(start, utcNow, false);
if (proxyResult.Success) {
if (proxyResult.Data.HasRecords) {
GpsRecord record = proxyResult.Data.LastRecord;
result = new LatLon(record.Latitude.Value, record.Longitude.Value);
}
} else {
Console.WriteLine(proxyResult.Message);
}
return result;
}

/// <summary>
/// Saves the current position to the server.
/// </summary>
private async static Task SendPositionAsync(GpsRecord pRecord) {
Boolean success = await positionProxy.PutPositionsAsync(new GpsRecord[] { pRecord });
if(!success) {
Console.WriteLine("Sending position was not successful");
}
}
}
}
10 changes: 10 additions & 0 deletions GPSDataCreator/app.example.config
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="localAPI" value="http://localhost/pilotapi/api/v1" />
<add key="username" value="admin" />
<add key="password" value="secret" />
<add key="logLevel" value="INFO" />
<add key="logfilePath" value="/home/dido/Documents/piLotDev/log" />
</appSettings>
</configuration>
11 changes: 11 additions & 0 deletions PiLot.sln
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,13 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "docs", "docs", "{0B397FE6-E
docs\user.md = docs\user.md
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GPSDataCreator", "GPSDataCreator\GPSDataCreator.csproj", "{373E850B-6EDA-474D-B695-032D61222163}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{97776635-E1EA-4D48-A17E-2E9FD1C9D5AC}"
ProjectSection(SolutionItems) = preProject
.editorconfig = .editorconfig
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -100,6 +107,10 @@ Global
{ED5B51D6-3644-4733-B562-C0B7ED994067}.Debug|Any CPU.Build.0 = Debug|Any CPU
{ED5B51D6-3644-4733-B562-C0B7ED994067}.Release|Any CPU.ActiveCfg = Release|Any CPU
{ED5B51D6-3644-4733-B562-C0B7ED994067}.Release|Any CPU.Build.0 = Release|Any CPU
{373E850B-6EDA-474D-B695-032D61222163}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{373E850B-6EDA-474D-B695-032D61222163}.Debug|Any CPU.Build.0 = Debug|Any CPU
{373E850B-6EDA-474D-B695-032D61222163}.Release|Any CPU.ActiveCfg = Release|Any CPU
{373E850B-6EDA-474D-B695-032D61222163}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
7 changes: 1 addition & 6 deletions PiLotAPICore/App_Data/global/app.json
Original file line number Diff line number Diff line change
@@ -1,6 +1 @@
{
"PiLot.Nav.activeRouteId": "15",
"PiLot.Model.Boat.currentBoatConfigName": "esmeralda",
"PiLot.Model.Common.boatTimeOffset": "180",
"PiLot.Model.Nav.currentRouteId": "2"
}
{"PiLot.Nav.activeRouteId":"15","PiLot.Model.Boat.currentBoatConfigName":"esmeralda","PiLot.Model.Common.boatTimeOffset":"60","PiLot.Model.Nav.currentRouteId":"2"}
28 changes: 0 additions & 28 deletions PiLotAPICore/Helpers/GeoHelper.cs

This file was deleted.

4 changes: 3 additions & 1 deletion PiLotAPICore/Helpers/GpsCache.cs
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,9 @@ private void PersistLatest() {
GpsRecord lastRecord = this.records[0];
if (this.previousSavedRecord != null) {
deltaT = lastRecord.UTC - this.previousSavedRecord.UTC;
deltaX = GeoHelper.Haversine(lastRecord.Latitude.Value, this.previousSavedRecord.Latitude.Value, lastRecord.Longitude.Value, this.previousSavedRecord.Longitude.Value);
LatLon latestPosition = new LatLon(lastRecord.Latitude.Value, lastRecord.Longitude.Value);
LatLon previousPosition = new LatLon(this.previousSavedRecord.Latitude.Value, this.previousSavedRecord.Longitude.Value);
deltaX = latestPosition.DistanceTo(previousPosition);
doPersist = (deltaT >= MINDELTAT) && (deltaX > MINDISTANCE);
} else {
doPersist = true;
Expand Down
9 changes: 8 additions & 1 deletion PiLotModel/Nav/GpsRecord.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ namespace PiLot.Model.Nav {
/// <summary>
/// Represents one GPS record
/// </summary>
public class GpsRecord {
public class GpsRecord : IComparable<GpsRecord> {

private const Char SEPARATOR = ';';

Expand Down Expand Up @@ -189,6 +189,13 @@ public DateTime GetUTCDate() {
return DateTimeHelper.FromJSTime(this.UTC);
}

/// <summary>
/// Default comparison based on UTC
/// </summary>
public Int32 CompareTo(GpsRecord pRecord) {
return this.UTC.CompareTo(pRecord.UTC);
}

#endregion

#region private methods
Expand Down
Loading

0 comments on commit e1f6305

Please sign in to comment.