NMEA0183 - Signal K parser

296 views
Skip to first unread message

Fabian Tollenaar

unread,
Apr 7, 2014, 7:38:53 PM4/7/14
to sig...@googlegroups.com
I've written a basic parser module based of jamesp/node-nmea (that is, I've used his codecs and helper functions). 

The Parser interface is implemented as a Transform stream (http://nodejs.org/api/stream.html#stream_class_stream_transform), 
which makes it very easy to pipe in a file stream, or a TCP stream, or a serial stream, or any other type of stream for that matter. 
The parser comes with a binary executable allowing you to do something like cat gps.nmea | nmea-signalk 

ATM I'm finishing up converting some of the original node-nmea codecs to output Signal K, and adding tests. 
As soon as that's done, I'll put the code on github. 

As with node-nmea, at the moment the number of NMEA 0183 sentences it can decode is relatively small, but it's very easy to add extra codecs. 
After initial release, I aim to improve the codec format, and clean up the code a bit more. 

I'll post updates in this thread. 

Teppo Kurki

unread,
Apr 8, 2014, 1:21:52 AM4/8/14
to sig...@googlegroups.com


tiistai 8. huhtikuuta 2014 Fabian Tollenaar <fab...@starting-point.nl> kirjoitti:

ATM I'm finishing up converting some of the original node-nmea codecs to output Signal K, and adding tests. 
As soon as that's done, I'll put the code on github. 


Great!  I'll switch Navgauge to use it once you have it available. 



Fabian Tollenaar | Starting Point

unread,
Apr 8, 2014, 11:13:54 AM4/8/14
to sig...@googlegroups.com
Guys, 

In an RMC message there is a field “magnetic variation”. Where should I put that in Signal K? 


--
You received this message because you are subscribed to the Google Groups "Signal K" group.
To unsubscribe from this group and stop receiving emails from it, send an email to signalk+u...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Fabian Tollenaar | Starting Point

unread,
Apr 8, 2014, 11:51:56 AM4/8/14
to sig...@googlegroups.com
Example output of a navigation child object after parsing an RMC sentence:

{
    "courseOverGroundTrue”: {
        "source":"self”,
        "timestamp":"2014-05-03T09:13:42.000Z”,
        "value”:269.52
    },

    "location”: {
        "latitude”: {
            "value":52.223141,
            "source":"self”,
            "timestamp":"2014-05-03T09:13:42.000Z”
        },
        "longitude”:{
            "value":4.545838,
            "source":"self”,
            "timestamp":"2014-05-03T09:13:42.000Z”
        }
    },
    
    "speedOverGround”: {
        "source":"self”,
        "timestamp":"2014-05-03T09:13:42.000Z”,
        "value”:0.47
    },

    "state”: {   
        "source":"self”,
        "timestamp":"2014-05-03T09:13:42.000Z”,
        "value":”valid”

Kees Verruijt

unread,
Apr 8, 2014, 11:59:35 AM4/8/14
to sig...@googlegroups.com
With the location, as it is relevant to that position.

Teppo Kurki

unread,
Apr 8, 2014, 1:08:30 PM4/8/14
to sig...@googlegroups.com
State (I assume you mean Status field from RMC) doesn't make any sense. Lots of 0183 messages have the validity fields. I think SignalK should ignore invalid messages. The only other option I see is that each RMC-derived value has validity flag, or if the default is that data is valid a flag indicating that the data is invalid.



Other stuff:
(A) I would like to see more info in the source. With multiple (0183) sources I want to know where the data is coming from, in my case for example /dev/plotter and /dev/vhf (USB adapters named by udev). 

(B) How do we deal with multiple concurrent values from multiple sources for the same piece of information in the tree? Example is Vessel Heading in N2K feed from Freya at 

One option is that the leaf value is either {value:...} or [{value:...},{value:,,,}], but it makes things iffy.

Also the same information is coming in different 0183 sentences with possibly different update rates. Should they be separate or the same? Include the sentence in the data item? For N2K each source has an id, which should be there.

(C) Longitude and latitude as different, unrelated values doesn't make any sense in electronic navigation, or can somebody name a relevant source that produces discrete values for these? I would prefer GeoJSON "coordinates": [125.6, 10.1] notation (optional elevation not really relevant I guess), crs is WGS84 unless specified as in GeoJSON


Tim Mathews

unread,
Apr 8, 2014, 1:49:47 PM4/8/14
to sig...@googlegroups.com
On Tue, Apr 8, 2014 at 1:08 PM, Teppo Kurki <t...@iki.fi> wrote:
State (I assume you mean Status field from RMC) doesn't make any sense. Lots of 0183 messages have the validity fields. I think SignalK should ignore invalid messages. The only other option I see is that each RMC-derived value has validity flag, or if the default is that data is valid a flag indicating that the data is invalid.

I agree, we shouldn't include validity flags in the model. However, SignalK conformant servers should log them somewhere and send an alarm message if some threshold is crossed (e.g. 15 invalid depth readings in a row or x number in the last minute or something). However, this is an implementation detail and not a data model issue. My vote is drop them from the model.
 
Other stuff:
(A) I would like to see more info in the source. With multiple (0183) sources I want to know where the data is coming from, in my case for example /dev/plotter and /dev/vhf (USB adapters named by udev).

I think that implies some sort of way to configure a "friendly" name in the server, no? I assume you'd rather see "Cockpit Plotter" or "Nav Station Plotter" as the source rather than /dev/plotter1 or /dev/plotter2?

(B) How do we deal with multiple concurrent values from multiple sources for the same piece of information in the tree? Example is Vessel Heading in N2K feed from Freya at 

One option is that the leaf value is either {value:...} or [{value:...},{value:,,,}], but it makes things iffy.

