Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

question: is it possible to only get data from one GNSS device on an N2K network? #426

Open
caspartfg opened this issue Sep 4, 2024 · 5 comments

Comments

@caspartfg
Copy link

Sorry if this is a dumb question.

First, the library is awesome has been absolutely brilliant for me building applications on our boat. -THAKNK YOU-
There is one minor problem I come up against and I've not been able to find the solution.

We have multiple GPS devices on our N2K network that write to the GNSS PGN (AIS, 2 x Chart Plotters, Starlink). Their antenna are in different places on the boat, (up to 7 meters away from each other). This means I can see my fix jumping around.

My question, how would I filter PGN responses by device ID so I can use just the one source? I'm using this function from the DataDisplay example:

(ParseN2kGNSS(N2kMsg,SID,DaysSince1970,SecondsSinceMidnight,
lat,lon,Altitude,
GNSStype,GNSSmethod,
nSatellites,HDOP,PDOP,GeoidalSeparation,
nReferenceStations,ReferenceStationType,ReferenceSationID,
AgeOfCorrection) )

I couldn't see how to link this back to a device name or other UUID?
I've looked for other functions too, but couldn't see the option there either.

FYI - in SignalK I can see the data split by device, so i'm assuming there is something in there somewhere I can use, so I suspect it's user error on my part.

Thanks so much in advance

Casp.

@ttlappalainen
Copy link
Owner

You need to use tN2kDeviceList. It tracks devices on the bus so that you can request source address with NAME, id:s or product from it. Normally source is static soon after start and stays same, if you do not add new devices. To check if there has been changes for sources, you can use tN2kDeviceList::ReadResetIsListUpdated. If that returns true, you need to check your interest device source from tN2kDeviceList. There is example DeviceAnalyzer how to use tN2kDeviceList.

@caspartfg
Copy link
Author

Thank you so much - I really appreciate it and will take a look now!...

@caspartfg
Copy link
Author

Timo, sorry, I know this isn't user support, but I can't figure out how I get from using the output of tN2kDeviceList through to applying some sort of NAME filter when getting my PGNs: NMEA2000.SetMsgHandler(HandleNMEA2000Msg). Again, apologies, i'm not a particularly strong developer. I've read through the documentation, but if you could point me in the right direction as I may have missed something. Again, thank you so much for your help and advice. I'll keep hacking away at this... Casp.

@ttlappalainen
Copy link
Owner

It is easy - at least for programmer who has designed the code.

tN2kDeviceList collects automatically list of all devices on the bus. Since it uses requests to get device information, it does it fast - you have full list of devices in few seconds after device has started.

// We need some mode variables
tN2kDeviceList *pN2kDeviceList;
uint8_t GPSSource=254;  // use at beginning null address
uint16_t MyGPSManufacturerCode=229; // You need to find your GPS manufacturer code. Here Garmin code.
uint16_t MyGPSUniqueID=7777; // You need to find your GPS unique ID e.g., by using mu NMEA Simulator

void HandleNMEA2000Msg(const tN2kMsg &N2kMsg);

// Setup as  normally + add device list
void setup() {
...
  NMEA2000.SetMsgHandler(HandleNMEA2000Msg);
  pN2kDeviceList = new tN2kDeviceList(&NMEA2000);
...
}

void HandleDevicesChanges() {
  if ( pN2kDeviceList->ReadResetIsListUpdated() ) {
    // Search source with manufacturer code and unique number. If we are strict this  does not define unique
    // device since same manufacturer may have both GPS and e.g., termperature sensor with same MyGPSUniqueID.
    // In real world it would be winning the lottery to have that case in single boat.
    // The strict search would be to usedevice NMEA2000 NAME and FindDeviceByName
    // see https://ttlappalainen.github.io/NMEA2000/md_7_glossary.html
    const tNMEA2000::tDevice *GPS=pN2kDeviceList->FindDeviceByIDs(MyGPSManufacturerCode,MyGPSUniqueID);
    if ( GPS!=0 ) {
      GPSSource=GPS->GetSource()
    } else {
      GPSSource=254; // We use null address in case device does not exist any more.
    }
  }
}

void HandleGNSS(const tN2kMsg &N2kMsg) {
  if ( N2kMsg.Source==GPSSource ) {
    // Do what you like with filtered message.
    ...
  }
}

void HandleNMEA2000Msg(const tN2kMsg &N2kMsg) {
  // You can handle message as you like. See also DataDisplay2.ino method
  switch ( N2kMsg.PGN ) {
    case 129029L: //GNSS
      HandleGNSS(N2kMsg);
      break;  
  }
}

void loop() {
  NMEA2000.ParseMessages();
  HandleDevicesChanges();
  ...
}

I remind again that you must keep you loop and handlers fast and non blocking to avoid problems with loss off messages or delayed responces see https://ttlappalainen.github.io/NMEA2000/pg_lib_ref.html#descRunningLibrary.

Code above does not handle any spare GPS. For that you have to add variables for all GPS, currentGPS and also save time for received GPS messages. Then if currentGPS has not received message within timeout, you switch currentGPS to next in priority which messagesa has been received within timeout.

@caspartfg
Copy link
Author

caspartfg commented Sep 5, 2024 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants