<commit_before>"""GPS NMEA data acquisition and configuration."""


import argparse
import io
import re
import selectors
import time

import pynmea2
import serial


class GPSStream:
    def __init__(self, port):
        self.port = serial.Serial(port, timeout=0)
        """GPS serial port stream."""
        
        sel = selectors.DefaultSelector()
        sel.register(port, selectors.EVENT_READ)
        self.sel = sel
        """Stream read selector object."""

        self.started = None
        """Timestamp of receipt of message start marker or `None`."""
        
        self.buff = b''
        """GPS stream receive buffer."""

        self.re = re.compile(br'''
            # Message start marker
            \$
        
            # Message type identifier
            (?: (?: G[A-Z]{4}) | (?: P[A-Z]{3}))

            # Message data
            [-.,A-Z0-9]*
        
            # Optional checksum
            (?: \*[0-9A-F]{2})?

            # Message end marker (CR-LF)
            \r\n
            ''', re.X | re.IGNORECASE)
        """NMEA message regular expression."""
    
    def _process(self):
        selected = self.sel.select()
        if not selected:
            raise InterruptedError
        
        timestamp = get_time_us()
        data = self.port.read(self.port.in_waiting)
        self.buff = self.buff + data
        
        out = []
        if self.started and b'\n' in data:
            try:
                out.append(self._parse_one())
            except Exception:
                pass
    
    def _parse_one(self):
        match = self.re.match(self.buff)
        if not match:
            ### clean buffer
            raise ValueError
        
        try:
            msg = pynmea2.parse(match.group())
            msg.time_us = self.started
        finally:
            self.started = None
            self.buff = self.buff[match.end():]
            ### clean buffer up to next $
        
        return msg        


def get_time_us():
    return int(time.clock_gettime(time.CLOCK_REALTIME) * 1e6)


def program_arguments():
    parser = argparse.ArgumentParser(description='Read GPS stream')
    parser.add_argument('gpsport')
    return parser.parse_args()


if __name__ == '__main__':
    args = program_arguments()
<commit_msg>Implemented GPS stream parsing.<commit_after>"""GPS NMEA data acquisition and configuration."""


import argparse
import io
import re
import selectors
import time

import pynmea2
import serial
import pymavlink.dialects.v10.ceaufmg as mavlink


class GPSStream:
    
    MAX_BUFF_SIZE = 100
    """Maximum required buffer size."""
    
    def __init__(self, port):
        self.port = serial.Serial(port, timeout=0)
        """GPS serial port stream."""
        
        sel = selectors.DefaultSelector()
        sel.register(port, selectors.EVENT_READ)
        self.sel = sel
        """Stream read selector object."""

        self.started = None
        """Timestamp of receipt of message start marker or `None`."""
        
        self.buff = bytearray()
        """GPS stream receive buffer."""
    
    def handle_nmea(self, msg, time_us):
        pass
    
    def handle_mavlink(self, msg):
        pass
    
    def _parse(self):
        """Parse and reset the message buffer."""
        try:
            text = self.buff.decode('ascii')
            msg = pynmea2.parse(text)
            self.handle_nmea(msg, self.started)
        except Exception:
            #### LOG ERROR
            pass
        finally:
            self.buff.clear()
            self.started = None
    
    def _process(self):
        """Process the GPS stream."""
        # Wait for data to arrive
        selected = self.sel.select()
        if not selected:
            raise InterruptedError

        # Retrieve the data available
        data = self.port.read(self.port.in_waiting)

        # Process each received character
        for char in data:
            if char == ord('$'):
                # Reset buffer and timestamp
                self.started = get_time_us()
                self.buff.clear()
                self.buff.append(char)
            elif self.started:
                self.buff.append(char)
                if char == ord('\n'):
                    self.parse()
                elif len(self.buff) > self.MAX_BUFF_SIZE + 50:
                    del self.buff[:-self.MAX_BUFF_SIZE] # truncate buffer


def get_time_us():
    return int(time.clock_gettime(time.CLOCK_REALTIME) * 1e6)


def program_arguments():
    parser = argparse.ArgumentParser(description='Read GPS stream')
    parser.add_argument('gpsport')
    return parser.parse_args()


if __name__ == '__main__':
    args = program_arguments()

{'fraction_non_alphanumeric': 0.10756802721088435, 'fraction_numerical': 0.00510204081632653, 'mean_word_length': 1.7546838407494145, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 4, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '565244', 'n_tokens_mistral': 1365, 'n_tokens_neox': 1310, 'n_words': 343}