Do you want to be able to display both on the client? Or just one? If just one, Kees has mentioned some "mapping" that he has done to tell his server which sources' values should be transmitted. Personally, I don't want to see more than one instance of any value, it would be distracting. I would however like to be able to specify a precedence, e.g. for GPS coordinates: "1. GPS receiver on stern rail, 2. Autopilot GPS receiver, 3. GPS from masthead".

Also the same information is coming in different 0183 sentences with possibly different update rates. Should they be separate or the same? Include the sentence in the data item? For N2K each source has an id, which should be there.

In the case of the same info coming from the same device at different rates like "Position Rapid Update" and "GNSS Position Data", they should all be the same data item.

(C) Longitude and latitude as different, unrelated values doesn't make any sense in electronic navigation, or can somebody name a relevant source that produces discrete values for these? I would prefer GeoJSON "coordinates": [125.6, 10.1] notation (optional elevation not really relevant I guess), crs is WGS84 unless specified as in GeoJSON

I think they're always together, and if having them already in GeoJSON is useful for plotting, then I say go for it. However, I wouldn't discount elevation altogether, it exists as 'Altitude' in the NMEA sentences and PGNs which deal with position, so if we're putting coordinates in an array which has space for elevation/altitude we should put it in. That said, [longitude, latitude, elevation] and not [latitude, longitude, elevation], what were they thinking?

Teppo Kurki

unread,
Apr 8, 2014, 3:11:13 PM4/8/14
to sig...@googlegroups.com
On Tue, Apr 8, 2014 at 8:49 PM, Tim Mathews <tmath...@gmail.com> wrote:
On Tue, Apr 8, 2014 at 1:08 PM, Teppo Kurki <t...@iki.fi> wrote:
State (I assume you mean Status field from RMC) doesn't make any sense. Lots of 0183 messages have the validity fields. I think SignalK should ignore invalid messages. The only other option I see is that each RMC-derived value has validity flag, or if the default is that data is valid a flag indicating that the data is invalid.

I agree, we shouldn't include validity flags in the model. However, SignalK conformant servers should log them somewhere and send an alarm message if some threshold is crossed (e.g. 15 invalid depth readings in a row or x number in the last minute or something). However, this is an implementation detail and not a data model issue. My vote is drop them from the model.

I agree - implementation detail. And there's the issue of missing updates totally (Navgauge multigauge stops displaying depth if the data is stale).
 
 
Other stuff:
(A) I would like to see more info in the source. With multiple (0183) sources I want to know where the data is coming from, in my case for example /dev/plotter and /dev/vhf (USB adapters named by udev).

I think that implies some sort of way to configure a "friendly" name in the server, no? I assume you'd rather see "Cockpit Plotter" or "Nav Station Plotter" as the source rather than /dev/plotter1 or /dev/plotter2?

Yes, in the metadata available in the api - or in the client. 

(B) How do we deal with multiple concurrent values from multiple sources for the same piece of information in the tree? Example is Vessel Heading in N2K feed from Freya at 

One option is that the leaf value is either {value:...} or [{value:...},{value:,,,}], but it makes things iffy.

Do you want to be able to display both on the client? Or just one? If just one, Kees has mentioned some "mapping" that he has done to tell his server which sources' values should be transmitted. Personally, I don't want to see more than one instance of any value, it would be distracting. I would however like to be able to specify a precedence, e.g. for GPS coordinates: "1. GPS receiver on stern rail, 2. Autopilot GPS receiver, 3. GPS from masthead".

I do think that the data model should definitely allow for multiple readings/sensors. Practical examples include fresh water level, temperature in different parts of the boat, multiple compasses (standalone/autopilot). Also you might want to compare the different readings at a glance, for example during calibration.

Mapping is a bit different thing. It can take place on the server so that the model that consumers see has already this logic built in, but it may as well be part of the consumer/UI.

Again this is a bit of an implementation detail, if we think about updates as individual messages, each containing update to some part of the tree. Still there is always the logical equivalent of "latest reading for this value from this sensor" and the model should accommodate that. How do you define stale? Milliseconds (roll), seconds (depth), minutes (barometric pressure)?


Also the same information is coming in different 0183 sentences with possibly different update rates. Should they be separate or the same? Include the sentence in the data item? For N2K each source has an id, which should be there.

In the case of the same info coming from the same device at different rates like "Position Rapid Update" and "GNSS Position Data", they should all be the same data item.

For example Freya has several sources/sensors for the same piece of info on the N2K bus. My point about different sentences with the same info is probably moot, but illustrates the problem.
 

(C) Longitude and latitude as different, unrelated values doesn't make any sense in electronic navigation, or can somebody name a relevant source that produces discrete values for these? I would prefer GeoJSON "coordinates": [125.6, 10.1] notation (optional elevation not really relevant I guess), crs is WGS84 unless specified as in GeoJSON

I think they're always together, and if having them already in GeoJSON is useful for plotting, then I say go for it. However, I wouldn't discount elevation altogether, it exists as 'Altitude' in the NMEA sentences and PGNs which deal with position, so if we're putting coordinates in an array which has space for elevation/altitude we should put it in. That said, [longitude, latitude, elevation] and not [latitude, longitude, elevation], what were they thinking?

I guess [x,y]. Comp sci majors, not navigators...

rob...@42.co.nz

unread,
Apr 8, 2014, 3:52:47 PM4/8/14
to sig...@googlegroups.com
I use GPX for tracks, Ive also looked at using the format, but it didnt seem to fit. However [ x,y,h] seems workable. I think we should keep h, it may prove useful for vehicles other than boats, eg subs, lakes, and other uses for the format - tracking buses etc.

Multiple data source - if you wanted one resultant vaue then its a averaging algorithm or something, if you want all, then we should consider a way to do that.

Rob

Fabian Tollenaar | Starting Point

