dotnet / iot

This repo includes .NET Core implementations for various IoT boards, chips, displays and PCBs.
MIT License
2.17k stars 583 forks source link

Add GPS (NEO-M8 / NMEA 0183 protocol) #677

Closed krwq closed 1 year ago

krwq commented 5 years ago

I'm currently working on GPS module bindings and just wanted to make sure no one duplicates the work. I already got basic functionality working but there is a lot of clean up left and support for some functionality is missing.

Multiple GPS/navigation devices use NMEA0183 protocol to communicate with the sensor. NEO-M8 supports multiple sentence types:

NMEA supports lots more than that though but will leave it out of scope

ZhangGaoxing commented 5 years ago

Maybe we can abstract a base class in this PR. I have a NEO-6M module. After this PR merge, I can help binding it.

krwq commented 5 years ago

@ZhangGaoxing I suspect the current class might work as is - it doesn't do almost anything except setting line endings on serial port - we might rename it (and folder) if it will work as is. Rest is basically implementation of NMEA0183.

After that is merged I was planning to add more sentences to NMEA0183 (at least all the device is sending by default) - I'm happy if you're willing to test with your device and fix any issues you might find (or perhaps your device might generate more sentences which might be interesting).

stevehayles commented 5 years ago

In the wild I see NMEA0183 being used as a data protocol at much faster rates than the standard of 4800 and also being used over UDP and TCP connections. My own parser originall used a serial port 'readline' approach but I hit major performance problems running on a lower powered device (RPi3) on a 'busy' stream of data.

I have moved to a System.IO.Pipelines based approach working with the underlying serial port stream and then a simple state machine to parse out incoming data. It avoids the allocations, copying and manipulation of the various buffers in the serial port read methods and the StringBuilder allocation in the Readline method.

The 'state machine' parser is much cleaner in my view, is more resilient to corrupt data and well matched to the Pipe approach. I am now working on parsing the data fields as ReadOnlySpan to further avoid allocations. I don't know whether any of this is suitable for this repo.

.NET Core running on things like the Rpi is really cool but I think it's a constant battle to maintain acceptable performance. Ideally, in the longer term, the serial port API would be updated with Memory/Span overloads and/or get wrapped with an IDuplexPipe directly.

krwq commented 5 years ago

@stevehayles I've already got very basic support PR open, feel free to go ahead and modify it or replace since I haven't recently got time to play with it and doesn't seem I will have more anytime soon.

Honestly I don't expect Stream vs Pipe to give that much of a difference in perf but not using Split or copying strings should give quite a boost

stevehayles commented 5 years ago

@krwq I'll take a look, thanks for the response. I'm trying to write some meaningful benchmarks but my early implementation using a Pipe seems very promising and I had (perhaps wrongly) assumed that the various buffer manipulations in SerialPort class were slowing things down and at the very least adding pressure on the GC.

Out of interest how would you feel about a more general parser that used attributes on the message class properties to help map the deserialization of the message ? There would be some overhead on startup as a downside but it would make introducing new message types almost trivial which I think would be a big plus

krwq commented 5 years ago

@stevehayles I have mixed feelings. On one hand the code will likely look cleaner but on the other hand I suspect it will add much more overhead to parsing...

Perhaps we could do something in between where we i.e. describe messages with JSON/XML/whatever and generate code from that in some kind of T4 template. Also unsure because i.e. RMC sentence contains very inconvenient units which I have initially simplified (i.e. magnetic variation instead of being positive value and West/East field separately are one field with a sign) - I suspect this might be more common pattern.

stevehayles commented 5 years ago

@krwq Agreed, I had mixed views as well, which is why I asked. My feeling is that the parser could be simple enough to make it worth while but I hear your reservations. I think it suits my specific use case so I am going to scaffold something up and have a look. If it looks acceptable to you I can work harder on a more suitable PR

On your last point, things like magnetic variation are perfectly acceptable as a float (as long as the sign convention is right) and in fact it's fairly standard in most navigation applications. I would consider NMEA0183 the odd-ball in its representation and in fact in it's big cousin NMEA2000 it's expressed in radians.

I'll take a look over your fork and go from there. Thanks

krwq commented 5 years ago

Thanks! Let me know if you have any questions!

stevehayles commented 5 years ago

@krwq Looking harder at this I think my current implementation is too heavily tied to the Pipe approach and the new SequencerReader class which means I am locked to .netstandard2.1 or netcoreapp3.0 which isn't going to work without a rewrite.

