First commit
This commit is contained in:
@@ -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.
|
||||
|
BIN
__pycache__/decimaldegrees.cpython-311.pyc
Normal file
BIN
__pycache__/decimaldegrees.cpython-311.pyc
Normal file
Binary file not shown.
BIN
__pycache__/decimaldegrees.cpython-37.pyc
Normal file
BIN
__pycache__/decimaldegrees.cpython-37.pyc
Normal file
Binary file not shown.
BIN
__pycache__/geo_util.cpython-311.pyc
Normal file
BIN
__pycache__/geo_util.cpython-311.pyc
Normal file
Binary file not shown.
BIN
__pycache__/geo_util.cpython-37.pyc
Normal file
BIN
__pycache__/geo_util.cpython-37.pyc
Normal file
Binary file not shown.
160
decimaldegrees.py
Normal file
160
decimaldegrees.py
Normal file
@@ -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
|
||||
|
108
geo_util.py
Normal file
108
geo_util.py
Normal file
@@ -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
|
||||
|
54
get_position.py
Normal file
54
get_position.py
Normal file
@@ -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)
|
4
gps_port.txt
Executable file
4
gps_port.txt
Executable file
@@ -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)
|
||||
|
23
send_beacon_aprs_1200bd.sh
Executable file
23
send_beacon_aprs_1200bd.sh
Executable file
@@ -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
|
23
send_beacon_aprs_lora.sh
Executable file
23
send_beacon_aprs_lora.sh
Executable file
@@ -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
|
Reference in New Issue
Block a user