unread,
Apr 8, 2014, 5:24:18 PM4/8/14
to sig...@googlegroups.com
On 8 Apr 2014, at 19:49, Tim Mathews <tmath...@gmail.com> wrote:

On Tue, Apr 8, 2014 at 1:08 PM, Teppo Kurki <t...@iki.fi> wrote:
State (I assume you mean Status field from RMC) doesn't make any sense. Lots of 0183 messages have the validity fields. I think SignalK should ignore invalid messages. The only other option I see is that each RMC-derived value has validity flag, or if the default is that data is valid a flag indicating that the data is invalid.

I agree, we shouldn't include validity flags in the model. However, SignalK conformant servers should log them somewhere and send an alarm message if some threshold is crossed (e.g. 15 invalid depth readings in a row or x number in the last minute or something). However, this is an implementation detail and not a data model issue. My vote is drop them from the model.

I agree as well, after all, Consumers will get information about the quality of the GPS fix through the GGA message (http://www.gpsinformation.org/dale/nmea.htm#GGA). If we choose to omit it, it should be added to the spec (including the advice that servers should keep track of invalids).

 
Other stuff:
(A) I would like to see more info in the source. With multiple (0183) sources I want to know where the data is coming from, in my case for example /dev/plotter and /dev/vhf (USB adapters named by udev).

I think that implies some sort of way to configure a "friendly" name in the server, no? I assume you'd rather see "Cockpit Plotter" or "Nav Station Plotter" as the source rather than /dev/plotter1 or /dev/plotter2?

I think naming is up to the server implementation: for instance, in the Producer/Server/Consumer system I’m building, the server and consumer only know which Producer send the data. The producer can be a program listening to a serial port parsing NMEA sentences, but unless that producer chooses (well, it’s developer) to share the serial address nobody down the wire will know. So, in my case, I would just put the identification of the producer in the source object. 

That said, I do think it would be a good idea to define some things that we want in the source. I’d say this object should contain (at least): 
- A name/label/identifier for the source. Can be whatever the developer wants (serial port, uuid, name of his cat) 
- Original type (N2K, 0183, SeaTalk/NG, etc) 
- ID/sentence name/…? (i.e., in the case of 0183, the type of the sentence, PGN in case of N2K)
- Any other suggestions?


(B) How do we deal with multiple concurrent values from multiple sources for the same piece of information in the tree? Example is Vessel Heading in N2K feed from Freya at 

One option is that the leaf value is either {value:...} or [{value:...},{value:,,,}], but it makes things iffy.

Do you want to be able to display both on the client? Or just one? If just one, Kees has mentioned some "mapping" that he has done to tell his server which sources' values should be transmitted. Personally, I don't want to see more than one instance of any value, it would be distracting. I would however like to be able to specify a precedence, e.g. for GPS coordinates: "1. GPS receiver on stern rail, 2. Autopilot GPS receiver, 3. GPS from masthead”.

I’m no fan of putting values in arrays. Instead, I think this should be an executive decision made on the server based on rules/configuration. The precedence idea seems best to me. To stay with GPS: server receives signals from the stern-mounted GPS and a backup GPS mouse connected to the server. Server is configured to treat stern-mounted GPS as primary and the GPS mouse as backup. In case of a bad fix or no location data for more than N seconds, a location object from the GPS mouse is used - until the stern GPS is available again. 


Also the same information is coming in different 0183 sentences with possibly different update rates. Should they be separate or the same? Include the sentence in the data item? For N2K each source has an id, which should be there.

In the case of the same info coming from the same device at different rates like "Position Rapid Update" and "GNSS Position Data", they should all be the same data item.

I think the format already solves this one right? We have one location object, which always contains the most recent version of the location (from whatever sentence). The source object will be updated accordingly (e.g. first lat/lon comes in via RMC sentence, then it’s updated with an incoming GLL sentence, etc


(C) Longitude and latitude as different, unrelated values doesn't make any sense in electronic navigation, or can somebody name a relevant source that produces discrete values for these? I would prefer GeoJSON "coordinates": [125.6, 10.1] notation (optional elevation not really relevant I guess), crs is WGS84 unless specified as in GeoJSON

I think they're always together, and if having them already in GeoJSON is useful for plotting, then I say go for it. However, I wouldn't discount elevation altogether, it exists as 'Altitude' in the NMEA sentences and PGNs which deal with position, so if we're putting coordinates in an array which has space for elevation/altitude we should put it in. That said, [longitude, latitude, elevation] and not [latitude, longitude, elevation], what were they thinking?

Personally, I like the more verbose syntax of writing them out in object keys.  That way, I don’t need to think about the order of the array and the indexes - I can just get lat or lon or elevation by key. However, it does seem unnecessary to add an additional timestamp and source object to lat, lon and elevation. IMHO the navigation object should then look something like this (not all keys are included, changes to source idem.):

{
    "courseOverGroundTrue”: {
        "source":"self”,
        "timestamp":"2014-05-03T09:13:42.000Z”,
        "value”:269.52
    },

    "location”: {
        “source”:”self",
        “timestamp”:"2014-05-03T09:13:42.000Z”,

        "latitude”:52.223141,
        "longitude”:4.545838,
        “altitude”: 22.1

    },
    
    "speedOverGround”: {
        "source":"self”,
        "timestamp":"2014-05-03T09:13:42.000Z”,
        "value”:0.47
    }
}

Fabian Tollenaar | Starting Point

unread,
Apr 8, 2014, 5:29:51 PM4/8/14
to sig...@googlegroups.com
On 8 Apr 2014, at 21:52, rob...@42.co.nz wrote:

I use GPX for tracks, Ive also looked at using the format, but it didnt seem to fit. However [ x,y,h] seems workable. I think we should keep h, it may prove useful for vehicles other than boats, eg subs, lakes, and other uses for the format - tracking buses etc.

I like your thinking, I want Signal K in a sub as well. Actually, I want a sub first! ;)


Multiple data source - if you wanted one resultant vaue then its a averaging algorithm or something, if you want all, then we should consider a way to do that.

An option would be to add an “alternatives” property to each property, that contains an array of objects of the same signature. This can be used by multiplexing servers to: a) choose the “primary”, best or most recent value and b) add all other versions of the value to the alternatives array, should a Consumer want to do something with it. 


Rob

On Tuesday, April 8, 2014 11:38:53 AM UTC+12, Fabian Tollenaar wrote:
I've written a basic parser module based of jamesp/node-nmea (that is, I've used his codecs and helper functions). 

The Parser interface is implemented as a Transform stream (http://nodejs.org/api/stream.html#stream_class_stream_transform), 
which makes it very easy to pipe in a file stream, or a TCP stream, or a serial stream, or any other type of stream for that matter. 
The parser comes with a binary executable allowing you to do something like cat gps.nmea | nmea-signalk 

ATM I'm finishing up converting some of the original node-nmea codecs to output Signal K, and adding tests. 
As soon as that's done, I'll put the code on github. 

As with node-nmea, at the moment the number of NMEA 0183 sentences it can decode is relatively small, but it's very easy to add extra codecs. 
After initial release, I aim to improve the codec format, and clean up the code a bit more. 

I'll post updates in this thread. 


Kees Verruijt

unread,
Apr 8, 2014, 5:52:53 PM4/8/14
to sig...@googlegroups.com

On 08 Apr 2014, at 23:24, Fabian Tollenaar | Starting Point <fab...@starting-point.nl> wrote:


(B) How do we deal with multiple concurrent values from multiple sources for the same piece of information in the tree? Example is Vessel Heading in N2K feed from Freya at 

One option is that the leaf value is either {value:...} or [{value:...},{value:,,,}], but it makes things iffy.

Do you want to be able to display both on the client? Or just one? If just one, Kees has mentioned some "mapping" that he has done to tell his server which sources' values should be transmitted. Personally, I don't want to see more than one instance of any value, it would be distracting. I would however like to be able to specify a precedence, e.g. for GPS coordinates: "1. GPS receiver on stern rail, 2. Autopilot GPS receiver, 3. GPS from masthead”.

I’m no fan of putting values in arrays. Instead, I think this should be an executive decision made on the server based on rules/configuration. The precedence idea seems best to me. To stay with GPS: server receives signals from the stern-mounted GPS and a backup GPS mouse connected to the server. Server is configured to treat stern-mounted GPS as primary and the GPS mouse as backup. In case of a bad fix or no location data for more than N seconds, a location object from the GPS mouse is used - until the stern GPS is available again. 

Not enough time to react to everything today, but I have a use case where you really want to have 2 instances of a particular item. My boat has a lift keel, and we have two depth sensors, one under the keel and one in the hull. I always have one IS20 showing the depth under keel and one depth of water (= hull + 50cm). I would like to see the same two sensors, with a custom friendly name, in the SignalK model.

The same would hold for things like tank levels.

And things like wind speed can be transmitted multiple times, once for apparent, once for true, once for north referenced, etc.

So you’d want a mapping from N2K src + N2K instance + N2K reference value to logical item.

Fabian Tollenaar | Starting Point

unread,
Apr 8, 2014, 6:51:19 PM4/8/14
to sig...@googlegroups.com
I’ve ended up rewriting the codecs as well, it might take a little bit more time than I expected. I’m sorry for that guys!


rob...@42.co.nz

unread,
Apr 8, 2014, 7:15:12 PM4/8/14
to sig...@googlegroups.com
Kees, I think we need a structure for 'sensors', an array or maybe an object (the same as vessels) where the individual sensors are added with nice names. Then its up to the server to populate these if you need, and up to the instrument to attach to the sensor rather than the vessel model, which is assumed to be the 'official' value.

so vessels.motu.environment.depth* is my 'official' and default depth source, but I can chose to instead display vessels.motu.sensors.hummingbird.depth*

In fact I wonder if we map it in localBoat - an implementation thing really
Rob

rob...@42.co.nz

unread,
Apr 8, 2014, 8:27:10 PM4/8/14
to sig...@googlegroups.com
magnetic variation = declination. in the navigation object

rob...@42.co.nz

unread,
Apr 8, 2014, 8:36:55 PM4/8/14
to sig...@googlegroups.com
This format makes sense because they always come together from the same source:


"location”: {
        “source”:”self",
        “timestamp”:"2014-05-03T09:13:42.000Z”,
        "latitude”:52.223141,
        "longitude”:4.545838
    },

but I think altitude is separate as its possibly from a different instrument (eg altimeter)

Rob

Tim Mathews

unread,
Apr 8, 2014, 9:26:29 PM4/8/14
to sig...@googlegroups.com
Latitude, longitude and altitude are part of PGN 129029 and sentences GGA and GGS. Altitude in this sense is the altitude of the GPS antenna above mean sea level and should always be reported as part of a position fix. I believe that we should keep them together in the "location" object.

rob...@42.co.nz

unread,
Apr 8, 2014, 11:10:45 PM4/8/14
to sig...@googlegroups.com
If its part of the GPS reading then it should stay together. While its not our current problem, I think we may eventually want a separate altitude too but it can wait. I will modify the format to bundle them when I work on it probably tonight

Kees Verruijt

unread,
Apr 9, 2014, 1:36:27 AM4/9/14
to sig...@googlegroups.com
I agree that how this is done exactly can indeed be left up to the implementation, but it is important that everything is ‘keyed’ access, no unnamed arrays.

As in your example you want to be able to route

