gpscat 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. #!/usr/bin/env python
  2. #
  3. "Display GPS output. Hexify it if necessary."
  4. # This file is Copyright (c) 2010 by the GPSD project
  5. # SPDX-License-Identifier: BSD-2-clause
  6. # This code runs compatibly under Python 2 and 3.x for x >= 2.
  7. # Preserve this property!
  8. from __future__ import absolute_import, print_function, division
  9. import getopt
  10. import os
  11. import select
  12. import socket
  13. import string
  14. import sys
  15. import termios
  16. # pylint wants local modules last
  17. try:
  18. import gps
  19. import gps.packet as sniffer
  20. from gps.misc import BINARY_ENCODING
  21. except ImportError as e:
  22. sys.stderr.write(
  23. "gpscat: can't load Python gps libraries -- check PYTHONPATH.\n")
  24. sys.stderr.write("%s\n" % e)
  25. sys.exit(1)
  26. gps_version = '3.19.1~dev'
  27. if gps.__version__ != gps_version:
  28. sys.stderr.write("gpscat: ERROR: need gps module version %s, got %s\n" %
  29. (gps_version, gps.__version__))
  30. sys.exit(1)
  31. # The spec says 82, but some receivers (TN-200, GSW 2.3.2) output 86 characters
  32. # the Skyrtaq S2525F8 emits 100 chars
  33. NMEA_MAX = 102
  34. # Lowest debug level at which packet getter begins to emit messages, minus one
  35. BASELEVEL = sniffer.LOG_IO
  36. highhalf_latch = True
  37. PRINTABLE = set(bytearray(string.printable, encoding=BINARY_ENCODING))
  38. def hexdump(st):
  39. "Convert string to hex string"
  40. dmp = ""
  41. for ch in bytearray(st): # bytearray gets array of ints in Python 2 and 3
  42. if ch in PRINTABLE:
  43. dmp += chr(ch)
  44. else:
  45. dmp += "\\x%02x" % ch
  46. return dmp
  47. debuglevel = 0
  48. def reporter(errlevel, mesg):
  49. "Report errors, depending on log level"
  50. if errlevel <= debuglevel:
  51. sys.stdout.write(mesg)
  52. def printusage():
  53. "Print usage"
  54. sys.stderr.write("usage: gpscat [-D debuglevel] [-h] [-p] [-s speed] [-t] "
  55. "[-V] serial-port\n")
  56. if __name__ == '__main__':
  57. try:
  58. try:
  59. (options, arguments) = getopt.getopt(sys.argv[1:], "hps:tD:V")
  60. except getopt.GetoptError as msg:
  61. print("gpscat: " + str(msg))
  62. raise SystemExit(1)
  63. speed = None
  64. parity = None
  65. stopbits = None
  66. rawmode = True
  67. typeflag = False
  68. for (switch, val) in options:
  69. if switch == '-D':
  70. debuglevel = BASELEVEL + int(val)
  71. elif switch == '-h':
  72. printusage()
  73. raise SystemExit(0)
  74. elif switch == '-p':
  75. rawmode = False
  76. elif switch == '-s':
  77. if val[-2] in ('N', 'E', 'O'):
  78. parity = val[-2]
  79. stopbits = int(val[-1])
  80. val = val[:-2]
  81. speed = int(val)
  82. elif switch == '-t':
  83. typeflag = True
  84. rawmode = False
  85. elif switch == '-V':
  86. sys.stderr.write("gpscat: Version %s\n" % gps_version)
  87. sys.exit(0)
  88. if len(arguments) != 1:
  89. printusage()
  90. raise SystemExit(1)
  91. if "rfcomm" in arguments[0]: # Bluetooth special case
  92. s = socket.socket(socket.AF_BLUETOOTH, socket.SOCK_STREAM,
  93. socket.BTPROTO_RFCOMM)
  94. s.connect((arguments[0], 1))
  95. tty = s.fileno()
  96. else: # Ordinary device
  97. tty = os.open(arguments[0], os.O_RDWR)
  98. if speed is not None:
  99. (iflag, oflag, cflag, lflag, ispeed, ospeed, cc) = \
  100. termios.tcgetattr(tty)
  101. try:
  102. ispeed = ospeed = eval("termios.B%d" % speed)
  103. except AttributeError:
  104. sys.stderr.write("gpscat: unknown baud rate %d\n" % speed)
  105. raise SystemExit(1)
  106. if stopbits:
  107. cflag &= ~termios.CSIZE
  108. cflag |= (termios.CS8, termios.CS7)[stopbits - 1]
  109. if parity:
  110. if parity == 'N':
  111. iflag &= ~termios.PARENB
  112. iflag &= ~termios.INPCK
  113. elif parity == 'O':
  114. iflag |= termios.INPCK
  115. cflag |= termios.PARENB
  116. cflag |= termios.PARODD
  117. elif parity == 'E':
  118. iflag |= termios.INPCK
  119. cflag |= termios.PARENB
  120. cflag &= ~termios.PARODD
  121. termios.tcsetattr(tty, termios.TCSANOW,
  122. [iflag, oflag, cflag, lflag, ispeed, ospeed, cc])
  123. if not rawmode:
  124. getter = sniffer.new()
  125. sniffer.register_report(reporter)
  126. seqno = 0
  127. while True:
  128. rlist, wlist, xlist = select.select([tty], [], [])
  129. if rlist == [tty]:
  130. if rawmode:
  131. buf = os.read(tty, NMEA_MAX)
  132. if not buf:
  133. break
  134. sys.stdout.write(hexdump(buf))
  135. else:
  136. (length, ptype, packet, counter) = getter.get(tty)
  137. seqno += 1
  138. if length == 0:
  139. break
  140. if typeflag:
  141. sys.stdout.write(repr(ptype) + " (" + repr(length) +
  142. "@" + repr(counter - length) + "): " +
  143. hexdump(packet))
  144. sys.stdout.write("\n")
  145. else:
  146. sys.stdout.write(hexdump(packet) + "\n")
  147. except KeyboardInterrupt:
  148. if rawmode:
  149. sys.stdout.write("\n")
  150. raise SystemExit(0)
  151. # Local variables:
  152. # mode: python
  153. # end: