Python Forum
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
using re.search()
#1
Hi,

I'm trying to read the outputs from a GPS device. The only data I'm interested in is the one between the words '$GPGGA' and '$GPGSA'.

The code below works but at times I get extra characters coming from outside my search and I cannot seem to find the culpit.

I appreciate some help.
TIA

rxData = b'$GPRMC,111956.00,A,4030.32925,N,00353.76292,W,0.208,,100521,,,A*61\r\n$GPVTG,,T,,M,0.208,N,0.384,K,A*26\r\n$GPGGA,111956.00,4030.32925,N,00353.76292,W,1,05,1.55,718.1,M,50.2,M,,*4C\r\n$GPGSA,A,3,31,29,25,26,18,,,,,,,,3.81,1.55,3.48*05\r\n$GPGSV,3,1,11,04,08,319,,0'

def readData():

    try:
        data = re.search("GPGGA,(.*)\r\n", rxData.decode("utf-8"))
        if data:
            data = data.group(1)
            print('data: {}'.format(data))
            #split string by, into array
            arry = data.split(',')
            # print(arry[0])
        time.sleep(1)
    except Exception as e:
        print(str(e))

readData()
The output should be
data: 111956.00,4030.32925,N,00353.76292,W,1,05,1.55,718.1,M,50.2,M,,*4C
but at times I get
data: 111956.00,4030.32925,N,00353.76292,W,1,05,1.55,718.1,M,50.2,M,,*4C$GPGSA,A,3,31,29,25,26,18,,,,,,,,3.81,1.55,3.48*05
Reply
#2
If I had to do this myself, I would first split on newlines, then split on commas. You can then ignore any lines that don't have the $GPGGA as the message.

rxData = b'$GPRMC,111956.00,A,4030.32925,N,00353.76292,W,0.208,,100521,,,A*61\r\n$GPVTG,,T,,M,0.208,N,0.384,K,A*26\r\n$GPGGA,111956.00,4030.32925,N,00353.76292,W,1,05,1.55,718.1,M,50.2,M,,*4C\r\n$GPGSA,A,3,31,29,25,26,18,,,,,,,,3.81,1.55,3.48*05\r\n$GPGSV,3,1,11,04,08,319,,0'

rxData = rxData.decode()
for line in rxData.splitlines():
    data = line.split(",")
    if data[0] == "$GPGGA":
        print(data)
Output:
['$GPGGA', '111956.00', '4030.32925', 'N', '00353.76292', 'W', '1', '05', '1.55', '718.1', 'M', '50.2', 'M', '', '*4C']
But there are modules out there that can read your stream directly and parse the NMEA sentences. I don't have your raw stream, so I can't demonstrate that. But I can use pynmeagps to parse that line.

from pynmeagps import NMEAReader

rxData = b'$GPRMC,111956.00,A,4030.32925,N,00353.76292,W,0.208,,100521,,,A*61\r\n$GPVTG,,T,,M,0.208,N,0.384,K,A*26\r\n$GPGGA,111956.00,4030.32925,N,00353.76292,W,1,05,1.55,718.1,M,50.2,M,,*4C\r\n$GPGSA,A,3,31,29,25,26,18,,,,,,,,3.81,1.55,3.48*05\r\n$GPGSV,3,1,11,04,08,319,,0'

rxData = rxData.decode()
for line in rxData.splitlines():
    data = line.split(",")
    if data[0] == "$GPGGA":
        print(NMEAReader.parse(line))
Output:
<NMEA(GPGGA, time=11:19:56, lat=40.505488, NS=N, lon=-3.896049, EW=W, quality=1, numSV=5, HDOP=1.55, alt=718.1, altUnit=M, sep=50.2, sepUnit=M, diffAge=, diffStation=)>
ebolisa likes this post
Reply
#3
(May-10-2021, 07:30 PM)bowlofred Wrote: If I had to do this myself, I would first split on newlines, then split on commas. You can then ignore any lines that don't have the $GPGGA as the message.

Thank you!! I cannot use the second option as I'm using Micropython and that library is not available.
Reply
#4
.* is greedy, and will consume as much as it can. If there's multiple newlines after GPGGA, then only the last would match the regex, and all the intermediates would show in your results (as you're seeing).

So you can either...
1) replace the .* with a character group that matches everything except a newline:GPGGA,([^\r\n]+)\r\n, or
2) add a non-greedy modifier to it: GPGGA,(.*?)\r\n
Reply
#5
(May-10-2021, 08:12 PM)ebolisa Wrote: Thank you!! I cannot use the second option as I'm using Micropython and that library is not available.

It just might be able to be ported. It appears the only external modules that it loads are struct and datetime. Neither are directly available, but both have similar micropython modules.
Reply
#6
Another option
rxData = b'$GPRMC,111956.00,A,4030.32925,N,00353.76292,W,0.208,,100521,,,A*61\r\n$GPVTG,,T,,M,0.208,N,0.384,K,A*26\r\n$GPGGA,111956.00,4030.32925,N,00353.76292,W,1,05,1.55,718.1,M,50.2,M,,*4C\r\n$GPGSA,A,3,31,29,25,26,18,,,,,,,,3.81,1.55,3.48*05\r\n$GPGSV,3,1,11,04,08,319,,0'

u = rxData.decode()
try:
    result = u.split('$GPGGA', 1)[1].split('$GPGSA', 1)[-2]
    print(result)
except IndexError:
    print('Not Found !')
Reply


Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020