vessels.motu.hummingbird.depth instead of search for “source”: “hummingbird” in all vessels.motu.data[] or through the vessels.motu.data.depth[] arrays.

In terms of the model, this means that all objects need a key.

Kees Verruijt

unread,
Apr 9, 2014, 1:47:56 AM4/9/14
to sig...@googlegroups.com

On 09 Apr 2014, at 02:36, rob...@42.co.nz wrote:


{
    "courseOverGroundTrue”: {
        "source":"self”,
        "timestamp":"2014-05-03T09:13:42.000Z”,
        "value”:269.52
    },

    "location”: {
        “source”:”self",
        “timestamp”:"2014-05-03T09:13:42.000Z”,
        "latitude”:52.223141,
        "longitude”:4.545838,
        “altitude”: 22.1
    },
    
    "speedOverGround”: {
        "source":"self”,
        "timestamp":"2014-05-03T09:13:42.000Z”,
        "value”:0.47
    }
}


I like the “location” object here, but shouldn’t we group SOG and COG into a velocity vector? If we want to keep SignalK relevant to non-mariners the same reasoning applies, and we might have a 3 dimensional velocity vector. That we mariners always have a zero value for the vertical speed (unless we have vessels.titanic or vessels.U57) should not mean we restrict our model that way. ESR, on one of the GPSD pages, is furious with the original NMEA developers for this reason.

This means the model becomes:

{
    “position”: {

        “source”:”self",
        “timestamp”:"2014-05-03T09:13:42.000Z”,
        "latitude”:52.223141,
        "longitude”:4.545838,
        “altitude”: 22.1,
“reference”: “WGS84"
    },
    
    “velocity”: {

        "source":"self”,
        "timestamp":"2014-05-03T09:13:42.000Z”,
        “horizontalSpeed”: 0.47
“verticalSpeed”: 0.0
“direction”: 269.52
    }
}


Kees Verruijt

unread,
Apr 9, 2014, 1:50:18 AM4/9/14
to sig...@googlegroups.com
I forgot errors, GPSD brings to our attention that we really would like to know the error in all 6 values. These would be optional, obviously.

Fabian Tollenaar | Starting Point

unread,
Apr 9, 2014, 2:32:05 AM4/9/14
to sig...@googlegroups.com
Thanks, I was already wondering why magneticVariation wasn't in the spec.. But I was wrong! 

Sent from my iPhone

Kees Verruijt

unread,
Apr 9, 2014, 2:42:40 AM4/9/14
to sig...@googlegroups.com
Fabian, I wondered the same and a quick Wikipedia lookup shows that in English they overload Declination (imo, too much) whereas in Dutch we always use  variatie (En: variation).

To prevent cultural misunderstanding, is it possible to use variation in the standard as well? It appears that this is understood in English and has the advantage of being easier to understand across languages.

Kees

Fabian Tollenaar | Starting Point

unread,
Apr 9, 2014, 2:44:15 AM4/9/14
to sig...@googlegroups.com


Sent from my iPhone

On 09 Apr 2014, at 07:47, Kees Verruijt <ke...@verruijt.net> wrote:

In this case, shouldn't STW be described in a similar manner? E.g 

    “velocityThroughWater”: {

        "source":"self”,
        "timestamp":"2014-05-03T09:13:42.000Z”,
        “horizontalSpeed”: 1.3
“verticalSpeed”: 0.0
    }
}

Side note: I prefer "position" over "location", as "location" has more the connotation of an actual place, for me.

Fabian Tollenaar | Starting Point

unread,
Apr 9, 2014, 2:46:27 AM4/9/14
to sig...@googlegroups.com
That, and I think that variation is (scientifically speaking) the more correct description of that measure. 

Fits in line with the arguments about using velocity instead of COG/SOG I'd say

Goedemorgen, trouwens!

Sent from my iPhone

Fabian Tollenaar

unread,
Apr 9, 2014, 10:07:17 AM4/9/14
to sig...@googlegroups.com
In between some work stuff I was writing the codec for the APB nmea message. Sentence below. I'm guessing a bit when it comes to mapping, as we don't have all descriptions yet. Is this correct?

/*
       0 1 2    3 4 5 6 7   8 9    10 11  12 13
       | | |    | | | | |   | |    |   |  |  |
$GPAPB,A,A,0.10,R,N,V,V,011,M,DEST,011,M,011,M*3C 

where:
APB     Autopilot format B
0 A       Loran-C blink/SNR warning, general warning 
1 A       Loran-C cycle warning 
2 0.10   cross-track error distance 
3 R       steer Right to correct (or L for Left) 
4 N       cross-track error units - nautical miles (K for kilometers) 
5 V       arrival alarm - circle 
6 V       arrival alarm - perpendicular 
7,8 011,M   magnetic bearing, origin to destination 
9 DEST     destination waypoint ID 
10,11 011,M   magnetic bearing, present position to destination 
12,13 011,M   magnetic heading to steer (bearings could True as 033,T) 
*3C Checksum
*/

Mapping:
currentRoute: { 
    bearingActual: 10 + 11,
    bearingDirect: 7 + 8,
    courseRequired: 12 + 13,
    eta: ,
    route: ,
    startTime: ,
    waypointLastTime: ,
    waypointLast: ,
    waypointNextEta: ,
    waypointNext: 9,
    xte: 2
}

Where do all the other values come from? Is the server supposed to calculate these over time?




Op dinsdag 8 april 2014 01:38:53 UTC+2 schreef Fabian Tollenaar:

rob...@42.co.nz

unread,
Apr 9, 2014, 3:54:38 PM4/9/14
to sig...@googlegroups.com
Fabian,
That looks correct.

The server needs to calculate eta, waypointEta, knows startTime, lastWaypointTime, and route, last and next waypoint.

Rob

rob...@42.co.nz

