From f88b6cba54d5e7c9695eefc68fb506dd1fc08409 Mon Sep 17 00:00:00 2001 From: DarcyB Date: Mon, 16 Oct 2023 22:50:22 -0700 Subject: [PATCH] Kenwood lmr (#154) * Initial supoport for proprietary Kenwood Land Mobile Radio AVL Data * Kenwood FleetSync II --- pynmea2/types/proprietary/kwd.py | 132 +++++++++++++++++++++++++++++++ test/test_proprietary.py | 71 +++++++++++++++++ 2 files changed, 203 insertions(+) diff --git a/pynmea2/types/proprietary/kwd.py b/pynmea2/types/proprietary/kwd.py index ca80945..132572f 100644 --- a/pynmea2/types/proprietary/kwd.py +++ b/pynmea2/types/proprietary/kwd.py @@ -6,6 +6,54 @@ from ... import nmea from ... import nmea_utils +class KLD(nmea.ProprietarySentence): + sentence_types = {} + + def __new__(_cls, manufacturer, data): + name = manufacturer + data[0] + cls = _cls.sentence_types.get(name, _cls) + return super(KLD, cls).__new__(cls) + + def __init__(self, manufacturer, data): + self.sentence_type = manufacturer + data[0] + super(KLD, self).__init__(manufacturer, data) + +class KND(nmea.ProprietarySentence): + sentence_types = {} + + def __new__(_cls, manufacturer, data): + name = manufacturer + data[0] + cls = _cls.sentence_types.get(name, _cls) + return super(KND, cls).__new__(cls) + + def __init__(self, manufacturer, data): + self.sentence_type = manufacturer + data[0] + super(KND, self).__init__(manufacturer, data) + +class KLS(nmea.ProprietarySentence): + sentence_types = {} + + def __new__(_cls, manufacturer, data): + name = manufacturer + data[0] + cls = _cls.sentence_types.get(name, _cls) + return super(KLS, cls).__new__(cls) + + def __init__(self, manufacturer, data): + self.sentence_type = manufacturer + data[0] + super(KLS, self).__init__(manufacturer, data) + +class KNS(nmea.ProprietarySentence): + sentence_types = {} + + def __new__(_cls, manufacturer, data): + name = manufacturer + data[0] + cls = _cls.sentence_types.get(name, _cls) + return super(KNS, cls).__new__(cls) + + def __init__(self, manufacturer, data): + self.sentence_type = manufacturer + data[0] + super(KNS, self).__init__(manufacturer, data) + class KWD(nmea.ProprietarySentence): sentence_types = {} @@ -102,3 +150,87 @@ class KWDWPL(KWD, nmea_utils.LatLonFix, nmea_utils.DatetimeFix, nmea_utils.Valid ("Waypoint Name", "wname"), ("Table and Symbol", "ts"), ) + +class KLDS(KLD, nmea_utils.LatLonFix, nmea_utils.DatetimeFix, nmea_utils.ValidStatusFix): + """ + $PKLDS,hhmmss,v,ddmm.mm,ns,dddmm.mm,ew,speed,course,ddmmyy,DD.dd,ewSV,fleet,svid,status,fut*99 + $PKLDS,001235,A,3544.6650,N,13940.1900,E,015.0,038.8,110498,10.80,W00,100,2000,15,00,*?? + """ + fields = ( + ("Subtype", "subtype"), + ("Time of Receipt", "timestamp", nmea_utils.timestamp), + ("GPS Status (Void)","status"), + ("Latitude", "lat"), + ("Latitude Direction", "lat_dir"), + ("Longitude", "lon"), + ("Longitude Direction", "lon_dir"), + ("Speed over Ground Knot", "sog", float), + ("Course over Ground", "cog", float), + ("Date", "datestamp", nmea_utils.datestamp), + ("Magnetic variation", "declination", float), + ("Declination Direction", "dec_dir"), + ("Fleet", "fleet", Decimal), + ("Sender ID", "senderid"), + ("Sender Status", "senderstatus", Decimal), + ("Future Reserved", "future", Decimal), + ) + + + +class KNDS(KND, nmea_utils.LatLonFix, nmea_utils.DatetimeFix, nmea_utils.ValidStatusFix): + """ + $PKNDS,hhmmss,v,ddmm.mm,ns,dddmm.mm,ew,speed,course,ddmmyy,DD.dd,ewSV,svid,status,fut*99 + $PKNDS,124640,A,4954.1458,N,11923.5992,W,000.0,000.0,120223,19.20,W00,U00002,207,00,*29 + + """ + fields = ( + ("Subtype", "subtype"), + ("Time of Receipt", "timestamp", nmea_utils.timestamp), + ("GPS Status (Void)","status"), + ("Latitude", "lat"), + ("Latitude Direction", "lat_dir"), + ("Longitude", "lon"), + ("Longitude Direction", "lon_dir"), + ("Speed over Ground Knot", "sog", float), + ("Course over Ground", "cog", float), + ("Date", "datestamp", nmea_utils.datestamp), + ("Magnetic variation", "declination", float), + ("Declination Direction", "dec_dir"), + ("Sender ID", "senderid"), + ("Sender Status", "senderstatus", Decimal), + ("Future Reserved", "future", Decimal), + ) + +class KLSH(KLS, nmea_utils.LatLonFix, nmea_utils.DatetimeFix, nmea_utils.ValidStatusFix): + """ + $PKLSH,ddmm.mm,ns,dddmm.mm,ew,hhmmss,v,fleet,svid,*99 + $PKLSH,4000.0000,N,13500.0000,E,021720,A,100,2000,* ?? + """ + fields = ( + ("Subtype", "subtype"), + ("Latitude", "lat"), + ("Latitude Direction", "lat_dir"), + ("Longitude", "lon"), + ("Longitude Direction", "lon_dir"), + ("Time of Receipt", "timestamp", nmea_utils.timestamp), + ("GPS Status (Void)","status"), + ("Fleet", "fleet", Decimal), + ("Sender ID", "senderid"), + ) + +class KNSH(KNS, nmea_utils.LatLonFix, nmea_utils.DatetimeFix, nmea_utils.ValidStatusFix): + """ + $PKLSH,ddmm.mm,ns,dddmm.mm,ew,hhmmss,v,svid,*99 + $PKNSH,4000.0000,N,13500.0000,E,021720,A,U00001,* ?? + """ + fields = ( + ("Subtype", "subtype"), + ("Latitude", "lat"), + ("Latitude Direction", "lat_dir"), + ("Longitude", "lon"), + ("Longitude Direction", "lon_dir"), + ("Time of Receipt", "timestamp", nmea_utils.timestamp), + ("GPS Status (Void)","status"), + ("Sender ID", "senderid"), + ) + diff --git a/test/test_proprietary.py b/test/test_proprietary.py index 58995f8..ce6aea3 100644 --- a/test/test_proprietary.py +++ b/test/test_proprietary.py @@ -255,3 +255,74 @@ def test_KWDWPL(): assert msg.ts == '/-' assert msg.latitude == 45.529833333333336 assert msg.longitude == -122.89133333333334 + +def test_PKNDS(): + # A sample proprietary Kenwood sentence used for GPS data communications in NEXEDGE Digital + data = "$PKNDS,114400,A,4954.1450,N,11923.6043,W,001.4,356.8,130223,19.20,W00,U00002,207,00,*2E" + msg = pynmea2.parse(data) + assert msg.manufacturer == "KND" + assert msg.timestamp == datetime.time(11, 44, 00, tzinfo=datetime.timezone.utc) + assert msg.status == 'A' + assert msg.is_valid == True + assert msg.lat == '4954.1450' + assert msg.lat_dir == 'N' + assert msg.lon == '11923.6043' + assert msg.lon_dir == 'W' + assert msg.datestamp == datetime.date(2023, 2, 13) + assert msg.datetime == datetime.datetime(2023, 2, 13, 11, 44, 00, tzinfo=datetime.timezone.utc) + assert msg.senderid == 'U00002' + assert msg.senderstatus == 207 + assert msg.latitude == 49.90241666666667 + assert msg.longitude == -119.393405 + +def test_PKNSH(): + # A sample proprietary Kenwood sentence used for GPS data communications in NEXEDGE Digital + data = "$PKNSH,4954.1450,N,11923.6043,W,114400,A,U00002,*44" + msg = pynmea2.parse(data) + assert msg.manufacturer == "KNS" + assert msg.timestamp == datetime.time(11, 44, 00, tzinfo=datetime.timezone.utc) + assert msg.status == 'A' + assert msg.is_valid == True + assert msg.lat == '4954.1450' + assert msg.lat_dir == 'N' + assert msg.lon == '11923.6043' + assert msg.lon_dir == 'W' + assert msg.senderid == 'U00002' + assert msg.latitude == 49.90241666666667 + assert msg.longitude == -119.393405 + +def test_PKLDS(): + # A sample proprietary Kenwood sentence used for GPS data communications in FleetSync II signaling + data = "$PKLDS,122434,A,4954.1474,N,11923.6044,W,001.1,194.9,130223,19.20,W00,100,1001,80,00,*60" + msg = pynmea2.parse(data) + assert msg.manufacturer == "KLD" + assert msg.timestamp == datetime.time(12, 24, 34, tzinfo=datetime.timezone.utc) + assert msg.status == 'A' + assert msg.is_valid == True + assert msg.lat == '4954.1474' + assert msg.lat_dir == 'N' + assert msg.lon == '11923.6044' + assert msg.lon_dir == 'W' + assert msg.datestamp == datetime.date(2023, 2, 13) + assert msg.datetime == datetime.datetime(2023, 2, 13, 12, 24, 34, tzinfo=datetime.timezone.utc) + assert msg.senderid == '1001' + assert msg.fleet == 100 + assert msg.latitude == 49.902456666666666 + assert msg.longitude == -119.39340666666666 + +def test_PKLSH(): + # A sample proprietary Kenwood sentence used for GPS data communications in FleetSync II signaling + data = "$PKLSH,4954.1474,N,11923.6044,W,122434,A,100,1001,*3F" + msg = pynmea2.parse(data) + assert msg.manufacturer == "KLS" + assert msg.timestamp == datetime.time(12, 24, 34, tzinfo=datetime.timezone.utc) + assert msg.status == 'A' + assert msg.is_valid == True + assert msg.lat == '4954.1474' + assert msg.lat_dir == 'N' + assert msg.lon == '11923.6044' + assert msg.lon_dir == 'W' + assert msg.senderid == '1001' + assert msg.fleet == 100 + assert msg.latitude == 49.902456666666666 + assert msg.longitude == -119.39340666666666