Out of interest will this library stay targetted at .netstandard2.0 / netcoreapp2.0 for the foreseeable future ?

krwq commented 5 years ago

@stevehayles I'd personally bump it to 3.0 since I always use latest bits but we have some people with strong opinion we should make it as low as possible and there are some clear benefits of targeting lower so I'm a bit torn.

Let's do following: can you show some sample code using your approach so that we have a sense of how APIs look like and if we find the approach better than the one not requiring 3.0 then we will consider bumping this? Also some general API shape if not included/clear in the sample (so i.e. only public/protected APIs without implementation)

stevehayles commented 5 years ago

@krwq Having pulled out an example from my in-house version I am no longer sure it's a good fit for this library. You can be a far better judge of that though.

Very early stage commit without documentation, tests or comments is here

https://github.com/stevehayles/iot/tree/nmea-protocol/src/devices/Nmea0183

It's using a stream rather than specifically tied to a SerialPort with the stream being processed by a PipeReader / PipeWriter combined with a SequenceReader. It's the SequenceReader that creates the .NETCore3.0 / .NETStandard2.0 requirement as it's not available as a package for lower API levels (yet ??)

There is a simple state machine that ties actions to various incoming states so the sentence is built 'on the fly'. All processing of the incoming stream is carried out using either the SequenceReader or on Span slices read using the reader. Each action returns a 'NMEAParseState' which is then called with the next sequence.

A specific NMEA sentence is created by inheriting from a base NmeaSentence class which contains various utilities to parse the 'fields' from the sentence. As a simple 'for instance' a sentence might look like this

// see https://gpsd.gitlab.io/gpsd/NMEA.html#_dbt_depth_below_transducer)

[NmeaSentence("DBT")]
public class DBT : NmeaSentence
{
    public DBT(string talkerId, string sentence) : base(talkerId, sentence) { }

    public double DepthFeet { get; private set; }

    public double DepthMetres { get; private set; }

    public double DepthFathoms { get; private set; }

    protected override void OnAppendField(int index, ReadOnlySpan<char> field)
    {
        switch (index)
        {
            case 1:
                DepthFeet = ParseDouble(field);
                break;
            case 3:
                DepthMetres = ParseDouble(field);
                break;
            case 5:
                DepthFathoms = ParseDouble(field);
                break;
        }
    }
}

The OnAppendField method is called with an index and a span and parsed appropriately. The existing implementation in the NEO-M8 branch has a lot more logic in the sentence classes but my preference is to leave these classes very thin as it's hard to cover all scenarios and fairly easy to extend these classes as needed.

The NmeaSentenceAttribute is used to create a compiled delegate factory to instantiate the correct NMEA sentence from within the parser but this could be a switch statement and simply 'new up' the correct sentence.

The final API is currently exposed as an 'IAsyncEnumerable' so calling the parser and returning messages is very simple

        SerialPort sp = new SerialPort(SERIAL_PORT_NAME);
        sp.Open();

        Nmea0183 nmea = new Nmea0183(sp.BaseStream);

        _ = Task.Run(async () =>
        {
            await foreach (var sentence in nmea.Messages())
            {
                switch (sentence)
                {
                    case DBT dbt:
                        Console.WriteLine($"{dbt.TalkerId} {dbt.Sentence} Metres: {dbt.DepthMetres} Feet: {dbt.DepthFeet} Fathoms: {dbt.DepthFathoms}");
                        break;
                }
            }
        });

        await nmea.Start();

Whatever the relevance if this, one question this definitely raises for me is whether any implementation is correctly being though of as a 'device' . This is really a 'protocol' and not neatly tied to a specific device instance and it doesn't quite feel right to me.

Should there be a Protocol namespace ?

Thanks for your help and consideration

krwq commented 5 years ago

@stevehayles if you notice my implementation I've actually split the protocol from the device (NeoM8 is basically opening serial port and uses Nmea0183 library underneath).

From the things you described above it sounds to me like there is a lot of things I can use from your code and reverse.

Nmea0183 implementation I provided takes string as an input and decodes it to a sentence object. Sentence object represent a specific sentence.

The parsing part seems like an implementation detail to me and I don't believe we should tie our API design with the way we parse unless it makes much difference which I don't currently believe it does (at the same time NeoM8 doesn't produce results too fast so didn't have an opportunity to observe).