unread,
Apr 9, 2014, 3:56:02 PM4/9/14
to sig...@googlegroups.com
Looking at it again we should add true and magnetic bearing variants.

Rob

On Thursday, April 10, 2014 2:07:17 AM UTC+12, Fabian Tollenaar wrote:

Fabian Tollenaar | Starting Point

unread,
Apr 9, 2014, 5:16:06 PM4/9/14
to sig...@googlegroups.com
On 9 Apr 2014, at 21:56, rob...@42.co.nz wrote:

Looking at it again we should add true and magnetic bearing variants.
Rob

What do you propose? I think we have three possibilities: 

bearingActualMagnetic:
bearingActualTrue:
bearingDirectMagnetic
bearingDirectTrue

— or —

bearingActual:
bearingActualType:
bearingDirect:
bearingDirectType:

— or —

bearingActual: {
    value: 11.1,
    type: ‘magnetic’
}

bearingDirect: {
    value: 9.81
    type: ‘true’
}

What do you guys like best?

rob...@42.co.nz

unread,
Apr 9, 2014, 6:08:45 PM4/9/14
to sig...@googlegroups.com
We should ahve actual specific 'urls' for each datapoint. If yu always have to check the type and make allowances thats a real hassle, esp in non browser environments.

bearingActualMagnetic:
bearingActualTrue:
bearingDirectMagnetic
bearingDirectTrue

but we could do
bearing.actual.magnetic:
                    .true:
           .direct.magnetic
                    .true
etc, eg group as objects

Fabian Tollenaar

unread,
Apr 15, 2014, 4:34:59 PM4/15/14
to sig...@googlegroups.com
Since the first release of the parser, I found a nasty bug when a sentence isn't in one chunk of (stream) data. This has been fixed! 


I'm eager to hear your feedback!

Teppo Kurki

unread,
Apr 16, 2014, 1:40:52 PM4/16/14
to sig...@googlegroups.com

I'm eager to hear your feedback!


