Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Shared/AgOpenWeb.RemoteServer/wwwroot/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -2890,7 +2890,7 @@ function renderSystemData() {
SD.hdual.classList.toggle('sd-bad', !!s.dualHeadingMissing);
const ago = v => tr('{n} s ago', { n: v < 10 ? v.toFixed(1) : Math.round(v) });
const rows = (d ? d.sentences : []).map(x =>
'<div class="sd-sent' + (x.age > 2 ? ' stale' : '') + '"><div class="sd-senthead"><span' + (x.type === 'REJECTED' ? '>' + esc(tr('Not accepted', {})) : ' translate="no">$' + esc(x.type)) +
'<div class="sd-sent' + (x.age > 2 ? ' stale' : '') + '"><div class="sd-senthead"><span' + (x.type === 'REJECTED' ? '>' + esc(tr('Not accepted', {})) : ' translate="no">' + (x.type === 'INSPVAX' ? '#' : '$') + esc(x.type)) +
'</span><span>' + esc(ago(x.age)) + '</span></div><div class="sd-senttext" translate="no">' + esc(x.text) + '</div></div>');
const html = rows.length ? rows.join('')
: '<div class="sa-hint">' + esc(s.gpsSentence === 'SIM' ? tr('The simulator is supplying the position; no sentence is being received.', {})
Expand Down
5 changes: 4 additions & 1 deletion Shared/AgOpenWeb.Services/UdpCommunicationService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -419,8 +419,11 @@ private void ProcessReceivedData(byte[] data, IPEndPoint remoteEndPoint)
Timestamp = DateTime.Now
});
}
else if (data.Length > 0 && data[0] == (byte)'$')
else if (data.Length > 0 && (data[0] == (byte)'$' || data[0] == (byte)'#' || data[0] == (byte)'%'))
{
// A '$' sentence or a Unicore '#'/'%' log: this is where the position comes
// from, so the RTCM corrections go back to this address (unicast on 2233) and
// Network IO names it.
MarkSourceSeen(SourceGpsNmea, remoteEndPoint);

// Text NMEA sentence (starts with $)
Expand Down
37 changes: 37 additions & 0 deletions Tests/AgOpenWeb.Services.Tests/UdpGpsPortsTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,42 @@ public IReadOnlyList<LocalNetworkAddress> GetIPv4Addresses() =>
new[] { new LocalNetworkAddress(IPAddress.Loopback, 8, "lo0") };
}

/// <summary>A receiver that prints only Unicore '#' logs (a UM981) is a GPS source too.</summary>
[Test]
public async Task A_hash_log_marks_the_GPS_source_address()
{
try
{
using var probe = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
probe.Bind(new IPEndPoint(IPAddress.Any, UdpCommunicationService.ModulePort));
}
catch (SocketException)
{
Assert.Ignore("port 9999 is held by another process on this machine");
}

var udp = new UdpCommunicationService(new Loopback());
await udp.StartAsync();
try
{
const string body = "#INSPVAXA,COM3,0,80.0,FINE,2439,503918.400,0,424572,0;INS_ALIGNING,NONE,0.0,0.0,-17.0,17.0,0.0,0.0,0.0,0.0,0.0,0.0,0,0,0,0,0,0,0,0,0,0,0";
var line = Encoding.ASCII.GetBytes(body + "*" + AgOpenWeb.Services.Gps.UnicoreCrc32.Compute(Encoding.ASCII.GetBytes(body[1..])).ToString("x8") + "\r\n");
using var sender = new UdpClient();
IPAddress? source = null;
for (int attempt = 0; attempt < 20 && source == null; attempt++)
{
sender.Send(line, line.Length, new IPEndPoint(IPAddress.Loopback, UdpCommunicationService.ModulePort));
for (int wait = 0; wait < 20 && source == null; wait++) { await Task.Delay(25); source = udp.GetGpsSourceAddress(); }
}
Assert.That(source, Is.EqualTo(IPAddress.Loopback));
}
finally
{
await udp.StopAsync();
udp.Dispose();
}
}

[TestCase(UdpCommunicationService.Gps1Port, GpsSource.Gps1)]
[TestCase(UdpCommunicationService.Gps2Port, GpsSource.Gps2)]
[TestCase(UdpCommunicationService.ModulePort, GpsSource.ModulePort)]
Expand Down Expand Up @@ -78,6 +114,7 @@ public async Task A_sentence_on_a_GPS_port_reaches_the_parser_with_its_source(in
}
Assert.That(seen, Is.True, $"no fix parsed from port {port}");
Assert.That(steer.LastGpsSource, Is.EqualTo(expected));
Assert.That(udp.GetGpsSourceAddress(), Is.EqualTo(IPAddress.Loopback), "where the corrections go back to");
}
finally
{
Expand Down
Loading
Loading