MCPcopy Create free account
hub / github.com/PierreGode/Ragnar / GPSManager

Class GPSManager

gps_manager.py:208–727  ·  view source on GitHub ↗

Manages a GPS source (gpsd socket or direct NMEA serial), providing real-time position data.

Source from the content-addressed store, hash-verified

206
207 # Stage 0: gpsd socket. If gpsd is running it already owns the serial port,
208 # so trying to open that port directly would fail. Defer to gpsd instead.
209 sock = _try_gpsd()
210 if sock:
211 sock.close()
212 logger.debug("gpsd detected — using gpsd socket")
213 return 'gpsd'
214
215 # Build the exclude set first so by-id keyword matches don't accidentally
216 # return an Espressif device that just happens to have "gnss" in its
217 # product string (rare, but bounded by being explicit).
218 if os.path.isdir(by_id):
219 for entry in os.listdir(by_id):
220 path = _resolve(entry)
221 if _port_is_espressif(path):
222 exclude.add(path)
223
224 # Stage 1: by-id keyword match (most reliable — udev says it's a GPS).
225 if os.path.isdir(by_id):
226 for entry in os.listdir(by_id):
227 lower = entry.lower()
228 if any(kw in lower for kw in ('gps', 'u-blox', 'ublox', 'nmea', 'gnss', 'bn-', 'vk-')):
229 path = _resolve(entry)
230 if os.path.exists(path) and path not in exclude:
231 return path
232
233 # Stage 2: by-id symlinks that aren't ESP32 — try the NMEA probe on each.
234 # Catches modules whose product string doesn't include a GPS keyword
235 # (generic CP210x / CH340 / FTDI bridges with no GPS-specific marking).
236 if os.path.isdir(by_id):
237 for entry in sorted(os.listdir(by_id)):
238 path = _resolve(entry)
239 if path in exclude or not os.path.exists(path):
240 continue
241 if _probe_nmea(path):
242 return path
243
244 # Stage 3: raw device nodes — covers USB serial, native UART, and Raspberry
245 # Pi serial ports (/dev/ttyAMA0, /dev/serial0) that have no by-id symlink.
246 candidates = []
247 for pattern in ('/dev/ttyACM*', '/dev/ttyUSB*', '/dev/ttyS[0-9]*', '/dev/ttyAMA*'):
248 candidates.extend(glob.glob(pattern))
249 for fixed in ('/dev/serial0', '/dev/serial1'):
250 if os.path.exists(fixed):
251 candidates.append(fixed)
252 seen = set()
253 for dev in sorted(candidates):
254 real = os.path.realpath(dev)
255 if dev in exclude or real in exclude or real in seen:
256 continue
257 seen.add(real)
258 if _probe_nmea(dev):
259 return dev
260
261 return None
262
263
264class GPSManager:
265 """Manages a GPS source (gpsd socket or direct NMEA serial), providing real-time position data."""

Callers 1

startMethod · 0.90

Calls

no outgoing calls

Tested by

no test coverage detected