Skip to content

Commit

Permalink
Merge pull request #1 from SkyTruth/dev
Browse files Browse the repository at this point in the history
Operational driver
  • Loading branch information
geowurster committed Sep 18, 2015
2 parents cc52ad0 + 15ec806 commit 6793877
Show file tree
Hide file tree
Showing 10 changed files with 377 additions and 0 deletions.
22 changes: 22 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
language: python

python:
- 2.7
- 3.3
- 3.4

install:
- sudo apt-get install -qq gcc-4.8 g++-4.8
- CC=g++-4.8 pip install -e .\[dev\]
- CC=g++-4.8 pip install git+git://github.com/schwehr/libais.git --upgrade
- pip install git+git://github.com/SkyTruth/gpsdio.git --upgrade

script:
- py.test tests --cov gpsdio_nmea_driver --cov-report term-missing

after_success:
- coveralls

notifications:
flowdock:
secure: sSDUIIuldA7tWGqgexf+nmeC/+Htm97bwcPaZOHv2+/c3jKsxUoMMnwkcT3ChqPTEvqs2pGoAYuSDDOWXYUZTpETmZyfECmSqPdfD9nePdqDCum8Q909jlttJWR4jmMuhToNifXdwIkPjnspnLrnxCj92/9/Nx/9uSo/+JfPfE0=
7 changes: 7 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
Changes
=======

0.1 (2015-09-18)
----------------

- Initial release.
17 changes: 17 additions & 0 deletions LICENSE.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
Copyright 2015 SkyTruth

Authors:

Kevin Wurster <[email protected]>

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
5 changes: 5 additions & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
include CHANGES.md
include LICENSE.txt
include MANIFEST.in
include README.rst
include setup.py
59 changes: 59 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
==================
gpsdio-nmea-driver
==================

An **experimental** gpsdio driver for parsing NMEA sentences directly into GPSd messages with `libais <https://github.com/schwehr/libais>`_.

.. image:: https://travis-ci.org/SkyTruth/gpsdio-nmea-driver.svg?branch=master
:target: https://travis-ci.org/SkyTruth/gpsdio-nmea-driver

.. image:: https://coveralls.io/repos/SkyTruth/gpsdio-nmea-driver/badge.svg?branch=master
:target: https://coveralls.io/r/SkyTruth/gpsdio-nmea-driver


Installation
------------

**NOTE:** This driver is experimental and requires an unreleased version of ``libais`` and ``gpsdio``.

With pip:

.. code-block:: console
$ pip install git+git://github.com/schwehr/libais.git --upgrade
$ pip install gpsdio-nmea-driver
From source:

.. code-block:: console
$ git clone https://github.com/SkyTruth/gpsdio
$ cd gpsdio-nmea-driver
$ python setup.py install
$ pip install git+git://github.com/schwehr/libais.git --upgrade
$ pip install git+git://github.com/schwehr/libais.git --upgrade
Developing
----------

.. code-block:: console
$ git clone https://github.com/SkyTruth/gpsdio-nmea-driver.git
$ cd gpsdio-nmea-driver
$ virtualenv venv
$ source venv/bin/activate
$ pip install -e .\[dev\]
$ py.test tests --cov gpsdio-nmea-driver --cov-report term-missing
Changelog
---------

See ``CHANGES.md``


License
-------

See ``LICENSE.txt``
32 changes: 32 additions & 0 deletions gpsdio_nmea_driver/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
"""
A gpsdio driver for parsing NMEA sentences directly into GPSd messages.
"""

import logging


logger = logging.getLogger('gpsdio-nmea')


__version__ = '0.1'
__author__ = 'Kevin Wurster'
__email__ = '[email protected]'
__source__ = 'https://github.com/SkyTruth/gpsdio-nmea-driver'
__license__ = """
Copyright 2014-2015 SkyTruth
Authors:
Kevin Wurster <[email protected]>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
"""
76 changes: 76 additions & 0 deletions gpsdio_nmea_driver/core.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
"""
gpsdio NMEA driver
"""


import codecs

import ais.compatibility.gpsd
import ais.stream
from gpsdio.base import BaseDriver
import six


def parse_ais_stream(msg_stream):

"""
Parse a stream of NMEA sentences, convert to GPSd, and yield.
Parameters
----------
msg_stream : iter
An iterable producing one NMEA sentence per iteration.
Yields
------
dict
"""

args = {
'ignore_tagblock_station': True,
'allow_unknown': True,
'allow_missing_timestamps': True
}

gpsd_mangle = ais.compatibility.gpsd.Mangler(copy_tagblock_timestamp=True)
for msg in map(gpsd_mangle, ais.stream.decode(msg_stream, **args)):
yield msg


class _NMEAParser(object):

"""
File-like object for interacting with the parser.
"""

