mirror of
https://github.com/thetechprepper/emcomm-tools-os-community.git
synced 2026-09-17 15:41:44 -04:00
Merge pull request #72 from thetechprepper/feature/find-winlink
Merge feature/find-winlink into release/r6
This commit is contained in:
Executable
+51
@@ -0,0 +1,51 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Author : Gaston Gonzalez
|
||||||
|
# Date : 29 November 2025
|
||||||
|
# Updated : 30 November 2025
|
||||||
|
# Purpose : Generates a denormalized Winlink RMS channel data set from
|
||||||
|
# Pat Winlink's JSON definition. Each line represents a single
|
||||||
|
# Winlink RMS channel. This generated file is the source for
|
||||||
|
# building the Winlink search index.
|
||||||
|
source /opt/emcomm-tools/bin/et-common
|
||||||
|
|
||||||
|
RMS_SRC_JSON_FILE=~/.local/share/pat/rmslist.json
|
||||||
|
RMS_DATA_OUT_FILE=/opt/emcomm-tools-api/data/rmslist.csv
|
||||||
|
|
||||||
|
# Return a denormalized list of RMS stations filtered by the supported
|
||||||
|
# Winlink modes in EmComm Tools Community.
|
||||||
|
#
|
||||||
|
# 0 Packet 1200
|
||||||
|
# 41 ARDOP 500
|
||||||
|
# 43 ARDOP 2000
|
||||||
|
# 50 VARA HF
|
||||||
|
# 51 VARA FM
|
||||||
|
# 52 VARA FM Wide
|
||||||
|
# 54 VARA HF 2750
|
||||||
|
|
||||||
|
cat ${RMS_SRC_JSON_FILE} | jq -r '
|
||||||
|
.Gateways[]
|
||||||
|
| . as $gw
|
||||||
|
| $gw.GatewayChannels[]
|
||||||
|
| select(.Mode | IN(0, 41, 43, 50, 51, 52, 54))
|
||||||
|
| [
|
||||||
|
$gw.BaseCallsign,
|
||||||
|
$gw.Callsign,
|
||||||
|
$gw.Latitude,
|
||||||
|
$gw.Longitude,
|
||||||
|
.SupportedModes,
|
||||||
|
.Mode,
|
||||||
|
.Frequency
|
||||||
|
]
|
||||||
|
| join("|")
|
||||||
|
' > ${RMS_DATA_OUT_FILE}
|
||||||
|
|
||||||
|
LINES=$(wc -l $RMS_DATA_OUT_FILE | awk '{print $1}')
|
||||||
|
echo "Created RMS dataset: ${RMS_DATA_OUT_FILE} with ${LINES} records."
|
||||||
|
echo
|
||||||
|
echo -e "${YELLOW}To update the Winlink index, perform the following as your normal user:${NC}"
|
||||||
|
echo
|
||||||
|
echo -e "${RED}DO NOT RUN THESE AS ROOT!${NC}"
|
||||||
|
echo
|
||||||
|
echo -e "${YELLOW}1. Stop the ETC API: ${WHITE}systemctl --user stop et-service-et-api${NC}"
|
||||||
|
echo -e "${YELLOW}2. Remove the old index: ${WHITE}rm -rf /opt/emcomm-tools-api/index/rmslist${NC}"
|
||||||
|
echo -e "${YELLOW}3. Start the ETC API: ${WHITE}systemctl --user start et-service-et-api${NC}"
|
||||||
Executable
+187
@@ -0,0 +1,187 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
#
|
||||||
|
# Author : Gaston
|
||||||
|
# Date : 30 November 2025
|
||||||
|
# Purpose : Finds Winlink RMS stations by channel near a given location
|
||||||
|
set -e
|
||||||
|
set -o pipefail
|
||||||
|
trap 'last_command=$current_command; current_command=$BASH_COMMAND' DEBUG
|
||||||
|
trap 'echo -e "${RED}\"${last_command}\" command failed with exit code $?.${NC}"' ERR
|
||||||
|
|
||||||
|
source /opt/emcomm-tools/bin/et-common
|
||||||
|
|
||||||
|
# Temporary file to hold location for all supported location types
|
||||||
|
LOCATION_FILE=/tmp/location.json
|
||||||
|
|
||||||
|
[[ -e ${TMP_FILE} ]] && rm ${TMP_FILE}
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
echo "Usage: $(basename $0) [OPTIONS]"
|
||||||
|
echo
|
||||||
|
echo "Location options (choose one):"
|
||||||
|
echo " --call CALLSIGN Search near callsign"
|
||||||
|
echo " --grid GRID Search near Maidenhead grid"
|
||||||
|
echo " --latlon LAT,LON Search near coordinates (use decimal degrees)"
|
||||||
|
echo
|
||||||
|
echo "If no location option is specified, your position will be pulled from a supported"
|
||||||
|
echo "ETC GPS unit or fallback to the grid square configured by 'et-user'."
|
||||||
|
echo
|
||||||
|
echo "Other options (optional):"
|
||||||
|
echo " -b BAND Band [70cm|2m|6m|10m|12m|15m|17m|20m|30m|40m|80m|160m]"
|
||||||
|
echo " -m MODE Mode [ardop|vara|packet]"
|
||||||
|
echo
|
||||||
|
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
loc_type=""
|
||||||
|
loc_value=""
|
||||||
|
band=""
|
||||||
|
mode=""
|
||||||
|
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case "$1" in
|
||||||
|
--call) loc_type="call"; loc_value="$2"; shift 2 ;;
|
||||||
|
--grid) loc_type="grid"; loc_value="$2"; shift 2 ;;
|
||||||
|
--latlon) loc_type="latlon"; loc_value="$2"; shift 2 ;;
|
||||||
|
-b) band="$2"; shift 2 ;;
|
||||||
|
-m) mode="$2"; shift 2 ;;
|
||||||
|
-*|--*) echo "Unknown option: $1"; usage ;;
|
||||||
|
-h|--help) usage ;;
|
||||||
|
*) echo "Unexpected argument: $1"; usage ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
# Use local ETC user position if location is not defined
|
||||||
|
if [[ -z $loc_type ]]; then
|
||||||
|
loc_type="gps"
|
||||||
|
fi
|
||||||
|
|
||||||
|
#echo "$loc_type = $loc_value"
|
||||||
|
|
||||||
|
case "$loc_type" in
|
||||||
|
gps)
|
||||||
|
curl -f -s "http://localhost:1981/api/geo/position" | jq .position > ${LOCATION_FILE}
|
||||||
|
if [[ $? -ne 0 ]]; then
|
||||||
|
echo -e "${RED}Can't determine your position for use as the transmitting station.${NC}" >&2
|
||||||
|
echo "Try specifying your callsign, grid or lat,lon." >&2
|
||||||
|
echo " --call CALLSIGN Search near callsign" >&2
|
||||||
|
echo " --grid GRID Search near Maidenhead grid" >&2
|
||||||
|
echo " --latlon LAT,LON Search near coordinates (use decimal degrees)" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
call)
|
||||||
|
curl -f -s "http://localhost:1981/api/license?callsign=${loc_value}" > ${LOCATION_FILE}
|
||||||
|
if [[ $? -ne 0 ]]; then
|
||||||
|
echo -e "${RED}Location not found for callsign: ${loc_value}.${NC}" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
grid)
|
||||||
|
curl -f -s "http://localhost:1981/api/geo/grid?gridSquare=${loc_value}" | jq '{lat: .position.lat, lon: .position.lon}' > ${LOCATION_FILE}
|
||||||
|
if [[ $? -ne 0 ]]; then
|
||||||
|
echo -e "${RED}Error converting grid to lat/lon using value: ${loc_value}.${NC}" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
latlon)
|
||||||
|
# Write directly to JSON for consistency
|
||||||
|
IFS=',' read -r tmpLat tmpLon <<< "$loc_value"
|
||||||
|
if [[ -z $tmpLat || -z $tmpLon ]]; then
|
||||||
|
echo -e "${RED}Invalid lat,lon format: $value. Expected 'lat,lon'.${NC}" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
jq -n --arg lat "$tmpLat" --arg lon "$tmpLon" '{lat: ($lat|tonumber), lon: ($lon|tonumber)}' > ${LOCATION_FILE}
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo -e "${RED}Invalid location type: $loc_type${NC}" >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
validate_latitude() {
|
||||||
|
local lat="$1"
|
||||||
|
|
||||||
|
if [[ -z "$lat" ]]; then
|
||||||
|
echo -e "${RED}Latitude can't be an empty value${NC}" >&2
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! [[ "$lat" =~ ^-?[0-9]+([.][0-9]+)?$ ]]; then
|
||||||
|
echo -e "${RED}Latitude must be a number${NC}" >&2
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
local latf
|
||||||
|
latf=$(printf "%.10f" "$lat" 2>/dev/null) || {
|
||||||
|
echo -e "${RED}Error converting latitude${NC}" >&2
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check range: -90 <= lat <= 90
|
||||||
|
if (( $(echo "$latf < -90" | bc -l) )) || (( $(echo "$latf > 90" | bc -l) )); then
|
||||||
|
echo -e "${RED}Latitude must be in range between -90 and 90 degrees${NC}" >&2
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
validate_longitude() {
|
||||||
|
local lon="$1"
|
||||||
|
|
||||||
|
if [[ -z "$lon" ]]; then
|
||||||
|
echo -e "${RED}Longitude can't be an empty value${NC}" >&2
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! [[ "$lon" =~ ^-?[0-9]+([.][0-9]+)?$ ]]; then
|
||||||
|
echo -e "${RED}Longitude must be a number${NC}" >&2
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
local lonf
|
||||||
|
lonf=$(printf "%.10f" "$lon" 2>/dev/null) || {
|
||||||
|
echo -e "${RED}Error converting longitude ${NC}" >&2
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check range: -180 <= lat <= 1800
|
||||||
|
if (( $(echo "$lon < -180" | bc -l) )) || (( $(echo "$lon > 180" | bc -l) )); then
|
||||||
|
echo -e "${RED}Longitude must be in range between -180 and 180 degrees${NC}" >&2
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
LAT=$(jq .lat $LOCATION_FILE)
|
||||||
|
LON=$(jq .lon $LOCATION_FILE)
|
||||||
|
|
||||||
|
validate_latitude "$LAT" || exit 1
|
||||||
|
validate_longitude "$LON" || exit 1
|
||||||
|
|
||||||
|
QUERY="http://localhost:1981/api/winlink/near?lat=${LAT}&lon=${LON}"
|
||||||
|
[[ -n "${band}" ]] && QUERY="${QUERY}&band=${band}"
|
||||||
|
[[ -n "${mode}" ]] && QUERY="${QUERY}&mode=${mode}"
|
||||||
|
|
||||||
|
OUT=$(curl -s "${QUERY}")
|
||||||
|
|
||||||
|
if [[ -z "${OUT}" ]] || [[ "${OUT}" = "[]" ]]; then
|
||||||
|
echo "No Winlink RMS channels found."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "Nearby Winlink RMS Channels:"
|
||||||
|
echo "----------------------------"
|
||||||
|
|
||||||
|
echo "${OUT}" | jq -r '
|
||||||
|
(["Station","Callsign","Lat","Lon","Mode","Freq","Band"] | @tsv),
|
||||||
|
(.[] | [
|
||||||
|
.callsign,
|
||||||
|
.base_callsign,
|
||||||
|
(.lat | tostring),
|
||||||
|
(.lon | tostring),
|
||||||
|
.mode,
|
||||||
|
(.freq | tostring),
|
||||||
|
.band
|
||||||
|
] | @tsv)
|
||||||
|
' | column -t -s $'\t'
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
# Author : Gaston Gonzalez
|
# Author : Gaston Gonzalez
|
||||||
# Date : 13 August 2025
|
# Date : 13 August 2025
|
||||||
# Updated : 12 November 2025
|
# Updated : 30 November 2025
|
||||||
# Purpose : Install EmComm Tools API
|
# Purpose : Install EmComm Tools API
|
||||||
set -e
|
set -e
|
||||||
trap 'last_command=$current_command; current_command=$BASH_COMMAND' DEBUG
|
trap 'last_command=$current_command; current_command=$BASH_COMMAND' DEBUG
|
||||||
@@ -11,7 +11,7 @@ trap 'et-log "\"${last_command}\" command failed with exit code $?."' ERR
|
|||||||
. ../overlay/opt/emcomm-tools/bin/et-common
|
. ../overlay/opt/emcomm-tools/bin/et-common
|
||||||
|
|
||||||
APP=et-api
|
APP=et-api
|
||||||
VERSION=1.1.1
|
VERSION=1.2.0
|
||||||
ET_API_JAR="emcomm-tools-api-${VERSION}.jar"
|
ET_API_JAR="emcomm-tools-api-${VERSION}.jar"
|
||||||
BASE_URL="https://github.com/thetechprepper/et-api-java/releases/download/${VERSION}"
|
BASE_URL="https://github.com/thetechprepper/et-api-java/releases/download/${VERSION}"
|
||||||
|
|
||||||
@@ -34,6 +34,7 @@ chmod 755 "${BIN_DIR}/${APP}"
|
|||||||
FILES=(
|
FILES=(
|
||||||
"faa.csv"
|
"faa.csv"
|
||||||
"license.csv"
|
"license.csv"
|
||||||
|
"rmslist.csv"
|
||||||
"zip2geo.csv"
|
"zip2geo.csv"
|
||||||
"zip2geo-elevation.csv"
|
"zip2geo-elevation.csv"
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user