1#!/usr/local/bin/python3.8 2# -*- coding: utf-8 -*- 3 4# Copyright (c) 2019 Grand Joldes (grandwork2@yahoo.com). 5# 6# This file is Copyright (c) 2019 by the GPSD project 7# 8# SPDX-License-Identifier: BSD-2-clause 9 10# This code run compatibly under Python 3.x for x >= 6. 11 12""" 13Example of using the asyncio Python interface to GPSD. This example 14demonstrates error handling by the application code when aiogps is not 15configured to handle automatic re-connection. 16""" 17 18import asyncio 19import logging 20import gps.aiogps 21 22 23async def get_gps_updates(gpsd: gps.aiogps.aiogps) -> None: 24 """ Receives and prints messages from GPSD. 25 26 The GPS status information is updated within aiogps every time a new 27 message is received. 28 This function also demonstrates what error messages can be expected when 29 auto reconnection is not used in aiogps (reconnect = 0). 30 """ 31 while True: 32 try: 33 async for msg in gpsd: 34 # Print received message 35 logging.info(f'Received: {msg}') 36 except asyncio.CancelledError: 37 return 38 except asyncio.IncompleteReadError: 39 logging.info('Connection closed by server') 40 except asyncio.TimeoutError: 41 logging.error('Timeout waiting for gpsd to respond') 42 except Exception as exc: # pylint: disable=W0703 43 logging.error(f'Error: {exc}') 44 # Try again in 1s 45 await asyncio.sleep(1) 46 47 48async def print_gps_info(gpsd: gps.aiogps.aiogps) -> None: 49 """ Prints GPS status every 5s """ 50 while True: 51 try: 52 await asyncio.sleep(5) 53 logging.info(f'\nGPS status:\n{gpsd}') 54 except asyncio.CancelledError: 55 return 56 except Exception as exc: # pylint: disable=W0703 57 logging.error(f'Error: {exc}') 58 59 60async def main(): 61 """ Main coroutine - executes 2 asyncio tasks in parralel """ 62 try: 63 # Example of using custom connection configuration 64 async with gps.aiogps.aiogps( 65 connection_args={ 66 'host': '127.0.0.1', 67 'port': 2947 68 }, 69 connection_timeout=5, 70 reconnect=0, # do not reconnect, raise errors 71 alive_opts={ 72 'rx_timeout': 5 73 } 74 ) as gpsd: 75 # These tasks will be executed in parallel 76 await asyncio.gather( 77 get_gps_updates(gpsd), 78 print_gps_info(gpsd), 79 return_exceptions=True 80 ) 81 except asyncio.CancelledError: 82 return 83 except Exception as exc: # pylint: disable=W0703 84 logging.error(f'Error: {exc}') 85 86 87def run(): 88 """ 89 Main function. 90 91 Because this code only compiles on Python versions >= 3.6, 92 it is not run directly, but through the example_aiogps_run wrapper, 93 which fails gracefully on unsupported Python versions. 94 """ 95 # Set up logging program logging 96 logging.basicConfig() 97 logging.root.setLevel(logging.INFO) 98 # Example of setting up logging level for aiogps - this setting will 99 # prevent all aiogps events from being logged 100 logging.getLogger('gps.aiogps').setLevel(logging.CRITICAL) 101 loop = asyncio.events.new_event_loop() 102 try: 103 asyncio.events.set_event_loop(loop) 104 loop.run_until_complete(main()) 105 except KeyboardInterrupt: 106 print('Got keyboard interrupt.') 107 finally: 108 print('Exiting.') 109 try: 110 for task in asyncio.Task.all_tasks(): 111 task.cancel() 112 finally: 113 loop.run_until_complete(loop.shutdown_asyncgens()) 114 asyncio.events.set_event_loop(None) 115 loop.close() 116