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

core-parsing.mddocs/

0

# Core Parsing and Generation

1

2

The core parsing system in pynmea2 provides functions and classes for converting between NMEA sentence strings and structured Python objects. This includes parsing incoming NMEA data, generating NMEA strings from data, and validating checksums.

3

4

## Main Parse Function

5

6

```python { .api }

7

def parse(line: str, check: bool = False) -> NMEASentence:

8

"""

9

Parse a string representing a NMEA 0183 sentence.

10

11

Args:

12

line: NMEA sentence string (leading '$' optional, trailing whitespace ignored)

13

check: If True, raise ChecksumError if checksum is missing

14

15

Returns:

16

NMEASentence object of appropriate subclass

17

18

Raises:

19

ParseError: If string cannot be parsed

20

ChecksumError: If checksum validation fails or missing when check=True

21

SentenceTypeError: If sentence type is not recognized

22

"""

23

```

24

25

### Usage Examples

26

27

```python

28

import pynmea2

29

30

# Parse with checksum validation (default)

31

msg = pynmea2.parse("$GPGGA,184353.07,1929.045,S,02410.506,E,1,04,2.6,100.00,M,-33.9,M,,0000*6D")

32

print(type(msg)) # <class 'pynmea2.types.talker.GGA'>

33

34

# Parse without requiring checksum

35

msg = pynmea2.parse("$GPGGA,184353.07,1929.045,S,02410.506,E,1,04,2.6,100.00,M,-33.9,M,,0000", check=False)

36

37

# Parse with strict checksum requirement

38

try:

39

msg = pynmea2.parse("$GPGGA,184353.07,1929.045,S,02410.506,E,1,04,2.6,100.00,M,-33.9,M,,0000", check=True)

40

except pynmea2.ChecksumError:

41

print("Checksum missing - required when check=True")

42

```

43

44

## Base NMEASentence Class

45

46

```python { .api }

47

class NMEASentence:

48

"""Base class for all NMEA sentence types."""

49

50

data: List[str]

51

sentence_types: Dict[str, Type['NMEASentence']]

52

53

@staticmethod

54

def parse(line: str, check: bool = False) -> 'NMEASentence':

55

"""

56

Parse NMEA sentence string into appropriate sentence object.

57

58

Args:

59

line: NMEA sentence string

60

check: Require checksum validation

61

62

Returns:

63

Appropriate NMEASentence subclass instance

64

"""

65

66

@staticmethod

67

def checksum(nmea_str: str) -> int:

68

"""

69

Calculate XOR checksum for NMEA string.

70

71

Args:

72

nmea_str: NMEA string without '$' or checksum

73

74

Returns:

75

Calculated checksum as integer

76

"""

77

78

def render(self, checksum: bool = True, dollar: bool = True, newline: Union[bool, str] = False) -> str:

79

"""

80

Render sentence as NMEA string.

81

82

Args:

83

checksum: Include checksum (*HH format)

84

dollar: Include leading '$'

85

newline: Include trailing newline (True = \\r\\n, str = custom)

86

87

Returns:

88

Formatted NMEA sentence string

89

"""

90

91

def identifier(self) -> str:

92

"""Return string identifier for sentence type (abstract method)."""

93

94

def __str__(self) -> str:

95

"""Return rendered NMEA sentence with checksum and dollar sign."""

96

97

def __repr__(self) -> str:

98

"""Return detailed representation showing field names and values."""

99

```

100

101

### Usage Examples

102

103

```python

104

import pynmea2

105

106

# Parse sentence

107

msg = pynmea2.parse("$GPGGA,184353.07,1929.045,S,02410.506,E,1,04,2.6,100.00,M,-33.9,M,,0000*6D")

108

109

# Generate NMEA string with different formatting options

110

print(msg.render()) # $GPGGA,184353.07,1929.045,S,02410.506,E,1,04,2.6,100.00,M,-33.9,M,,0000*6D

111

print(msg.render(checksum=False)) # $GPGGA,184353.07,1929.045,S,02410.506,E,1,04,2.6,100.00,M,-33.9,M,,0000

112

print(msg.render(dollar=False)) # GPGGA,184353.07,1929.045,S,02410.506,E,1,04,2.6,100.00,M,-33.9,M,,0000*6D

113

print(msg.render(newline=True)) # $GPGGA,184353.07,1929.045,S,02410.506,E,1,04,2.6,100.00,M,-33.9,M,,0000*6D\r\n

114

115

# Calculate checksum manually

116

nmea_str = "GPGGA,184353.07,1929.045,S,02410.506,E,1,04,2.6,100.00,M,-33.9,M,,0000"

117

checksum = pynmea2.NMEASentence.checksum(nmea_str)

118

print(f"Checksum: {checksum:02X}") # Checksum: 6D

119

120

# String representations

121

print(str(msg)) # $GPGGA,184353.07,1929.045,S,02410.506,E,1,04,2.6,100.00,M,-33.9,M,,0000*6D

122

print(repr(msg)) # <GGA(timestamp=datetime.time(18, 43, 53), lat='1929.045', ...)>

123

```

124

125

## TalkerSentence Class

126

127

```python { .api }

128

class TalkerSentence(NMEASentence):

129

"""Base class for standard NMEA talker sentences."""

130

131

talker: str

132

sentence_type: str

133

data: List[str]

134

135

def __init__(self, talker: str, sentence_type: str, data: List[str]):

136

"""

137

Initialize talker sentence.

138

139

Args:

140

talker: Two-character talker ID (e.g., 'GP', 'GL', 'GA')

141

sentence_type: Three-character sentence type (e.g., 'GGA', 'RMC')

142

data: List of sentence field data as strings

143

"""

144

145

def identifier(self) -> str:

146

"""Return sentence identifier (e.g., 'GPGGA,')."""

147

```

