Add signal id to GSV

This commit is contained in:
Morten Nielsen 2020-09-23 20:44:33 -07:00
parent 84bb5f5118
commit abf660df7e
5 changed files with 238 additions and 13 deletions

View file

@ -75,9 +75,12 @@ namespace NmeaParser.Gnss
List<string> properties = new List<string>();
lock (m_lock)
{
if(m_allMessages.ContainsKey(message.MessageType) && m_allMessages[message.MessageType].Equals(message))
string msgid = message.MessageType;
if (message is Gsv gsv && gsv.GnssSignalId != '0')
msgid = msgid + "|" + gsv.GnssSignalId;
if (m_allMessages.ContainsKey(msgid) && m_allMessages[msgid].Equals(message))
return; // Nothing to update/notify
m_allMessages[message.MessageType] = message;
m_allMessages[msgid] = message;
}
properties.Add(nameof(AllMessages));
if(message.TalkerId != NmeaParser.Talker.GlobalNavigationSatelliteSystem && !(message is Gsv) && message.MessageType.Length > 2)

View file

@ -15,6 +15,7 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
namespace NmeaParser.Messages
{
@ -58,12 +59,20 @@ namespace NmeaParser.Messages
else if ( satellites != SatellitesInView)
return false; // Messages do not match
if ((message.Length - 3) % 4 == 1) // v4.1+ adds system id to the last message. Example L1=1, and L2=6 on GPS satellites
{
var id = message.Last();
if (id.Length == 1)
{
GnssSignalId = id[0];
}
}
for (int i = 3; i < message.Length - 3; i += 4)
{
if (message[i].Length == 0)
continue;
else
svs.Add(new SatelliteVehicle(talkerType, message, i));
svs.Add(new SatelliteVehicle(talkerType, GnssSignalId, message, i));
}
return true;
}
@ -79,6 +88,78 @@ namespace NmeaParser.Messages
/// </summary>
public IReadOnlyList<SatelliteVehicle> SVs => svs.AsReadOnly();
/// <summary>
/// Gets the GNSS Signal ID
/// </summary>
/// <remarks>
/// <table>
/// <thead>
/// <tr><th>System</th><th>Signal ID</th><th>Signal Channel</th></tr>
/// </thead>
/// <tbody>
/// <tr><td>GPS</td><td>0</td><td>All signals</td></tr>
/// <tr><td></td><td>1</td><td>L1 C/1</td></tr>
/// <tr><td></td><td>2</td><td>L1 P(Y)</td></tr>
/// <tr><td></td><td>3</td><td>L1 M</td></tr>
/// <tr><td></td><td>4</td><td>L2 P(Y)</td></tr>
/// <tr><td></td><td>5</td><td>L2C-M</td></tr>
/// <tr><td></td><td>6</td><td>L2C-L</td></tr>
/// <tr><td></td><td>7</td><td>L5-I</td></tr>
/// <tr><td></td><td>8</td><td>L5-Q</td></tr>
/// <tr><td></td><td>9-F</td><td>Reserved</td></tr>
/// <tr><td>GLONASS</td><td>0</td><td>All signals</td></tr>
/// <tr><td></td><td>1</td><td>G1 C/A</td></tr>
/// <tr><td></td><td>2</td><td>G1 P</td></tr>
/// <tr><td></td><td>3</td><td>G2 C/A</td></tr>
/// <tr><td></td><td>4</td><td>GLONASS (M) G2 P</td></tr>
/// <tr><td></td><td>5-F</td><td>Reserved</td></tr>
/// <tr><td>GALILEO</td><td>0</td><td>All signals</td></tr>
/// <tr><td></td><td>1</td><td>E5a</td></tr>
/// <tr><td></td><td>2</td><td>E5b</td></tr>
/// <tr><td></td><td>3</td><td>E5 a+b</td></tr>
/// <tr><td></td><td>4</td><td>E6-A</td></tr>
/// <tr><td></td><td>5</td><td>E6-BC</td></tr>
/// <tr><td></td><td>6</td><td>L1-A</td></tr>
/// <tr><td></td><td>7</td><td>L1-BC</td></tr>
/// <tr><td></td><td>8-F</td><td>Reserved</td></tr>
/// <tr><td>BeiDou System</td><td>0</td><td>All signals</td></tr>
/// <tr><td></td><td>1</td><td>B1I</td></tr>
/// <tr><td></td><td>2</td><td>B1Q</td></tr>
/// <tr><td></td><td>3</td><td>B1C</td></tr>
/// <tr><td></td><td>4</td><td>B1A</td></tr>
/// <tr><td></td><td>5</td><td>B2-a</td></tr>
/// <tr><td></td><td>6</td><td>B2-b</td></tr>
/// <tr><td></td><td>7</td><td>B2 a+b</td></tr>
/// <tr><td></td><td>8</td><td>B3I</td></tr>
/// <tr><td></td><td>9</td><td>B3Q</td></tr>
/// <tr><td></td><td>A</td><td>B3A</td></tr>
/// <tr><td></td><td>B</td><td>B2I</td></tr>
/// <tr><td></td><td>C</td><td>B2Q</td></tr>
/// <tr><td></td><td>D-F</td><td>Reserved</td></tr>
/// <tr><td>QZSS</td><td>0</td><td>All signals</td></tr>
/// <tr><td></td><td>1</td><td>L1 C/A</td></tr>
/// <tr><td></td><td>2</td><td>L1C (D)</td></tr>
/// <tr><td></td><td>3</td><td>L1C (P)</td></tr>
/// <tr><td></td><td>4</td><td>LIS</td></tr>
/// <tr><td></td><td>5</td><td>L2C-M</td></tr>
/// <tr><td></td><td>6</td><td>L2C-L</td></tr>
/// <tr><td></td><td>7</td><td>L5-I</td></tr>
/// <tr><td></td><td>8</td><td>L5-Q</td></tr>
/// <tr><td></td><td>9</td><td>L6D</td></tr>
/// <tr><td></td><td>A</td><td>L6E</td></tr>
/// <tr><td></td><td>B-F</td><td>Reserved</td></tr>
/// <tr><td>NavIC (IRNSS)</td><td>0</td><td>All signals</td></tr>
/// <tr><td></td><td>1</td><td>L5-SPS</td></tr>
/// <tr><td></td><td>2</td><td>S-SPS</td></tr>
/// <tr><td></td><td>3</td><td>L5-RS</td></tr>
/// <tr><td></td><td>4</td><td>S-RS</td></tr>
/// <tr><td></td><td>5</td><td>L1-SPS</td></tr>
/// <tr><td></td><td>6-F</td><td>Reserved</td></tr>
/// </tbody>
///</table>
/// </remarks>
public char GnssSignalId { get; private set; } = '0';
/// <summary>
/// Returns an enumerator that iterates through the collection.
/// </summary>
@ -103,7 +184,7 @@ namespace NmeaParser.Messages
/// </summary>
public sealed class SatelliteVehicle
{
internal SatelliteVehicle(Talker talker, string[] message, int startIndex)
internal SatelliteVehicle(Talker talker, char signalId, string[] message, int startIndex)
{
Id = int.Parse(message[startIndex], CultureInfo.InvariantCulture);
if (double.TryParse(message[startIndex + 1], NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out double e))
@ -113,6 +194,7 @@ namespace NmeaParser.Messages
int snr = -1;
if (int.TryParse(message[startIndex + 3], out snr))
SignalToNoiseRatio = snr;
GnssSignalId = signalId;
TalkerId = talker;
}
@ -121,6 +203,12 @@ namespace NmeaParser.Messages
/// </summary>
public Talker TalkerId { get; }
/// <summary>
/// Gets the GNSS Signal ID.
/// </summary>
/// <seealso cref="Gsv.GnssSignalId"/>
public char GnssSignalId { get; }
/// <summary>
/// Satellite ID number
/// </summary>

View file

@ -54,8 +54,30 @@
BorderBrush="Black"
Margin="5,0" Width="20"
BorderThickness="1"
ToolTip="{Binding SignalToNoiseRatio}"
VerticalAlignment="Bottom">
<Border.ToolTip>
<StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Text="System: " />
<TextBlock Text="{Binding Converter={StaticResource heightconv}, ConverterParameter=Name}" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Text="Azimuth: " />
<TextBlock Text="{Binding Azimuth}" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Text="Elevation: " />
<TextBlock Text="{Binding Elevation}" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Text="SNR: " />
<TextBlock Text="{Binding SignalToNoiseRatio}" />
<TextBlock Text="dB" />
</StackPanel>
</StackPanel>
</Border.ToolTip>
<Border.Background>
<SolidColorBrush Color="{Binding Converter={StaticResource conv}}" />
</Border.Background>

View file

@ -27,10 +27,10 @@ namespace SampleApp.WinDesktop
{
InitializeComponent();
}
Dictionary<Talker, Gsv> messages = new Dictionary<Talker, Gsv>();
Dictionary<string, Gsv> messages = new Dictionary<string, Gsv>();
public void SetGsv(Gsv message)
{
messages[message.TalkerId] = message;
messages[message.TalkerId + "+" + message.GnssSignalId] = message;
UpdateSatellites();
}
public void ClearGsv()
@ -41,16 +41,128 @@ namespace SampleApp.WinDesktop
private void UpdateSatellites()
{
satellites.ItemsSource = messages.Values.SelectMany(g => g.SVs);
}
}
satellites.ItemsSource = messages.Values.SelectMany(g => g.SVs).OrderBy(s=>s.GnssSignalId).OrderBy(s => s.Id).OrderByDescending(s => s.TalkerId);
}
internal static string SignalIdToName(char signalId, Talker talkerId)
{
if (signalId != '0')
{
var talker = talkerId;
if (talker == Talker.GlobalPositioningSystem)
{
switch (signalId)
{
case '1': return "L1 C/A";
case '2': return "L1 P(Y)";
case '3': return "L1 M";
case '4': return "L2 P(Y)";
case '5': return "L2C-M";
case '6': return "L2C-L";
case '7': return "L5-I";
case '8': return "L5-Q";
}
}
else if (talker == Talker.GlonassReceiver)
{
switch (signalId)
{
case '1': return "G1 C/A";
case '2': return "G1 P";
case '3': return "G2 C/A";
case '4': return "GLONASS (M) G2 P";
}
}
else if (talker == Talker.GalileoPositioningSystem)
{
switch (signalId)
{
case '1': return "E5a";
case '2': return "E5b";
case '3': return "E5 a+b";
case '4': return "E6-A";
case '5': return "E6-BC";
case '6': return "L1-A";
case '7': return "L1-BC";
}
}
else if (talker == Talker.BeiDouNavigationSatelliteSystem)
{
switch (signalId)
{
case '1': return "B1I";
case '2': return "B1Q";
case '3': return "B1C";
case '4': return "B1A";
case '5': return "B2-a";
case '6': return "B2-b";
case '7': return "B2 a+b";
case '8': return "B3I";
case '9': return "B3Q";
case 'A': return "B3A";
case 'B': return "B2I";
case 'C': return "B2Q";
}
}
else if (talker == Talker.QuasiZenithSatelliteSystem)
{
switch (signalId)
{
case '1': return "L1 C/A";
case '2': return "L1C (D)";
case '3': return "L1C (P)";
case '4': return "LIS";
case '5': return "L2C-M";
case '6': return "L2C-L";
case '7': return "L5-I";
case '8': return "L5-Q";
case '9': return "L6D";
case 'A': return "L6E";
}
}
else if (talker == Talker.IndianRegionalNavigationSatelliteSystem)
{
switch (signalId)
{
case '1': return "L5-SPS";
case '2': return "S-SPS<";
case '3': return "L5-RS";
case '4': return "S-RS";
case '5': return "L1-SPS";
}
}
}
return string.Empty;
}
}
public class SnrToHeightConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if(value is SatelliteVehicle sv)
{
return Math.Max(10, sv.SignalToNoiseRatio * 2);
if (parameter as string == "Name")
{
string name;
if (sv.TalkerId == Talker.GlobalPositioningSystem)
name = "GPS";
else if (sv.TalkerId == Talker.GlonassReceiver)
name = "GLONASS";
else if (sv.TalkerId == Talker.BeiDouNavigationSatelliteSystem)
name = "BeiDou";
else if (sv.TalkerId == Talker.QuasiZenithSatelliteSystem)
name = "QZSS";
else if (sv.TalkerId == Talker.IndianRegionalNavigationSatelliteSystem)
name = "NavIC IRNSS";
else
name = sv.TalkerId.ToString();
var signalName = SatelliteSnr.SignalIdToName(sv.GnssSignalId, sv.TalkerId);
if (!string.IsNullOrEmpty(signalName))
name += " (" + signalName + ")";
return name;
}
else
return Math.Max(10, sv.SignalToNoiseRatio * 2);
}
return value;
}

View file

@ -27,10 +27,10 @@ namespace SampleApp.WinDesktop
{
InitializeComponent();
}
Dictionary<Talker, Gsv> messages = new Dictionary<Talker, Gsv>();
Dictionary<string, Gsv> messages = new Dictionary<string, Gsv>();
public void SetGsv(Gsv message)
{
messages[message.TalkerId] = message;
messages[message.TalkerId + "+" + message.GnssSignalId] = message;
UpdateSatellites();
}
public void ClearGsv()