Knio / pynmea2

Python library for parsing the NMEA 0183 protocol (GPS)

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Correct method for parsing proprietary sentences?

proximous opened this issue · comments

I have a Seapath MRU. It outputs the following proprietary sentences:

$PSXN,20,horiz-qual,hgt-qual,head-qual,rp-qual*csum term
$PSXN,22,gyro-calib,gyro-offs*csum term
$PSXN,23,roll,pitch,head,heave*csum term
$PSXN,24,roll-rate,pitch-rate,yaw-rate,vertical-vel*csum term
$PSXN,21,event*csum term

where:

horiz-qual: Horizontal position and velocity quality: 0 = normal, 1 = reduced performance, 2= invalid data.
hgt-qual: Height and vertical velocity quality: 0 = normal, 1 = reduced performance, 2 =invalid data.
head-qual: Heading quality: 0 = normal, 1 = reduced performance, 2 = invalid data.
rp-qual: Roll and pitch quality: 0 = normal, 1 = reduced performance, 2 = invalid data.
gyro-calib: Gyro calibration value since system start-up in degrees on format d.dd.
gyro-offs: Short-term gyro offset in degrees on format d.dd.
roll: Roll in degrees on format d.dd. Positive with port side up.
pitch: Pitch in degrees on format d.dd. Positive with bow up.
heave: Heave in metres on format d.dd. Positive down.
roll-rate: Roll rate in degrees per second on format d.dd. Positive when port side is moving upwards.
pitch-rate: Pitch rate in degrees per second on format d.dd. Positive when bow is moving upwards.
yaw-rate: Yaw rate in degrees per second on format d.dd. Positive when bow is moving towards starboard.
vertical-vel: Vertical velocity in metres per second on format d.dd. Positive when moving downwards.
event: Event code: 1 = system restart.
csum: Checksum (exclusive or) of all characters between, but not including, the preceding $ and * , hexadecimal (00 - FF).
term: CR-LF (2 bytes, values 13 and 10).

with sample data:

'$PSXN,20,0,0,0,0*3B',
'$PSXN,23,0.30,-0.97,298.57,0.13*1B',
'$PSXN,26,0,44.5000,0.7800,-0.9000,NRP*6D',

So I created the following class:

class SXN(pynmea2.ProprietarySentence):
    def __init__(self, manufacturer, data):
        super(SXN, self).__init__(manufacturer, data)
        self.sentence_type = data[1]
        if self.sentence_type == '23':
            SXN.fields = (
                ('Empty', '_'),
                ('sentence', 's'),
                ('roll', 'roll'),
                ('pitch', 'pitch'),
                ('head', 'head'),
                ('heave', 'heave')
            )
            SXN.name_to_idx = dict((f[1], i) for i, f in enumerate(SXN.fields))

This seems to work for the $PSXN,23 message, but as I think about supporting the others it seems kludgey. Is there a better approach?

You can override the __new__ method to pick the correct class, and then implement each of those messages as their own types. I have made a commit that does this and defines the first message. Would you mind adding the rest?

https://github.com/Knio/pynmea2/compare/sxn - 18a621b

I created a pull request:
#69

It adds support for messages 21-24 and a test case for 23. (I only have real data for 20 and 23. I'll try to capture data for the other messages and add tests for them once I have real data.)

Thanks! I merged this into master and uploaded version 1.10.0