One thing I could have done better is to create some kind of common class for decoding the sentence (currently it returns just object since the objects seemed different enough to me and I didn't see why they should have a base class since they are not exactly similar but having a common class is good just from the structure point of view).

One thing I like about your design is the awaitable foreach loop which actually makes one of the APIs cleaner than mine (although mine doesn't focus on polling) but as you mentioned we not yet can use it (although this is just a syntax sugar). The attributes part I don't feel strongly either way. I think we should focus on functionality without any attributes first and attributes should simplify the code but we should not write code completely based on the attributes.

The design I currently proposed allows to easily convert sentence object into a sentence string and back because my focus was to be able to communicate both way but I think this is an easy add.

I think one thing we can do is perhaps you should take a look at my implementation first and see the approach I've taken and see how you would adjust it to work with yours. Next step is I'd do the changes, merge my PR and you could use it as a starting point for your stuff (if the API is same this should go rather smooth).

I'd refrain from adding any attributes as a first step - this creates abstraction layer which is hard to automate so I'd do this part separately after we have solid design in place.

shaggygi commented 5 years ago

Not sure if related, but referencing this just in case...

https://github.com/microsoft/referencesource/pull/120/

dotMorten commented 5 years ago

Take a look at https://github.com/dotMorten/NmeaParser

krwq commented 5 years ago

Ok, now we got 3 implementations 😄 @dotMorten do you have any specifc plans? I'm wondering if you're planning to support your package long term or would prefer to join the effort with us? P.S. Sample app is really cool!

dotMorten commented 5 years ago

I have been supporting and maintaining this for years. It should cover your use cases I believe. Just grab the nuget

krwq commented 5 years ago

I'll need to double check if we can depend on packages with different license and if there are any issues with stuff like security fixes before we can add a dependency

krwq commented 5 years ago

Ok asking people around seems it is possibility but it's not the easiest:

I think best thing to do now would be perhaps to create a gps branch where we add new devices depending on this package. For some time we will point people to the source code and eventually we create a package with all those.

@stevehayles @shaggygi @joperezr any thoughts? Should we go with that or add stuff from my PR + what @stevehayles wrote and not have external dependencies?

IMO makes sense to depend on this since this has already been tested by many people and flushed out of most of the bugs

shaggygi commented 5 years ago

I'd say recommend/reference @dotMorten work as he def knows his stuff when it comes to this topic. Bindings can just implement the byte conversions (if needed) between messages and specific binding registers, etc.

joperezr commented 5 years ago

I think best thing to do now would be perhaps to create a gps branch where we add new devices depending on this package.

This won't be super easy either and will be hard to maintain and hard to merge back when ready. My 2 cents on this is that if we can get away without having to add external dependencies that would be ideal, since I believe that the internal process to add a new external reference might take a bit of time. Same goes for the requirement to build a new package and separate the bindings. If we decide to go now with avoiding the external dependency and check in @krwq's code instead and have the binding work on top of that, it is easy in the future to decide to move into adding @dotMorten's package as a dependency. Going the other way around will not be as easy.

krwq commented 5 years ago

What if we added perhaps some kind of abstraction we could share between projects? I'd prefer that we didn't re-implement this.

Also I don't think merging back the branch would be hard. We would work in a separate directory which doesn't touch any existing files until we are ready

stevehayles commented 5 years ago

@krwq I think my approach to this was from a particular requirement to really focus on the performance as I work in an area where NMEA0183 is quite frankly abused as a protocol to carry GPS and IMU data at much faster speeds than it was really designed to do.

As such I think I should remain separate with my solution but I agree with your comment about not re-implementing this. To be honest when I looked at from the perspective of this library it felt 'wrong' to be trying to shoe horn in as a device. It definitely isn't a device and it lead to me the question about whether there are other protocols that are in a similar 'class'. The question then remains if this is the focus of this library or not

krwq commented 5 years ago

@stevehayles I'd recommend following:

also might be worth investigating if in your case SerialPort is not the limiting factor. I.e. by default the baud rate is 9600 which is rather slow if you think about hundreds of reads per second.

stevehayles commented 5 years ago

@krwq I have a fully working NMEA / AIS decoder in production use, my original issue came from trying to run it on an RPi and hitting performance problems. From there it was clear (in my use case) that a re-write of the parser was needed at the same time I noticed you were adding NMEA to this library and potentially it seemed like a good fit.

The code I pushed was a small refactored subset of what I run in-house to show what the API might look like. I think the motives are not as well aligned as I thought so I will step out.

Great work on everything by the way, being able to seriously approach lower level devices from the .NET world is fantastic

krwq commented 4 years ago

I'm thinking, perhaps there is a way to create interface in such a way that we don't need to take dependency but everything is usable.

The idea is following:

interface INmea0183Device
{
    string ReadSentenceString();
}
public static class Nmea0183DeviceExtensions
{
    // this should match the signature in the other repo
    public static object ReadSentence(this INmea0183Device device)
    {
        return DoStuffWithTheSentence(ReadSentenceString());
    }
}

do you think that would be acceptable?

pgrawehr commented 4 years ago

@krwq, @stevehayles @dotMorten Any futher progress/updates on this issue? NMEA Support is actually a central part for my project(s) as well, so I would be interested in a suggested approach/solution to get this integrated.

I have not yet analyzed the proposed solutions in detail, but one important part would be to have an NMEA component that is bi-directional, so it should be able to both read and write to a stream, and it seems there are no existing implementations able to do that.

[Reason: While NMEA is used as a protocol from GPS receivers, it is also used as general message protocol on ships, where different sensors may send different data. For instance, one could use a BNO055 as a compass source to feed heading back to the network or a pressure sensor for weather information. While modern ships use NMEA 2000, most messages are also available in NMEA 0183 and there are affordable converters between the two. While the NMEA 0183 standard is basically open and well documented, the NMEA 2000 reference documentation is $4000 😠 ]

krwq commented 4 years ago

@pgrawehr my prototype in PR allows writing but the device I have doesn't (it only sends data with some constant interval)

pgrawehr commented 4 years ago

@krwq Thanks, I hadn't inspected it that deeply yet. I have set up some infrastructure that should allow me to simulate both receiving and sending data, so I'll try out your PR soon then.

krwq commented 4 years ago

@pgrawehr note the support is super limited and the NMEA sentences are relatively simple... what kind of device do you have?

pgrawehr commented 4 years ago

Well, the device that I have is a sailboat 😄

Or at least, that's what I want to use it with. The existing (quite new) electronics installation includes some sensors (wind, speed trough water, GPS) and a simple display. It has a bi-directional NMEA 0183 interface where I want to connect the Pi to. On the Pi, I can run navigation software (just evaluating the possibilities) and have additional sensors (i.e I've got a small IMU, some extra environmental sensors, etc). The software shall feed information back to the ship's bus, where the display can make use of the extra information (i.e. heading vs track to compute drift and currents, or bearing to waypoint as help for steering). Of course, all of this could be bought somehow, but that wouldn't be much fun and it would be really expensive.

Of course, I can't take my boat into my office, so for now I'm only having a setup with simulated NMEA data, and I'm still investigating on the exact data flow there (the software packages I've evaluated so far are also not really free of flaws yet).

