or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

core-parsing.mddepth-sonar.mdgps-positioning.mdindex.mdnavigation-course.mdproprietary-sentences.mdstream-processing.mdutilities.mdwind-weather.md

stream-processing.mddocs/

0

# Stream Processing

1

2

Stream processing capabilities allow handling continuous NMEA data from files, serial ports, and other streaming sources with flexible error handling and parsing options.

3

4

## NMEAStreamReader

5

6

```python { .api }

7

class NMEAStreamReader:

8

"""Reads NMEA sentences from a stream with configurable error handling."""

9

10

def __init__(self, stream=None, errors: str = 'raise'):

11

"""

12

Create NMEAStreamReader object.

13

14

Args:

15

stream: File-like object with readline() method (optional)

16

errors: Error handling behavior:

17

- 'raise': Raise exception on parse errors (default)

18

- 'yield': Yield ParseError objects as stream elements

19

- 'ignore': Skip parse errors silently

20

"""

21

22

def next(self, data: str = None) -> Iterator[NMEASentence]:

23

"""

24

Parse data and yield NMEA sentence objects.

25

26

Args:

27

data: Optional string data to parse. If None, reads from stream.

28

29

Yields:

30

NMEASentence objects or ParseError objects (if errors='yield')

31

"""

32

33

def __iter__(self) -> Iterator[List[NMEASentence]]:

34

"""Iterator protocol support for use in for loops."""

35

36

def __next__(self) -> List[NMEASentence]:

37

"""Python 3 iterator protocol."""

38

```

39

40

### Usage Examples

41

42

```python

43

import pynmea2

44

import io

45

46

# Stream processing with string data

47

nmea_data = """$GPGGA,184353.07,1929.045,S,02410.506,E,1,04,2.6,100.00,M,-33.9,M,,0000*6D

48

$GPRMC,184353.07,A,1929.045,S,02410.506,E,0.13,309.62,120598,,A*70

49

invalid sentence

50

$GPGLL,1929.045,S,02410.506,E,184353.07,A,A*4C"""

51

52

stream = io.StringIO(nmea_data)

53

reader = pynmea2.NMEAStreamReader(stream, errors='ignore')

54

55

for batch in reader:

56

for msg in batch:

57

print(f"{type(msg).__name__}: {msg}")

58

59

# Manual data feeding

60

reader = pynmea2.NMEAStreamReader(errors='yield')

61

for sentence in reader.next("$GPGGA,184353.07,1929.045,S,02410.506,E,1,04,2.6,100.00,M,-33.9,M,,0000*6D\n"):

62

if isinstance(sentence, pynmea2.ParseError):

63

print(f"Parse error: {sentence}")

64

else:

65

print(f"Parsed: {sentence}")

66

67

# File processing with error handling

68

with open('nmea_log.txt', 'r') as f:

69

reader = pynmea2.NMEAStreamReader(f, errors='raise')

70

try:

71

for batch in reader:

72

for msg in batch:

73

print(f"Position: {getattr(msg, 'latitude', 'N/A')}, {getattr(msg, 'longitude', 'N/A')}")

74

except pynmea2.ParseError as e:

75

print(f"Failed to parse: {e}")

76

```

77

78

## NMEAFile

79

80

```python { .api }

81

class NMEAFile:

82

"""File reader for NMEA sentences with file-like interface."""

83

84

def __init__(self, f, *args, **kwargs):

85

"""

86

Open NMEA file for reading.

87

88

Args:

89

f: File path string or file-like object

90

*args, **kwargs: Additional arguments passed to open() if f is a path

91

"""

92

93

def open(self, fp: str, mode: str = 'r'):

94

"""Open file at specified path."""

95

96

def close(self):

97

"""Close the file."""

98

99

def __iter__(self) -> Iterator[NMEASentence]:

100

"""Iterate through file yielding NMEA sentences."""

101

102

def next(self) -> NMEASentence:

103

"""Read next NMEA sentence from file."""

104

105

def readline(self) -> NMEASentence:

106

"""Read next NMEA sentence (alias for next())."""

107

108

def read(self) -> List[NMEASentence]:

109

"""Read all sentences as list."""

110

111

def parse(self, s: str) -> NMEASentence:

112

"""Parse single sentence string."""

113

114

def __enter__(self):

115

"""Context manager entry."""

116

117

def __exit__(self, exc_type, exc_val, exc_tb):

118

"""Context manager exit."""

119

```

