ttlappalainen / NMEA0183

Library for handling NMEA0183 messages
73 stars 47 forks source link

Parse RTE without std lib + additional example to print GPS output #6

Closed tonswieb closed 6 years ago

ttlappalainen commented 6 years ago

Are you sure that noone has used the other version. This is not anymore backward compatible.

tonswieb commented 6 years ago

What do you mean with "noone"? Which version?

ttlappalainen commented 6 years ago

I meant has anyone used previous version. I checked it probably too quickly. push_back was commented out, so it had not worked. I were just worried about compatibility. It is annoying, hwn libraries will be updated so that compatibility changes. Ofthen this can be solved by publishing new method and making old as deprecated and causein compiler warning to change to new method.

ttlappalainen commented 6 years ago

Hi,

Instead of having e.g. RTE with defined sizes you could chnage it to:

 struct tRTEBase {
    //'c' = complete route list, 'w' = first listed waypoint is start of current leg
    char type;
    unsigned int routeID;
        size_t MaxWpInRTE;
        size_t MaxWpLength;
    char **wp;
    unsigned int nrOfwp;
       tRTEBase(char **buffer, size_t _MaxWpInRTE,  size_t _MaxWpLength) : 
          wp(buffer), MaxWpInRTE(_MaxWpInRTE), MaxWpLength(_MaxWpLength) {}
 };

Then use tRTEBase in functions. Also define:

template <size_t MAX_WP, size_t MAX_LENGTH>
class tStaticRTE : public tRTEBase {
 public:
  tStaticRTE () : tRTEBase (_buffer, MAX_WP, MAX_LENGTH) {
  }

 private:
  unsigned char _buffer[MAX_WP][MAX_LENGTH];
};

Then you can use it on code: tStaticRTE<20,32> RTE; Also you can put to your own code: using tRTE=tStaticRTE<20,32>; So you can just use: tRTE RTE;

The problem with defines on Arduino IDE is that you can not set them on your code. Arduino IDE allways uses defines on the library and the thely way to chnage sizez is to modify library.

tonswieb commented 6 years ago

Ok. Thanks. Good to know. Didn't know it is an Arduino restriction.

I tried your suggestion, but run into the following error: libraries/NMEA0183/NMEA0183Messages.h: In instantiation of 'tStaticRTE<MAX_WP, MAX_LENGTH>::tStaticRTE() [with unsigned int MAX_WP = 20u; unsigned int MAX_LENGTH = 32u]': sketch/NMEA0183Gateway.cpp:376:8: required from here NMEA0183/NMEA0183Messages.h:62:56: error: no matching function for call to 'tRTEBase::tRTEBase(char [20][32], unsigned int, unsigned int)' tStaticRTE () : tRTEBase (_buffer, MAX_WP, MAX_LENGTH) { ^ NMEA0183/NMEA0183Messages.h:62:56: note: candidates are: NMEA0183/NMEA0183Messages.h:55:8: note: tRTEBase::tRTEBase(char**, size_t, size_t) tRTEBase(char **buffer, size_t _MaxWpInRTE, size_t _MaxWpLength) : ^ NMEA0183/NMEA0183Messages.h:55:8: note: no known conversion for argument 1 from 'char [20][32]' to 'char**' NMEA0183/NMEA0183Messages.h:44:8: note: constexpr tRTEBase::tRTEBase(const tRTEBase&) struct tRTEBase { ^ NMEA0183/NMEA0183Messages.h:44:8: note: candidate expects 1 argument, 3 provided NMEA0183/NMEA0183Messages.h:44:8: note: constexpr tRTEBase::tRTEBase(tRTEBase&&) NMEA0183/NMEA0183Messages.h:44:8: note: candidate expects 1 argument, 3 provided exit status 1 Error compiling for board Arduino/Genuino Mega or Mega 2560.

Any ideas how to resolve this?

For a memory management perspective I guess it might be even better to not use the 2D-array and the defines. Instead store the raw RTE content in a char[80] in tRTE and let the calling application determine the max. number of waypoints and waypoint length it wants to support.

ttlappalainen commented 6 years ago

I just wrote the sample quickly. Could it be that I have defined on template unsigned char _buffer[MAX_WP][MAX_LENGTH]; but on tRTEBase char **wp;? So it should have either char or unsigned char in every place.

You could also have them in one dimensional buffer and put the strings each after each with null separator as I have on splitted message to fields. The final terminator is 0, so there must be extra 0 after last string.

The simplest way would be just copy the whole message inside RTE class and have [] operator for waypoints. Then you can simply handle them on your code e.g. with std:list, if you have room in code memory.

The better solution would be to make it a bit clever class, which grows itself, so it could catch whole RTE instead of just one single message points. One problem is that if you provide RTE, which has been started and then routeID does not match - you should then just return false. So actually you need a list of RTE:s. So I think that this leads that you have to write simple way for main interface and then make a RTEList class, which is on own module. That can then use e.g. std::list, since it will not be linked if it is not used. Or what you think?

tonswieb commented 6 years ago

I understand, no problem. Using either unsigned char or char did not change anything. So I finally gave up and implemented using the 1D array and add [] operator to tRTE struct. That turns out to work perfectly.

Combining the RTE's into a list was already handled in its own module which in turn calls NMEA0183. The complete RTE list can take up quite some memory, so I don't think it is good idea to have it in the NMEA0183 module.

The calling library which combines the RTE into a list can be found here: https://github.com/tonswieb/NMEAGateway I did not sync it yet with the latest commits in the NMEA0138. I used to use std::list, but when using it as a global var it turns out it leaks memory and letting the GPS switch routes often will be OOM the Arduino. So I ended up using a fixed 2D array for the waypoint names.

ttlappalainen commented 6 years ago

Yes, complete RTE on this module would destroy to use module on small processors.

Could you add separator line //***** and comment for RTE how to use it. It is not probaply clear for novice that this RTE contains only one message and full RTE requires detecting header information (RouteID, current sentence, total sentences). You could put your code link to the comment as example.

tonswieb commented 6 years ago

Added line separator and some additional comment in the header.