Select to view content in your preferred language

GPS Logging

368
4
07-25-2022 02:37 PM
pshearon
New Contributor II

How can I log NMEA messages coming from a NmeaLocationDataSource?

public event EventHandler<Location>? LocationChanged; <--- this gives a location object, but not the raw messages  that lead to that point. What are the chances of getting those in an event? Or some other way?

 

Regards,

Patrick Shearon

0 Kudos
4 Replies
dotMorten_esri
Esri Notable Contributor

There's no out-of-the-box support for this today (it's on our backlog). However, you could intercept the NMEA stream with a stream interceptor class. For example:

public class StreamInterceptor : Stream
{
    private readonly Stream _baseStream;

    public StreamInterceptor(Stream baseStream)
    {
        _baseStream = baseStream;
    }

    public event EventHandler<string>? OnData;

    public override int Read(byte[] buffer, int offset, int count)
    {
        int read = _baseStream.Read(buffer, offset, count);
        if (read > 0)
        {
            OnData?.Invoke(this, Encoding.UTF8.GetString(buffer, 0, read));
        }
        return read;
    }

    public override bool CanRead => _baseStream.CanRead;

    public override bool CanSeek => _baseStream.CanSeek;

    public override bool CanWrite => _baseStream.CanWrite;

    public override long Length => _baseStream.Length;

    public override long Position { get => _baseStream.Position; set => _baseStream.Position = value; }

    public override void Flush() => _baseStream.Flush();

    public override long Seek(long offset, SeekOrigin origin) => _baseStream.Seek(offset, origin);

    public override void SetLength(long value) => _baseStream.SetLength(value);

    public override void Write(byte[] buffer, int offset, int count) => _baseStream.Write(buffer, offset, count);
}

 

Then you could create the nmea datasource using this new stream type and listen to the OnData event:

SerialPort p = new SerialPort("COM3");
NmeaLocationDataSource ds = NmeaLocationDataSource.FromStreamCreator(
    onStart: (ds) =>
    {
        p.Open();
        var sl = new StreamInterceptor(p.BaseStream);
        sl.OnData += (s, nmeaString) =>
        {
            Console.Write(nmeaString); // NMEA raw data string
        };
        return Task.FromResult<System.IO.Stream>(sl);
    },
    onStop: (ds) =>
    {
        p.Close();
        return Task.CompletedTask;
    }
    );

ds.StartAsync();

 

0 Kudos
pshearon
New Contributor II

What would you recommend for FromBluetooth devices?

0 Kudos
dotMorten_esri
Esri Notable Contributor

If you're using .NET 6, you don't actually need to use the bluetooth version, but can still use them as a serial port (Windows will assign them port numbers). But otherwise, you'd have to grab the bluetooth data stream yourself before using the above.

0 Kudos
pshearon
New Contributor II

Thanks a lot, your insight has been very helpful. Since it's all on windows (.NET 6) I will be going with System.IO.Ports.SerialPort and that StreamInterceptor.  All of my tests worked with your suggestions!

Regards,

Patrick Shearon

0 Kudos