120

121

### Usage Examples

122

123

```python

124

import pynmea2

125

126

# Read NMEA file with context manager

127

with pynmea2.NMEAFile('gps_log.nmea') as nmea_file:

128

for sentence in nmea_file:

129

if hasattr(sentence, 'latitude'):

130

print(f"Position: {sentence.latitude}, {sentence.longitude}")

131

132

# Read all sentences at once

133

nmea_file = pynmea2.NMEAFile('gps_log.nmea')

134

all_sentences = nmea_file.read()

135

nmea_file.close()

136

137

print(f"Total sentences: {len(all_sentences)}")

138

gga_sentences = [s for s in all_sentences if isinstance(s, pynmea2.GGA)]

139

print(f"GGA sentences: {len(gga_sentences)}")

140

141

# Read file line by line

142

nmea_file = pynmea2.NMEAFile('gps_log.nmea')

143

try:

144

while True:

145

sentence = nmea_file.next()

146

print(sentence)

147

except StopIteration:

148

pass

149

finally:

150

nmea_file.close()

151

152

# Open file with custom parameters

153

nmea_file = pynmea2.NMEAFile('gps_log.nmea', mode='r', encoding='utf-8')

154

```

155

156

## Serial Port Processing

157

158

```python

159

import pynmea2

160

import serial

161

import io

162

163

# Process NMEA data from serial GPS device

164

ser = serial.Serial('/dev/ttyUSB0', 4800, timeout=5.0)

165

sio = io.TextIOWrapper(io.BufferedRWPair(ser, ser))

166

167

reader = pynmea2.NMEAStreamReader(sio, errors='ignore')

168

169

try:

170

for batch in reader:

171

for msg in batch:

172

if isinstance(msg, pynmea2.GGA) and msg.is_valid:

173

print(f"GPS Fix: {msg.latitude:.6f}, {msg.longitude:.6f}")

174

print(f"Altitude: {msg.altitude}m, Satellites: {msg.num_sats}")

175

elif isinstance(msg, pynmea2.RMC) and msg.is_valid:

176

print(f"Speed: {msg.spd_over_grnd} knots, Course: {msg.true_course}°")

177

178

except KeyboardInterrupt:

179

print("Stopping GPS monitoring")

180

finally:

181

ser.close()

182

```

183

184

## Error Handling Strategies

185

186

### Raise Errors (Default)

187

188

```python

189

reader = pynmea2.NMEAStreamReader(stream, errors='raise')

190

try:

191

for batch in reader:

192

for msg in batch:

193

process_message(msg)

194

except pynmea2.ParseError as e:

195

print(f"Parse failed: {e}")

196

# Handle error and potentially continue

197

```

198

199

### Yield Errors

200

201

```python

202

reader = pynmea2.NMEAStreamReader(stream, errors='yield')

203

for batch in reader:

204

for item in batch:

205

if isinstance(item, pynmea2.ParseError):

206

print(f"Skipping bad sentence: {item}")

207

else:

208

process_message(item)

209

```

210

211

### Ignore Errors

212

213

```python

214

reader = pynmea2.NMEAStreamReader(stream, errors='ignore')

215

for batch in reader:

216

for msg in batch:

217

# Only valid sentences are yielded

218

process_message(msg)

219

```

220

221

## Performance Considerations

222

223

```python

224

import pynmea2

225

226

# Efficient processing of large files

227

def process_large_nmea_file(filename):

228

gga_count = 0

229

positions = []

230

231

with pynmea2.NMEAFile(filename) as f:

232

for sentence in f:

233

if isinstance(sentence, pynmea2.GGA) and sentence.is_valid:

234

gga_count += 1

235

positions.append((sentence.latitude, sentence.longitude))

236

237

# Process in batches to manage memory

238

if len(positions) >= 1000:

239

process_position_batch(positions)

240

positions.clear()

241

242

# Process remaining positions

243

if positions:

244

process_position_batch(positions)

245

246

return gga_count

247

248

def process_position_batch(positions):

249

# Batch processing logic

250

pass

251

```