diff --git a/overlay/etc/skel/.config/systemd/user/default.target.wants/et-service-et-api.service b/overlay/etc/skel/.config/systemd/user/default.target.wants/et-service-et-api.service new file mode 120000 index 0000000..f342cf2 --- /dev/null +++ b/overlay/etc/skel/.config/systemd/user/default.target.wants/et-service-et-api.service @@ -0,0 +1 @@ +../et-service-et-api.service \ No newline at end of file diff --git a/overlay/etc/skel/.config/systemd/user/default.target.wants/et-service-mbtileserver.service b/overlay/etc/skel/.config/systemd/user/default.target.wants/et-service-mbtileserver.service new file mode 120000 index 0000000..bf304cb --- /dev/null +++ b/overlay/etc/skel/.config/systemd/user/default.target.wants/et-service-mbtileserver.service @@ -0,0 +1 @@ +../et-service-mbtileserver.service \ No newline at end of file diff --git a/overlay/etc/skel/.config/systemd/user/et-service-dump1090.service b/overlay/etc/skel/.config/systemd/user/et-service-dump1090.service new file mode 100644 index 0000000..b6b9166 --- /dev/null +++ b/overlay/etc/skel/.config/systemd/user/et-service-dump1090.service @@ -0,0 +1,21 @@ +# Author : Gaston Gonzalez +# Date : 7 June 2025 +# Purpose : User systemd unit file for EmComm Tools dump1090 service +# +# Usage: +# Check status : systemctl --user status et-service-dump1090 +# Start service : systemctl --user start et-service-dump1090 +# Stop service : systemctl --user stop et-service-dump1090 +# Reload this config : systemctl --user daemon-reload + +[Unit] +Description=EmComm Tools dump1090 service +# Disable conditional check for SDR device. Allow et-dump1090 to enforce. +#ConditionPathExists=/dev/et-sdr + +[Service] +ExecStart=/opt/emcomm-tools/bin/et-dump1090 +Restart=no + +[Install] +WantedBy=multi-user.target diff --git a/overlay/etc/skel/.config/systemd/user/et-service-et-api.service b/overlay/etc/skel/.config/systemd/user/et-service-et-api.service new file mode 100644 index 0000000..320b4c1 --- /dev/null +++ b/overlay/etc/skel/.config/systemd/user/et-service-et-api.service @@ -0,0 +1,19 @@ +# Author : Gaston Gonzalez +# Date : 13 August 2025 +# Purpose : User systemd unit file for EmComm Tools API +# +# Usage: +# Check status : systemctl --user status et-service-et-api +# Start service : systemctl --user start et-service-et-api +# Stop service : systemctl --user stop et-service-et-api +# Reload this config : systemctl --user daemon-reload + +[Unit] +Description=EmComm Tools API + +[Service] +ExecStart=/opt/emcomm-tools-api/bin/et-api +Restart=always + +[Install] +WantedBy=default.target diff --git a/overlay/etc/skel/.config/systemd/user/et-service-mbtileserver.service b/overlay/etc/skel/.config/systemd/user/et-service-mbtileserver.service new file mode 100644 index 0000000..aa6f560 --- /dev/null +++ b/overlay/etc/skel/.config/systemd/user/et-service-mbtileserver.service @@ -0,0 +1,19 @@ +# Author : Gaston Gonzalez +# Date : 5 July 2025 +# Purpose : User systemd unit file for EmComm Tools raster tile service +# +# Usage: +# Check status : systemctl --user status et-service-mbtileservice +# Start service : systemctl --user start et-service-mbtileservice +# Stop service : systemctl --user stop et-service-mbtileservice +# Reload this config : systemctl --user daemon-reload + +[Unit] +Description=EmComm Tools raster tile service + +[Service] +ExecStart=/opt/emcomm-tools/bin/et-mbtileserver +Restart=always + +[Install] +WantedBy=default.target diff --git a/overlay/etc/skel/.local/share/emcomm-tools/mbtileserver/tilesets/README.md b/overlay/etc/skel/.local/share/emcomm-tools/mbtileserver/tilesets/README.md new file mode 100644 index 0000000..92513d6 --- /dev/null +++ b/overlay/etc/skel/.local/share/emcomm-tools/mbtileserver/tilesets/README.md @@ -0,0 +1 @@ +Copy your `.mbtiles` file here. diff --git a/overlay/etc/skel/.local/share/emcomm-tools/voacap/et-voacap.sh b/overlay/etc/skel/.local/share/emcomm-tools/voacap/et-voacap.sh new file mode 100755 index 0000000..e01b3d7 --- /dev/null +++ b/overlay/etc/skel/.local/share/emcomm-tools/voacap/et-voacap.sh @@ -0,0 +1,315 @@ +#!/bin/bash +# +# Author : Gaston Gonzalez +# Date : 23 May 2023 +# Updated : 24 August 2025 +# Purpose : Offline HF prediction using voacapl +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 + +lookup_station() { + local type="$1" # call | grid | latlon + local value="$2" # callsign | grid | "lat,lon" + local json_file="$3" + + case "$type" in + call) + curl -f -s "http://localhost:1981/api/license?callsign=${value}" > "$json_file" + if [[ $? -ne 0 ]]; then + echo -e "${RED}Location not found for callsign: ${value}.${NC}" >&2 + return 1 + fi + ;; + grid) + curl -f -s "http://localhost:1981/api/geo/grid?gridSquare=${value}" | jq '{lat: .position.lat, lon: .position.lon}' > "$json_file" + if [[ $? -ne 0 ]]; then + echo -e "${RED}Error converting grid to lat/lon using value: ${value}.${NC}" >&2 + return 1 + fi + ;; + latlon) + # Write directly to JSON for consistency + local lat lon + IFS=',' read -r lat lon <<< "$value" + if [[ -z $lat || -z $lon ]]; then + echo -e "${RED}Invalid lat,lon format: $value. Expected 'lat,lon'.${NC}" >&2 + return 1 + fi + jq -n --arg lat "$lat" --arg lon "$lon" '{lat: ($lat|tonumber), lon: ($lon|tonumber)}' > "$json_file" + ;; + *) + echo -e "${RED}Invalid station type: $type${NC}" >&2 + return 1 + ;; + esac + + # Extract lat/lon regardless of type + local lat lon + lat=$(jq .lat "$json_file") + lon=$(jq .lon "$json_file") + + echo "$lat $lon" +} + +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 +} + +ET_SSN="${HOME}/.local/share/emcomm-tools/voacap/ssn.txt" +if [[ ! -e ${ET_SSN} ]]; then + echo -e "${RED}Sunspot number file not available:${WHITE}${ET_SSN}${NC}" + echo -e "${YELLOW}Try running the following to fetch the sunspot numbers (requires Internet):${NC}" + echo -e "${WHITE}cd ${HOME}/.local/share/emcomm-tools/voacap${NC}" + echo -e "${WHITE}./fetch-ssn.sh${NC}" + + exit 1 +fi + +usage() { + echo "Usage: $(basename $0) [OPTIONS]" + echo + echo "Station options (choose one per TX and RX):" + echo " --tx-call CALLSIGN Transmitting station callsign" + echo " --tx-grid GRID Transmitting station Maidenhead grid" + echo " --tx-latlon LAT,LON Transmitting station coordinates in decimal degrees" + echo " --rx-call CALLSIGN Receiving station callsign" + echo " --rx-grid GRID Receiving station Maidenhead grid" + echo " --rx-latlon LAT,LON Receiving station coordinates in decimal degrees" + echo + echo "Other options:" + echo " -p POWER Output power [5|20|100|500|1500]" + echo " -m MODE Mode [AM|CW|JS8|SSB]" + echo + + exit 1 +} + +tx_type="" +tx_value="" +rx_type="" +rx_value="" +power="" +mode="" + +while [[ $# -gt 0 ]]; do + case "$1" in + --tx-call) tx_type="call"; tx_value="$2"; shift 2 ;; + --tx-grid) tx_type="grid"; tx_value="$2"; shift 2 ;; + --tx-latlon) tx_type="latlon"; tx_value="$2"; shift 2 ;; + --rx-call) rx_type="call"; rx_value="$2"; shift 2 ;; + --rx-grid) rx_type="grid"; rx_value="$2"; shift 2 ;; + --rx-latlon) rx_type="latlon"; rx_value="$2"; shift 2 ;; + -p) power="$2"; shift 2 ;; + -m) mode="$2"; shift 2 ;; + -*|--*) echo "Unknown option: $1"; usage ;; + *) echo "Unexpected argument: $1"; usage ;; + esac +done + +# Validate required args +[[ -z $tx_type || -z $rx_type || -z $power || -z $mode ]] && usage + +#echo "TX ($tx_type): $tx_value" +#echo "RX ($rx_type): $rx_value" +#echo "Power: $power" +#echo "Mode: $mode" + +# Allow for case-insensitve match of the user-defined operating mode +MODE=$mode +case "${MODE,,}" in + js8) + MD="13.0" + ;; + cw) + MD="24.0" + ;; + ssb) + MD="38.0" + ;; + am) + MD="49.0" + ;; + *) + echo -e "${RED}Unknown mode: ${MODE}${NC}" >&2 + usage + exit 1 + ;; +esac + +ET_VOA_WORKING_DIR=$HOME/itshfbc/run +ET_VOA_REPORT=${ET_VOA_WORKING_DIR}/voacapl.txt +INP=${ET_VOA_WORKING_DIR}/voacapx.dat +OUT=${ET_VOA_WORKING_DIR}/voacapx.out + +# Year = 2023 +YEAR=$(echo $(date '+%Y')) + +# Month (May) = 5.00 +MONTH=$(date +'%m') +MONTH_FMT=$(date +'%-m.00') + +####################################################################### +# TX Antenna +####################################################################### + +if ! result=$(lookup_station "$tx_type" "$tx_value" tx-station.json); then + if [[ "$tx_type" == "call" ]]; then + echo "Try specifying a grid or lat,lon for the transmitting station." + echo " --tx-grid GRID Transmitting station Maidenhead grid" + echo " --tx-latlon LAT,LON Transmitting station coordinates in decimal degrees" + fi + exit 1 +fi +read TL TK <<< "$result" + +validate_latitude "$TL" || exit 1 +validate_longitude "$TK" || exit 1 + +TL1=$( awk -v n1=$TL -v n2=90 -v n3=-90 'BEGIN {if (n1n2) printf ("%s", "a"); else printf ("%.2f", n1);}' ) + +# add North or South (N/S) +TLA=$( awk -v n1=$TL1 -v n2=0 'BEGIN {if (n1n2) printf ("%s", "a"); else printf ("%.2f", n1);}' ) + +# add East or West (E/W) +TLO=$( awk -v n1=$TK1 -v n2=0 'BEGIN {if (n1n2) printf ("%s", "a"); else printf ("%.2f", n1);}' ) + +# add North or South +RLA=$( awk -v n1=$RL1 -v n2=0 'BEGIN {if (n1n2) printf ("%s", "a"); else printf ("%.2f", n1);}' ) + +# add East or West +RLO=$( awk -v n1=$RK1 -v n2=0 'BEGIN {if (n1. (117.) +ssn=`grep "$YEAR $MONTH" ${ET_SSN} | awk '{print $5}' | cut -d"." -f1` + +# read more about fine-tuning your input file: +# http://www.voacap.com/voacapw.html +# http://www.voacap.com/frequency.html + +echo -e "\n" + +cat << END | tee $INP +LINEMAX 999 number of lines-per-page +COEFFS CCIR +TIME 1 24 1 1 +MONTH $YEAR $MONTH_FMT +SUNSPOT $ssn. +LABEL $TX$RX +CIRCUIT $TLA $TLO $RLA $RLO S 0 +SYSTEM 1. 155. 3.00 90. $MD 3.00 0.10 +FPROB 1.00 1.00 1.00 0.00 +ANTENNA 1 1 2 30 0.000[samples/sample.00 ] 0.0 $PW +ANTENNA 2 2 2 30 0.000[samples/sample.00 ] 0.0 0.0000 +FREQUENCY 3.60 5.30 7.1010.1014.1018.1021.1024.9028.20 0.00 0.00 +METHOD 30 0 +BOTLINES 8 12 21 +TOPLINES 1 2 3 4 6 +EXECUTE +QUIT + +END + +voacapl -s ~/itshfbc +echo "voacapl exited with $? using in=$INP and out=$OUT" + +(tail -n +27 $OUT | head -n 5 && grep -e'- REL' $OUT && grep -e'- S DBW' $OUT) | ./rel.pl > ${ET_VOA_REPORT} +cat ${ET_VOA_REPORT} diff --git a/overlay/etc/skel/.local/share/emcomm-tools/voacap/fetch-ssn.sh b/overlay/etc/skel/.local/share/emcomm-tools/voacap/fetch-ssn.sh new file mode 100755 index 0000000..f0b84c9 --- /dev/null +++ b/overlay/etc/skel/.local/share/emcomm-tools/voacap/fetch-ssn.sh @@ -0,0 +1,15 @@ +#!/bin/bash +# Author : Gaston Gonzalez +# Date : 16 August 2025 +# Purpose : Fetch SSNs for VOACAP prediction + +source /opt/emcomm-tools/bin/et-common + +FILE="ssn.txt" +URL="https://www.sidc.be/silso/FORECASTS/prediML.txt" +curl -s -f -L -o ${FILE} ${URL} + +if [[ $? -ne 0 ]]; then + echo -e "${RED}Failed to update ${FILE} from: ${URL}." + exit 1 +fi diff --git a/overlay/etc/skel/.local/share/emcomm-tools/voacap/rel.pl b/overlay/etc/skel/.local/share/emcomm-tools/voacap/rel.pl new file mode 100755 index 0000000..6448585 --- /dev/null +++ b/overlay/etc/skel/.local/share/emcomm-tools/voacap/rel.pl @@ -0,0 +1,133 @@ +#!/usr/bin/perl +# Author: Jari Perkiömäki OH6BG +# 12 June 2016: initial release +# 18 June 2016: added Long-Path predictions; use unpack for extracting table data +# 18 June 2016: added Power, Mode; small improvements +# + +use strict; +use warnings; + +my @relhour = (); +my @sdbwhour = (); +my @co = (); +my @mo = (); +my @pwr = (); +my @db = (); +my $km = 0; +my $mi = 0; +my $brn = 0; +my $fh; +my $voa; +my $mode; +my $path = "Short-Path"; + +# main loop +open $fh, '>>', \$voa or die $!; +process (); +close $fh; +print $voa; +exit; + +### end ### + +sub process { + my $format = 'A4 A5 A5 A5 A5 A5 A5 A5 A5 A5'; + while (<>) { + + s/^\s+|\s+$//g; + + if ( substr ($_, -1) eq "s" ) { @mo = split /\s+/; } + + elsif ( substr ($_, -2) eq "kW" ) { @pwr = split /\s+/; } + elsif ( substr ($_, -2) eq "dB" ) { + + @db = split /\s+/; + if ( $db[13] eq "24.0" ) { $mode = "CW"; } + elsif ( $db[13] eq "38.0" ) { $mode = "SSB"; } + else { $mode = "AM"; } + + } + + elsif ( /Long/ ) { $path = "Long-Path"; } + + elsif ( substr ($_, -1) =~ /\d/ ) { + + @co = split /\s+/; + $brn = sprintf "%d", $co[9] + 0.5; + $km = sprintf "%d", $co[12] + 0.5; + $mi = sprintf "%d", ($co[12] * 0.62137) + 0.5; + + } + + elsif ( substr ($_, -3) eq "REL" ) { push (@relhour, [ unpack( $format, $_ ) ] ); } + elsif ( substr ($_, -3) eq "DBW" ) { push (@sdbwhour,[ unpack( $format, $_ ) ] ); } + + } # while + + for ($fh) { + print $_ "VOACAP Prediction via $path. $mo[0] $mo[1]: SSN $mo[4] Power = $pwr[$#pwr], $mode\n"; + print $_ "TX ($co[0]$co[1], $co[2]$co[3]) to RX ($co[5]$co[6], $co[7]$co[8]): $km km, $mi mi, $brn deg\n\n"; + print $_ " | 01|02|03|04|05|06|07|08|09|10|11|12|13|14|15|16|17|18|19|20|21|22|23|24|\n"; + } + + foreach my $freq (reverse 1..9) { + print $fh band($freq) . "|"; + foreach my $h (0..23) { print $fh makehourfreq( $h, $freq ); } + print $fh "|" . band($freq) . "\n"; + } + + for ($fh) { + print $_ " | 01|02|03|04|05|06|07|08|09|10|11|12|13|14|15|16|17|18|19|20|21|22|23|24|\n\n"; + print $_ "A = 90 - 100% d = 25 - 49% * = REL 0%, but Signal Power over Noise\n"; + print $_ "B = 75 - 89% e = 10 - 24%\n"; + print $_ "C = 50 - 74% f = 1 - 9%\n\n"; + } + + @relhour = (); + @sdbwhour = (); + + } # process + +sub makehourfreq { + + my $h = $_[0]; + my $f = $_[1]; + my $r = $relhour[$h][$f]; + my $s = $sdbwhour[$h][$f]; + + if ( ($r == 0.00 && $s >= -167) ) { return " * "; } + else { return col($relhour[$h][$f]); } + + } + +sub band { + + my $b = $_[0]; + + if ($b == 1) { return "80"; } + if ($b == 2) { return "60"; } + if ($b == 3) { return "40"; } + if ($b == 4) { return "30"; } + if ($b == 5) { return "20"; } + if ($b == 6) { return "17"; } + if ($b == 7) { return "15"; } + if ($b == 8) { return "12"; } + if ($b == 9) { return "10"; } + + } + +sub col { + + my $rel = $_[0]; + + if ($rel == 0.00 ) { return " "; } + elsif ($rel >= 0.01 && $rel < 0.10 ) { return " f "; } + elsif ($rel >= 0.10 && $rel < 0.25 ) { return " e "; } + elsif ($rel >= 0.25 && $rel < 0.50 ) { return " d "; } + elsif ($rel >= 0.50 && $rel < 0.75 ) { return " C "; } + elsif ($rel >= 0.75 && $rel < 0.90 ) { return " B "; } + elsif ($rel >= 0.90 && $rel < 1.01 ) { return " A "; } + else { return " - "; } + + } \ No newline at end of file diff --git a/overlay/etc/skel/.local/share/emcomm-tools/voacap/ssn.txt b/overlay/etc/skel/.local/share/emcomm-tools/voacap/ssn.txt new file mode 100644 index 0000000..d7fd966 --- /dev/null +++ b/overlay/etc/skel/.local/share/emcomm-tools/voacap/ssn.txt @@ -0,0 +1,18 @@ +2025 02 2025.122 : 145.4 5.0 +2025 03 2025.204 : 145.5 10.2 +2025 04 2025.286 : 145.0 15.5 +2025 05 2025.371 : 143.1 20.7 +2025 06 2025.453 : 140.9 24.6 +2025 07 2025.538 : 137.3 26.5 +2025 08 2025.623 : 133.1 27.0 +2025 09 2025.705 : 129.4 27.3 +2025 10 2025.790 : 126.1 29.0 +2025 11 2025.873 : 123.2 30.0 +2025 12 2025.958 : 120.8 29.3 +2026 01 2026.042 : 118.0 28.2 +2026 02 2026.122 : 114.6 27.4 +2026 03 2026.204 : 110.4 25.8 +2026 04 2026.286 : 106.1 24.6 +2026 05 2026.371 : 102.1 23.8 +2026 06 2026.453 : 97.8 23.9 +2026 07 2026.538 : 94.0 25.1 diff --git a/overlay/etc/skel/add-ons/docs/create-doc-site.sh b/overlay/etc/skel/add-ons/docs/create-doc-site.sh new file mode 100755 index 0000000..ea744a2 --- /dev/null +++ b/overlay/etc/skel/add-ons/docs/create-doc-site.sh @@ -0,0 +1,25 @@ +#!/bin/bash +# Author : Gaston Gonzalez +# Date : 3 April 2025 +# Updated : 24 April 2024 +# Purpose : Creates a Jekyll doc site +set -e +source /opt/emcomm-tools/bin/et-common + +function usage() { + echo "$(basename $0) " +} + +if [[ $# -ne 1 ]]; then + usage + exit 1 +fi + +SITE="$1" + +rbenv local 3.3.8 +gem install jekyll bundler && jekyll new ${SITE} + +echo -e "${YELLOW}1. Move into the site directory: ${WHITE}cd ${SITE}${NC}" +echo -e "${YELLOW}2. Build and start site: ${WHITE}bundle exec jekyll serve${NC}" +echo -e "${YELLOW}3. Access site in web browser: ${WHITE}min http://localhost:4000${NC}" diff --git a/overlay/etc/skel/add-ons/docs/install-doc-tools.sh b/overlay/etc/skel/add-ons/docs/install-doc-tools.sh new file mode 100755 index 0000000..4dba6c1 --- /dev/null +++ b/overlay/etc/skel/add-ons/docs/install-doc-tools.sh @@ -0,0 +1,41 @@ +#!/bin/bash +# Author : Gaston Gonzalez +# Date : 2 April 2025 +# Updated : 24 April 2025 +# Purpose : Installs documentation tooling +set -e + +RUBY_VERSION="3.3.8" + +if [[ "${EUID}" -eq 0 ]]; then + echo "This script be run as your normal user, not as root." + exit 1 +fi + +if [[ ! -e ~/.rbenv ]]; then + echo "Install 'rbenv' into your home directory..." + git clone https://github.com/rbenv/rbenv.git ~/.rbenv + + echo "Adding 'rbenv' into your path..." + echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bash_profile + echo 'eval "$(rbenv init - bash)"' >> ~/.bash_profile + + echo "Adding 'ruby-build' plugin..." + git clone https://github.com/rbenv/ruby-build.git ~/.rbenv/plugins/ruby-build +fi + +source ~/.bash_profile + + +echo "Installing Ruby ${RUBY_VERSION}..." +rbenv install ${RUBY_VERSION} +rbenv global ${RUBY_VERSION} + +echo "Using ruby version: $(ruby -v)" +echo "Using gem version: $(gem -v)" + +ruby -v | grep "${RUBY_VERSION}" +if [[ $? -ne 0 ]]; then + "The documentation tool requires Ruby ${RUBY_VERSION}." + exit 1 +fi diff --git a/overlay/etc/udev/rules.d/77-et-ftx1.rules b/overlay/etc/udev/rules.d/77-et-ftx1.rules new file mode 100644 index 0000000..b33cb23 --- /dev/null +++ b/overlay/etc/udev/rules.d/77-et-ftx1.rules @@ -0,0 +1,38 @@ +# Author : Gaston Gonzalez +# Date : 21 May 2025 +# Updated : 16 May 2025 +# Purpose : udev rules for the Yaesu FTX-1 via USB-C +# +# Preconditions: +# 1. Yaesu FTX-1 is selected via et-radio +# 2. Yaesu FTX-1 is connected via USB-C cable +# +# Postconditions: +# 1. /dev/et-cat created +# 2. /dev/et-audio created +# 3. rigctld is started +# +# Note: As of 05/21/25 Yaesu has not published their CAT control command specification. This is a +# temporary integration that does not include CAT control support. It will only key the PTT +# and provide audio in/out. You MUST set the frequency and mode yourself. + +# Special rule to ensure that the second serial interface (/dev/ttyUSB5) is tagged as ET_DEVICE=FTX-1 so +# that it can be used in the next CAT control rule. +KERNEL=="ttyUSB[0-9]*", SUBSYSTEM=="tty", PROGRAM="/opt/emcomm-tools/sbin/udev-tester.sh yaesu-ftx1", \ + ATTRS{bInterfaceNumber}=="01", \ + ENV{ET_DEVICE}="FTX-1" + +# CAT control device will only match if PROGRAM above matches (exit status=0) +SUBSYSTEM=="tty", ENV{ET_DEVICE}=="FTX-1", \ + ATTRS{idVendor}=="10c4", ATTRS{idProduct}=="ea70",\ + ACTION=="add", \ + ENV{ET_SUBDEVICE}="CAT", GROUP="dialout", MODE="0660", SYMLINK+="et-cat", \ + RUN+="/usr/bin/systemctl start rigctld" + +# Audio device will only match if PROGRAM above matches (exit status=0) +SUBSYSTEM=="sound", ATTRS{idVendor}=="0d8c", ATTRS{idProduct}=="0016", \ + PROGRAM="/opt/emcomm-tools/sbin/udev-tester.sh yaesu-ftx1", \ + ACTION=="add", \ + ENV{ET_DEVICE}="FTX-1", \ + ATTR{id}="ET_AUDIO", \ + ENV{ET_SUBDEVICE}="AUDIO", GROUP="audio", MODE="0660", SYMLINK+="et-audio" diff --git a/overlay/etc/udev/rules.d/85-brltty.rules b/overlay/etc/udev/rules.d/85-brltty.rules new file mode 100644 index 0000000..ba00dcb --- /dev/null +++ b/overlay/etc/udev/rules.d/85-brltty.rules @@ -0,0 +1,7 @@ +# Author : Gaston Gonzalez +# Date : 31 May 2025 +# Updated : 4 June 2025 +# Purpose : Empty udev rule to prevent the BRLTTY subsystem from +# invoking /lib/udev/rules.d/85-brltty.rules. These rules +# hijack some USB devices used by ETC operators. The Bionics +# MicroFox-50 was one of these hijacked devices. diff --git a/overlay/etc/udev/rules.d/99-et-sdr.rules b/overlay/etc/udev/rules.d/99-et-sdr.rules new file mode 100644 index 0000000..e32cdfd --- /dev/null +++ b/overlay/etc/udev/rules.d/99-et-sdr.rules @@ -0,0 +1,15 @@ +# Author : Gaston Gonzalez +# Date : 7 June 2025 +# Purpose : udev rules for supported SDRs +# +# Supported Devices +# 1. RTL-SDR Blog v2 +# +# Preconditions: +# 1. SDR connected via USB cable +# +# Postconditions: +# 1. /dev/et-sdr created + +KERNEL=="swradio0", \ + GROUP="dialout", MODE="0660", SYMLINK+="et-sdr" diff --git a/overlay/opt/emcomm-tools/bin/et-aircraft b/overlay/opt/emcomm-tools/bin/et-aircraft new file mode 100755 index 0000000..c6a0a93 --- /dev/null +++ b/overlay/opt/emcomm-tools/bin/et-aircraft @@ -0,0 +1,39 @@ +#!/bin/bash +# +# Author : Gaston Gonzalez +# Date : 4 June 2025 +# Update : 8 July 2025 +# Purpose : Wrapper script around ADS-B integration +# +# Preconditions: +# 1. RTL-SDR v2 is connected and detected +# +# Postconditions: +# 1. dump1099 systemd service is launched +# 2. et-aircraft-app launched + +source /opt/emcomm-tools/bin/et-common + +CLEAN_UP=1 + +cleanup() { + if [[ ${CLEAN_UP} -eq 1 ]]; then + et-log "Stopping dump1099 service" + systemctl --user stop et-service-dump1090 + fi +} + +# Stop dump1099 on exit +trap cleanup EXIT + +if [[ ! -e ${ET_DEVICE_SDR} ]]; then + notify-user "No ${ET_DEVICE_SDR} detected. Reconnect your SDR." + CLEAN_UP=0 + exit 1 +fi + +systemctl --user restart et-service-dump1090 +if [[ $? -eq 0 ]]; then + start_and_wait_for_service et-service-dump1090 + et-aircraft-app +fi diff --git a/overlay/opt/emcomm-tools/bin/et-audio b/overlay/opt/emcomm-tools/bin/et-audio index 2f921e5..dc33bde 100755 --- a/overlay/opt/emcomm-tools/bin/et-audio +++ b/overlay/opt/emcomm-tools/bin/et-audio @@ -2,7 +2,7 @@ # # Author : Gaston Gonzalez # Date : 31 October 2024 -# Updated : 11 November 2024 +# Updated : 31 May 2024 # Purpose : Configures ET audio device with sane defaults # # Preconditions @@ -85,6 +85,18 @@ update-config () { et-log "Applied amixer settings for ${ET_DEVICE_NAME}" ;; + "FTX-1") + # Unmute Speaker a set volume. Adjust if remote station can't decode you. Your TX controls. + amixer -q -c ${AUDIO_CARD} sset Speaker Playback Switch 42% unmute + # Unmute Mic + amixer -q -c ${AUDIO_CARD} sset Mic Playback Switch 52% unmute + # Set "L/R Capture" to 19. Adjust if you can't decode received audio. Your RX controls. + amixer -q -c ${AUDIO_CARD} sset Mic Capture Switch 31% unmute + # Disable Auto Gain Control + amixer -q -c ${AUDIO_CARD} sset 'Auto Gain Control' mute + + et-log "Applied amixer settings for ${ET_DEVICE_NAME}" + ;; *) et-log "No ALSA configuration specified for this ET_DEVICE." ;; diff --git a/overlay/opt/emcomm-tools/bin/et-common b/overlay/opt/emcomm-tools/bin/et-common index b6b1539..bc781dd 100755 --- a/overlay/opt/emcomm-tools/bin/et-common +++ b/overlay/opt/emcomm-tools/bin/et-common @@ -1,8 +1,15 @@ #!/bin/bash # Author : Gaston Gonzalez # Date : 1 February 2025 +# Updated : 20 August 2025 # Purpose : Common environment variables and functions +# Standardized device paths for supported hardware +export ET_DEVICE_AUDIO="/dev/et-audio" +export ET_DEVICE_CAT="/dev/et-cat" +export ET_DEVICE_GPS="/dev/et-gps" +export ET_DEVICE_SDR="/dev/et-sdr" + export ESC="\x1B" export RED="${ESC}[1;31m" export BLUE="${ESC}[1;34m" @@ -11,7 +18,126 @@ export WHITE="${ESC}[97m" export YELLOW="${ESC}[1;33m" export NC="${ESC}[0m" +# Display an error message in the terminal show-err-dialog() { local message="$1" dialog --title "Notification" --msgbox "$message" 8 60 } + +# Display a notification message as a UI popup in the desktop +notify-user() { + notify-send -t 5000 --app-name="EmComm Tools" "$1" +} + +exit_if_no_sdr() { + if [[ ! -e ${ET_DEVICE_SDR} ]]; then + et-log "No ${ET_DEVICE_SDR} detected." + exit 1 + fi +} + +exit_on_service_failure() { + local systemd_unit_name="$1" + systemctl is-active --user --quiet "${systemd_unit_name}" + if [ $? -ne 0 ]; then + et-log "Can't start mode. ${systemd_unit_name} failed to start." + exit 1 + fi +} + +start_and_wait_for_service() { + local timeout=15 # Total time to wait in seconds + local interval=2 # Interval between checks in seconds + local systemd_unit_name="$1" + local elapsed=0 + + et-log "Starting ${systemd_unit_name}..." + systemctl --user start ${systemd_unit_name} + + et-log "Waiting for ${systemd_unit_name} to become active..." + + while ! systemctl is-active --user --quiet "${systemd_unit_name}"; do + sleep "$interval" + elapsed=$((elapsed + interval)) + if [ "$elapsed" -ge "$timeout" ]; then + et-log "Timeout reached. ${systemd_unit_name} failed to start." + exit 1 + fi + et-log "Waiting for ${systemd_unit_name} to become active..." + done + + # Some applications even when started still need a bit of extra time to be available. + # Add a short think time of 2 seconds. The ARDOP modem requies extra time. + sleep 2 + + # Do one more check to ensure that we are running, otherwise exit. + exit_on_service_failure ${systemd_unit_name} +} + + +# download_with_retries downloads a file from a URL with retry and checksum support. +# +# This function attempts to download a file up to a maximum number of retries. +# If a checksum is provided, the downloaded file will be verified against it. +# On checksum mismatch, the file is deleted and the download retried. +# +# Args: +# url: The URL of the file to download. (required) +# filename: The local filename to save the file as. (required) +# checksum: Optional sha256 checksum string to validate the downloaded file. +# max_retries: Optional max number of retries (default: 3). +# wait_seconds: Optional wait time in seconds between retries (default: 2). +# +# Returns: +# 0 if the file was successfully downloaded (and checksum verified if given). +# 1 if arguments are missing, download fails after all retries, +# or checksum verification fails. +# +# Example: +# download_with_retries "https://example.com/file.tar.gz" "file.tar.gz" +# download_with_retries "https://example.com/file.tar.gz" "file.tar.gz" "abc123..." 5 3 +download_with_retries() { + local url="$1" + local filename="$2" + local checksum="$3" # expected checksum (sha256) + local max_retries="${4:-3}" # default = 3 retries + local wait_seconds="${5:-2}" # default = 2s wait between retries + + # Require at least URL and filename + if [[ -z "$url" || -z "$filename" ]]; then + echo "Usage: download_with_retries [checksum] [max_retries] [wait_seconds]" + return 1 + fi + + for ((i=1; i<=max_retries; i++)); do + echo "Attempt $i of $max_retries to download $url..." + + if curl -L -f -o "$filename" "$url"; then + echo "Download successful: $filename" + + if [[ -n "$checksum" ]]; then + echo "Verifying checksum..." + local file_checksum + file_checksum=$(sha256sum "$filename" | awk '{print $1}') + + if [[ "$file_checksum" == "$checksum" ]]; then + echo "Checksum OK" + return 0 + else + echo "Checksum mismatch (expected $checksum, got $file_checksum)" + rm -f "$filename" + fi + else + # no checksum provided, just succeed + return 0 + fi + else + echo "Download failed (attempt $i)." + fi + + sleep "$wait_seconds" + done + + echo "Download failed after $max_retries attempts." + return 1 +} diff --git a/overlay/opt/emcomm-tools/bin/et-dump1090 b/overlay/opt/emcomm-tools/bin/et-dump1090 new file mode 100755 index 0000000..3d3c0c8 --- /dev/null +++ b/overlay/opt/emcomm-tools/bin/et-dump1090 @@ -0,0 +1,55 @@ +#!/bin/bash +# +# Author : Gaston Gonzalez +# Date : 7 June 2025 +# Purpose : Wrapper script around dump1090 +# +# Preconditions: +# 1. RTL-SDR v2 is connected and detected +# +# Postconditions: +# 1. dump1099 map is updated with your position if available +# 2. dump1099 is launched with network and HTTP server support + +source /opt/emcomm-tools/bin/et-common + +DUMP1090_CONF_DIR="${HOME}/.local/share/emcomm-tools/dump1090" +DUMP1090_MAP_HTML="${DUMP1090_CONF_DIR}/gmap.html" + +exit_if_no_sdr + +if [[ ! -e ${DUMP1090_MAP_HTML} ]]; then + et-log "Map HTML not found: ${DUMP1090_MAP_HTML}" + notify-user "Map HTML not found: ${DUMP1090_MAP_HTML}" + exit 1 +fi + +CWD_DIR=$(pwd) + +cd ${DUMP1090_CONF_DIR} + +MY_LAT_LON=$(et-system-info et-gps) +if [[ $? -eq 0 ]]; then + if echo "${MY_LAT_LON}" | grep -Eq '^[-+]?[0-9]+(\.[0-9]+)?\s*,\s*[-+]?[0-9]+(\.[0-9]+)?$'; then + LAT=$(echo ${MY_LAT_LON} | cut -d "," -f1) + LON=$(echo ${MY_LAT_LON} | cut -d "," -f2) + ZOOM=10 + + sed -i "s/CenterLat=[^;]*;/CenterLat=${LAT};/g" ${DUMP1090_MAP_HTML} + sed -i "s/CenterLon=[^;]*;/CenterLon=${LON};/g" ${DUMP1090_MAP_HTML} + sed -i "s/setView(\[.*\], *[0-9]*);/setView([${LAT}, ${LON}], ${ZOOM});/" ${DUMP1090_MAP_HTML} + + et-log "Updated map center with your current location." + fi +fi + +CMD="dump1090 --net --net-http-port 1090" +et-log "Starting dump1090 in ${DUMP1090_CONF_DIR} with: ${CMD}" + +${CMD} + +if [[ $? -ne 0 ]]; then + et-log "Error starting dump1090." +fi + +cd ${CWD_DIR} diff --git a/overlay/opt/emcomm-tools/bin/et-mbtileserver b/overlay/opt/emcomm-tools/bin/et-mbtileserver new file mode 100755 index 0000000..672f728 --- /dev/null +++ b/overlay/opt/emcomm-tools/bin/et-mbtileserver @@ -0,0 +1,40 @@ +#!/bin/bash +# +# Author : Gaston Gonzalez +# Date : 5 July 2025 +# Purpose : Wrapper script for starting the raster tile server +# +# Preconditions: +# 1. At least one .mbtiles files exist in the tileset directory +# +# Postconditions: +# 1. mbtileserver is started +# 2. Tile server available at http://localhost:8000/services + +TILESERVER_HOME="${HOME}/.local/share/emcomm-tools/mbtileserver" +TILESERVER_TILE_DIR="${TILESERVER_HOME}/tilesets" + +start() { + CWD_DIR=$(pwd) + + cd ${TILESERVER_HOME} + CMD="mbtileserver" + et-log "Starting raster tile server in ${TILESERVER_HOME} with: ${CMD}" + + ${CMD} + + cd ${CWD_DIR} +} + +if [[ ! -e ${TILESERVER_TILE_DIR} ]]; then + et-log "Tile set directory does not exist: ${TILESERVER_TILE_DIR}." + exit 1 +fi + +ls ${TILESERVER_TILE_DIR}/*.mbtiles +if [[ $? -ne 0 ]]; then + et-log "Can't start tile server. No .mbtiles in ${TILESERVER_TILE_DIR}" + exit 1 +fi + +start diff --git a/overlay/opt/emcomm-tools/bin/et-voacap b/overlay/opt/emcomm-tools/bin/et-voacap new file mode 100755 index 0000000..10f085f --- /dev/null +++ b/overlay/opt/emcomm-tools/bin/et-voacap @@ -0,0 +1,14 @@ +#!/bin/bash +# +# Author : Gaston Gonzalez +# Date : 17 August 2025 +# Purpose : Wrapper script for VOACAP + +VOACAP_DIR=${HOME}/.local/share/emcomm-tools/voacap +CWD_DIR=$(pwd) + +cd ${VOACAP_DIR} + +./et-voacap.sh $@ + +cd ${CWD_DIR} diff --git a/overlay/opt/emcomm-tools/conf/radios.d/yaesu-ftx1.json b/overlay/opt/emcomm-tools/conf/radios.d/yaesu-ftx1.json new file mode 100644 index 0000000..4883b13 --- /dev/null +++ b/overlay/opt/emcomm-tools/conf/radios.d/yaesu-ftx1.json @@ -0,0 +1,25 @@ +{ + "id": "yaesu-ftx1", + "vendor": "Yaesu", + "model": "FTX-1 (No CAT)", + "rigctrl": { + "id": "1", + "baud": "38400", + "ptt": "RTS", + "pttOnly": "true" + }, + "notes": [ + "Tune radio to desired frequency.", + "Long press [MODE], then set accordingly for HF or VHF/UHF.", + "For HF operation:", + "- First, select 'DATA-U'.", + "- Then, long press 'PRESET' and select 'FT8'.", + "- The 'PRESET' button should be highlighted in blue.", + "For VHF/UHF FM operation:", + "- First, select 'FM'.", + "- Then, long press 'PRESET' and select 'FT8'.", + "- The 'PRESET' button should be highlighted in blue." + ], + "fieldNotes": [ + ] +} diff --git a/overlay/opt/emcomm-tools/conf/template.d/bbs/bpq32.simple.cfg b/overlay/opt/emcomm-tools/conf/template.d/bbs/bpq32.simple.cfg index 6eef1f7..cf29908 100644 --- a/overlay/opt/emcomm-tools/conf/template.d/bbs/bpq32.simple.cfg +++ b/overlay/opt/emcomm-tools/conf/template.d/bbs/bpq32.simple.cfg @@ -64,11 +64,11 @@ PORT MINQUAL=201 ; Entries in the nodes table with qualities ; greater or equal to MINQUAL will be sent on ; this port. A value of 0 sends everything. - MAXFRAME=6 ; Max outstanding frames (1 thru 7) + MAXFRAME=2 ; Max outstanding frames (1 thru 7) FRACK=5000 ; Level 2 timout in milliseconds RESPTIME=1000 ; Level 2 delayed ack timer in milliseconds RETRIES=100 ; Level 2 maximum retry value - PACLEN=236 ; Default max packet length for this port + PACLEN=128 ; Default max packet length for this port UNPROTO=FBB ; BTEXT broadcast addrs format: ; DEST[,digi1[,digi2]] L3ONLY=0 ; 1=No user downlink connects on this port diff --git a/overlay/opt/emcomm-tools/conf/template.d/winlink/config.ardop.json b/overlay/opt/emcomm-tools/conf/template.d/winlink/config.ardop.json index 35bfb95..21032fd 100644 --- a/overlay/opt/emcomm-tools/conf/template.d/winlink/config.ardop.json +++ b/overlay/opt/emcomm-tools/conf/template.d/winlink/config.ardop.json @@ -73,8 +73,8 @@ "ptt_ctrl": false }, "gpsd": { - "enable_http": false, - "allow_forms": false, + "enable_http": true, + "allow_forms": true, "use_server_time": false, "addr": "localhost:2947" }, diff --git a/overlay/opt/emcomm-tools/conf/template.d/winlink/config.ax25-agw.json b/overlay/opt/emcomm-tools/conf/template.d/winlink/config.ax25-agw.json index dc4caa4..02ffae5 100644 --- a/overlay/opt/emcomm-tools/conf/template.d/winlink/config.ax25-agw.json +++ b/overlay/opt/emcomm-tools/conf/template.d/winlink/config.ax25-agw.json @@ -73,8 +73,8 @@ "ptt_ctrl": false }, "gpsd": { - "enable_http": false, - "allow_forms": false, + "enable_http": true, + "allow_forms": true, "use_server_time": false, "addr": "localhost:2947" }, diff --git a/overlay/opt/emcomm-tools/conf/template.d/winlink/config.ax25-native.json b/overlay/opt/emcomm-tools/conf/template.d/winlink/config.ax25-native.json index b39879d..a11ad84 100644 --- a/overlay/opt/emcomm-tools/conf/template.d/winlink/config.ax25-native.json +++ b/overlay/opt/emcomm-tools/conf/template.d/winlink/config.ax25-native.json @@ -68,8 +68,8 @@ "ptt_ctrl": false }, "gpsd": { - "enable_http": false, - "allow_forms": false, + "enable_http": true, + "allow_forms": true, "use_server_time": false, "addr": "localhost:2947" }, diff --git a/overlay/opt/emcomm-tools/conf/template.d/winlink/config.vara-fm.json b/overlay/opt/emcomm-tools/conf/template.d/winlink/config.vara-fm.json index 0f9930a..16237fe 100644 --- a/overlay/opt/emcomm-tools/conf/template.d/winlink/config.vara-fm.json +++ b/overlay/opt/emcomm-tools/conf/template.d/winlink/config.vara-fm.json @@ -73,8 +73,8 @@ "ptt_ctrl": true }, "gpsd": { - "enable_http": false, - "allow_forms": false, + "enable_http": true, + "allow_forms": true, "use_server_time": false, "addr": "localhost:2947" }, diff --git a/overlay/opt/emcomm-tools/conf/template.d/winlink/config.vara-hf.json b/overlay/opt/emcomm-tools/conf/template.d/winlink/config.vara-hf.json index 0f9930a..16237fe 100644 --- a/overlay/opt/emcomm-tools/conf/template.d/winlink/config.vara-hf.json +++ b/overlay/opt/emcomm-tools/conf/template.d/winlink/config.vara-hf.json @@ -73,8 +73,8 @@ "ptt_ctrl": true }, "gpsd": { - "enable_http": false, - "allow_forms": false, + "enable_http": true, + "allow_forms": true, "use_server_time": false, "addr": "localhost:2947" }, diff --git a/overlay/opt/emcomm-tools/sbin/udev-tester.sh b/overlay/opt/emcomm-tools/sbin/udev-tester.sh index 28565b4..9f60211 100755 --- a/overlay/opt/emcomm-tools/sbin/udev-tester.sh +++ b/overlay/opt/emcomm-tools/sbin/udev-tester.sh @@ -1,7 +1,7 @@ #!/bin/bash # Author : Gaston Gonzalez # Date : 11 October 2024 -# Updated : 8 December 2024 +# Updated : 21 May 2025 # Purpose : Perform tests that can be used by the udev subsystem to aid # in rule development. This is intended to by used with the PROGRAM # directive inside of a udev rule. @@ -13,6 +13,20 @@ ET_HOME=/opt/emcomm-tools ACTIVE_RADIO="${ET_HOME}/conf/radios.d/active-radio.json" +# Exit with a 0 exit status if, and only if, the currently selected radio is +# a Yaesu FTX-1. +test_yaesu_ftx1() { + if [ -L "${ET_HOME}/conf/radios.d/active-radio.json" ]; then + ID=$(cat "${ET_HOME}/conf/radios.d/active-radio.json" | jq -r .id) + + if [[ "$ID" == "yaesu-ftx1" ]]; then + exit 0 + fi + fi + + exit 1 +} + # Exit with a 0 exit status if, and only if, the currently selected radio is # a Yaesu FT-891. test_yaesu_ft891() { @@ -82,6 +96,9 @@ if [ $# -ne 1 ]; then fi case $1 in + yaesu-ftx1) + test_yaesu_ftx1 + ;; yaesu-ft891) test_yaesu_ft891 ;; diff --git a/overlay/opt/emcomm-tools/sbin/wrapper-rigctld.sh b/overlay/opt/emcomm-tools/sbin/wrapper-rigctld.sh index 165a638..1c1b9ab 100755 --- a/overlay/opt/emcomm-tools/sbin/wrapper-rigctld.sh +++ b/overlay/opt/emcomm-tools/sbin/wrapper-rigctld.sh @@ -2,7 +2,7 @@ # # Author : Gaston Gonzalez # Date : 9 October 2024 -# Updated : 28 October 2024 +# Updated : 31 May 2025 # Purpose : Wrapper startup/shutdown script around systemd/rigctld ET_HOME=/opt/emcomm-tools @@ -41,8 +41,19 @@ start() { ID=$(cat ${ET_HOME}/conf/radios.d/active-radio.json | jq -r .rigctrl.id) PTT=$(cat ${ET_HOME}/conf/radios.d/active-radio.json | jq -r .rigctrl.ptt) - CMD="rigctld -m ${ID} -P ${PTT} " - et-log "Starting rigctld in VOX mode with: ${CMD}" + # Special case for select radios that only need to key the PTT, but do + # do not have CAT control support. This edge case was added for radios + # like the Yaesu FTX-1 Field before Yaesu published their CAT commands. + PTT_ONLY=$(cat ${ET_HOME}/conf/radios.d/active-radio.json | jq -r .rigctrl.pttOnly) + + if [ "${PTT_ONLY}" = "true" ]; then + CMD="rigctld -m ${ID} -p ${CAT_DEVICE} -P ${PTT} " + et-log "Starting rigctld in PTT-only mode with: ${CMD}" + else + CMD="rigctld -m ${ID} -P ${PTT} " + et-log "Starting rigctld in VOX mode with: ${CMD}" + fi + $CMD exit 0 fi diff --git a/overlay/usr/share/applications/et-aircraft.desktop b/overlay/usr/share/applications/et-aircraft.desktop new file mode 100644 index 0000000..6e03a75 --- /dev/null +++ b/overlay/usr/share/applications/et-aircraft.desktop @@ -0,0 +1,11 @@ +[Desktop Entry] +Version=1.0 +Name=et-aircraft +Comment=dump1090 ADB-S tracker for EmComm Tools +Exec=/opt/emcomm-tools/bin/et-aircraft +Icon=et-aircraft-icon-black-192 +Terminal=false +X-MultipleArgs=false +Type=Application +Categories=HamRadio; +StartupNotify=true diff --git a/overlay/usr/share/glib-2.0/schemas/90_ubuntu-settings.gschema.override b/overlay/usr/share/glib-2.0/schemas/90_ubuntu-settings.gschema.override index 8ee080b..13f00af 100644 --- a/overlay/usr/share/glib-2.0/schemas/90_ubuntu-settings.gschema.override +++ b/overlay/usr/share/glib-2.0/schemas/90_ubuntu-settings.gschema.override @@ -12,7 +12,7 @@ show-desktop-icons = false picture-uri = 'file:///usr/share/backgrounds/emcomm-tools-wallpaper.png' [org.gnome.shell] -favorite-apps = ['emcomm-tools.desktop', 'js8call.desktop', 'org.gnome.Terminal.desktop', 'navit.desktop', 'min.desktop', 'org.gnome.Nautilus.desktop'] +favorite-apps = ['emcomm-tools.desktop', 'js8call.desktop', 'et-aircraft.desktop', 'org.gnome.Terminal.desktop', 'navit.desktop', 'min.desktop', 'org.gnome.Nautilus.desktop'] last-selected-power-profile = 'performance' [org.gnome.system.location] diff --git a/overlay/usr/share/icons/et-aircraft-icon-black-192.png b/overlay/usr/share/icons/et-aircraft-icon-black-192.png new file mode 100644 index 0000000..987cadf Binary files /dev/null and b/overlay/usr/share/icons/et-aircraft-icon-black-192.png differ diff --git a/scripts/configure-gnome.sh b/scripts/configure-gnome.sh index d03af38..dee371b 100755 --- a/scripts/configure-gnome.sh +++ b/scripts/configure-gnome.sh @@ -2,17 +2,17 @@ # # Author : Gaston Gonzalez # Date : 16 March 2024 -# Updated : 9 October 2024 +# Updated : 8 June 2025 # Purpose : Configure GNOME -et-log "Configuring GNOME" +et-log "Configuring GNOME..." cp ../overlay/usr/share/glib-2.0/schemas/90_ubuntu-settings.gschema.override \ /usr/share/glib-2.0/schemas/ -cp ../overlay/usr/share/icons/emcomm-tools-icon-black-512.png \ +cp ../overlay/usr/share/icons/*.png \ /usr/share/icons/ -chmod 644 /usr/share/icons/emcomm-tools-*.png +chmod 644 /usr/share/icons/et-*.png glib-compile-schemas /usr/share/glib-2.0/schemas/ diff --git a/scripts/download-et-maps.sh b/scripts/download-et-maps.sh new file mode 100755 index 0000000..058f7d6 --- /dev/null +++ b/scripts/download-et-maps.sh @@ -0,0 +1,31 @@ +#!/bin/bash +# Author : Gaston Gonzalez +# Date : 6 July 2025 +# Purpose : Downloads pre-rendered raster map tiles in mbtile format + +BASE_URL="https://github.com/thetechprepper/emcomm-tools-os-community/releases/download" +RELEASE="emcomm-tools-os-community-20250401-r4-final-4.0.0" +TILESET_DIR="/etc/skel/.local/share/emcomm-tools/mbtileserver/tilesets" + +OPTIONS=( + "us" "United States" + "ca" "Canada" +) + +SELECTED_COUNTRY=$(dialog --clear --menu "Select a country" 15 40 5 "${OPTIONS[@]}" 2>&1 >/dev/tty) +EXIT_STATUS=$? + +tput sgr 0 && clear + +if [[ $EXIT_STATUS -eq 0 ]]; then + DOWNLOAD_FILE="osm-${SELECTED_COUNTRY}-zoom0to10-20250703.mbtiles" + DOWNLOAD_URL="${BASE_URL}/${RELEASE}/${DOWNLOAD_FILE}" + + if [[ ! -e ${DOWNLOAD_FILE} ]]; then + et-log "Downloading ${DOWNLOAD_URL}" + curl -L -f -o ${DOWNLOAD_FILE} ${DOWNLOAD_URL} + fi + + et-log "Moving ${DOWNLOAD_FILE} ${TILESET_DIR}" + mv -v ${DOWNLOAD_FILE} ${TILESET_DIR} +fi diff --git a/scripts/install-dev-tools.sh b/scripts/install-dev-tools.sh index 8d972a4..e14cc70 100755 --- a/scripts/install-dev-tools.sh +++ b/scripts/install-dev-tools.sh @@ -2,7 +2,7 @@ # # Author : Gaston Gonzalez # Date : 29 December 2023 -# Updated : 20 October 2024 +# Updated : 24 April 2025 # Purpose : Install development tools set -e @@ -37,3 +37,10 @@ then sudo apt update sudo apt install --no-install-recommends cubic -y fi + + +# libyaml-dev - needed for Ruby via rbenv +et-log "Installing tools needed for ETC R5" +apt install \ + libyaml-dev \ + -y diff --git a/scripts/install-dictionary.sh b/scripts/install-dictionary.sh new file mode 100755 index 0000000..44e17e8 --- /dev/null +++ b/scripts/install-dictionary.sh @@ -0,0 +1,12 @@ +#!/bin/bash +# Author : Gaston Gonzalez +# Date : 22 July 2025 +# Purpose : Install a small offline English dictionary + +et-log "Installing offline dictionary..." + +apt install \ + dict \ + dictd \ + dict-gcide \ + -y diff --git a/scripts/install-doc-tools.sh b/scripts/install-doc-tools.sh new file mode 100755 index 0000000..97b2ef2 --- /dev/null +++ b/scripts/install-doc-tools.sh @@ -0,0 +1,12 @@ +#!/bin/bash +# Author : Gaston Gonzalez +# Date : 22 July 2025 +# Purpose : Install documentation tools + +apt install \ + pandoc \ + texlive \ + texlive-latex-recommended \ + texlive-fonts-recommended \ + texlive-latex-extra \ + -y diff --git a/scripts/install-dump1090.sh b/scripts/install-dump1090.sh new file mode 100755 index 0000000..0ffdd5f --- /dev/null +++ b/scripts/install-dump1090.sh @@ -0,0 +1,60 @@ +#!/bin/bash +# Author : Gaston Gonzalez +# Date : 4 June 2025 +# Updated : 6 July 2025 +# Purpose : Install dump1090 (ADB-S aircraft tracking) +set -e +trap 'last_command=$current_command; current_command=$BASH_COMMAND' DEBUG +trap 'et-log "\"${last_command}\" command failed with exit code $?."' ERR + +. ./env.sh + +APP=dump1090 +VERSION=master +DOWNLOAD_FILE=dump1090-master.zip +BIN_FILE=dump1090 +INSTALL_DIR="/opt/${APP}-${VERSION}" +INSTALL_BIN_DIR="${INSTALL_DIR}/bin" +LINK_PATH="/opt/${APP}" +DUMP1090_CONF_DIR="/etc/skel/.local/share/emcomm-tools/dump1090" + +if [[ ! -e ${ET_DIST_DIR}/${DOWNLOAD_FILE} ]]; then + + URL="https://github.com/thetechprepper/dump1090/archive/refs/heads/master.zip" + + et-log "Downloading ${APP}: ${URL}" + curl -s -L -o ${DOWNLOAD_FILE} --fail ${URL} + + mv -v ${DOWNLOAD_FILE} ${ET_DIST_DIR} +fi + +CWD_DIR=`pwd` + +# Only build once +if [[ ! -e "${ET_SRC_DIR}/${APP}/${BIN_FILE}" ]]; then + cd ${ET_SRC_DIR} + unzip -o ${ET_DIST_DIR}/${DOWNLOAD_FILE} + + cd dump1090-master + + et-log "Building ${APP}.." + make +fi + +[[ ! -e ${INSTALL_BIN_DIR} ]] && mkdir -v -p ${INSTALL_BIN_DIR} +cp -v "${ET_SRC_DIR}/${APP}-master/${BIN_FILE}" ${INSTALL_BIN_DIR} + +# Install HTML map +[[ ! -e ${DUMP1090_CONF_DIR} ]] && mkdir -v -p ${DUMP1090_CONF_DIR} +cp -v "${ET_SRC_DIR}/${APP}-master/gmap.html" ${DUMP1090_CONF_DIR} + +[[ -e ${LINK_PATH} ]] && rm ${LINK_PATH} +ln -s ${INSTALL_DIR} ${LINK_PATH} + +stow -v -d /opt ${APP} -t /usr/local + +cd $CWD_DIR + +et-log "Updating launcher icon to support PNP..." +cp -v ../overlay/usr/share/applications/et-aircraft.desktop /usr/share/applications/ + diff --git a/scripts/install-et-aircraft.sh b/scripts/install-et-aircraft.sh new file mode 100755 index 0000000..7b7531d --- /dev/null +++ b/scripts/install-et-aircraft.sh @@ -0,0 +1,27 @@ +#!/bin/bash +# Author : Gaston Gonzalez +# Date : 9 July 2025 +# Updated : 20 August 2025 +# Purpose : Install et-aircraft-app +set -e +trap 'last_command=$current_command; current_command=$BASH_COMMAND' DEBUG +trap 'et-log "\"${last_command}\" command failed with exit code $?."' ERR + +. ./env.sh +. ../overlay/opt/emcomm-tools/bin/et-common + +APP=et-aircraft-app +VERSION=1.0.0 +DOWNLOAD_FILE="${APP}_${VERSION}_amd64.deb" + +et-log "Installing ${APP} ${VERSION}..." + +if [[ ! -e ${ET_DIST_DIR}/${DOWNLOAD_FILE} ]]; then + + URL="https://github.com/thetechprepper/et-aircraft-app/releases/download/${VERSION}/${DOWNLOAD_FILE}" + + download_with_retries ${URL} ${DOWNLOAD_FILE} + mv ${DOWNLOAD_FILE} ${ET_DIST_DIR} +fi + +DEBIAN_FRONTEND=noninteractive dpkg -i "${ET_DIST_DIR}/${DOWNLOAD_FILE}" diff --git a/scripts/install-et-api.sh b/scripts/install-et-api.sh new file mode 100755 index 0000000..4829230 --- /dev/null +++ b/scripts/install-et-api.sh @@ -0,0 +1,51 @@ +#!/bin/bash +# Author : Gaston Gonzalez +# Date : 13 August 2025 +# Updated : 20 August 2025 +# Purpose : Install EmComm Tools API +set -e +trap 'last_command=$current_command; current_command=$BASH_COMMAND' DEBUG +trap 'et-log "\"${last_command}\" command failed with exit code $?."' ERR + +. ./env.sh +. ../overlay/opt/emcomm-tools/bin/et-common + +APP=et-api +VERSION=1.0.0 +ET_API_JAR="emcomm-tools-api-${VERSION}-SNAPSHOT.jar" +BASE_URL="https://github.com/thetechprepper/et-api-java/releases/download/${VERSION}" + +INSTALL_DIR="/opt/emcomm-tools-api" +BIN_DIR="${INSTALL_DIR}/bin" +DATA_DIR="${INSTALL_DIR}/data" +INDEX_DIR="${INSTALL_DIR}/index" + +et-log "Installing ${APP} ${VERSION}..." + +mkdir -v -p "${BIN_DIR}" "${DATA_DIR}" "${INDEX_DIR}" + +# Download and install et-api uber JAR +URL="${BASE_URL}/${ET_API_JAR}" +download_with_retries ${URL} ${APP} +mv ${APP} ${BIN_DIR} +chmod 755 "${BIN_DIR}/${APP}" + +# Download pre-built data sets +FILES=( + "faa.csv" + "license.csv" + "zip2geo.csv" + "zip2geo-elevation.csv" +) +for file in "${FILES[@]}"; do + URL="${BASE_URL}/${file}" + + et-log "Downloading data set: ${URL}" + download_with_retries ${URL} ${file} + mv ${file} ${DATA_DIR} +done + +et-log "Applying permissions..." +chgrp -v -R ${ET_GROUP} ${DATA_DIR} ${INDEX_DIR} +chmod -v 775 ${DATA_DIR} ${INDEX_DIR} +chmod -v 664 ${DATA_DIR}/*.csv diff --git a/scripts/install-gis-tools.sh b/scripts/install-gis-tools.sh new file mode 100755 index 0000000..616010d --- /dev/null +++ b/scripts/install-gis-tools.sh @@ -0,0 +1,18 @@ +#!/bin/bash +# +# Author : Gaston Gonzalez +# Date : 26 April 2025 +# Updated : 30 April 2025 +# Purpose : Installs misc GIS tools from apt +set -e +trap 'last_command=$current_command; current_command=$BASH_COMMAND' DEBUG +trap 'et-log "\"${last_command}\" command failed with exit code $?."' ERR + +et-log "Installing GIS tools..." + +apt install \ + gpsbabel \ + gpsbabel-gui \ + sqlite3 \ + qgis \ + -y diff --git a/scripts/install-mbtileserver.sh b/scripts/install-mbtileserver.sh new file mode 100755 index 0000000..0407605 --- /dev/null +++ b/scripts/install-mbtileserver.sh @@ -0,0 +1,44 @@ +#!/bin/bash +# Author : Gaston Gonzalez +# Date : 24 April 2025 +# Upated : 25 April 2025 +# Purpose : Install mbtileserver +set -e +trap 'last_command=$current_command; current_command=$BASH_COMMAND' DEBUG +trap 'et-log "\"${last_command}\" command failed with exit code $?."' ERR + +. ./env.sh + +APP=mbtileserver +VERSION=0.11.0 +DOWNLOAD_FILE="${APP}_v${VERSION}_linux_amd64.zip" +INSTALL_DIR="/opt/${APP}-${VERSION}" +INSTALL_BIN_DIR="${INSTALL_DIR}/bin" +LINK_PATH="/opt/${APP}" + +et-log "Installing ${APP} ${VERSION}..." + +if [[ ! -e ${ET_DIST_DIR}/${DOWNLOAD_FILE} ]]; then + + URL="https://github.com/consbio/mbtileserver/releases/download/v${VERSION}/${DOWNLOAD_FILE}" + + et-log "Downloading ${APP}: ${URL}" + curl -s -L -o ${DOWNLOAD_FILE} --fail ${URL} + + mv ${DOWNLOAD_FILE} ${ET_DIST_DIR} +fi + +CWD_DIR=`pwd` + +[[ ! -e ${INSTALL_BIN_DIR} ]] && mkdir -v -p ${INSTALL_BIN_DIR} +cd ${INSTALL_BIN_DIR} +unzip "${ET_DIST_DIR}/${DOWNLOAD_FILE}" +mv "mbtileserver_v${VERSION}_linux_amd64" ${APP} +chmod 755 ${APP} + +[[ -e ${LINK_PATH} ]] && rm ${LINK_PATH} +ln -s ${INSTALL_DIR} ${LINK_PATH} + +stow -v -d /opt ${APP} -t /usr/local + +cd $CWD_DIR diff --git a/scripts/install-mbutil.sh b/scripts/install-mbutil.sh new file mode 100755 index 0000000..d7b6ad3 --- /dev/null +++ b/scripts/install-mbutil.sh @@ -0,0 +1,40 @@ +#!/bin/bash +# Author : Gaston Gonzalez +# Date : 25 April 2025 +# Purpose : Install mbutil to allow for creation of offline tilesets +set -e +trap 'last_command=$current_command; current_command=$BASH_COMMAND' DEBUG +trap 'et-log "\"${last_command}\" command failed with exit code $?."' ERR + +. ./env.sh + +APP=mbutil +VERSION=0.3.0 +DOWNLOAD_FILE="${APP}-${VERSION}.tar.gz" +SRC_DIR="${ET_SRC_DIR}/${APP}-${VERSION}" +INSTALL_DIR="/opt/${APP}-${VERSION}" +INSTALL_BIN_DIR="${INSTALL_DIR}/bin" +LINK_PATH="/opt/${APP}" + +et-log "Installing ${APP} ${VERSION}..." + +if [[ ! -e "${ET_DIST_DIR}/${DOWNLOAD_FILE}" ]]; then + + URL="https://github.com/mapbox/mbutil/archive/refs/tags/v${VERSION}.tar.gz" + + et-log "Downloading ${APP}: ${URL}" + curl -s -L -o ${DOWNLOAD_FILE} --fail ${URL} + + mv ${DOWNLOAD_FILE} ${ET_DIST_DIR} +fi + +CWD_DIR=`pwd` + +et-log "Unpacking ${APP} ${VERSION} source..." +tar -xzf "${ET_DIST_DIR}/${DOWNLOAD_FILE}" +mv "${APP}-${VERSION}" ${ET_SRC_DIR} && cd ${SRC_DIR} + +et-log "Installing ${APP} ${VERSION} globally..." +python setup.py install + +cd $CWD_DIR diff --git a/scripts/install-python.sh b/scripts/install-python.sh new file mode 100755 index 0000000..75e9603 --- /dev/null +++ b/scripts/install-python.sh @@ -0,0 +1,18 @@ +#!/bin/bash +# +# Author : Gaston Gonzalez +# Date : 25 April 2025 +# Purpose : Installs Python 2 +set -e +trap 'last_command=$current_command; current_command=$BASH_COMMAND' DEBUG +trap 'et-log "\"${last_command}\" command failed with exit code $?."' ERR + +et-log "Installing Python 2..." + +apt install \ + python2 \ + python-setuptools \ + -y + +# Set Python 2 as the default +update-alternatives --install /usr/bin/python python /usr/bin/python2 1 diff --git a/scripts/install-rf-analysis-tools.sh b/scripts/install-rf-analysis-tools.sh new file mode 100755 index 0000000..6bdfee1 --- /dev/null +++ b/scripts/install-rf-analysis-tools.sh @@ -0,0 +1,12 @@ +#!/bin/bash +# +# Author : Gaston Gonzalez +# Date : 22 May 2024 +# Updated : 4 June 2025 +# Purpose : Install RF prediction and analysis tools +set -e + +et-log "Installing RF prediction and analysis tools..." +apt install \ + splat \ + -y diff --git a/scripts/install-sdr-tools.sh b/scripts/install-sdr-tools.sh new file mode 100755 index 0000000..8bb01ad --- /dev/null +++ b/scripts/install-sdr-tools.sh @@ -0,0 +1,12 @@ +#!/bin/bash +# +# Author : Gaston Gonzalez +# Date : 4 June 2025 +# Purpose : Install SDR tools +set -e + +et-log "Installing SDR tools..." +apt install \ + rtl-sdr \ + librtlsdr-dev \ + -y diff --git a/scripts/install-voacap.sh b/scripts/install-voacap.sh new file mode 100755 index 0000000..2e60a61 --- /dev/null +++ b/scripts/install-voacap.sh @@ -0,0 +1,52 @@ +#!/bin/bash +# Author : Gaston Gonzalez +# Date : 5 June 2023 +# Updated : 16 August 2025 +# Purpose : Install Dire Wolf +# +# References: +# 1. https://github.com/jawatson/voacapl +# 2. https://github.com/jawatson/voacapl/wiki +# 3. http://www.greg-hand.com/hfwin32.html +set -e +trap 'last_command=$current_command; current_command=$BASH_COMMAND' DEBUG +trap 'et-log "\"${last_command}\" command failed with exit code $?."' ERR + +. ./env.sh + +APP=voacapl +VERSION=0.7.6 +REPO=https://github.com/thetechprepper/voacapl +REPO_SRC_DIR="/opt/src/${APP}" +INSTALL_DIR="/opt/${APP}-${VERSION}" +LINK_PATH="/opt/${APP}" + +et-log "Installing voacapl build dependencies..." +apt install gfortran -y + +[[ ! -e ${ET_SRC_DIR} ]] && mkdir ${ET_SRC_DIR} + +CWD_DIR=`pwd` + +if [[ ! -e ${REPO_SRC_DIR} ]]; then + cd ${ET_SRC_DIR} && git clone ${REPO} +fi + +cd ${REPO_SRC_DIR} +./configure --prefix=${INSTALL_DIR} +make && make install + +# patch prefix location +sed -i 's|__PREFIX__|/opt/voacapl-0.7.6|' makeitshfbc + +[[ -e /root/itshfbc ]] && rm -rf /root/itshfbc +[[ -e /etc/skel/itshfbc ]] && rm -rf /etc/skel/itshfbc + +./makeitshfbc && mv /root/itshfbc /etc/skel + +[[ -e ${LINK_PATH} ]] && rm ${LINK_PATH} +ln -s ${INSTALL_DIR} ${LINK_PATH} + +cd ${CWD_DIR} + +stow -v -d /opt ${APP} -t /usr/local diff --git a/scripts/install.sh b/scripts/install.sh index 8cef27f..655e658 100755 --- a/scripts/install.sh +++ b/scripts/install.sh @@ -2,8 +2,8 @@ # # Author : Gaston Gonzalez # Date : 16 March 2024 -# Updated : 18 March 2025 -# Purpose : Main installer for EmComm Tools OS Community +# Updated : 16 August 2025 +# Purpose : Main installer for EmComm Tools Community (ETC) . ./env.sh . ./functions.sh @@ -60,3 +60,30 @@ exitIfNotRoot [ ! -z "${ET_EXPERT}" ] && ./download-wikipedia.sh ./install-wine.sh + +# Install GIS applications and dependencies +./install-mbtileserver.sh +./install-python.sh +./install-mbutil.sh +./install-gis-tools.sh + +# Install RF analysis and prediction tools +./install-rf-analysis-tools.sh + +# Install SDR tools +./install-sdr-tools.sh +./install-dump1090.sh + +# Install ETC custom maps +./download-et-maps.sh + +# Install ETC applications +./install-et-api.sh +./install-et-aircraft.sh + +# Install documentation tools +./install-dictionary.sh +#./install-doc-tools.sh + +# Install prediction tools +./install-voacap.sh diff --git a/tests/test-dump1090.sh b/tests/test-dump1090.sh new file mode 100755 index 0000000..23764fd --- /dev/null +++ b/tests/test-dump1090.sh @@ -0,0 +1,7 @@ +#!/bin/bash +# Author : Gaston Gonzalez +# Date : 5 May 2025 +# Purpose : Test dump1090 installation + +OUT=$(which dump1090) +exit $? diff --git a/tests/test-et-aircraft.sh b/tests/test-et-aircraft.sh new file mode 100755 index 0000000..1a90b56 --- /dev/null +++ b/tests/test-et-aircraft.sh @@ -0,0 +1,8 @@ +#!/bin/bash +# Author : Gaston Gonzalez +# Date : 9 July 2025 +# Updated : 13 August 2025 +# Purpose : Test et-aircraft installation + +OUT=$(which et-aircraft-app) +exit $? diff --git a/tests/test-et-api.sh b/tests/test-et-api.sh new file mode 100755 index 0000000..b6d9bee --- /dev/null +++ b/tests/test-et-api.sh @@ -0,0 +1,23 @@ +#!/bin/bash +# Author : Gaston Gonzalez +# Date : 13 August 2025 +# Updated : 20 August 2025 +# Purpose : Test et-api installation + +FILES=( + "faa.csv" + "license.csv" + "zip2geo.csv" + "zip2geo-elevation.csv" +) + +for file in "${FILES[@]}"; do + OUT=$(ls /opt/emcomm-tools-api/data/${file} 2>/dev/null) + if [[ $? -ne 0 ]]; then + echo -e "\t* Required file '$file' does not exist." + exit 1 + fi +done + +OUT=$(ls /opt/emcomm-tools-api/bin/et-api 2>/dev/null) +exit $? diff --git a/tests/test-gpsbabel.sh b/tests/test-gpsbabel.sh new file mode 100755 index 0000000..fadb749 --- /dev/null +++ b/tests/test-gpsbabel.sh @@ -0,0 +1,7 @@ +#!/bin/bash +# Author : Gaston Gonzalez +# Date : 30 April 2025 +# Purpose : Test GPSBabel installation + +OUT=$(which gpsbabel && which gpsbabelfe) +exit $? diff --git a/tests/test-mbtileserver.sh b/tests/test-mbtileserver.sh new file mode 100755 index 0000000..2af23d2 --- /dev/null +++ b/tests/test-mbtileserver.sh @@ -0,0 +1,7 @@ +#!/bin/bash +# Author : Gaston Gonzalez +# Date : 24 April 2025 +# Purpose : Test mbtileserver installation + +OUT=$(which mbtileserver) +exit $? diff --git a/tests/test-mbutil.sh b/tests/test-mbutil.sh new file mode 100755 index 0000000..83d5863 --- /dev/null +++ b/tests/test-mbutil.sh @@ -0,0 +1,7 @@ +#!/bin/bash +# Author : Gaston Gonzalez +# Date : 25 April 2025 +# Purpose : Test mb-util installation + +OUT=$(which mb-util) +exit $? diff --git a/tests/test-paracon b/tests/test-paracon.sh similarity index 100% rename from tests/test-paracon rename to tests/test-paracon.sh diff --git a/tests/test-python.sh b/tests/test-python.sh new file mode 100755 index 0000000..6e29648 --- /dev/null +++ b/tests/test-python.sh @@ -0,0 +1,7 @@ +#!/bin/bash +# Author : Gaston Gonzalez +# Date : 25 November 2025 +# Purpose : Test Python installation + +OUT=$(python --version 2>&1 | grep "2.7") +exit $? diff --git a/tests/test-qgis.sh b/tests/test-qgis.sh new file mode 100755 index 0000000..4cecf9a --- /dev/null +++ b/tests/test-qgis.sh @@ -0,0 +1,7 @@ +#!/bin/bash +# Author : Gaston Gonzalez +# Date : 25 April 2025 +# Purpose : Test QGIS installation + +OUT=$(which qgis) +exit $? diff --git a/tests/test-sqlite.sh b/tests/test-sqlite.sh new file mode 100755 index 0000000..629f861 --- /dev/null +++ b/tests/test-sqlite.sh @@ -0,0 +1,7 @@ +#!/bin/bash +# Author : Gaston Gonzalez +# Date : 25 April 2025 +# Purpose : Test SQLite installation + +OUT=$(sqlite3 -version | grep "^3[.]") +exit $? diff --git a/tests/test-voacap.sh b/tests/test-voacap.sh new file mode 100755 index 0000000..04836c3 --- /dev/null +++ b/tests/test-voacap.sh @@ -0,0 +1,7 @@ +#!/bin/bash +# Author : Gaston Gonzalez +# Date : 16 August 2025 +# Purpose : Test VOACAP installation + +OUT=$(which voacapl) +exit $?