- wow, you've put quite a lot of effort into the whole infastructure
- why Tape and not something more widely used like Mocha (maybe it's just my noobness, never heard of Tape before)
- node-nmea has some test cases, they could be adapted easily to SignalK output (https://github.com/jamesp/node-nmea/tree/master/test)
- I prefer double-space indenting, but it's your call
- is Lodash really needed? not that it is a huge deal here
- why the modes?

My next steps connected to this are
- rewrite Navgauge UI to use SignalK messages
- use the new parser for Cassiopeia (my boat) nmea input for the coming season



Teppo Kurki

unread,
Apr 16, 2014, 2:11:54 PM4/16/14
to sig...@googlegroups.com

That said, I’d like to set up a little “social boating” experiment. I’ll put my server implementation online as soon as it’s in a useable state. Let’s set up a different thread to talk about specifics (e.g., what things do we want to do with the data. Do we just want to see each other, or do we for instance also want to communicate?)

My main driver for interoperability is to have a common format for communicating navigation data between a 'server' and a 'client' using today's format.

Main use case is that I could  download a closed or open source application, fire it up on a device that is connected to my boat's wifi hotspot and data would start flowing to the application.

Today this is impossible, as all the different equipment and applications use a multitude of nmea 0183, n2k and proprietary formats. The only common format seems to be good old nmea 0183 over tcp. That is why I need to transcode my n2k wind data to 0183 to get it to display on iNavX and iRegatta.




Fabian Tollenaar | Starting Point

unread,
Apr 16, 2014, 3:52:43 PM4/16/14
to sig...@googlegroups.com
On 16 Apr 2014, at 20:11, Teppo Kurki <t...@iki.fi> wrote:


That said, I’d like to set up a little “social boating” experiment. I’ll put my server implementation online as soon as it’s in a useable state. Let’s set up a different thread to talk about specifics (e.g., what things do we want to do with the data. Do we just want to see each other, or do we for instance also want to communicate?)

My main driver for interoperability is to have a common format for communicating navigation data between a 'server' and a 'client' using today's format.

Main use case is that I could  download a closed or open source application, fire it up on a device that is connected to my boat's wifi hotspot and data would start flowing to the application.

I agree, that’s probably why we’re all in this.. something that would be cool to add would be voice (or video) communication between boats (so, if we’re on the water and in range we could babble all we’d want without polluting radio frequencies). SIP tech is not that hard to implement on the server level, we’d only have to think about what information would go into signal k (IP, audio codec, port, etc)


Today this is impossible, as all the different equipment and applications use a multitude of nmea 0183, n2k and proprietary formats. The only common format seems to be good old nmea 0183 over tcp. That is why I need to transcode my n2k wind data to 0183 to get it to display on iNavX and iRegatta.





Fabian Tollenaar

unread,
Apr 20, 2014, 2:25:17 PM4/20/14
to sig...@googlegroups.com, Teppo Kurki
I realised I never replied to this, I'm sorry about that. Was off sailing.. See below ;)

Op woensdag 16 april 2014 19:40:52 UTC+2 schreef Teppo Kurki:

I'm eager to hear your feedback!


- wow, you've put quite a lot of effort into the whole infastructure
- why Tape and not something more widely used like Mocha (maybe it's just my noobness, never heard of Tape before)

No specific reason, I simply like the syntax of tape (nice and compact). If you prefer mocha, jasmine or whatever that's okay too, might allow us to share some the tests related to validation of the signal k output!
 
- node-nmea has some test cases, they could be adapted easily to SignalK output (https://github.com/jamesp/node-nmea/tree/master/test
- I prefer double-space indenting, but it's your call

I've learned programming using (hard) tabs, but recently I've been convinced that tabs are evil . So, I guess I don't mind too much, but I'd prefer to keep writing 4 spaces if nobody else objects. However, if you feel like there are good reasons to unify tab space, coding style etc. for all parsers, I'm all ears ;)
 
- is Lodash really needed? not that it is a huge deal here

No, but it's very convenient when looping objects, deep-comparing objects using _.isEqual and cloning objects (last one is necessary when returning signal K data: you don't want to return a pointer to the internal object managed by the parser, because you don't know what software down the line might do with the object). Since it's on the server anyway, only a small footprint, I didn't see it as a huge issue. But, as I'm only using a fraction of the methods available in the namespace, it might be worthwhile to put only those in a "local" helper file.  
 
- why the modes?

Mainly to keep different modes of running decoupled: the parser's input and output is different depending on usage (piped, forked or stand alone). I realise there is some overlap there and it's not very DRY, especially comparing standalone to the fork version, so this could be something to improve at some point. 
 

My next steps connected to this are
- rewrite Navgauge UI to use SignalK messages
- use the new parser for Cassiopeia (my boat) nmea input for the coming season

Let me know if you'd like to see any specific changes to the parser!  

rob...@42.co.nz

unread,
Apr 20, 2014, 9:20:55 PM4/20/14
to sig...@googlegroups.com
Fabian,

Good work. The concept is also quite similar to Kimmo's java marineapi (https://github.com/ktuukkan ) Its a good pattern, easily extendable and efficient. If you have a look at his code you will also see meta-interfaces (PositionSentence, HeadingSentence, etc) so when he parses a given sentence it can fire position or heading, etc events. Then I can just listen for position events and get all sources. Not sure if interfaces are possible for javascript the same way.

Rob

Fabian Tollenaar | Starting Point

unread,
Apr 21, 2014, 4:15:27 AM4/21/14
to sig...@googlegroups.com
On 21 Apr 2014, at 03:20, rob...@42.co.nz wrote:

Fabian,

Good work. The concept is also quite similar to Kimmo's java marineapi (https://github.com/ktuukkan ) Its a good pattern, easily extendable and efficient. If you have a look at his code you will also see meta-interfaces (PositionSentence, HeadingSentence, etc) so when he parses a given sentence it can fire position or heading, etc events. Then I can just listen for position events and get all sources. Not sure if interfaces are possible for javascript the same way.

Thanks! yes, it is. Atm it's emitting a “sentence” event (name will be changed to “data” in an upcoming release) whenever the signalk object changes (so, on any sentence). I could add events for specific Signal K groups, if that makes sense from a user point of view (I can imagine a use case where a developer uses the parser directly - without a server in between - where the dev would only want to listen to specific Signal K groups, effectively using the Parser as a filter on incoming NMEA0183 data).
 

Rob

On Wednesday, April 16, 2014 8:34:59 AM UTC+12, Fabian Tollenaar wrote:
Since the first release of the parser, I found a nasty bug when a sentence isn't in one chunk of (stream) data. This has been fixed! 


I'm eager to hear your feedback!




Op dinsdag 8 april 2014 01:38:53 UTC+2 schreef Fabian Tollenaar:
I've written a basic parser module based of jamesp/node-nmea (that is, I've used his codecs and helper functions). 

The Parser interface is implemented as a Transform stream (http://nodejs.org/api/stream.html#stream_class_stream_transform), 
which makes it very easy to pipe in a file stream, or a TCP stream, or a serial stream, or any other type of stream for that matter. 
The parser comes with a binary executable allowing you to do something like cat gps.nmea | nmea-signalk 

ATM I'm finishing up converting some of the original node-nmea codecs to output Signal K, and adding tests. 
As soon as that's done, I'll put the code on github. 

As with node-nmea, at the moment the number of NMEA 0183 sentences it can decode is relatively small, but it's very easy to add extra codecs. 
After initial release, I aim to improve the codec format, and clean up the code a bit more. 

I'll post updates in this thread. 


rob...@42.co.nz

unread,
Apr 21, 2014, 5:43:26 PM4/21/14
to sig...@googlegroups.com
Fabian,

Re emitting events, I think you have two things here that should be separate.

1. The parsing of NMEA into signal K, its 'area of concern' is to receive, parse, transform. It should emit events relating to the process, not the content.
2. The updating of the local signal K model, which should emit events based on new/changed/deleted keys. I have been thinking about this too, not sure how best to implement it in java script (easy in java!). Data consumers will be listening for the signal k data, not the nmea data (events). So ideally any change to the local model should emit an a signal k snippet to all consumers

Kimmos code emits NMEA data events because it doesnt have the concept of a global model, it assumes that the listener will use the data directly and know about NMEA

Rob

Fabian Tollenaar | Starting Point

unread,
Apr 21, 2014, 6:28:50 PM4/21/14
to sig...@googlegroups.com, rob...@42.co.nz
Sent from my iPhone

On 21 Apr 2014, at 23:43, "rob...@42.co.nz" <rob...@42.co.nz> wrote:

Fabian,

Re emitting events, I think you have two things here that should be separate.

1. The parsing of NMEA into signal K, its 'area of concern' is to receive, parse, transform. It should emit events relating to the process, not the content.
That is roughly how the parser works; a stream of NMEA sentences is piped into the parser (which is a Transform stream). The transform process of the parser consist of aggregating data until a full sentence is buffered, validating the sentence, parsing the sentence, encoding the values into a signal k child object. That child object is subsequently merged into an internal signal k object. Every time a merge changes the object, an event is emitted. 
Events, in the context of a node.js stream, have the sole purpose of transferring data to anyone listening to these events without blocking the stream. Since events are the primary way to read data of a stream, they are inevitably about both content (e.g the "data" event) and about process (e.g the "error" event).
Currently, the data event emits a full signal k object whenever any of it's child objects changes. I can see a use case where it might be useful to listen to changes in certain child objects - so an event for every child object that is fired when changed would make sense.

2. The updating of the local signal K model, which should emit events based on new/changed/deleted keys. I have been thinking about this too, not sure how best to implement it in java script (easy in java!). Data consumers will be listening for the signal k data, not the nmea data (events). So ideally any change to the local model should emit an a signal k snippet to all consumers
That is an easy one when using node.js streams: pipe the parser directly into the server implementation, and broadcast a new version on the websocket connection whenever an update is coming from down the line. 

rob...@42.co.nz

unread,
Apr 21, 2014, 6:39:40 PM4/21/14
to sig...@googlegroups.com, rob...@42.co.nz
See below


On Tuesday, April 22, 2014 10:28:50 AM UTC+12, Fabian Tollenaar wrote:
Sent from my iPhone

On 21 Apr 2014, at 23:43, "rob...@42.co.nz" <rob...@42.co.nz> wrote:

Fabian,

Re emitting events, I think you have two things here that should be separate.

1. The parsing of NMEA into signal K, its 'area of concern' is to receive, parse, transform. It should emit events relating to the process, not the content.
That is roughly how the parser works; a stream of NMEA sentences is piped into the parser (which is a Transform stream). The transform process of the parser consist of aggregating data until a full sentence is buffered, validating the sentence, parsing the sentence, encoding the values into a signal k child object. That child object is subsequently merged into an internal signal k object. Every time a merge changes the object, an event is emitted. 
Events, in the context of a node.js stream, have the sole purpose of transferring data to anyone listening to these events without blocking the stream. Since events are the primary way to read data of a stream, they are inevitably about both content (e.g the "data" event) and about process (e.g the "error" event).
Currently, the data event emits a full signal k object whenever any of it's child objects changes. I can see a use case where it might be useful to listen to changes in certain child objects - so an event for every child object that is fired when changed would make sense.
2. The updating of the local signal K model, which should emit events based on new/changed/deleted keys. I have been thinking about this too, not sure how best to implement it in java script (easy in java!). Data consumers will be listening for the signal k data, not the nmea data (events). So ideally any change to the local model should emit an a signal k snippet to all consumers
That is an easy one when using node.js streams: pipe the parser directly into the server implementation, and broadcast a new version on the websocket connection whenever an update is coming from down the line. 

I do something similar at the moment - that is receive an update (or NMEA etc), merge into local model, make any subsequent internal calculations (like true wind) collect updates and transmit the changes. But its a manual process tracking the updates. What I want is to enforce updates the model to emit events that cause the key to be transmitted to clients. Then receive/parse/save, updating calculated values, and transmission of changes are totally decoupled.

  In java I can safely wrap the local model and limit access to it to well-defined methods which fire events. In javascript I'm not sure how to stop code just going straight to the key.

Rob

Fabian Tollenaar

unread,
May 1, 2014, 6:28:10 AM5/1/14
to sig...@googlegroups.com, rob...@42.co.nz, Teppo Kurki
Guys!

I've been absent for a while, I'm sorry for that. I was on a short trip to Vlieland, and I always try to leave the laptop shut down as much as possible ;)

Anyway, I'm planning to implement some final implementation changes to my nmea0183 parser this weekend. That will free up some of my free time to get back to work on my server implementation and spec-related issues.

Cheers!


Op dinsdag 22 april 2014 00:39:40 UTC+2 schreef rob...@42.co.nz:

Fabian Tollenaar

unread,
May 6, 2014, 12:05:57 PM5/6/14
to sig...@googlegroups.com
Just pushed an update to the NMEA0183 parser, the parser is now usable. Although, extra codecs do need to be written..

Jean Vasic

unread,
Mar 31, 2022, 3:51:32 PM3/31/22
to Signal K
Hi,
So finally do we have in the Signalk model the distance and bearing of the boat to the next waypoint ? Which I understand can be found in RMB ?

Thanks
Jean

Teppo Kurki

unread,
Apr 1, 2022, 1:25:27 AM4/1/22
to signalk
On Thu, Mar 31, 2022 at 10:51 PM Jean Vasic <jean....@gmail.com> wrote:
Hi,
So finally do we have in the Signalk model the distance and bearing of the boat to the next waypoint ? Which I understand can be found in RMB ?

Yes, since 2017.
 

Thanks
Jean

Le mardi 6 mai 2014 à 18:05:57 UTC+2, Fabian Tollenaar a écrit :
Just pushed an update to the NMEA0183 parser, the parser is now usable. Although, extra codecs do need to be written..





Op dinsdag 8 april 2014 01:38:53 UTC+2 schreef Fabian Tollenaar:
I've written a basic parser module based of jamesp/node-nmea (that is, I've used his codecs and helper functions). 

The Parser interface is implemented as a Transform stream (http://nodejs.org/api/stream.html#stream_class_stream_transform), 
which makes it very easy to pipe in a file stream, or a TCP stream, or a serial stream, or any other type of stream for that matter. 
The parser comes with a binary executable allowing you to do something like cat gps.nmea | nmea-signalk 

ATM I'm finishing up converting some of the original node-nmea codecs to output Signal K, and adding tests. 
As soon as that's done, I'll put the code on github. 

As with node-nmea, at the moment the number of NMEA 0183 sentences it can decode is relatively small, but it's very easy to add extra codecs. 
After initial release, I aim to improve the codec format, and clean up the code a bit more. 

I'll post updates in this thread. 

--
You received this message because you are subscribed to the Google Groups "Signal K" group.
To unsubscribe from this group and stop receiving emails from it, send an email to signalk+u...@googlegroups.com.

Jean Vasic

unread,
Apr 2, 2022, 10:32:29 AM4/2/22
to Signal K
Ok found in GitHub, thanks ! Didn’t realize that the pdf v1.5 was a bit outdated.
Reply all
Reply to author
Forward
0 new messages