From b035adda26c7e5ec6b1df34ef38beb6573b2d1e7 Mon Sep 17 00:00:00 2001 From: Morten Nielsen Date: Tue, 28 Jul 2020 21:07:53 -0700 Subject: [PATCH] Add early beginnings of NTRIP tab --- src/SampleApp.WinDesktop/MainWindow.xaml | 5 +- src/SampleApp.WinDesktop/MainWindow.xaml.cs | 2 +- src/SampleApp.WinDesktop/Ntrip/Carrier.cs | 23 +++ src/SampleApp.WinDesktop/Ntrip/Caster.cs | 59 ++++++++ src/SampleApp.WinDesktop/Ntrip/Client.cs | 140 ++++++++++++++++++ src/SampleApp.WinDesktop/Ntrip/NtripSource.cs | 23 +++ src/SampleApp.WinDesktop/Ntrip/NtripStream.cs | 52 +++++++ src/SampleApp.WinDesktop/NtripView.xaml | 74 +++++++++ src/SampleApp.WinDesktop/NtripView.xaml.cs | 102 +++++++++++++ 9 files changed, 478 insertions(+), 2 deletions(-) create mode 100644 src/SampleApp.WinDesktop/Ntrip/Carrier.cs create mode 100644 src/SampleApp.WinDesktop/Ntrip/Caster.cs create mode 100644 src/SampleApp.WinDesktop/Ntrip/Client.cs create mode 100644 src/SampleApp.WinDesktop/Ntrip/NtripSource.cs create mode 100644 src/SampleApp.WinDesktop/Ntrip/NtripStream.cs create mode 100644 src/SampleApp.WinDesktop/NtripView.xaml create mode 100644 src/SampleApp.WinDesktop/NtripView.xaml.cs diff --git a/src/SampleApp.WinDesktop/MainWindow.xaml b/src/SampleApp.WinDesktop/MainWindow.xaml index d693e8f..ef5541f 100644 --- a/src/SampleApp.WinDesktop/MainWindow.xaml +++ b/src/SampleApp.WinDesktop/MainWindow.xaml @@ -75,7 +75,7 @@ - + 1200 2400 4800 @@ -91,6 +91,9 @@ + + + diff --git a/src/SampleApp.WinDesktop/MainWindow.xaml.cs b/src/SampleApp.WinDesktop/MainWindow.xaml.cs index fa5c453..0e71fbd 100644 --- a/src/SampleApp.WinDesktop/MainWindow.xaml.cs +++ b/src/SampleApp.WinDesktop/MainWindow.xaml.cs @@ -14,7 +14,7 @@ namespace SampleApp.WinDesktop public partial class MainWindow : Window { private Queue messages = new Queue(101); - private NmeaParser.NmeaDevice currentDevice; + public static NmeaParser.NmeaDevice currentDevice; //Dialog for browsing to nmea log files private Microsoft.Win32.OpenFileDialog nmeaOpenFileDialog = new Microsoft.Win32.OpenFileDialog() { diff --git a/src/SampleApp.WinDesktop/Ntrip/Carrier.cs b/src/SampleApp.WinDesktop/Ntrip/Carrier.cs new file mode 100644 index 0000000..aed0979 --- /dev/null +++ b/src/SampleApp.WinDesktop/Ntrip/Carrier.cs @@ -0,0 +1,23 @@ +// ******************************************************************************* +// * Licensed under the Apache License, Version 2.0 (the "License"); +// * you may not use this file except in compliance with the License. +// * You may obtain a copy of the License at +// * +// * http://www.apache.org/licenses/LICENSE-2.0 +// * +// * Unless required by applicable law or agreed to in writing, software +// * distributed under the License is distributed on an "AS IS" BASIS, +// * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// * See the License for the specific language governing permissions and +// * limitations under the License. +// ****************************************************************************** + +namespace NmeaParser.Gnss.Ntrip +{ + public enum Carrier : int + { + No = 0, + L1 = 1, + L1L2 = 2 + } +} diff --git a/src/SampleApp.WinDesktop/Ntrip/Caster.cs b/src/SampleApp.WinDesktop/Ntrip/Caster.cs new file mode 100644 index 0000000..639f1f5 --- /dev/null +++ b/src/SampleApp.WinDesktop/Ntrip/Caster.cs @@ -0,0 +1,59 @@ +// ******************************************************************************* +// * Licensed under the Apache License, Version 2.0 (the "License"); +// * you may not use this file except in compliance with the License. +// * You may obtain a copy of the License at +// * +// * http://www.apache.org/licenses/LICENSE-2.0 +// * +// * Unless required by applicable law or agreed to in writing, software +// * distributed under the License is distributed on an "AS IS" BASIS, +// * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// * See the License for the specific language governing permissions and +// * limitations under the License. +// ****************************************************************************** + +using System.Globalization; +using System.Net; + +namespace NmeaParser.Gnss.Ntrip +{ + public class Caster : NtripSource + { + internal Caster (string[] d) + { + var a = d[1].Split(':'); + Address = IPAddress.Parse(a[0]); + Port = int.Parse(a[1]); + Identifier = d[3]; + Operator = d[4]; + SupportsNmea = d[5] == "1"; + CountryCode = d[6]; + Latitude = double.Parse(d[7], CultureInfo.InvariantCulture); + Longitude = double.Parse(d[8], CultureInfo.InvariantCulture); + FallbackAddress = IPAddress.Parse(d[9]); + } + + public Caster(IPAddress address, int port, string identifier, string _operator, bool supportsNmea, string countryCode, double latitude, double longitude, IPAddress fallbackkAddress) + { + Address = address; + Port = port; + Identifier = identifier; + Operator = _operator; + SupportsNmea = supportsNmea; + CountryCode = countryCode; + Latitude = latitude; + Longitude = longitude; + FallbackAddress = fallbackkAddress; + } + + public IPAddress Address { get; } + public int Port { get; } + public string Identifier { get; } + public string Operator { get; } + public bool SupportsNmea { get; } + public string CountryCode { get; } + public double Latitude { get; } + public double Longitude { get; } + public IPAddress FallbackAddress { get; } + } +} diff --git a/src/SampleApp.WinDesktop/Ntrip/Client.cs b/src/SampleApp.WinDesktop/Ntrip/Client.cs new file mode 100644 index 0000000..9c1b540 --- /dev/null +++ b/src/SampleApp.WinDesktop/Ntrip/Client.cs @@ -0,0 +1,140 @@ +// ******************************************************************************* +// * Licensed under the Apache License, Version 2.0 (the "License"); +// * you may not use this file except in compliance with the License. +// * You may obtain a copy of the License at +// * +// * http://www.apache.org/licenses/LICENSE-2.0 +// * +// * Unless required by applicable law or agreed to in writing, software +// * distributed under the License is distributed on an "AS IS" BASIS, +// * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// * See the License for the specific language governing permissions and +// * limitations under the License. +// ****************************************************************************** + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net.Sockets; +using System.Threading.Tasks; + +namespace NmeaParser.Gnss.Ntrip +{ + public class Client : IDisposable + { + private readonly string _host; + private readonly int _port; + private string? _auth; + private Socket? sckt; + private bool connected; + private Task? runningTask; + + public Client(string host, int port) + { + _host = host; + _port = port; + } + + public Client(string host, int port, string username, string password) : this(host, port) + { + _auth = Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(username + ":" + password)); + } + + public IEnumerable GetSourceTable() + { + string data = ""; + byte[] buffer = new byte[1024]; + using (var sck = Request("")) + { + int count; + while ((count = sck.Receive(buffer)) > 0) + { + data += System.Text.Encoding.UTF8.GetString(buffer, 0, count); + } + } + var lines = data.Split('\n'); + List sources = new List(); + foreach (var item in lines) + { + var d = item.Split(';'); + if (d.Length == 0) continue; + if (d[0] == "ENDSOURCETABLE") + break; + if (d[0] == "CAS") + { + sources.Add(new Caster(d)); + } + else if (d[0] == "STR") + { + sources.Add(new NtripStream(d)); + } + } + return sources; + } + + private Socket Request(string path) + { + var sckt = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); + sckt.Blocking = true; + sckt.Connect(_host, _port); + + string msg = $"GET /{path} HTTP/1.1\r\n"; + msg += "User-Agent: NTRIP ntripclient\r\n"; + if (_auth != null) + { + msg += "Authorization: Basic " + _auth + "\r\n"; + } + msg += "Accept: */*\r\nConnection: close\r\n"; + msg += "\r\n"; + + byte[] data = System.Text.Encoding.ASCII.GetBytes(msg); + sckt.Send(data); + return sckt; + } + + public void Connect(string strName) + { + if (sckt != null) throw new Exception("Connection already open"); + sckt = Request(strName); + connected = true; + runningTask = Task.Run(ReceiveThread); + } + + private async Task ReceiveThread() + { + byte[] buffer = new byte[65536]; + + while (connected && sckt != null) + { + int count = sckt.Receive(buffer); + if (count > 0) + { + DataReceived?.Invoke(this, buffer.Take(count).ToArray()); + } + await Task.Delay(10); + } + sckt?.Shutdown(SocketShutdown.Both); + sckt?.Dispose(); + sckt = null; + } + + public Task CloseAsync() + { + if (runningTask != null) + { + connected = false; + var t = runningTask; + runningTask = null; + return t; + } + return Task.CompletedTask; + } + + public void Dispose() + { + _ = CloseAsync(); + } + + public event EventHandler? DataReceived; + } +} diff --git a/src/SampleApp.WinDesktop/Ntrip/NtripSource.cs b/src/SampleApp.WinDesktop/Ntrip/NtripSource.cs new file mode 100644 index 0000000..8cc71da --- /dev/null +++ b/src/SampleApp.WinDesktop/Ntrip/NtripSource.cs @@ -0,0 +1,23 @@ +// ******************************************************************************* +// * Licensed under the Apache License, Version 2.0 (the "License"); +// * you may not use this file except in compliance with the License. +// * You may obtain a copy of the License at +// * +// * http://www.apache.org/licenses/LICENSE-2.0 +// * +// * Unless required by applicable law or agreed to in writing, software +// * distributed under the License is distributed on an "AS IS" BASIS, +// * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// * See the License for the specific language governing permissions and +// * limitations under the License. +// ****************************************************************************** + +namespace NmeaParser.Gnss.Ntrip +{ + public class NtripSource + { + protected NtripSource() + { + } + } +} diff --git a/src/SampleApp.WinDesktop/Ntrip/NtripStream.cs b/src/SampleApp.WinDesktop/Ntrip/NtripStream.cs new file mode 100644 index 0000000..9893109 --- /dev/null +++ b/src/SampleApp.WinDesktop/Ntrip/NtripStream.cs @@ -0,0 +1,52 @@ +// ******************************************************************************* +// * Licensed under the Apache License, Version 2.0 (the "License"); +// * you may not use this file except in compliance with the License. +// * You may obtain a copy of the License at +// * +// * http://www.apache.org/licenses/LICENSE-2.0 +// * +// * Unless required by applicable law or agreed to in writing, software +// * distributed under the License is distributed on an "AS IS" BASIS, +// * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// * See the License for the specific language governing permissions and +// * limitations under the License. +// ****************************************************************************** + +using System; +using System.Globalization; + +namespace NmeaParser.Gnss.Ntrip +{ + public class NtripStream : NtripSource + { + internal NtripStream(string[] d) + { + Mountpoint = d[1]; + Identifier = d[2]; + Format = d[3]; + FormatDetails = d[4]; + if (int.TryParse(d[5], out int carrier)) + Carrier = (Carrier)carrier; + else + { + + } + Network = d[7]; + CountryCode = d[8]; + Latitude = double.Parse(d[9], CultureInfo.InvariantCulture); + Longitude = double.Parse(d[10], CultureInfo.InvariantCulture); + SupportsNmea = d[11] == "1"; + } + + public string Mountpoint { get; } + public string Identifier { get; } + public string Format { get; } + public string FormatDetails { get; } + public Carrier Carrier { get; } + public string Network { get; } + public string CountryCode { get; } + public double Latitude { get; } + public double Longitude { get; } + public bool SupportsNmea { get; } + } +} diff --git a/src/SampleApp.WinDesktop/NtripView.xaml b/src/SampleApp.WinDesktop/NtripView.xaml new file mode 100644 index 0000000..97d31ff --- /dev/null +++ b/src/SampleApp.WinDesktop/NtripView.xaml @@ -0,0 +1,74 @@ + + + + + + + + + + + + + + + + + + + + + + + + +