forked from platypush/platypush
Added GPS backend
This commit is contained in:
parent
c9dc1aac44
commit
39b0c3b741
6 changed files with 151 additions and 1 deletions
|
@ -221,6 +221,7 @@ autodoc_mock_imports = ['googlesamples.assistant.grpc.audio_helpers',
|
||||||
'pyHS100',
|
'pyHS100',
|
||||||
'grpc',
|
'grpc',
|
||||||
'envirophat',
|
'envirophat',
|
||||||
|
'gps',
|
||||||
]
|
]
|
||||||
|
|
||||||
sys.path.insert(0, os.path.abspath('../..'))
|
sys.path.insert(0, os.path.abspath('../..'))
|
||||||
|
|
103
platypush/backend/gps.py
Normal file
103
platypush/backend/gps.py
Normal file
|
@ -0,0 +1,103 @@
|
||||||
|
import gps
|
||||||
|
import threading
|
||||||
|
import time
|
||||||
|
|
||||||
|
from platypush.backend import Backend
|
||||||
|
from platypush.message.event.gps import GPSVersionEvent, GPSDeviceEvent, GPSUpdateEvent
|
||||||
|
|
||||||
|
|
||||||
|
class GpsBackend(Backend):
|
||||||
|
"""
|
||||||
|
This backend can interact with a GPS device and listen for events.
|
||||||
|
|
||||||
|
Triggers:
|
||||||
|
|
||||||
|
* :class:`platypush.message.event.gps.GPSVersionEvent` when a GPS device advertises its version data
|
||||||
|
* :class:`platypush.message.event.gps.GPSDeviceEvent` when a GPS device is connected or updated
|
||||||
|
* :class:`platypush.message.event.gps.GPSUpdateEvent` when a GPS device has new data
|
||||||
|
|
||||||
|
Requires:
|
||||||
|
|
||||||
|
* **gps** (``pip install gps``)
|
||||||
|
* **gpsd** daemon running (``apt-get install gpsd`` or ``pacman -S gpsd`` depending on your distro)
|
||||||
|
|
||||||
|
Once installed gpsd you need to run it and associate it to your device. Example if your GPS device communicates
|
||||||
|
over USB and is available on /dev/ttyUSB0::
|
||||||
|
|
||||||
|
[sudo] gpsd /dev/ttyUSB0 -F /var/run/gpsd.sock
|
||||||
|
|
||||||
|
The best option is probably to run gpsd at startup as a systemd service.
|
||||||
|
"""
|
||||||
|
|
||||||
|
_fail_sleep_time = 5.0
|
||||||
|
|
||||||
|
def __init__(self, gpsd_server='localhost', gpsd_port=2947, **kwargs):
|
||||||
|
"""
|
||||||
|
:param gpsd_server: gpsd daemon server name/address (default: localhost)
|
||||||
|
:type gpsd_server: str
|
||||||
|
:param gpsd_port: Port of the gpsd daemon (default: 2947)
|
||||||
|
:type gpsd_port: int or str
|
||||||
|
"""
|
||||||
|
super().__init__(**kwargs)
|
||||||
|
|
||||||
|
self.gpsd_server = gpsd_server
|
||||||
|
self.gpsd_port = gpsd_port
|
||||||
|
self._session = None
|
||||||
|
self._session_lock = threading.RLock()
|
||||||
|
self._devices = {}
|
||||||
|
|
||||||
|
def _get_session(self):
|
||||||
|
with self._session_lock:
|
||||||
|
if not self._session:
|
||||||
|
self._session = gps.gps(host=self.gpsd_server, port=self.gpsd_port, reconnect=True)
|
||||||
|
self._session.stream(gps.WATCH_ENABLE | gps.WATCH_NEWSTYLE)
|
||||||
|
|
||||||
|
return self._session
|
||||||
|
|
||||||
|
def _gps_report_to_event(self, report):
|
||||||
|
if report.get('class').lower() == 'version':
|
||||||
|
return GPSVersionEvent(release=report.get('release'),
|
||||||
|
rev=report.get('rev'),
|
||||||
|
proto_major=report.get('proto_major'),
|
||||||
|
proto_minor=report.get('proto_minor'))
|
||||||
|
if report.get('class').lower() == 'devices':
|
||||||
|
for device in report.get('devices', []):
|
||||||
|
if device.get('path') not in self._devices or device != self._devices.get('path'):
|
||||||
|
self._devices[device.get('path')] = device
|
||||||
|
return GPSDeviceEvent(path=device.get('path'), activated=device.get('activated'),
|
||||||
|
native=device.get('native'), bps=device.get('bps'),
|
||||||
|
parity=device.get('parity'), stopbits=device.get('stopbits'),
|
||||||
|
cycle=device.get('cycle'), driver=device.get('driver'))
|
||||||
|
if report.get('class').lower() == 'device':
|
||||||
|
self._devices[report.get('path')] = report
|
||||||
|
return GPSDeviceEvent(path=report.get('path'), activated=report.get('activated'),
|
||||||
|
native=report.get('native'), bps=report.get('bps'),
|
||||||
|
parity=report.get('parity'), stopbits=report.get('stopbits'),
|
||||||
|
cycle=report.get('cycle'), driver=report.get('driver'))
|
||||||
|
if report.get('class').lower() == 'tpv':
|
||||||
|
return GPSUpdateEvent(device=report.get('device'), latitude=report.get('lat'), longitude=report.get('lon'),
|
||||||
|
altitude=report.get('alt'), mode=report.get('mode'), epv=report.get('epv'),
|
||||||
|
eph=report.get('eph'), sep=report.get('sep'))
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
super().run()
|
||||||
|
self.logger.info('Initialized GPS backend on {}:{}'.format(self.gpsd_server, self.gpsd_port))
|
||||||
|
|
||||||
|
while not self.should_stop():
|
||||||
|
try:
|
||||||
|
session = self._get_session()
|
||||||
|
report = session.next()
|
||||||
|
event = self._gps_report_to_event(report)
|
||||||
|
if event:
|
||||||
|
self.bus.post(event)
|
||||||
|
except Exception as e:
|
||||||
|
if isinstance(e, StopIteration):
|
||||||
|
self.logger.warning('GPS service connection lost, check that gpsd is running')
|
||||||
|
else:
|
||||||
|
self.logger.exception(e)
|
||||||
|
|
||||||
|
self._session = None
|
||||||
|
time.sleep(self._fail_sleep_time)
|
||||||
|
|
||||||
|
|
||||||
|
# vim:sw=4:ts=4:et:
|
|
@ -1,4 +1,3 @@
|
||||||
import json
|
|
||||||
import time
|
import time
|
||||||
|
|
||||||
from threading import Timer
|
from threading import Timer
|
||||||
|
|
44
platypush/message/event/gps.py
Normal file
44
platypush/message/event/gps.py
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
from platypush.message.event import Event
|
||||||
|
|
||||||
|
|
||||||
|
class GPSEvent(Event):
|
||||||
|
"""
|
||||||
|
Generic class for GPS events
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
class GPSVersionEvent(GPSEvent):
|
||||||
|
"""
|
||||||
|
Event usually triggered on startup or reconnection, when the GPS device advertises its version parameters
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, release=None, rev=None, proto_major=None, proto_minor=None, *args, **kwargs):
|
||||||
|
super().__init__(release=release, rev=rev, proto_major=proto_major, proto_minor=proto_minor, *args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
class GPSDeviceEvent(GPSEvent):
|
||||||
|
"""
|
||||||
|
Event triggered when a new GPS device is connected or reconfigured
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, path, activated=None, native=False, bps=None, parity=None, stopbits=None,
|
||||||
|
cycle=None, driver=None, *args, **kwargs):
|
||||||
|
super().__init__(*args, path=path, activated=activated, native=native, bps=bps, parity=parity,
|
||||||
|
stopbits=stopbits, cycle=cycle, driver=driver, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
class GPSUpdateEvent(GPSEvent):
|
||||||
|
"""
|
||||||
|
Event triggered upon GPS status update
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, device=None, latitude=None, longitude=None, altitude=None, mode=None, epv=None, eph=None,
|
||||||
|
sep=None, *args, **kwargs):
|
||||||
|
super().__init__(*args, device=device, latitude=latitude, longitude=longitude, altitude=altitude,
|
||||||
|
mode=mode, epv=epv, eph=eph, sep=sep, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
# vim:sw=4:ts=4:et:
|
|
@ -150,3 +150,5 @@ pyScss
|
||||||
# Support for enviropHAT
|
# Support for enviropHAT
|
||||||
# envirophat
|
# envirophat
|
||||||
|
|
||||||
|
# Support for GPS integration
|
||||||
|
# gps
|
||||||
|
|
1
setup.py
1
setup.py
|
@ -172,6 +172,7 @@ setup(
|
||||||
'Support for compiling SASS/SCSS styles to CSS': ['pyScss'],
|
'Support for compiling SASS/SCSS styles to CSS': ['pyScss'],
|
||||||
'Support for NFC tags': ['nfcpy>=1.0', 'ndef'],
|
'Support for NFC tags': ['nfcpy>=1.0', 'ndef'],
|
||||||
'Support for enviropHAT': ['envirophat'],
|
'Support for enviropHAT': ['envirophat'],
|
||||||
|
'Support for GPS': ['gps'],
|
||||||
# 'Support for Leap Motion backend': ['git+ssh://git@github.com:BlackLight/leap-sdk-python3.git'],
|
# 'Support for Leap Motion backend': ['git+ssh://git@github.com:BlackLight/leap-sdk-python3.git'],
|
||||||
# 'Support for Flic buttons': ['git+https://@github.com/50ButtonsEach/fliclib-linux-hci.git']
|
# 'Support for Flic buttons': ['git+https://@github.com/50ButtonsEach/fliclib-linux-hci.git']
|
||||||
# 'Support for media subtitles': ['git+https://github.com/agonzalezro/python-opensubtitles#egg=python-opensubtitles']
|
# 'Support for media subtitles': ['git+https://github.com/agonzalezro/python-opensubtitles#egg=python-opensubtitles']
|
||||||
|
|
Loading…
Reference in a new issue