example_aiogps.py 3.6 KB

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