commit 0ff9e48e2e11538aba77c6d4590dc0ca2b671421 Author: BlubbFish Date: Mon Aug 3 22:12:18 2026 +0200 first commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3f2a16b --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +.vs +GPSDLib/bin +GPSDLib/obj \ No newline at end of file diff --git a/GPSDLib.sln b/GPSDLib.sln new file mode 100644 index 0000000..9366da9 --- /dev/null +++ b/GPSDLib.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.31112.23 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GPSDLib", "GPSDLib\GPSDLib.csproj", "{570367E6-EA1B-4558-B414-D8C2537283F9}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "litjson", "..\litjson\litjson\litjson.csproj", "{1CCC9A15-799A-4FFD-8030-4B9EEA881F13}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {570367E6-EA1B-4558-B414-D8C2537283F9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {570367E6-EA1B-4558-B414-D8C2537283F9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {570367E6-EA1B-4558-B414-D8C2537283F9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {570367E6-EA1B-4558-B414-D8C2537283F9}.Release|Any CPU.Build.0 = Release|Any CPU + {1CCC9A15-799A-4FFD-8030-4B9EEA881F13}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1CCC9A15-799A-4FFD-8030-4B9EEA881F13}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1CCC9A15-799A-4FFD-8030-4B9EEA881F13}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1CCC9A15-799A-4FFD-8030-4B9EEA881F13}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {C0D8961F-6017-4E9E-B98C-CDE6D67C47B9} + EndGlobalSection +EndGlobal diff --git a/GPSDLib/Exception/ConnectionLostException.cs b/GPSDLib/Exception/ConnectionLostException.cs new file mode 100644 index 0000000..31dcd06 --- /dev/null +++ b/GPSDLib/Exception/ConnectionLostException.cs @@ -0,0 +1,9 @@ +using System; + +namespace Ghostware.GPSDLib.Exceptions { + public class ConnectionLostException : Exception { + public ConnectionLostException() : base("The connection is lost.") { + + } + } +} \ No newline at end of file diff --git a/GPSDLib/Exception/NotConnectedException.cs b/GPSDLib/Exception/NotConnectedException.cs new file mode 100644 index 0000000..c31fcb0 --- /dev/null +++ b/GPSDLib/Exception/NotConnectedException.cs @@ -0,0 +1,9 @@ +using System; + +namespace Ghostware.GPSDLib.Exceptions { + public class NotConnectedException : Exception { + public NotConnectedException() : base("The connection is not open. Plz connect first!") { + + } + } +} \ No newline at end of file diff --git a/GPSDLib/Exception/UnknownTypeException.cs b/GPSDLib/Exception/UnknownTypeException.cs new file mode 100644 index 0000000..dd00864 --- /dev/null +++ b/GPSDLib/Exception/UnknownTypeException.cs @@ -0,0 +1,9 @@ +using System; + +namespace Ghostware.GPSDLib.Exceptions { + public class UnknownTypeException : Exception { + public UnknownTypeException() : base("Unknown Class Type") { + + } + } +} \ No newline at end of file diff --git a/GPSDLib/GPSDLib.csproj b/GPSDLib/GPSDLib.csproj new file mode 100644 index 0000000..d731fcf --- /dev/null +++ b/GPSDLib/GPSDLib.csproj @@ -0,0 +1,11 @@ + + + + netcoreapp3.1 + + + + + + + diff --git a/GPSDLib/GpsdConstants.cs b/GPSDLib/GpsdConstants.cs new file mode 100644 index 0000000..bd95b0a --- /dev/null +++ b/GPSDLib/GpsdConstants.cs @@ -0,0 +1,11 @@ +using System; + +using Ghostware.GPSDLib.Models; + +namespace Ghostware.GPSDLib { + public static class GpsdConstants { + public static GpsdOptions DefaultGpsdOptions = new GpsdOptions(true, true); + public const String DisableCommand = "?WATCH={\"enable\":false}"; + public const String PollCommand = "?POLL;"; + } +} \ No newline at end of file diff --git a/GPSDLib/GpsdDataParser.cs b/GPSDLib/GpsdDataParser.cs new file mode 100644 index 0000000..7a434c8 --- /dev/null +++ b/GPSDLib/GpsdDataParser.cs @@ -0,0 +1,30 @@ +using System; + +using Ghostware.GPSDLib.Models; + + +using LitJson; + +namespace Ghostware.GPSDLib { + public class GpsdDataParser { + public Object GetGpsData(String gpsData) { + try { + JsonData json = JsonMapper.ToObject(gpsData); + if(json.ContainsKey("class") && json["class"].IsString) { + return json["class"].ToString() switch { + "VERSION" => new GpsdVersion(json), + "DEVICES" => new GpsDevices(json), + "DEVICE" => new GpsDevice(json), + "WATCH" => new GpsdOptions(json), + "TPV" => new GpsLocation(json), + "SKY" => new GpsSky(json), + _ => null, + }; + } + } catch(Exception e) { + Console.WriteLine(e); + } + return null; + } + } +} \ No newline at end of file diff --git a/GPSDLib/GpsdService.cs b/GPSDLib/GpsdService.cs new file mode 100644 index 0000000..1080d39 --- /dev/null +++ b/GPSDLib/GpsdService.cs @@ -0,0 +1,261 @@ +using System; +using System.Diagnostics; +using System.IO; +using System.Net; +using System.Net.Sockets; +using System.Reflection; +using System.Security; +using System.Threading.Tasks; + +using Ghostware.GPSDLib.Exceptions; +using Ghostware.GPSDLib.Models; + +namespace Ghostware.GPSDLib { + public class GpsdService : IDisposable { + #region Private Properties + + private TcpClient _client; + private StreamReader _streamReader; + private StreamWriter _streamWriter; + + private GpsdDataParser _gpsdDataParser; + + private readonly String _serverAddress; + private readonly Int32 _serverPort; + + private Boolean _proxyEnabled; + private String _proxyAddress; + private Int32 _proxyPort; + private Boolean _proxyAuthenticationEnabled; + private String _proxyUsername; + private SecureString _proxyPassword; + + private GpsLocation _previousGpsLocation; + private GpsSky _lastSky; + + + private Int32 _retryReadCount; + + #endregion + + #region Properties + + public Boolean IsRunning { + get; set; + } + public Int32 ReadFrequenty { get; set; } = 1000; + public Int32 RetryRead { get; set; } = 3; + + public GpsdOptions GpsOptions { + get; set; + } + + + #endregion + + #region Events + + public delegate void VersionEventHandler(Object source, GpsdVersion e); + public delegate void LocationEventHandler(Object source, Tuple e); + public delegate void RawLocationEventHandler(Object source, String rawLocation); + public event VersionEventHandler OnGpsdVersionChanged; + public event LocationEventHandler OnLocationChanged; + public event RawLocationEventHandler OnRawLocationChanged; + + #endregion + + #region Constructors + + public GpsdService(String serverAddress, Int32 serverPort) { + this._serverAddress = serverAddress; + this._serverPort = serverPort; + this.GpsOptions = GpsdConstants.DefaultGpsdOptions; + this.IsRunning = true; + } + + public GpsdService(String serverAddress, Int32 serverPort, GpsdOptions gpsOptions = null) : this(serverAddress, serverPort) => this.GpsOptions = gpsOptions ?? GpsdConstants.DefaultGpsdOptions; + + #endregion + + #region Connection Functionality + + public Boolean Connect() { + this._client = this._proxyEnabled ? this.ConnectViaHttpProxy() : new TcpClient(this._serverAddress, this._serverPort); + this._streamReader = new StreamReader(this._client.GetStream()); + this._streamWriter = new StreamWriter(this._client.GetStream()); + + this._gpsdDataParser = new GpsdDataParser(); + + String gpsData = this._streamReader.ReadLine(); + Object message = this._gpsdDataParser.GetGpsData(gpsData); + if(!(message is GpsdVersion version)) { + return false; + } + + OnGpsdVersionChanged?.Invoke(this, version); + this.ExecuteGpsdCommand(this.GpsOptions.GetCommand()); + return true; + } + + public Boolean Disconnect() { + this.StopGpsReading(); + this.Dispose(); + return true; + } + + #endregion + + #region Gps Reading Functionality + + /// + /// This task reads the gps. This task will run in a loop, so keep in mind to run it in a thread. + /// + /// Exception when client is not connected or streamreader is null. Plz call connect! + /// Exception when the connection is lost. + public void StartGpsReading() { + if(this._streamReader == null || !this._client.Connected) { + throw new NotConnectedException(); + } + + this._retryReadCount = this.RetryRead; + this.IsRunning = true; + while(this.IsRunning) { + if(!this._client.Connected) { + throw new ConnectionLostException(); + } + + try { + String gpsData = this._streamReader.ReadLine(); + OnRawLocationChanged?.Invoke(this, gpsData); + if(gpsData == null) { + if(this._retryReadCount == 0) { + throw new ConnectionLostException(); + } + this._retryReadCount--; + continue; + } + + Object message = this._gpsdDataParser.GetGpsData(gpsData); + if(message is GpsSky sky) { + this._lastSky = sky; + } + if(!(message is GpsLocation gpsLocation) || this._previousGpsLocation != null && gpsLocation.Time.Subtract(new TimeSpan(0, 0, 0, 0, this.ReadFrequenty)) <= this._previousGpsLocation.Time) { + continue; + } + + OnLocationChanged?.Invoke(this, new Tuple(gpsLocation,this._lastSky)); + this._previousGpsLocation = gpsLocation; + } catch(IOException) { + return; + } + } + } + + public Task StartGpsReadingAsync() => new Task(this.StartGpsReading); + + + public void StopGpsReading() { + if(!this.IsRunning) { + return; + } + + this.IsRunning = false; + this.ExecuteGpsdCommand(GpsdConstants.DisableCommand); + } + + #endregion + + #region Helper Functions + + private void ExecuteGpsdCommand(String command) { + if(this._streamWriter == null) { + return; + } + + this._streamWriter.WriteLine(command); + this._streamWriter.Flush(); + } + + #endregion + + #region Proxies + + public void SetProxy(String proxyAddress, Int32 proxyPort) { + this._proxyEnabled = true; + this._proxyAddress = proxyAddress; + this._proxyPort = proxyPort; + } + + public void SetProxyAuthentication(String username, String password) { + this._proxyAuthenticationEnabled = true; + this._proxyUsername = username; + + SecureString securePass = new SecureString(); + foreach(Char passwordChar in password) { + securePass.AppendChar(passwordChar); + } + this._proxyPassword = securePass; + } + + public void SetProxyAuthentication(String username, SecureString password) { + this._proxyAuthenticationEnabled = true; + this._proxyUsername = username; + this._proxyPassword = password; + } + + public void DisableProxy() => this._proxyEnabled = false; + + private TcpClient ConnectViaHttpProxy() { + UriBuilder uriBuilder = new UriBuilder { + Scheme = Uri.UriSchemeHttp, + Host = _proxyAddress, + Port = _proxyPort + }; + + Uri proxyUri = uriBuilder.Uri; + WebRequest request = WebRequest.Create("http://" + this._serverAddress + ":" + this._serverPort); + WebProxy webProxy = new WebProxy(proxyUri); + + request.Proxy = webProxy; + request.Method = "CONNECT"; + + if(this._proxyAuthenticationEnabled) { + webProxy.Credentials = new NetworkCredential(this._proxyUsername, this._proxyPassword); + } else { + webProxy.UseDefaultCredentials = true; + } + + WebResponse response = request.GetResponse(); + Stream responseStream = response.GetResponseStream(); + Debug.Assert(responseStream != null); + + const BindingFlags flags = BindingFlags.NonPublic | BindingFlags.Instance; + + Type rsType = responseStream.GetType(); + PropertyInfo connectionProperty = rsType.GetProperty("Connection", flags); + + Object connection = connectionProperty.GetValue(responseStream, null); + Type connectionType = connection.GetType(); + PropertyInfo networkStreamProperty = connectionType.GetProperty("NetworkStream", flags); + + Object networkStream = networkStreamProperty.GetValue(connection, null); + Type nsType = networkStream.GetType(); + PropertyInfo socketProperty = nsType.GetProperty("Socket", flags); + Socket socket = (Socket)socketProperty.GetValue(networkStream, null); + + return new TcpClient { Client = socket }; + } + + #endregion + + #region Dispose + + public void Dispose() { + this._streamReader?.Close(); + this._streamWriter?.Close(); + this._client?.Close(); + } + + #endregion + } +} \ No newline at end of file diff --git a/GPSDLib/Models/GpsDevice.cs b/GPSDLib/Models/GpsDevice.cs new file mode 100644 index 0000000..4ffb409 --- /dev/null +++ b/GPSDLib/Models/GpsDevice.cs @@ -0,0 +1,59 @@ +using System; + +using LitJson; + +namespace Ghostware.GPSDLib.Models { + public class GpsDevice { + public GpsDevice(JsonData json) { + this.Path = json["path"].ToString(); + if(json.ContainsKey("driver")) { + this.Driver = json["driver"].ToString(); + } + this.Activated = DateTime.Parse(json["activated"].ToString(), new System.Globalization.CultureInfo("en-US", false)); + this.Flags = Double.Parse(json["flags"].ToString().Replace(',', '.'), System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture); + this.Native = Double.Parse(json["native"].ToString().Replace(',', '.'), System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture); + this.Bps = Double.Parse(json["bps"].ToString().Replace(',', '.'), System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture); + this.Parity = json["parity"].ToString(); + this.Stopbits = Double.Parse(json["stopbits"].ToString().Replace(',', '.'), System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture); + this.Cycle = Double.Parse(json["cycle"].ToString().Replace(',', '.'), System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture); + } + + public String Path { + get; set; + } + + public String Driver { + get; set; + } + + public DateTime Activated { + get; set; + } + + public Double Flags { + get; set; + } + + public Double Native { + get; set; + } + + public Double Bps { + get; set; + } + + public String Parity { + get; set; + } + + public Double Stopbits { + get; set; + } + + public Double Cycle { + get; set; + } + + public override String ToString() => $"Path: {this.Path} - Driver: {this.Driver} - Activated: {this.Activated} - Flags: {this.Flags} - Native: {this.Native} - Bps: {this.Bps} - Parity: {this.Parity} - Stopbits: {this.Stopbits} - Cycle: {this.Cycle}"; + } +} \ No newline at end of file diff --git a/GPSDLib/Models/GpsDevices.cs b/GPSDLib/Models/GpsDevices.cs new file mode 100644 index 0000000..87894f3 --- /dev/null +++ b/GPSDLib/Models/GpsDevices.cs @@ -0,0 +1,18 @@ +using System.Collections.Generic; + +using LitJson; + +namespace Ghostware.GPSDLib.Models { + public class GpsDevices { + public GpsDevices(JsonData json) { + this.Devices = new List(); + foreach(JsonData item in json["devices"]) { + this.Devices.Add(new GpsDevice(item)); + } + } + + public List Devices { + get; set; + } + } +} \ No newline at end of file diff --git a/GPSDLib/Models/GpsLocation.cs b/GPSDLib/Models/GpsLocation.cs new file mode 100644 index 0000000..55e7489 --- /dev/null +++ b/GPSDLib/Models/GpsLocation.cs @@ -0,0 +1,73 @@ +using System; + +using LitJson; + +namespace Ghostware.GPSDLib.Models { + public class GpsLocation { + public GpsLocation(JsonData json) { + this.Device = json["device"].ToString(); + this.Mode = Double.Parse(json["mode"].ToString().Replace(',', '.'), System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture); + if(json.ContainsKey("time")) { + this.Time = DateTime.Parse(json["time"].ToString(), new System.Globalization.CultureInfo("en-US", false)); + } + if(json.ContainsKey("ept")) { + this.Ept = Double.Parse(json["ept"].ToString().Replace(',', '.'), System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture); + } + if(json.ContainsKey("alt")) { + this.Altitute = Double.Parse(json["alt"].ToString().Replace(',', '.'), System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture); + } + if(json.ContainsKey("lat")) { + this.Latitude = Double.Parse(json["lat"].ToString().Replace(',', '.'), System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture); + } + if(json.ContainsKey("lon")) { + this.Longitude = Double.Parse(json["lon"].ToString().Replace(',', '.'), System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture); + } + if(json.ContainsKey("track")) { + this.Track = Double.Parse(json["track"].ToString().Replace(',', '.'), System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture); + } + if(json.ContainsKey("speed")) { + this.SpeedKnots = Double.Parse(json["speed"].ToString().Replace(',', '.'), System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture); + } + } + + public String Device { + get; set; + } + + public Double Mode { + get; set; + } + + public DateTime Time { + get; set; + } + + public Double Ept { + get; set; + } + + public Double Altitute { + get; set; + } + + public Double Latitude { + get; set; + } + + public Double Longitude { + get; set; + } + + public Double Track { + get; set; + } + + public Double SpeedKnots { + get; set; + } + + public Double Speed => this.SpeedKnots * 1.852; + + public override String ToString() => $"Device: {this.Device} - Mode: {this.Mode} - Time: {this.Time} - Latitude: {this.Latitude} - Longitude: {this.Longitude} - Altitute: {this.Altitute} - Track: {this.Track} - Speed: {this.Speed}"; + } +} \ No newline at end of file diff --git a/GPSDLib/Models/GpsSatelites.cs b/GPSDLib/Models/GpsSatelites.cs new file mode 100644 index 0000000..8f5a019 --- /dev/null +++ b/GPSDLib/Models/GpsSatelites.cs @@ -0,0 +1,41 @@ +using System; + +using LitJson; + +namespace Ghostware.GPSDLib.Models { + public class GpsSatelites { + + public GpsSatelites(JsonData json) { + this.PRN = Double.Parse(json["PRN"].ToString().Replace(',', '.'), System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture); + if(json.ContainsKey("el")) { + this.El = Double.Parse(json["el"].ToString().Replace(',', '.'), System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture); + } + this.Az = Double.Parse(json["az"].ToString().Replace(',', '.'), System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture); + this.Ss = Double.Parse(json["ss"].ToString().Replace(',', '.'), System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture); + this.Used = Boolean.Parse(json["used"].ToString()); + this.Gnssid = Double.Parse(json["gnssid"].ToString().Replace(',', '.'), System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture); + this.Svid = Double.Parse(json["svid"].ToString().Replace(',', '.'), System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture); + } + public Double PRN { + get; + } + public Double El { + get; + } + public Double Az { + get; + } + public Double Ss { + get; + } + public Boolean Used { + get; + } + public Double Gnssid { + get; + } + public Double Svid { + get; + } + } +} \ No newline at end of file diff --git a/GPSDLib/Models/GpsSky.cs b/GPSDLib/Models/GpsSky.cs new file mode 100644 index 0000000..ef01f22 --- /dev/null +++ b/GPSDLib/Models/GpsSky.cs @@ -0,0 +1,47 @@ +using System; +using System.Collections.Generic; + +using LitJson; + +namespace Ghostware.GPSDLib.Models { + public class GpsSky { + public GpsSky(JsonData json) { + this.Vdop = Double.Parse(json["vdop"].ToString().Replace(',', '.'), System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture); + this.Hdop = Double.Parse(json["hdop"].ToString().Replace(',', '.'), System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture); + this.Pdop = Double.Parse(json["pdop"].ToString().Replace(',', '.'), System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture); + if(json.ContainsKey("nSat")) { + this.Sat = Double.Parse(json["nSat"].ToString().Replace(',', '.'), System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture); + } + if(json.ContainsKey("uSat") && this.Sat == 0) { + this.Sat = Double.Parse(json["uSat"].ToString().Replace(',', '.'), System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture); + } + if(json.ContainsKey("satellites")) { + this.Satelites = new List(); + foreach(JsonData item in json["satellites"]) { + this.Satelites.Add(new GpsSatelites(item)); + } + } + } + + public Double Vdop { + get; + } + + public Double Hdop { + get; + } + + public Double Pdop { + get; + } + + public Double Sat { + get; + } + public List Satelites { + get; + } + + public override String ToString() => $"Vdop: {this.Vdop} - Hdop: {this.Hdop} - Ndop: {this.Pdop} - Satelites: {this.Sat}"; + } +} \ No newline at end of file diff --git a/GPSDLib/Models/GpsdOptions.cs b/GPSDLib/Models/GpsdOptions.cs new file mode 100644 index 0000000..b14396c --- /dev/null +++ b/GPSDLib/Models/GpsdOptions.cs @@ -0,0 +1,60 @@ +using System; +using System.Collections.Generic; +using System.Runtime.Serialization; + +using LitJson; + +namespace Ghostware.GPSDLib.Models { + public class GpsdOptions { + public GpsdOptions(JsonData json) { + this.Enable = Boolean.Parse(json["enable"].ToString()); + this.Json = Boolean.Parse(json["json"].ToString()); + this.Nmea = Boolean.Parse(json["nmea"].ToString()); + this.Raw = Double.Parse(json["raw"].ToString().Replace(',', '.'), System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture); + this.Scaled = Boolean.Parse(json["scaled"].ToString()); + this.Timing = Boolean.Parse(json["timing"].ToString()); + this.Split24 = Boolean.Parse(json["split24"].ToString()); + this.Pps = Boolean.Parse(json["pps"].ToString()); + } + + public GpsdOptions(Boolean enable, Boolean json) { + this.Enable = enable; + this.Json = json; + } + + public Boolean Enable { + get; set; + } + + public Boolean Json { + get; set; + } + + public Boolean Nmea { + get; set; + } + + public Double Raw { + get; set; + } + + public Boolean Scaled { + get; set; + } + + public Boolean Timing { + get; set; + } + + public Boolean Split24 { + get; set; + } + + public Boolean Pps { + get; set; + } + + + public String GetCommand() => $"?WATCH={JsonMapper.ToJson(new Dictionary() { { "enable", this.Enable }, { "json", this.Json }, { "nmea", this.Nmea }, { "raw", this.Raw }, { "scaled", this.Scaled }, { "timing", this.Timing }, { "split24", this.Split24 }, { "pps", this.Pps } })}"; + } +} \ No newline at end of file diff --git a/GPSDLib/Models/GpsdVersion.cs b/GPSDLib/Models/GpsdVersion.cs new file mode 100644 index 0000000..be8fd78 --- /dev/null +++ b/GPSDLib/Models/GpsdVersion.cs @@ -0,0 +1,33 @@ +using System; +using System.Runtime.Serialization; + +using LitJson; + +namespace Ghostware.GPSDLib.Models { + public class GpsdVersion { + public GpsdVersion(JsonData json) { + this.Release = Double.Parse(json["release"].ToString().Replace(',', '.'), System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture); + this.Rev = Double.Parse(json["rev"].ToString().Replace(',', '.'), System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture); + this.ProtoMajor = Double.Parse(json["proto_major"].ToString().Replace(',', '.'), System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture); + this.ProtoMinor = Double.Parse(json["proto_minor"].ToString().Replace(',', '.'), System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture); + } + + public Double Release { + get; set; + } + + public Double Rev { + get; set; + } + + public Double ProtoMajor { + get; set; + } + + public Double ProtoMinor { + get; set; + } + + public override String ToString() => $"Release: {this.Release} - Revision: {this.Rev} - ProtoMajor: {this.ProtoMajor} - ProtoMinor: {this.ProtoMinor}"; + } +} \ No newline at end of file