parent
40c241f40f
commit
88a7503a50
11 changed files with 373 additions and 1 deletions
@ -1,3 +1,3 @@ |
||||
# get_gps_position |
||||
|
||||
Reads GPS position from gpds on Linux systems |
||||
Reads GPS position from gpds on Linux systems. This program is used in the PE1RXF Reticulum Portable Server from Mees Electronics. |
||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,160 @@ |
||||
#!/usr/bin/env python |
||||
# -*- coding: utf-8 -*- |
||||
|
||||
""" |
||||
PyDecimalDegrees - geographic coordinates conversion utility. |
||||
|
||||
Copyright (C) 2006-2013 by Mateusz Łoskot <mateusz@loskot.net> |
||||
Copyright (C) 2010-2013 by Evan Wheeler <ewheeler@unicef.org> |
||||
|
||||
This file is part of PyDecimalDegrees module. |
||||
|
||||
This software is provided 'as-is', without any express or implied warranty. |
||||
In no event will the authors be held liable for any damages arising from |
||||
the use of this software. |
||||
|
||||
Permission is granted to anyone to use this software for any purpose, |
||||
including commercial applications, and to alter it and redistribute it freely, |
||||
subject to the following restrictions: |
||||
1. The origin of this software must not be misrepresented; you must not |
||||
claim that you wrote the original software. If you use this software |
||||
in a product, an acknowledgment in the product documentation would be |
||||
appreciated but is not required. |
||||
2. Altered source versions must be plainly marked as such, and must not be |
||||
misrepresented as being the original software. |
||||
3. This notice may not be removed or altered from any source distribution. |
||||
|
||||
DESCRIPTION |
||||
|
||||
DecimalDegrees module provides functions to convert between |
||||
degrees/minutes/seconds and decimal degrees. |
||||
|
||||
Original source distribution: |
||||
http://mateusz.loskot.net/software/gis/pydecimaldegrees/ |
||||
|
||||
Inspired by Walter Mankowski's Geo::Coordinates::DecimalDegrees module |
||||
for Perl, originally located in CPAN Archives: |
||||
http://search.cpan.org/~waltman/Geo-Coordinates-DecimalDegrees-0.05/ |
||||
|
||||
doctest examples are based following coordinates: |
||||
DMS: 121 8' 6" |
||||
DM: 121 8.1' |
||||
DD: 121.135 |
||||
|
||||
To run doctest units just execut this module script as follows |
||||
(-v instructs Python to run script in verbose mode): |
||||
|
||||
$ python decimaldegrees.py [-v] |
||||
|
||||
""" |
||||
|
||||
import decimal as libdecimal |
||||
|
||||
from decimal import Decimal as D |
||||
|
||||
__revision__ = '$Revision: 1.1 $' |
||||
|
||||
|
||||
def decimal2dms(decimal_degrees): |
||||
""" Converts a floating point number of degrees to the equivalent |
||||
number of degrees, minutes, and seconds, which are returned |
||||
as a 3-element tuple of decimals. If 'decimal_degrees' is negative, |
||||
only degrees (1st element of returned tuple) will be negative, |
||||
minutes (2nd element) and seconds (3rd element) will always be positive. |
||||
|
||||
Example: |
||||
|
||||
>>> decimal2dms(121.135) |
||||
(Decimal('121'), Decimal('8'), Decimal('6.000')) |
||||
>>> decimal2dms(-121.135) |
||||
(Decimal('-121'), Decimal('8'), Decimal('6.000')) |
||||
|
||||
""" |
||||
|
||||
degrees = D(int(decimal_degrees)) |
||||
decimal_minutes = libdecimal.getcontext().multiply( |
||||
(D(str(decimal_degrees)) - degrees).copy_abs(), D(60)) |
||||
minutes = D(int(decimal_minutes)) |
||||
seconds = libdecimal.getcontext().multiply( |
||||
(decimal_minutes - minutes), D(60)) |
||||
return (degrees, minutes, seconds) |
||||
|
||||
|
||||
def decimal2dm(decimal_degrees): |
||||
""" |
||||
Converts a floating point number of degrees to the degress & minutes. |
||||
|
||||
Returns a 2-element tuple of decimals. |
||||
|
||||
If 'decimal_degrees' is negative, only degrees (1st element of returned |
||||
tuple) will be negative, minutes (2nd element) will always be positive. |
||||
|
||||
Example: |
||||
|
||||
>>> decimal2dm(121.135) |
||||
(Decimal('121'), Decimal('8.100')) |
||||
>>> decimal2dm(-121.135) |
||||
(Decimal('-121'), Decimal('8.100')) |
||||
|
||||
""" |
||||
degrees = D(int(decimal_degrees)) |
||||
|
||||
minutes = libdecimal.getcontext().multiply( |
||||
(D(str(decimal_degrees)) - degrees).copy_abs(), D(60)) |
||||
|
||||
return (degrees, minutes) |
||||
|
||||
|
||||
def dms2decimal(degrees, minutes, seconds): |
||||
""" Converts degrees, minutes, and seconds to the equivalent |
||||
number of decimal degrees. If parameter 'degrees' is negative, |
||||
then returned decimal-degrees will also be negative. |
||||
|
||||
NOTE: this method returns a decimal.Decimal |
||||
|
||||
Example: |
||||
|
||||
>>> dms2decimal(121, 8, 6) |
||||
Decimal('121.135') |
||||
>>> dms2decimal(-121, 8, 6) |
||||
Decimal('-121.135') |
||||
|
||||
""" |
||||
decimal = D(0) |
||||
degs = D(str(degrees)) |
||||
mins = libdecimal.getcontext().divide(D(str(minutes)), D(60)) |
||||
secs = libdecimal.getcontext().divide(D(str(seconds)), D(3600)) |
||||
|
||||
if degrees >= D(0): |
||||
decimal = degs + mins + secs |
||||
else: |
||||
decimal = degs - mins - secs |
||||
|
||||
return libdecimal.getcontext().normalize(decimal) |
||||
|
||||
|
||||
def dm2decimal(degrees, minutes): |
||||
""" Converts degrees and minutes to the equivalent number of decimal |
||||
degrees. If parameter 'degrees' is negative, then returned decimal-degrees |
||||
will also be negative. |
||||
|
||||
Example: |
||||
|
||||
>>> dm2decimal(121, 8.1) |
||||
Decimal('121.135') |
||||
>>> dm2decimal(-121, 8.1) |
||||
Decimal('-121.135') |
||||
|
||||
""" |
||||
return dms2decimal(degrees, minutes, 0) |
||||
|
||||
|
||||
def run_doctest(): # pragma: no cover |
||||
"""Runs doctests for this module.""" |
||||
import doctest |
||||
return doctest.testmod() |
||||
|
||||
|
||||
if __name__ == '__main__': |
||||
run_doctest() # pragma: no cover |
||||
|
@ -0,0 +1,108 @@ |
||||
#!/usr/bin/env python |
||||
# -*- coding: utf-8 -*- |
||||
|
||||
"""Python APRS Module Geo Utility Function Definitions.""" |
||||
|
||||
import decimaldegrees |
||||
|
||||
__author__ = 'Greg Albrecht W2GMD <oss@undef.net>' # NOQA pylint: disable=R0801 |
||||
__copyright__ = 'Copyright 2017 Greg Albrecht and Contributors' # NOQA pylint: disable=R0801 |
||||
__license__ = 'Apache License, Version 2.0' # NOQA pylint: disable=R0801 |
||||
|
||||
|
||||
def dec2dm_lat(dec: float) -> str: |
||||
""" |
||||
Converts DecDeg to APRS Coord format. |
||||
|
||||
See: http://ember2ash.com/lat.htm |
||||
|
||||
Source: http://stackoverflow.com/questions/2056750 |
||||
|
||||
Example: |
||||
>>> test_lat = 37.7418096 |
||||
>>> aprs_lat = dec2dm_lat(test_lat) |
||||
>>> aprs_lat |
||||
'3744.51N' |
||||
>>> test_lat = -8.01 |
||||
>>> aprs_lat = dec2dm_lat(test_lat) |
||||
>>> aprs_lat |
||||
'0800.60S' |
||||
""" |
||||
dec_min = decimaldegrees.decimal2dm(dec) |
||||
|
||||
deg = dec_min[0] |
||||
abs_deg = abs(deg) |
||||
|
||||
if not deg == abs_deg: |
||||
suffix = 'S' |
||||
else: |
||||
suffix = 'N' |
||||
|
||||
return "%02d%05.2f%s" % (abs_deg, dec_min[1], suffix) |
||||
|
||||
|
||||
def dec2dm_lng(dec: float) -> str: |
||||
""" |
||||
Converts DecDeg to APRS Coord format. |
||||
|
||||
See: http://ember2ash.com/lat.htm |
||||
|
||||
Example: |
||||
>>> test_lng = 122.38833 |
||||
>>> aprs_lng = dec2dm_lng(test_lng) |
||||
>>> aprs_lng |
||||
'12223.30E' |
||||
>>> test_lng = -99.01 |
||||
>>> aprs_lng = dec2dm_lng(test_lng) |
||||
>>> aprs_lng |
||||
'09900.60W' |
||||
""" |
||||
dec_min = decimaldegrees.decimal2dm(dec) |
||||
|
||||
deg = dec_min[0] |
||||
abs_deg = abs(deg) |
||||
|
||||
if not deg == abs_deg: |
||||
suffix = 'W' |
||||
else: |
||||
suffix = 'E' |
||||
|
||||
return "%03d%05.2f%s" % (abs_deg, dec_min[1], suffix) |
||||
|
||||
|
||||
def ambiguate(pos: float, ambiguity: int) -> str: |
||||
""" |
||||
Adjust ambiguity of position. |
||||
|
||||
Derived from @asdil12's `process_ambiguity()`. |
||||
|
||||
>>> pos = '12345.67N' |
||||
>>> ambiguate(pos, 0) |
||||
'12345.67N' |
||||
>>> ambiguate(pos, 1) |
||||
'12345.6 N' |
||||
>>> ambiguate(pos, 2) |
||||
'12345. N' |
||||
>>> ambiguate(pos, 3) |
||||
'1234 . N' |
||||
""" |
||||
num = bytearray(pos, 'UTF-8') |
||||
for i in range(0, ambiguity): |
||||
if i > 1: |
||||
# skip the dot |
||||
i += 1 |
||||
# skip the direction |
||||
i += 2 |
||||
num[-i] = ord(' ') |
||||
return num.decode() |
||||
|
||||
|
||||
def run_doctest(): # pragma: no cover |
||||
"""Runs doctests for this module.""" |
||||
import doctest |
||||
return doctest.testmod() |
||||
|
||||
|
||||
if __name__ == '__main__': |
||||
run_doctest() # pragma: no cover |
||||
|
@ -0,0 +1,54 @@ |
||||
# |
||||
# Simple program to read gpsd and return the APRS formatted position string including the APRS symbol. |
||||
# Can be used to generate position beacons |
||||
# |
||||
# (C)2025 M.T. Konstapel https://meezenest.nl/mees |
||||
# |
||||
# get_position.oy is free software: you can redistribute it and/or modify |
||||
# it under the terms of the GNU General Public License as published by |
||||
# the Free Software Foundation, either version 3 of the License, or |
||||
# (at your option) any later version. |
||||
# |
||||
# PE1RXF-APRS-server is distributed in the hope that it will be useful, |
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
# GNU General Public License for more details. |
||||
# |
||||
|
||||
# You should have received a copy of the GNU General Public License |
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>. |
||||
# |
||||
|
||||
import gpsd2 |
||||
|
||||
import geo_util |
||||
|
||||
# Define APRS symbol, camp ground = /; |
||||
SymbolTableIdentifier = '/' |
||||
SymbolCode = ';' |
||||
|
||||
try: |
||||
# Connect to the local gpsd |
||||
gpsd2.connect() |
||||
|
||||
# Connect somewhere else |
||||
gpsd2.connect(host="127.0.0.1", port=2947) |
||||
|
||||
# Get gps position |
||||
packet = gpsd2.get_current() |
||||
|
||||
# See the inline docs for GpsResponse for the available data |
||||
aprs_position = packet.position() |
||||
except: |
||||
aprs_position = (0,0) |
||||
|
||||
|
||||
# Translate the gps location data to the APRS location standard |
||||
aprs_lat = geo_util.dec2dm_lat(aprs_position[0]) |
||||
aprs_lng = geo_util.dec2dm_lng(aprs_position[1]) |
||||
aprs_location='!'+aprs_lat+SymbolTableIdentifier+aprs_lng+SymbolCode |
||||
|
||||
aprs_beacon = aprs_location + 'Portable HAM station' |
||||
|
||||
print(aprs_location) |
||||
#print(aprs_beacon) |
@ -0,0 +1,4 @@ |
||||
Serial port gps module: |
||||
|
||||
serial_port=$(readlink -f /dev/serial/by-path/platform-20980000.usb-usb-0:1.3:1.0-port0) |
||||
|
@ -0,0 +1,23 @@ |
||||
#!/bin/bash |
||||
|
||||
POSITION="$(/usr/bin/python /home/marcel/ham/gps/get_position.py)" |
||||
INFO="Portable HAM Station" |
||||
|
||||
if [ "$POSITION" != "!0000.00N/00000.00E;" ]; then |
||||
|
||||
# Set arguments for beacon program |
||||
args[0]=-d |
||||
args[1]="APRX29 $Path" |
||||
args[2]=-s |
||||
args[3]=aprs_1200bd |
||||
args[4]="$POSITION$INFO" |
||||
|
||||
# Send position beacon |
||||
/usr/sbin/beacon "${args[@]}" |
||||
|
||||
echo "Position beacon send." |
||||
|
||||
#/usr/sbin/beacon -d "APRX29" -s aprs_lora $BEACON |
||||
else |
||||
echo "No GPS signal found. Nothing to do." |
||||
fi |
@ -0,0 +1,23 @@ |
||||
#!/bin/bash |
||||
|
||||
POSITION="$(/usr/bin/python /home/marcel/ham/gps/get_position.py)" |
||||
INFO="Portable HAM Station" |
||||
|
||||
if [ "$POSITION" != "!0000.00N/00000.00E;" ]; then |
||||
|
||||
# Set arguments for beacon program |
||||
args[0]=-d |
||||
args[1]="APRX29 $Path" |
||||
args[2]=-s |
||||
args[3]=aprs_lora |
||||
args[4]="$POSITION$INFO" |
||||
|
||||
# Send position beacon |
||||
/usr/sbin/beacon "${args[@]}" |
||||
|
||||
echo "Position beacon send." |
||||
|
||||
#/usr/sbin/beacon -d "APRX29" -s aprs_lora $BEACON |
||||
else |
||||
echo "No GPS signal found. Nothing to do." |
||||
fi |
Loading…
Reference in new issue