Compare commits

...

23 commits

Author SHA1 Message Date
dherrada
98c0c22041 Fixed discord invite link 2020-07-08 16:49:04 -04:00
dherrada
486e055d55
Revert version to right version 2020-06-11 13:56:52 -04:00
dherrada
a117badd4d
Merge pull request #47 from fvzeppelin/master
stability improvements
2020-06-08 17:35:24 -04:00
Frank von Zeppelin
6f4cd1c41b change version to 3.6.3 2020-06-08 22:08:55 +02:00
Frank von Zeppelin
10a4a02794 black'ed 2020-06-08 21:10:47 +02:00
Frank von Zeppelin
ed11af0270 fixes 2020-06-01 20:50:58 +02:00
dherrada
67b8715f2f
Merge pull request #45 from adafruit/dherrada-patch-2
Fix typo (Needs testing)
2020-05-07 16:30:35 -04:00
dherrada
c19da5b839
Fix typo 2020-05-07 16:10:21 -04:00
Dan Halbert
82ecc0c9d5
Merge pull request #42 from dherrada/i2c-fix
Changed busio.i2c to board.i2c
2020-05-06 12:06:05 -04:00
Kattni
ebd10f1ad6
Update board.I2C() 2020-04-29 16:54:36 -04:00
Kattni
026be6a6a0
Update board.I2C() 2020-04-29 16:54:14 -04:00
Kattni
1d628c323b
Fixing board.I2C() 2020-04-29 16:53:55 -04:00
Scott Shawcroft
04f9254522
Merge pull request #43 from adafruit/black-update
Black reformatting with Python 3 target.
2020-04-09 09:35:51 -07:00
Kattni Rembor
8667df8f21 Black reformatting with Python 3 target. 2020-04-08 15:28:43 -04:00
sommersoft
368be93dc4 build.yml: add black formatting check
Signed-off-by: sommersoft <sommersoft@gmail.com>
2020-04-07 16:11:24 -05:00
dherrada
157fd77ca9 Changed busio.i2c to board.i2c 2020-03-27 14:05:46 -04:00
Kattni
b1752a6006
Merge pull request #41 from adafruit/pylint-update
Ran black, updated to pylint 2.x
2020-03-17 13:52:25 -04:00
dherrada
7a53465688 Ran black, updated to pylint 2.x 2020-03-16 14:57:40 -04:00
sommersoft
6368ff37a7 update code of coduct: discord moderation contact section
Signed-off-by: sommersoft <sommersoft@gmail.com>
2020-03-15 18:26:57 -05:00
Kattni
c768fe5f37
Merge pull request #40 from sommersoft/patch_coc
Update Code of Conduct
2020-03-13 15:40:34 -04:00
sommersoft
2c16e39fb0 update code of conduct 2020-03-13 13:38:36 -05:00
sommersoft
65847e345e update pylintrc for black
Signed-off-by: sommersoft <sommersoft@gmail.com>
2020-03-08 19:06:31 -05:00
sommersoft
8e9210d8f7 build.yml: move pylint, black, and Sphinx installs to each repo; add description to 'actions-ci/install.sh'
Signed-off-by: sommersoft <sommersoft@gmail.com>
2020-03-05 10:05:29 -06:00
11 changed files with 332 additions and 250 deletions

View file

@ -34,11 +34,18 @@ jobs:
with:
repository: adafruit/actions-ci-circuitpython-libs
path: actions-ci
- name: Install deps
- name: Install dependencies
# (e.g. - apt-get: gettext, etc; pip: circuitpython-build-tools, requirements.txt; etc.)
run: |
source actions-ci/install.sh
- name: Pip install pylint, black, & Sphinx
run: |
pip install --force-reinstall pylint black==19.10b0 Sphinx sphinx-rtd-theme
- name: Library version
run: git describe --dirty --always --tags
- name: Check formatting
run: |
black --check --target-version=py35 .
- name: PyLint
run: |
pylint $( find . -path './adafruit*.py' )

View file

@ -52,7 +52,7 @@ confidence=
# no Warning level messages displayed, use"--disable=all --enable=classes
# --disable=W"
# disable=import-error,print-statement,parameter-unpacking,unpacking-in-except,old-raise-syntax,backtick,long-suffix,old-ne-operator,old-octal-literal,import-star-module-level,raw-checker-failed,bad-inline-option,locally-disabled,locally-enabled,file-ignored,suppressed-message,useless-suppression,deprecated-pragma,apply-builtin,basestring-builtin,buffer-builtin,cmp-builtin,coerce-builtin,execfile-builtin,file-builtin,long-builtin,raw_input-builtin,reduce-builtin,standarderror-builtin,unicode-builtin,xrange-builtin,coerce-method,delslice-method,getslice-method,setslice-method,no-absolute-import,old-division,dict-iter-method,dict-view-method,next-method-called,metaclass-assignment,indexing-exception,raising-string,reload-builtin,oct-method,hex-method,nonzero-method,cmp-method,input-builtin,round-builtin,intern-builtin,unichr-builtin,map-builtin-not-iterating,zip-builtin-not-iterating,range-builtin-not-iterating,filter-builtin-not-iterating,using-cmp-argument,eq-without-hash,div-method,idiv-method,rdiv-method,exception-message-attribute,invalid-str-codec,sys-max-int,bad-python3-import,deprecated-string-function,deprecated-str-translate-call
disable=print-statement,parameter-unpacking,unpacking-in-except,old-raise-syntax,backtick,long-suffix,old-ne-operator,old-octal-literal,import-star-module-level,raw-checker-failed,bad-inline-option,locally-disabled,locally-enabled,file-ignored,suppressed-message,useless-suppression,deprecated-pragma,apply-builtin,basestring-builtin,buffer-builtin,cmp-builtin,coerce-builtin,execfile-builtin,file-builtin,long-builtin,raw_input-builtin,reduce-builtin,standarderror-builtin,unicode-builtin,xrange-builtin,coerce-method,delslice-method,getslice-method,setslice-method,no-absolute-import,old-division,dict-iter-method,dict-view-method,next-method-called,metaclass-assignment,indexing-exception,raising-string,reload-builtin,oct-method,hex-method,nonzero-method,cmp-method,input-builtin,round-builtin,intern-builtin,unichr-builtin,map-builtin-not-iterating,zip-builtin-not-iterating,range-builtin-not-iterating,filter-builtin-not-iterating,using-cmp-argument,eq-without-hash,div-method,idiv-method,rdiv-method,exception-message-attribute,invalid-str-codec,sys-max-int,bad-python3-import,deprecated-string-function,deprecated-str-translate-call,import-error
disable=print-statement,parameter-unpacking,unpacking-in-except,old-raise-syntax,backtick,long-suffix,old-ne-operator,old-octal-literal,import-star-module-level,raw-checker-failed,bad-inline-option,locally-disabled,locally-enabled,file-ignored,suppressed-message,useless-suppression,deprecated-pragma,apply-builtin,basestring-builtin,buffer-builtin,cmp-builtin,coerce-builtin,execfile-builtin,file-builtin,long-builtin,raw_input-builtin,reduce-builtin,standarderror-builtin,unicode-builtin,xrange-builtin,coerce-method,delslice-method,getslice-method,setslice-method,no-absolute-import,old-division,dict-iter-method,dict-view-method,next-method-called,metaclass-assignment,indexing-exception,raising-string,reload-builtin,oct-method,hex-method,nonzero-method,cmp-method,input-builtin,round-builtin,intern-builtin,unichr-builtin,map-builtin-not-iterating,zip-builtin-not-iterating,range-builtin-not-iterating,filter-builtin-not-iterating,using-cmp-argument,eq-without-hash,div-method,idiv-method,rdiv-method,exception-message-attribute,invalid-str-codec,sys-max-int,bad-python3-import,deprecated-string-function,deprecated-str-translate-call,import-error,bad-continuation
# Enable the message, report, category or checker with the given id(s). You can
# either give multiple identifier separated by comma (,) or put this option
@ -119,7 +119,8 @@ spelling-store-unknown-words=no
[MISCELLANEOUS]
# List of note tags to take in consideration, separated by a comma.
notes=FIXME,XXX,TODO
# notes=FIXME,XXX,TODO
notes=FIXME,XXX
[TYPECHECK]
@ -300,7 +301,7 @@ function-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$
# Good variable names which should always be accepted, separated by a comma
# good-names=i,j,k,ex,Run,_
good-names=r,g,b,i,j,k,n,ex,Run,_
good-names=r,g,b,w,i,j,k,n,x,y,z,ex,ok,Run,_
# Include a hint for the correct naming format with invalid-name
include-naming-hint=no
@ -422,7 +423,7 @@ max-returns=6
max-statements=50
# Minimum number of public methods for a class (see R0903).
min-public-methods=2
min-public-methods=1
[EXCEPTIONS]

View file

@ -34,13 +34,15 @@ Examples of unacceptable behavior by participants include:
* Excessive or unwelcome helping; answering outside the scope of the question
asked
* Trolling, insulting/derogatory comments, and personal or political attacks
* Promoting or spreading disinformation, lies, or conspiracy theories against
a person, group, organisation, project, or community
* Public or private harassment
* Publishing others' private information, such as a physical or electronic
address, without explicit permission
* Other conduct which could reasonably be considered inappropriate
The goal of the standards and moderation guidelines outlined here is to build
and maintain a respectful community. We ask that you dont just aim to be
and maintain a respectful community. We ask that you dont just aim to be
"technically unimpeachable", but rather try to be your best self.
We value many things beyond technical expertise, including collaboration and
@ -72,10 +74,10 @@ You may report in the following ways:
In any situation, you may send an email to <support@adafruit.com>.
On the Adafruit Discord, you may send an open message from any channel
to all Community Helpers by tagging @community helpers. You may also send an
open message from any channel, or a direct message to @kattni#1507,
@tannewt#4653, @Dan Halbert#1614, @cater#2442, @sommersoft#0222, or
@Andon#8175.
to all Community Moderators by tagging @community moderators. You may
also send an open message from any channel, or a direct message to
@kattni#1507, @tannewt#4653, @Dan Halbert#1614, @cater#2442,
@sommersoft#0222, @Mr. Certainly#0472 or @Andon#8175.
Email and direct message reports will be kept confidential.
@ -83,7 +85,7 @@ In situations on Discord where the issue is particularly egregious, possibly
illegal, requires immediate action, or violates the Discord terms of service,
you should also report the message directly to Discord.
These are the steps for upholding our communitys standards of conduct.
These are the steps for upholding our communitys standards of conduct.
1. Any member of the community may report any situation that violates the
Adafruit Community Code of Conduct. All reports will be reviewed and
@ -124,4 +126,4 @@ For other projects adopting the Adafruit Community Code of
Conduct, please contact the maintainers of those projects for enforcement.
If you wish to use this code of conduct for your own project, consider
explicitly mentioning your moderation policy or making a copy with your
own moderation policy so as to avoid confusion.
own moderation policy so as to avoid confusion.

View file

@ -7,7 +7,7 @@ Introduction
:alt: Documentation Status
.. image :: https://img.shields.io/discord/327254708534116352.svg
:target: https://discord.gg/nBQh6qu
:target: https://adafru.it/discord
:alt: Discord
.. image:: https://github.com/adafruit/Adafruit_CircuitPython_GPS/workflows/Build%20CI/badge.svg

View file

@ -62,34 +62,36 @@ def _parse_degrees(nmea_data):
raw = float(nmea_data)
deg = raw // 100
minutes = raw % 100
return deg + minutes/60
return deg + minutes / 60
def _parse_int(nmea_data):
if nmea_data is None or nmea_data == '':
if nmea_data is None or nmea_data == "":
return None
return int(nmea_data)
def _parse_float(nmea_data):
if nmea_data is None or nmea_data == '':
if nmea_data is None or nmea_data == "":
return None
return float(nmea_data)
def _parse_str(nmea_data):
if nmea_data is None or nmea_data == '':
if nmea_data is None or nmea_data == "":
return None
return str(nmea_data)
# lint warning about too many attributes disabled
#pylint: disable-msg=R0902
# pylint: disable-msg=R0902
class GPS:
"""GPS parsing module. Can parse simple NMEA data sentences from serial
GPS modules to read latitude, longitude, and more.
"""
def __init__(self, uart, debug=False):
self._uart = uart
# Initialize null starting values for GPS attributes.
@ -137,11 +139,14 @@ class GPS:
data_type, args = sentence
data_type = bytes(data_type.upper(), "ascii")
# return sentence
if data_type in (b'GPGLL', b'GNGGL'): # GLL, Geographic Position Latitude/Longitude
if data_type in (
b"GPGLL",
b"GNGLL",
): # GLL, Geographic Position Latitude/Longitude
self._parse_gpgll(args)
elif data_type in (b'GPRMC', b'GNRMC'): # RMC, minimum location info
elif data_type in (b"GPRMC", b"GNRMC"): # RMC, minimum location info
self._parse_gprmc(args)
elif data_type in (b'GPGGA', b'GNGGA'): # GGA, 3d location fix
elif data_type in (b"GPGGA", b"GNGGA"): # GGA, 3d location fix
self._parse_gpgga(args)
return True
@ -151,15 +156,15 @@ class GPS:
Note you should NOT add the leading $ and trailing * to the command
as they will automatically be added!
"""
self.write(b'$')
self.write(b"$")
self.write(command)
if add_checksum:
checksum = 0
for char in command:
checksum ^= char
self.write(b'*')
self.write(bytes('{:02x}'.format(checksum).upper(), "ascii"))
self.write(b'\r\n')
self.write(b"*")
self.write(bytes("{:02x}".format(checksum).upper(), "ascii"))
self.write(b"\r\n")
@property
def has_fix(self):
@ -213,18 +218,18 @@ class GPS:
return None
sentence = self.readline()
if sentence is None or sentence == b'' or len(sentence) < 1:
if sentence is None or sentence == b"" or len(sentence) < 1:
return None
try:
sentence = str(sentence, 'ascii').strip()
sentence = str(sentence, "ascii").strip()
except UnicodeError:
return None
# Look for a checksum and validate it if present.
if len(sentence) > 7 and sentence[-3] == '*':
if len(sentence) > 7 and sentence[-3] == "*":
# Get included checksum, then calculate it and compare.
expected = int(sentence[-2:], 16)
actual = 0
for i in range(1, len(sentence)-3):
for i in range(1, len(sentence) - 3):
actual ^= ord(sentence[i])
if actual != expected:
return None # Failed to validate checksum.
@ -247,25 +252,27 @@ class GPS:
sentence = sentence[:-3]
# Parse out the type of sentence (first string after $ up to comma)
# and then grab the rest as data within the sentence.
delimiter = sentence.find(',')
delimiter = sentence.find(",")
if delimiter == -1:
return None # Invalid sentence, no comma after data type.
data_type = sentence[1:delimiter]
return (data_type, sentence[delimiter+1:])
return (data_type, sentence[delimiter + 1 :])
def _parse_gpgll(self, args):
data = args.split(',')
if data is None or data[0] is None:
data = args.split(",")
if data is None or data[0] is None or (data[0] == ""):
return # Unexpected number of params.
# Parse latitude and longitude.
self.latitude = _parse_degrees(data[0])
if self.latitude is not None and \
data[1] is not None and data[1].lower() == 's':
if self.latitude is not None and data[1] is not None and data[1].lower() == "s":
self.latitude *= -1.0
self.longitude = _parse_degrees(data[2])
if self.longitude is not None and \
data[3] is not None and data[3].lower() == 'w':
if (
self.longitude is not None
and data[3] is not None
and data[3].lower() == "w"
):
self.longitude *= -1.0
time_utc = int(_parse_int(float(data[4])))
if time_utc is not None:
@ -274,19 +281,21 @@ class GPS:
secs = time_utc % 100
# Set or update time to a friendly python time struct.
if self.timestamp_utc is not None:
self.timestamp_utc = time.struct_time((
0, 0, 0, hours, mins, secs, 0, 0, -1))
self.timestamp_utc = time.struct_time(
(0, 0, 0, hours, mins, secs, 0, 0, -1)
)
else:
self.timestamp_utc = time.struct_time((0, 0, 0, hours, mins,
secs, 0, 0, -1))
self.timestamp_utc = time.struct_time(
(0, 0, 0, hours, mins, secs, 0, 0, -1)
)
# Parse data active or void
self.isactivedata = _parse_str(data[5])
def _parse_gprmc(self, args):
# Parse the arguments (everything after data type) for NMEA GPRMC
# minimum location fix sentence.
data = args.split(',')
if data is None or len(data) < 11 or data[0] is None:
data = args.split(",")
if data is None or len(data) < 11 or data[0] is None or (data[0] == ""):
return # Unexpected number of params.
# Parse fix time.
time_utc = int(_parse_float(data[0]))
@ -296,25 +305,38 @@ class GPS:
secs = time_utc % 100
# Set or update time to a friendly python time struct.
if self.timestamp_utc is not None:
self.timestamp_utc = time.struct_time((
self.timestamp_utc.tm_year, self.timestamp_utc.tm_mon,
self.timestamp_utc.tm_mday, hours, mins, secs, 0, 0, -1))
self.timestamp_utc = time.struct_time(
(
self.timestamp_utc.tm_year,
self.timestamp_utc.tm_mon,
self.timestamp_utc.tm_mday,
hours,
mins,
secs,
0,
0,
-1,
)
)
else:
self.timestamp_utc = time.struct_time((0, 0, 0, hours, mins,
secs, 0, 0, -1))
self.timestamp_utc = time.struct_time(
(0, 0, 0, hours, mins, secs, 0, 0, -1)
)
# Parse status (active/fixed or void).
status = data[1]
self.fix_quality = 0
if status is not None and status.lower() == 'a':
if status is not None and status.lower() == "a":
self.fix_quality = 1
# Parse latitude and longitude.
self.latitude = _parse_degrees(data[2])
if self.latitude is not None and \
data[3] is not None and data[3].lower() == 's':
if self.latitude is not None and data[3] is not None and data[3].lower() == "s":
self.latitude *= -1.0
self.longitude = _parse_degrees(data[4])
if self.longitude is not None and \
data[5] is not None and data[5].lower() == 'w':
if (
self.longitude is not None
and data[5] is not None
and data[5].lower() == "w"
):
self.longitude *= -1.0
# Parse out speed and other simple numeric values.
self.speed_knots = _parse_float(data[6])
@ -324,28 +346,35 @@ class GPS:
day = int(data[8][0:2])
month = int(data[8][2:4])
year = 2000 + int(data[8][4:6]) # Y2k bug, 2 digit year assumption.
# This is a problem with the NMEA
# spec and not this code.
# This is a problem with the NMEA
# spec and not this code.
if self.timestamp_utc is not None:
# Replace the timestamp with an updated one.
# (struct_time is immutable and can't be changed in place)
self.timestamp_utc = time.struct_time((year, month, day,
self.timestamp_utc.tm_hour,
self.timestamp_utc.tm_min,
self.timestamp_utc.tm_sec,
0,
0,
-1))
self.timestamp_utc = time.struct_time(
(
year,
month,
day,
self.timestamp_utc.tm_hour,
self.timestamp_utc.tm_min,
self.timestamp_utc.tm_sec,
0,
0,
-1,
)
)
else:
# Time hasn't been set so create it.
self.timestamp_utc = time.struct_time((year, month, day, 0, 0,
0, 0, 0, -1))
self.timestamp_utc = time.struct_time(
(year, month, day, 0, 0, 0, 0, 0, -1)
)
def _parse_gpgga(self, args):
# Parse the arguments (everything after data type) for NMEA GPGGA
# 3D location fix sentence.
data = args.split(',')
if data is None or len(data) != 14:
data = args.split(",")
if data is None or len(data) != 14 or (data[0] == ""):
return # Unexpected number of params.
# Parse fix time.
time_utc = int(_parse_float(data[0]))
@ -355,20 +384,33 @@ class GPS:
secs = time_utc % 100
# Set or update time to a friendly python time struct.
if self.timestamp_utc is not None:
self.timestamp_utc = time.struct_time((
self.timestamp_utc.tm_year, self.timestamp_utc.tm_mon,
self.timestamp_utc.tm_mday, hours, mins, secs, 0, 0, -1))
self.timestamp_utc = time.struct_time(
(
self.timestamp_utc.tm_year,
self.timestamp_utc.tm_mon,
self.timestamp_utc.tm_mday,
hours,
mins,
secs,
0,
0,
-1,
)
)
else:
self.timestamp_utc = time.struct_time((0, 0, 0, hours, mins,
secs, 0, 0, -1))
self.timestamp_utc = time.struct_time(
(0, 0, 0, hours, mins, secs, 0, 0, -1)
)
# Parse latitude and longitude.
self.latitude = _parse_degrees(data[1])
if self.latitude is not None and \
data[2] is not None and data[2].lower() == 's':
if self.latitude is not None and data[2] is not None and data[2].lower() == "s":
self.latitude *= -1.0
self.longitude = _parse_degrees(data[3])
if self.longitude is not None and \
data[4] is not None and data[4].lower() == 'w':
if (
self.longitude is not None
and data[4] is not None
and data[4].lower() == "w"
):
self.longitude *= -1.0
# Parse out fix quality and other simple numeric values.
self.fix_quality = _parse_int(data[5])
@ -378,8 +420,8 @@ class GPS:
self.height_geoid = _parse_float(data[10])
def _parse_gpgsa(self, args):
data = args.split(',')
if data is None:
data = args.split(",")
if data is None or (data[0] == ""):
return # Unexpected number of params
# Parse selection mode
@ -401,8 +443,8 @@ class GPS:
def _parse_gpgsv(self, args):
# Parse the arguments (everything after data type) for NMEA GPGGA
# 3D location fix sentence.
data = args.split(',')
if data is None:
data = args.split(",")
if data is None or (data[0] == ""):
return # Unexpected number of params.
# Parse number of messages
@ -418,13 +460,13 @@ class GPS:
sat_tup = data[3:]
satdict = {}
for i in range(len(sat_tup)/4):
j = i*4
key = "gps{}".format(i+(4*(self.mess_num-1)))
satnum = _parse_int(sat_tup[0+j]) # Satellite number
satdeg = _parse_int(sat_tup[1+j]) # Elevation in degrees
satazim = _parse_int(sat_tup[2+j]) # Azimuth in degrees
satsnr = _parse_int(sat_tup[3+j]) # signal-to-noise ratio in dB
for i in range(len(sat_tup) / 4):
j = i * 4
key = "gps{}".format(i + (4 * (self.mess_num - 1)))
satnum = _parse_int(sat_tup[0 + j]) # Satellite number
satdeg = _parse_int(sat_tup[1 + j]) # Elevation in degrees
satazim = _parse_int(sat_tup[2 + j]) # Azimuth in degrees
satsnr = _parse_int(sat_tup[3 + j]) # signal-to-noise ratio in dB
value = (satnum, satdeg, satazim, satsnr)
satdict[key] = value
@ -446,14 +488,18 @@ class GPS:
pass
self.satellites_prev = self.satellites
class GPS_GtopI2C(GPS):
"""GTop-compatible I2C GPS parsing module. Can parse simple NMEA data
sentences from an I2C-capable GPS module to read latitude, longitude, and more.
"""
def __init__(self, i2c_bus, *, address=_GPSI2C_DEFAULT_ADDRESS, debug=False,
timeout=5):
import adafruit_bus_device.i2c_device as i2c_device
super().__init__(None, debug) # init the parent with no UART
def __init__(
self, i2c_bus, *, address=_GPSI2C_DEFAULT_ADDRESS, debug=False, timeout=5
):
import adafruit_bus_device.i2c_device as i2c_device # pylint: disable=import-outside-toplevel
super().__init__(None, debug) # init the parent with no UART
self._i2c = i2c_device.I2CDevice(i2c_bus, address)
self._lastbyte = None
self._charbuff = bytearray(1)
@ -470,8 +516,8 @@ class GPS_GtopI2C(GPS):
# 'stuffed' newlines and then append to our result array for byteification
i2c.readinto(self._charbuff)
char = self._charbuff[0]
if (char == ord('\n')) and (self._lastbyte != ord('\r')):
continue # skip duplicate \n's!
if (char == ord("\n")) and (self._lastbyte != ord("\r")):
continue # skip duplicate \n's!
result.append(char)
self._lastbyte = char # keep track of the last character approved
return bytearray(result)
@ -494,15 +540,15 @@ class GPS_GtopI2C(GPS):
timeout = time.monotonic() + self._timeout
while timeout > time.monotonic():
# check if our internal buffer has a '\n' termination already
if self._internalbuffer and (self._internalbuffer[-1] == ord('\n')):
if self._internalbuffer and (self._internalbuffer[-1] == ord("\n")):
break
char = self.read(1)
if not char:
continue
self._internalbuffer.append(char[0])
#print(bytearray(self._internalbuffer))
if self._internalbuffer and self._internalbuffer[-1] == ord('\n'):
# print(bytearray(self._internalbuffer))
if self._internalbuffer and self._internalbuffer[-1] == ord("\n"):
ret = bytearray(self._internalbuffer)
self._internalbuffer = [] # reset the buffer to empty
self._internalbuffer = [] # reset the buffer to empty
return ret
return None # no completed data yet

View file

@ -2,7 +2,8 @@
import os
import sys
sys.path.insert(0, os.path.abspath('..'))
sys.path.insert(0, os.path.abspath(".."))
# -- General configuration ------------------------------------------------
@ -10,34 +11,37 @@ sys.path.insert(0, os.path.abspath('..'))
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = [
'sphinx.ext.autodoc',
'sphinx.ext.intersphinx',
'sphinx.ext.viewcode',
"sphinx.ext.autodoc",
"sphinx.ext.intersphinx",
"sphinx.ext.viewcode",
]
intersphinx_mapping = {'python': ('https://docs.python.org/3.4', None),'CircuitPython': ('https://circuitpython.readthedocs.io/en/latest/', None)}
intersphinx_mapping = {
"python": ("https://docs.python.org/3.4", None),
"CircuitPython": ("https://circuitpython.readthedocs.io/en/latest/", None),
}
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
templates_path = ["_templates"]
source_suffix = '.rst'
source_suffix = ".rst"
# The master toctree document.
master_doc = 'index'
master_doc = "index"
# General information about the project.
project = u'Adafruit GPS Library'
copyright = u'2017 Tony DiCola'
author = u'Tony DiCola'
project = "Adafruit GPS Library"
copyright = "2017 Tony DiCola"
author = "Tony DiCola"
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The short X.Y version.
version = u'1.0'
version = "1.0"
# The full version, including alpha/beta/rc tags.
release = u'1.0'
release = "1.0"
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
@ -49,7 +53,7 @@ language = None
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
# This patterns also effect to html_static_path and html_extra_path
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store', '.env', 'CODE_OF_CONDUCT.md']
exclude_patterns = ["_build", "Thumbs.db", ".DS_Store", ".env", "CODE_OF_CONDUCT.md"]
# The reST default role (used for this markup: `text`) to use for all
# documents.
@ -61,7 +65,7 @@ default_role = "any"
add_function_parentheses = True
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'
pygments_style = "sphinx"
# If true, `todo` and `todoList` produce output, else they produce nothing.
todo_include_todos = False
@ -75,59 +79,62 @@ todo_emit_warnings = True
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
#
on_rtd = os.environ.get('READTHEDOCS', None) == 'True'
on_rtd = os.environ.get("READTHEDOCS", None) == "True"
if not on_rtd: # only import and set the theme if we're building docs locally
try:
import sphinx_rtd_theme
html_theme = 'sphinx_rtd_theme'
html_theme_path = [sphinx_rtd_theme.get_html_theme_path(), '.']
html_theme = "sphinx_rtd_theme"
html_theme_path = [sphinx_rtd_theme.get_html_theme_path(), "."]
except:
html_theme = 'default'
html_theme_path = ['.']
html_theme = "default"
html_theme_path = ["."]
else:
html_theme_path = ['.']
html_theme_path = ["."]
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']
html_static_path = ["_static"]
# The name of an image file (relative to this directory) to use as a favicon of
# the docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
# pixels large.
#
html_favicon = '_static/favicon.ico'
html_favicon = "_static/favicon.ico"
# Output file base name for HTML help builder.
htmlhelp_basename = 'AdafruitGPSLibrarydoc'
htmlhelp_basename = "AdafruitGPSLibrarydoc"
# -- Options for LaTeX output ---------------------------------------------
latex_elements = {
# The paper size ('letterpaper' or 'a4paper').
#
# 'papersize': 'letterpaper',
# The font size ('10pt', '11pt' or '12pt').
#
# 'pointsize': '10pt',
# Additional stuff for the LaTeX preamble.
#
# 'preamble': '',
# Latex figure (float) alignment
#
# 'figure_align': 'htbp',
# The paper size ('letterpaper' or 'a4paper').
#
# 'papersize': 'letterpaper',
# The font size ('10pt', '11pt' or '12pt').
#
# 'pointsize': '10pt',
# Additional stuff for the LaTeX preamble.
#
# 'preamble': '',
# Latex figure (float) alignment
#
# 'figure_align': 'htbp',
}
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title,
# author, documentclass [howto, manual, or own class]).
latex_documents = [
(master_doc, 'AdafruitGPSLibrary.tex', u'Adafruit GPS Library Documentation',
author, 'manual'),
(
master_doc,
"AdafruitGPSLibrary.tex",
"Adafruit GPS Library Documentation",
author,
"manual",
),
]
# -- Options for manual page output ---------------------------------------
@ -135,8 +142,13 @@ latex_documents = [
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
(master_doc, 'adafruitGPSlibrary', u'Adafruit GPS Library Documentation',
[author], 1)
(
master_doc,
"adafruitGPSlibrary",
"Adafruit GPS Library Documentation",
[author],
1,
)
]
# -- Options for Texinfo output -------------------------------------------
@ -145,7 +157,13 @@ man_pages = [
# (source start file, target name, title, author,
# dir menu entry, description, category)
texinfo_documents = [
(master_doc, 'AdafruitGPSLibrary', u'Adafruit GPS Library Documentation',
author, 'AdafruitGPSLibrary', 'One line description of project.',
'Miscellaneous'),
(
master_doc,
"AdafruitGPSLibrary",
"Adafruit GPS Library Documentation",
author,
"AdafruitGPSLibrary",
"One line description of project.",
"Miscellaneous",
),
]

View file

@ -15,12 +15,12 @@ import adafruit_gps
# which means new lines are added at the end and all old data is kept.
# Change this path to point at internal storage (like '/gps.txt') or SD
# card mounted storage ('/sd/gps.txt') as desired.
LOG_FILE = 'gps.txt' # Example for writing to internal path gps.txt
LOG_FILE = "gps.txt" # Example for writing to internal path gps.txt
# File more for opening the log file. Mode 'ab' means append or add new lines
# to the end of the file rather than erasing it and starting over. If you'd
# like to erase the file and start clean each time use the value 'wb' instead.
LOG_MODE = 'ab'
LOG_MODE = "ab"
# If writing to SD card on a microcontroller customize and uncomment these
# lines to import the necessary library and initialize the SD card:
@ -47,15 +47,15 @@ uart = busio.UART(board.TX, board.RX, baudrate=9600, timeout=10)
# If using a USB/Serial converter, use pyserial and update the serial
# port name to match the serial connection for the GPS!
#import serial
#uart = serial.Serial("/dev/ttyUSB0", baudrate=9600, timeout=10)
# import serial
# uart = serial.Serial("/dev/ttyUSB0", baudrate=9600, timeout=10)
# If using I2C, we'll create an I2C interface to talk to using default pins
#i2c = busio.I2C(board.SCL, board.SDA)
# i2c = board.I2C()
# Create a GPS module instance.
gps = adafruit_gps.GPS(uart) # Use UART/pyserial
#gps = adafruit_gps.GPS_GtopI2C(i2c) # Use I2C interface
gps = adafruit_gps.GPS(uart) # Use UART/pyserial
# gps = adafruit_gps.GPS_GtopI2C(i2c) # Use I2C interface
# Main loop just reads data from the GPS module and writes it back out to
# the output file while also printing to serial output.
@ -64,6 +64,6 @@ with open(LOG_FILE, LOG_MODE) as outfile:
sentence = gps.readline()
if not sentence:
continue
print(str(sentence, 'ascii').strip())
print(str(sentence, "ascii").strip())
outfile.write(sentence)
outfile.flush()

View file

@ -14,15 +14,15 @@ import adafruit_gps
uart = busio.UART(board.TX, board.RX, baudrate=9600, timeout=10)
# for a computer, use the pyserial library for uart access
#import serial
#uart = serial.Serial("/dev/ttyUSB0", baudrate=9600, timeout=10)
# import serial
# uart = serial.Serial("/dev/ttyUSB0", baudrate=9600, timeout=10)
# If using I2C, we'll create an I2C interface to talk to using default pins
#i2c = busio.I2C(board.SCL, board.SDA)
# i2c = board.I2C()
# Create a GPS module instance.
gps = adafruit_gps.GPS(uart) # Use UART/pyserial
#gps = adafruit_gps.GPS_GtopI2C(i2c) # Use I2C interface
gps = adafruit_gps.GPS(uart) # Use UART/pyserial
# gps = adafruit_gps.GPS_GtopI2C(i2c) # Use I2C interface
# Initialize the GPS module by changing what data it sends and at what rate.
# These are NMEA extensions for PMTK_314_SET_NMEA_OUTPUT and
@ -31,22 +31,22 @@ gps = adafruit_gps.GPS(uart) # Use UART/pyserial
# https://cdn-shop.adafruit.com/datasheets/PMTK_A11.pdf
# Turn on the basic GGA and RMC info (what you typically want)
gps.send_command(b'PMTK314,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0')
gps.send_command(b"PMTK314,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0")
# Turn on just minimum info (RMC only, location):
#gps.send_command(b'PMTK314,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0')
# gps.send_command(b'PMTK314,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0')
# Turn off everything:
#gps.send_command(b'PMTK314,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0')
# gps.send_command(b'PMTK314,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0')
# Tuen on everything (not all of it is parsed!)
#gps.send_command(b'PMTK314,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0')
# gps.send_command(b'PMTK314,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0')
# Set update rate to once a second (1hz) which is what you typically want.
gps.send_command(b'PMTK220,1000')
gps.send_command(b"PMTK220,1000")
# Or decrease to once every two seconds by doubling the millisecond value.
# Be sure to also increase your UART timeout above!
#gps.send_command(b'PMTK220,2000')
# gps.send_command(b'PMTK220,2000')
# You can also speed up the rate, but don't go too fast or else you can lose
# data during parsing. This would be twice a second (2hz, 500ms delay):
#gps.send_command(b'PMTK220,500')
# gps.send_command(b'PMTK220,500')
# Main loop runs forever printing data as it comes in
timestamp = time.monotonic()
@ -56,10 +56,10 @@ while True:
if data is not None:
# convert bytearray to string
data_string = ''.join([chr(b) for b in data])
data_string = "".join([chr(b) for b in data])
print(data_string, end="")
if time.monotonic() - timestamp > 5:
# every 5 seconds...
gps.send_command(b'PMTK605') # request firmware version
gps.send_command(b"PMTK605") # request firmware version
timestamp = time.monotonic()

View file

@ -14,15 +14,15 @@ import adafruit_gps
uart = busio.UART(board.TX, board.RX, baudrate=9600, timeout=10)
# for a computer, use the pyserial library for uart access
#import serial
#uart = serial.Serial("/dev/ttyUSB0", baudrate=9600, timeout=10)
# import serial
# uart = serial.Serial("/dev/ttyUSB0", baudrate=9600, timeout=10)
# If using I2C, we'll create an I2C interface to talk to using default pins
#i2c = busio.I2C(board.SCL, board.SDA)
# i2c = board.I2C()
# Create a GPS module instance.
gps = adafruit_gps.GPS(uart, debug=False) # Use UART/pyserial
#gps = adafruit_gps.GPS_GtopI2C(i2c, debug=False) # Use I2C interface
gps = adafruit_gps.GPS(uart, debug=False) # Use UART/pyserial
# gps = adafruit_gps.GPS_GtopI2C(i2c, debug=False) # Use I2C interface
# Initialize the GPS module by changing what data it sends and at what rate.
# These are NMEA extensions for PMTK_314_SET_NMEA_OUTPUT and
@ -31,22 +31,22 @@ gps = adafruit_gps.GPS(uart, debug=False) # Use UART/pyserial
# https://cdn-shop.adafruit.com/datasheets/PMTK_A11.pdf
# Turn on the basic GGA and RMC info (what you typically want)
gps.send_command(b'PMTK314,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0')
gps.send_command(b"PMTK314,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0")
# Turn on just minimum info (RMC only, location):
#gps.send_command(b'PMTK314,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0')
# gps.send_command(b'PMTK314,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0')
# Turn off everything:
#gps.send_command(b'PMTK314,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0')
# gps.send_command(b'PMTK314,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0')
# Tuen on everything (not all of it is parsed!)
#gps.send_command(b'PMTK314,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0')
# gps.send_command(b'PMTK314,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0')
# Set update rate to once a second (1hz) which is what you typically want.
gps.send_command(b'PMTK220,1000')
gps.send_command(b"PMTK220,1000")
# Or decrease to once every two seconds by doubling the millisecond value.
# Be sure to also increase your UART timeout above!
#gps.send_command(b'PMTK220,2000')
# gps.send_command(b'PMTK220,2000')
# You can also speed up the rate, but don't go too fast or else you can lose
# data during parsing. This would be twice a second (2hz, 500ms delay):
#gps.send_command(b'PMTK220,500')
# gps.send_command(b'PMTK220,500')
# Main loop runs forever printing the location, etc. every second.
last_print = time.monotonic()
@ -62,32 +62,35 @@ while True:
last_print = current
if not gps.has_fix:
# Try again if we don't have a fix yet.
print('Waiting for fix...')
print("Waiting for fix...")
continue
# We have a fix! (gps.has_fix is true)
# Print out details about the fix like location, date, etc.
print('=' * 40) # Print a separator line.
print('Fix timestamp: {}/{}/{} {:02}:{:02}:{:02}'.format(
gps.timestamp_utc.tm_mon, # Grab parts of the time from the
gps.timestamp_utc.tm_mday, # struct_time object that holds
gps.timestamp_utc.tm_year, # the fix time. Note you might
gps.timestamp_utc.tm_hour, # not get all data like year, day,
gps.timestamp_utc.tm_min, # month!
gps.timestamp_utc.tm_sec))
print('Latitude: {0:.6f} degrees'.format(gps.latitude))
print('Longitude: {0:.6f} degrees'.format(gps.longitude))
print('Fix quality: {}'.format(gps.fix_quality))
print("=" * 40) # Print a separator line.
print(
"Fix timestamp: {}/{}/{} {:02}:{:02}:{:02}".format(
gps.timestamp_utc.tm_mon, # Grab parts of the time from the
gps.timestamp_utc.tm_mday, # struct_time object that holds
gps.timestamp_utc.tm_year, # the fix time. Note you might
gps.timestamp_utc.tm_hour, # not get all data like year, day,
gps.timestamp_utc.tm_min, # month!
gps.timestamp_utc.tm_sec,
)
)
print("Latitude: {0:.6f} degrees".format(gps.latitude))
print("Longitude: {0:.6f} degrees".format(gps.longitude))
print("Fix quality: {}".format(gps.fix_quality))
# Some attributes beyond latitude, longitude and timestamp are optional
# and might not be present. Check if they're None before trying to use!
if gps.satellites is not None:
print('# satellites: {}'.format(gps.satellites))
print("# satellites: {}".format(gps.satellites))
if gps.altitude_m is not None:
print('Altitude: {} meters'.format(gps.altitude_m))
print("Altitude: {} meters".format(gps.altitude_m))
if gps.speed_knots is not None:
print('Speed: {} knots'.format(gps.speed_knots))
print("Speed: {} knots".format(gps.speed_knots))
if gps.track_angle_deg is not None:
print('Track angle: {} degrees'.format(gps.track_angle_deg))
print("Track angle: {} degrees".format(gps.track_angle_deg))
if gps.horizontal_dilution is not None:
print('Horizontal dilution: {}'.format(gps.horizontal_dilution))
print("Horizontal dilution: {}".format(gps.horizontal_dilution))
if gps.height_geoid is not None:
print('Height geo ID: {} meters'.format(gps.height_geoid))
print("Height geo ID: {} meters".format(gps.height_geoid))

View file

@ -9,13 +9,13 @@ import rtc
import adafruit_gps
uart = busio.UART(board.TX, board.RX, baudrate=9600, timeout=10)
#i2c = busio.I2C(board.SCL, board.SDA)
# i2c = busio.I2C(board.SCL, board.SDA)
gps = adafruit_gps.GPS(uart, debug=False)
#gps = adafruit_gps.GPS_GtopI2C(i2c, debug=False) # Use I2C interface
# gps = adafruit_gps.GPS_GtopI2C(i2c, debug=False) # Use I2C interface
gps.send_command(b'PMTK314,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0')
gps.send_command(b'PMTK220,1000')
gps.send_command(b"PMTK314,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0")
gps.send_command(b"PMTK220,1000")
print("Set GPS as time source")
rtc.set_time_source(gps)
@ -33,30 +33,39 @@ while True:
print("No time data from GPS yet")
continue
# Time & date from GPS informations
print('Fix timestamp: {:02}/{:02}/{} {:02}:{:02}:{:02}'.format(
gps.timestamp_utc.tm_mon, # Grab parts of the time from the
gps.timestamp_utc.tm_mday, # struct_time object that holds
gps.timestamp_utc.tm_year, # the fix time. Note you might
gps.timestamp_utc.tm_hour, # not get all data like year, day,
gps.timestamp_utc.tm_min, # month!
gps.timestamp_utc.tm_sec))
print(
"Fix timestamp: {:02}/{:02}/{} {:02}:{:02}:{:02}".format(
gps.timestamp_utc.tm_mon, # Grab parts of the time from the
gps.timestamp_utc.tm_mday, # struct_time object that holds
gps.timestamp_utc.tm_year, # the fix time. Note you might
gps.timestamp_utc.tm_hour, # not get all data like year, day,
gps.timestamp_utc.tm_min, # month!
gps.timestamp_utc.tm_sec,
)
)
#Time & date from internal RTC
print('RTC timestamp: {:02}/{:02}/{} {:02}:{:02}:{:02}'.format(
the_rtc.datetime.tm_mon,
the_rtc.datetime.tm_mday,
the_rtc.datetime.tm_year,
the_rtc.datetime.tm_hour,
the_rtc.datetime.tm_min,
the_rtc.datetime.tm_sec))
# Time & date from internal RTC
print(
"RTC timestamp: {:02}/{:02}/{} {:02}:{:02}:{:02}".format(
the_rtc.datetime.tm_mon,
the_rtc.datetime.tm_mday,
the_rtc.datetime.tm_year,
the_rtc.datetime.tm_hour,
the_rtc.datetime.tm_min,
the_rtc.datetime.tm_sec,
)
)
#Time & date from time.localtime() function
# Time & date from time.localtime() function
local_time = time.localtime()
print("Local time: {:02}/{:02}/{} {:02}:{:02}:{:02}".format(
local_time.tm_mon,
local_time.tm_mday,
local_time.tm_year,
local_time.tm_hour,
local_time.tm_min,
local_time.tm_sec))
print(
"Local time: {:02}/{:02}/{} {:02}:{:02}:{:02}".format(
local_time.tm_mon,
local_time.tm_mday,
local_time.tm_year,
local_time.tm_hour,
local_time.tm_min,
local_time.tm_sec,
)
)

View file

@ -7,6 +7,7 @@ https://github.com/pypa/sampleproject
# Always prefer setuptools over distutils
from setuptools import setup, find_packages
# To use a consistent encoding
from codecs import open
from os import path
@ -14,47 +15,42 @@ from os import path
here = path.abspath(path.dirname(__file__))
# Get the long description from the README file
with open(path.join(here, 'README.rst'), encoding='utf-8') as f:
with open(path.join(here, "README.rst"), encoding="utf-8") as f:
long_description = f.read()
setup(
name='adafruit-circuitpython-gps',
name="adafruit-circuitpython-gps",
use_scm_version=True,
setup_requires=['setuptools_scm'],
description='CircuitPython library for GPS modules.',
setup_requires=["setuptools_scm"],
description="CircuitPython library for GPS modules.",
long_description=long_description,
long_description_content_type='text/x-rst',
long_description_content_type="text/x-rst",
# The project's main homepage.
url='https://github.com/adafruit/Adafruit_CircuitPython_GPS',
url="https://github.com/adafruit/Adafruit_CircuitPython_GPS",
# Author details
author='Adafruit Industries',
author_email='circuitpython@adafruit.com',
install_requires=['pyserial', 'Adafruit-Blinka', 'adafruit-circuitpython-busdevice'],
author="Adafruit Industries",
author_email="circuitpython@adafruit.com",
install_requires=[
"pyserial",
"Adafruit-Blinka",
"adafruit-circuitpython-busdevice",
],
# Choose your license
license='MIT',
license="MIT",
# See https://pypi.python.org/pypi?%3Aaction=list_classifiers
classifiers=[
'Development Status :: 3 - Alpha',
'Intended Audience :: Developers',
'Topic :: Software Development :: Libraries',
'Topic :: System :: Hardware',
'License :: OSI Approved :: MIT License',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5',
"Development Status :: 3 - Alpha",
"Intended Audience :: Developers",
"Topic :: Software Development :: Libraries",
"Topic :: System :: Hardware",
"License :: OSI Approved :: MIT License",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.4",
"Programming Language :: Python :: 3.5",
],
# What does your project relate to?
keywords='adafruit gps module latitude longitude breakout hardware micropython circuitpython',
keywords="adafruit gps module latitude longitude breakout hardware micropython circuitpython",
# You can just specify the packages manually here if your project is
# simple. Or you can use find_packages().
py_modules=['adafruit_gps'],
py_modules=["adafruit_gps"],
)