def __init__(self, f):
if isinstance(f, six.string_types):
self._f = codecs.open(f, encoding='utf-8')
else:
self._f = f
self._parser = parse_ais_stream(self._f)

def __enter__(self):
return self

def __exit__(self, exc_type, exc_val, exc_tb):
self.close()

def __iter__(self):
return self

def __next__(self):
return next(self._parser)

next = __next__

def __getattr__(self, item):
return getattr(self._f, item)


class NMEA(BaseDriver):

io_modes = 'r',
extensions = 'nmea',
driver_name = 'NMEA'

def open(self, name, mode='r'):
return _NMEAParser(name)
87 changes: 87 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
#!/usr/bin/python


"""
Setup script for gpsdio-nmea-driver
"""


import os
import sys

from setuptools.command.test import test as TestCommand
from setuptools import find_packages
from setuptools import setup


# https://pytest.org/latest/goodpractises.html
class PyTest(TestCommand):
user_options = [('pytest-args=', 'a', "Arguments to pass to py.test")]

def initialize_options(self):
TestCommand.initialize_options(self)
self.pytest_args = ['tests']

def finalize_options(self):
TestCommand.finalize_options(self)
self.test_args = []
self.test_suite = True

def run_tests(self):
# Import here, because outside the eggs aren't loaded
import pytest
errno = pytest.main(self.pytest_args)
sys.exit(errno)


with open('README.rst') as f:
readme = f.read().strip()


version = None
author = None
email = None
source = None
with open(os.path.join('gpsdio_nmea_driver', '__init__.py')) as f:
for line in f:
if line.strip().startswith('__version__'):
version = line.split('=')[1].strip().replace('"', '').replace("'", '')
elif line.strip().startswith('__author__'):
author = line.split('=')[1].strip().replace('"', '').replace("'", '')
elif line.strip().startswith('__email__'):
email = line.split('=')[1].strip().replace('"', '').replace("'", '')
elif line.strip().startswith('__source__'):
source = line.split('=')[1].strip().replace('"', '').replace("'", '')
elif None not in (version, author, email, source):
break


setup(
author=author,
author_email=email,
cmdclass={'test': PyTest},
description="A gpsdio driver for parsing NMEA sentences directly into GPSd messages.",
entry_points='''
[gpsdio.driver_plugins]
NMEA=gpsdio_nmea_driver.core:NMEA
''',
extras_require={
'dev': [
'pytest',
'pytest-cov',
]
},
install_requires=[
'libais>=0.15',
'gpsdio>=0.0.7',
'six'
],
license='Apache 2.0',
long_description=readme,
include_package_data=True,
keywords="gpsdio NMEA driver AIS libais",
name="gpsdio-nmea-driver",
packages=find_packages(exclude=['test']),
url=source,
version=version,
)
23 changes: 23 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
"""
Fixtures
"""


import os

import pytest


@pytest.fixture(scope='function')
def types_nmea_path():
return os.path.join('tests', 'data', 'types.nmea')


@pytest.fixture(scope='function')
def types_json_path():
return os.path.join('tests', 'data', 'types.json')


@pytest.fixture(scope='function')
def types_nmea_gz_path():
return os.path.join('tests', 'data', 'types.nmea.gz')
49 changes: 49 additions & 0 deletions tests/test_core.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
"""
Unittests for gpsdio_nmea_driver.core
"""


import gpsdio
import gpsdio.drivers
from gpsdio_nmea_driver import core


def validate_stream(stream):
for msg in stream:
assert 'mmsi' in msg and 'type' in msg

def test_registered():
assert 'NMEA' in gpsdio.drivers.registered_drivers
assert gpsdio.drivers.registered_drivers['NMEA'] is core.NMEA


def test_read(types_nmea_path):
with gpsdio.open(types_nmea_path) as src:
validate_stream(src)


def test_read_compressed(types_nmea_gz_path):
with gpsdio.open(types_nmea_gz_path) as src:
idx = 0
for idx, msg in enumerate(src):
assert 'mmsi' in msg and 'type' in msg
assert idx > 0


def test_read_both(types_nmea_path, types_nmea_gz_path):
with gpsdio.open(types_nmea_path) as dsrc, gpsdio.open(types_nmea_gz_path) as csrc:
for idx, (d, c) in enumerate(zip(dsrc, csrc)):
assert d == c
assert 'mmsi' in d and 'type' in d
assert 'mmsi' in c and 'type' in c
assert idx > 0


def test_driver_directly(types_nmea_path):
with core.NMEA(types_nmea_path) as src:
validate_stream(src)


def test_file_obj_directly_str(types_nmea_path):
with core._NMEAParser(types_nmea_path) as src:
validate_stream(src)

0 comments on commit 6793877

Please sign in to comment.