It looks like one will generally have an NMEA server, offering the data stream over UDP or TCP, where clients can connect to and also send data back, and that's then distributed to other applications or to physical RS-232 ports. There are meanwhile even hardware solutions that provide such a server and directly connect to the ship's bus (i.e. https://www.yachtd.com/products/ethernet_gateway.html). Older devices, like the one I have, convert to RS-232, but the server can run on the Pi as well, so technically, that's very similar - A bi-directional interface to sensors and displays.

Ellerbach commented 4 years ago

I just found this discussion open for quite some time. I've been using https://github.com/dotMorten/NmeaParser for NMEA parsing with various kind of GPS. It's just working great. It parses almost anything, works over serial port or just with a Stream and couple of other options. I've seen as well an associated PR #679 for quite some time now. I was just wondering if it would make sense to recommend to use the NmeaParser or if this effort to provide a NMEA parser in this .NET Core IoT repo is something that needs to be continued?

dotMorten commented 4 years ago

Thanks. I've lately been adding a GPS aggregator as well that helps with combining many messages, and different talker IDs like GPS, Galileo, Glonass and Beidou, as it's not that trivial to do. I've been doing that because I've been realizing having a NMEA parser is far from enough but you really need to interpret and combine the messages as well

pgrawehr commented 4 years ago

I have a working version ready (see https://github.com/pgrawehr/iot/tree/PublishWithOldVersion2/src/devices/Nmea0183), also with some message routing and interpretation features. It's been running as a message server on my ship for 3 months now, with almost no known issues.

The only reason I haven't created a PR yet is that they're not being reviewed right now. PRs that just lie around help no one.

maximpn commented 4 years ago

Are there any news about the NMEA protocol integration? I'd like to know what is the plan? Use the MR proposed above or integrate the mentioned above library.

Ellerbach commented 4 years ago

@mpalenov , I'm more in favor of using the external existing implementation as it is much more complete and supports a lot of protocoles, and super easy to integrate with any of our device. So something similar as for UnitsNet. Now, I would love to ear as well @krwq , @joperezr and @richlander points of view.

pgrawehr commented 4 years ago

As stated above, I've got a working and quite complete version of @krwq s solution running for quite some time. It needs more documentation still, but I could present it later. Not the most pressing problem right now, IMHO.

If I find time, I'll also have a look at the other implementations, but from what I saw so far, they're all lacking important features (I.e some can only parse, not write, or only from serial ports, not arbitrary streams)

dotMorten commented 4 years ago

@pgrawehr what's your scenario for writing? NmeaParser does all the other things and properly handles all the different satellite systems which you must be able to with multi band receivers that is standard today (the NEO-M8 mentioned here does GPS, Galileo, GLONASS and BeiDou so each location message is sent 4 times and an additional combined one, but not for all messages)

pgrawehr commented 4 years ago

@dotMorten : The Nmea receivers I have worked with so far are also multi-band, but I haven't seen one with extra position messages (just the combined one). Do you have a message stream snippet, so I can see how this looks like?

I have two NMEA0183 input streams, one from a GPS receiver, the other from an NMEA2000-to-0183 bridge with attached wind and depth sensors, AIS receiver and data displays. I also have three NMEA0183 output streams, one to the autopilot, one back to the bridge and one to a local network server socket, to which OpenCpn connects. And I have several other sensors attached, namely a BMP680 sensor and an IMU. I'm now parsing each input stream and send the data to the relevant other streams (ie. the GPS data or the temperature to the NMEA2000 bridge, the wind data to the autopilot, etc.). So I have a message routing system in place that parses messages and forwards them (according to rules). Other messages are built directly in software, like the attitude messages, as they originate from the Pi.

This may look like this (sending HDM and HDT sentences from IMU data):

HeadingMagnetic mag = new HeadingMagnetic(value.X);
_router.SendSentence(mag);

if (_magneticVariation != null)
{
    HeadingTrue hdt = new HeadingTrue(value.X + _magneticVariation.Value.Degrees);
    _router.SendSentence(hdt);
}
krwq commented 4 years ago

I think we should write down all trade-offs of using external package vs integrating our own. If external is complete I'm more in favor using external to not compete with other open source projects for no reason. If there is large gap then we should consider contributing to the external project before we create our own implementation. If there are good reasons to not use external we could potentially have implementation here (I haven't done enough investigation to know what I prefer yet).

dotMorten commented 4 years ago

@pgrawehr It does appear that my GPS device is a bit misconfigured. According to the spec you shouldn't get GLRMC or GPRMC when there's a GNRMC:

image

pgrawehr commented 4 years ago

I think we have two implementations available which have both their advantages and disadvantages. Would be best to combine the advantages somehow. I'll try to later write down a comparison table (or maybe rather a feature table).

pgrawehr commented 4 years ago

Feature wish list / comparison chart

To be extended / completed...

-------------------------------------------------------------------------------------------------------
| Feature                                            | dotMorten/NmeaParser           | Own solution [prototype](https://github.com/pgrawehr/iot/tree/PublishWithOldVersion2/src/devices/Nmea0183) |
-------------------------------------------------------------------------------------------------------
| Basic message parsing                              | (/)                            | (/)
| Messages supported already                         | BOD, DTM, GBS, GGA, GLL,       | BOD, BWC, DBS, GGA, GLL, HDG, HDT, HDM, MDA, MWV  
|                                                    | GNS, GRS, GSA, GST, GSV, RMA,  | RMC, RMB, RPM, RTE, VTG, VHW, WPT, XTE, ZDA
|                                                    | RMB, RMC, RTE, VLW, VTG, ZDA
| Non-standard messages supported                    | PGRME, PGRMZ, PLTIT, PTNLA,
|                                                    | PTNLB
| Extensibility                                      | Yes, attribute                 | Yes, registration method
| Unknown messages supported                         | ?                              | (/)
| Message construction (for outgoing msgs)           | (x)                            | (/)
| Input sources                                      | Stream (serial, network)       | Stream (serial, network)
| Nmea server socket                                 | ?                              | (/)
| Message routing (from one client to another)       | (x)                            | (/)
| Extra features                                     | ?                              | Message filter, Auto pilot control, Logging, Sentence Cache, Geoid calculations (distance, direction)

@dotMorten : Please extend (and please disregard/correct my POV).

PS: Just looking at the supported messages, it seems quite obvious that the two solutions where developed with different applications in mind.

dotMorten commented 4 years ago

This is starting to feel a little bit like a pissing contest, but in any case you missed some stuff for NmeaParser Messages missed: RMA, RMB, RMC, RTE, VLW, VTG, ZDA (and very simple to add more, and I'll gladly add more as people request them). Version support: Verified up to 4.11 (there are some important additions around signals ids in 4.11 that'll make a lot of parsers misinterpret things - especially GSV and GSA) Extra features:

Just looking at the supported messages, it seems quite obvious that the two solutions where developed with different applications in mind.

Considering you skipped all the basic messages in that comparison (and 3 of the ones you support that NmeaParser doesn't are deprecated), not sure that's a fair estimate. Features like "message filter, Auto pilot control, Logging, Sentence Cache, Geoid calculations (distance, direction)" isn't in a nmea library, because it's not really nmea related, but would be easy to add, and there are already libraries out there that does a good job on many of those.

If anything, your post seems to only argue that there shouldn't be an out-of-the-box NMEA library, but people should just use the one that fits their needs the best.

Ellerbach commented 4 years ago

@pgrawehr and @dotMorten, I'd like to understand how to best leverage both of your efforts which are complementary and sometimes overlapping. Some of the questions may looks like but:

I feel Issues on GitHub are sometimes limited to have a deep discussion and in interactive way. Happy to setup a call or anything more real time discussion with some audio and video to try to understand what can be done. And I'm very open to have 2 different elements sitting on different repos if they are really serving 2 different purposes. I'm as well a huge fan of adding where it makes sense and joining efforts. My email: laurelle@microsoft.com, my discord: Ellerbach#6489 Please don't hesitate both of you to reach out and we'll find a convenient time/moment to go thru all this and see what can be the result.

If a discussion in a more dynamic an non issue way will happen, of course, for the full transparency, the ley outcomes will be shared here.

pgrawehr commented 4 years ago

@Ellerbach : Yea, I'm absolutelly open to this, and it's probably the best way forward to really do this in a live talk. I'm currently still travelling and have usually poor internet connectivity, so I suggest we do this after I get back home (about two weeks from now). @dotMorten : Sorry, I didn't intentionally skip these messages, I was just being blind while looking at the code files. I also agree that whether the additional features belong to the NMEA library itself may be questioned.

Ellerbach commented 4 years ago

I'm currently still travelling and have usually poor internet connectivity, so I suggest we do this after I get back home (about two weeks from now).

@pgrawehr, any time you'll be ready, just reach out :-)

dotMorten commented 4 years ago

Sure I'll be happy to talk, but I want to be clear: I build NmeaParser for myself, and it has the features I need., and if others find them useful that's just awesome sauce on the side This way I ensure it's being dogfooded and doesn't contain a bunch of features I never use/test, or features I don't fully understand but now have to maintain. In my many years of open source, my most successful and popular repos has been the ones where I did exactly that. The NMEA parser has almost 20 years of history in it, evolving many times, and based on many lessons learned over the years. It should be easy to build any sort of extension on top of this library, like auto pilot etc.

But in the end I don't really see how any of this matters in this discussion. My impression here is that the discussion is whether there should be built-in NMEA support, or whether to use an external library. The more external libraries the better, but that's really a separate discussion from whether NMEA should be in-box or not. My vote is definitely for relying on external libraries rather than duplicating effort, and letting people choose which one fits their needs the best.

pgrawehr commented 4 years ago

Well, I think if we go with recommending an external lib (or several), we should still have an understanding of what each one can deliver and maybe provide example integrations.

maximpn commented 4 years ago

I agree that for IoT project users it doesn't significantly matter if use the in-box functionality or some external library and it would be great to have a recommended library/libraries description with some examples since it will significantly reduce the time required to set up a project on top of this.

Ellerbach commented 4 years ago

It should be easy to build any sort of extension on top of this library, like auto pilot etc.

Reason 1 to talk :-)

Well, I think if we go with recommending an external lib (or several), we should still have an understanding of what each one can deliver and maybe provide example integrations.

Reason 2 to talk :-)

My impression here is that the discussion is whether there should be built-in NMEA support, or whether to use an external library

Reason 3 to talk :-) And we're already using external libraries when it makes sense like UnitsNet for example.