148

149

### Usage Examples

150

151

```python

152

import pynmea2

153

154

# Create GGA sentence manually

155

gga_data = ['184353.07', '1929.045', 'S', '02410.506', 'E', '1', '04', '2.6', '100.00', 'M', '-33.9', 'M', '', '0000']

156

msg = pynmea2.GGA('GP', 'GGA', gga_data)

157

158

print(msg.talker) # 'GP'

159

print(msg.sentence_type) # 'GGA'

160

print(msg.identifier()) # 'GPGGA,'

161

print(str(msg)) # $GPGGA,184353.07,1929.045,S,02410.506,E,1,04,2.6,100.00,M,-33.9,M,,0000*6D

162

```

163

164

## ProprietarySentence Class

165

166

```python { .api }

167

class ProprietarySentence(NMEASentence):

168

"""Base class for proprietary manufacturer sentences."""

169

170

manufacturer: str

171

data: List[str]

172

173

def __init__(self, manufacturer: str, data: List[str]):

174

"""

175

Initialize proprietary sentence.

176

177

Args:

178

manufacturer: Three-character manufacturer code (e.g., 'ASH', 'GRM')

179

data: List of sentence field data as strings

180

"""

181

182

def identifier(self) -> str:

183

"""Return sentence identifier (e.g., 'PASH')."""

184

```

185

186

### Usage Examples

187

188

```python

189

import pynmea2

190

191

# Parse proprietary sentence

192

msg = pynmea2.parse("$PGRME,15.0,M,45.0,M,25.0,M*22")

193

print(type(msg)) # <class 'pynmea2.types.proprietary.grm.GRME'>

194

print(msg.manufacturer) # 'GRM'

195

print(msg.identifier()) # 'PGRM'

196

197

# Create proprietary sentence manually

198

data = ['15.0', 'M', '45.0', 'M', '25.0', 'M']

199

msg = pynmea2.GRME('GRM', data)

200

print(str(msg)) # $PGRME,15.0,M,45.0,M,25.0,M*22

201

```

202

203

## QuerySentence Class

204

205

```python { .api }

206

class QuerySentence(NMEASentence):

207

"""Class for NMEA query sentences."""

208

209

talker: str

210

listener: str

211

sentence_type: str

212

data: List[str]

213

214

def __init__(self, talker: str, listener: str, sentence_type: str):

215

"""

216

Initialize query sentence.

217

218

Args:

219

talker: Two-character querying device ID

220

listener: Two-character target device ID

221

sentence_type: Three-character requested sentence type

222

"""

223

224

def identifier(self) -> str:

225

"""Return query identifier (e.g., 'CCGPQ,GGA')."""

226

```

227

228

### Usage Examples

229

230

```python

231

import pynmea2

232

233

# Parse query sentence

234

msg = pynmea2.parse("$CCGPQ,GGA")

235

print(type(msg)) # <class 'pynmea2.nmea.QuerySentence'>

236

print(msg.talker) # 'CC'

237

print(msg.listener) # 'GP'

238

print(msg.sentence_type) # 'GGA'

239

print(msg.identifier()) # 'CCGPQ,GGA'

240

241

# Create query sentence manually

242

query = pynmea2.QuerySentence('CC', 'GP', 'GGA')

243

print(str(query)) # $CCGPQ,GGA*27

244

```

245

246

## Field Access and Dynamic Properties

247

248

All sentence objects provide dynamic field access based on the sentence type's field definitions:

249

250

```python

251

import pynmea2

252

253

msg = pynmea2.parse("$GPGGA,184353.07,1929.045,S,02410.506,E,1,04,2.6,100.00,M,-33.9,M,,0000*6D")

254

255

# Access fields by name (defined in sentence class)

256

print(msg.timestamp) # datetime.time(18, 43, 53, 70000)

257

print(msg.lat) # '1929.045'

258

print(msg.lat_dir) # 'S'

259

print(msg.gps_qual) # '1'

260

print(msg.altitude) # 100.0

261

262

# Access raw field data by index

263

print(msg.data[0]) # '184353.07'

264

print(msg.data[1]) # '1929.045'

265

print(msg.data[2]) # 'S'

266

267

# Set field values (modifies data list)

268

msg.gps_qual = '2'

269

print(msg.gps_qual) # '2'

270

print(msg.data[5]) # '2'

271

```

272

273

## Error Handling

274

275

```python { .api }

276

class ParseError(ValueError):

277

"""Base exception for NMEA parsing errors."""

278

279

def __init__(self, message: str, data: str):

280

"""Initialize with error message and problematic data."""

281

282

class ChecksumError(ParseError):

283

"""Raised when NMEA sentence checksum validation fails."""

284

285

class SentenceTypeError(ParseError):

286

"""Raised when sentence type is not recognized."""

287

```

288

289

### Error Handling Examples

290

291

```python

292

import pynmea2

293

294

# Handle parse errors

295

try:

296

msg = pynmea2.parse("invalid nmea data")

297

except pynmea2.ParseError as e:

298

print(f"Parse error: {e.args[0]}") # Error message

299

print(f"Bad data: {e.args[1]}") # Raw data that failed

300

301

# Handle checksum errors

302

try:

303

msg = pynmea2.parse("$GPGGA,184353.07,1929.045,S,02410.506,E,1,04,2.6,100.00,M,-33.9,M,,0000*FF")

304

except pynmea2.ChecksumError as e:

305

print(f"Checksum error: {e}")

306

307

# Handle unknown sentence types

308

try:

309

msg = pynmea2.parse("$GPXYZ,some,unknown,sentence,type*12")

310

except pynmea2.SentenceTypeError as e:

311

print(f"Unknown sentence type: {e}")

312

```