NMEA2000 icon indicating copy to clipboard operation
NMEA2000 copied to clipboard

Parser PGN129794 Callsign

Open ronzeiller opened this issue 5 years ago • 9 comments

Hi Timo,

have here:

uint32_t _UserID;  // MMSI
uint32_t _IMONumber;
char _Callsign[7];
uint8_t _VesselType;
char _Name[20];

if ( ParseN2kPGN129794(N2kMsg, _MessageID, _Repeat, _UserID, _IMONumber, _Callsign, _Name, _VesselType,  _Length, _Beam, _PosRefStbd, _PosRefBow, _ETAdate, _ETAtime, _Draught, _Destination, _AISversion, _GNSStype, _DTE, _AISinfo) ) {

Serial.print("_IMONumber: "); Serial.println(_IMONumber);
Serial.print("_Callsign: "); Serial.println(_Callsign);
Serial.print("_VesselType: "); Serial.println(_VesselType);
Serial.print("_Name: "); Serial.println(_Name);

// some other stuff
}

for some Callsigns I get "strange" chars from Parser. Here some examples:

UserID: 238613210 _IMONumber: 4294967295 _Callsign: 9A4838 ⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮ _VesselType: 30 _Name: NAPREDAK ZADAR


_Repeat: 0 _UserID: 235111527 _IMONumber: 1004340 _Callsign: 2IOS7 ⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮ _VesselType: 37 _Name: MARO SUKOSAN
_Destination: SUKOSAN

Found these in Callsigns only, not in Vessel Names or Destination Those boats always come with the same value in Callsign. For conversion into AIS those chars get filtered out and will cause no problem. Just wondering from where they could come.....

ronzeiller avatar Nov 09 '19 22:11 ronzeiller

declaring

char _Callsign[8];
char _Name[21];

seems to do it! forgot the space for termination......

ronzeiller avatar Nov 10 '19 13:11 ronzeiller

I am not sure is is good to define parameters like char _Callsign[8]; Other option is to use char *buf, size_t bufLen.

These messages are also type, where class would work better. I have sample for some class with lots of parameters. It is easier to use, since you can set any field or read just one field. Function way with long parameter list gets ugly.

ttlappalainen avatar Nov 10 '19 19:11 ttlappalainen

Yes, agree, for sure. At the beginning the whole thing was more or less a proof of principle, but it is growing now :-) Added an AISMsg Class for that, also doing conversions from N2k enum types etc.. May be we end up with (an overloaded or somehow else made) N2kParser which just gets tAISMsg &AISMsg as parameter some day? But let´s see....

ronzeiller avatar Nov 11 '19 12:11 ronzeiller

It is sometimes so that you have to write code twice. First you make it working and to get understand whole problematic. Then clean it up in nice way.

Attached is sample I wrote as an example. Strings are still problematic, since you need local variable, where you copy content, when you request it first time. Then you can return const char * to that local variable. With this method some things gets easier specially with messages having lot of often unnecessary fields.

N2kMsgClasses.zip

ttlappalainen avatar Nov 11 '19 16:11 ttlappalainen

The whole AIS library I wrote is based on two std::string with a lot´s of std::bitset<30>(iTemp).to_string() conversions because it is a little bit tricky with 6bit.

When the whole string is put together it is converted into special AIS-Ascii and this payload is handed over as c_str() to your NMEA0183 machine. I have two strings, one for the binary and one for the decoded part. If I could sendMessage directly from the AIS-Converter, or if I could return more than one NMEA0183 Message at once (see https://github.com/ttlappalainen/NMEA2000/issues/154#issuecomment-552433934), I could use the binary string for the ascii decoded as well to save storage without any new allocation. Another solution could be, that the Payload is part of tAISMsg class which is handed over as reference. I do not see, why string should be problematic?

ronzeiller avatar Nov 11 '19 17:11 ronzeiller

I do not see problems to use string, if you have enough memory. String is dynamic class and will be created to heap. When you do not need it anymore, it will be deleted from heap. The problem may come, when you continuously create and delete those and may have some other bigger blocks created/deleted on heap. Memory can fragment and run over. So here enough memory is important. When heap has space to fragment, then finally on some time it will clean up again, when parts has been released. Naturally this is also small performance problem, due to reservation and release of memory.

ttlappalainen avatar Nov 11 '19 19:11 ttlappalainen

If this AIS is used, than in some kind of "Actisense Reader and Sender" . What happens if there will be a global string defined for AIS only, e.g. with str.reserve(500) Would that solve the fragmentation problem?

ronzeiller avatar Nov 11 '19 22:11 ronzeiller

Should help, but can not be sure. According documentation it should keep its capacity as soon as you do not change it by some other function.

The problem with global allocation is that then it eats always that memory. That is reason why I use just plain char buffers for known handling. If you define char[500] inside you function, it allocates it fast from stack and when function ends, stack will be freed - no heap allocation at all. So when this kind of converter handling will be done in series, there is no problem with stack either.

Strings are nice and easy. But when you e.g. do StrA=StrB, First StrA old capacity may be freed and new capacity allocated from heap and finally data will be copied. As in your converter you know pretty well all data so it should be easy to use just char buffers.

Programming these small things requires bit thinking. Memory and speed are not unlimited like on PC. On the other hand PC "unlimited" resources teaches programmers not to think memory or speed at all.

ttlappalainen avatar Nov 12 '19 05:11 ttlappalainen

You are right. And bit counting in char is somehow funny too :-) Started with it and it´s nice.

ronzeiller avatar Nov 13 '19 22:11 ronzeiller