Files
suphicakir 96b396149e initial commit
initial commit
2026-07-13 22:20:40 +03:00

363 lines
13 KiB
Bash
Executable File

#!/usr/bin/env bash
# Terminal Colors
C_GREEN='\033[92m'
C_YELLOW='\033[93m'
C_BLUE='\033[94m'
C_CYAN='\033[96m'
C_RED='\033[91m'
C_BOLD='\033[1m'
C_RESET='\033[0m'
clear
echo -e "${C_CYAN}${C_BOLD}"
echo " _ ___ ___ ___ ___ "
echo " /_\ | _ \| _ \/ __| | _ ) ___ __ _ __ ___ _ _ "
echo " / _ \| _/| /\__ \ | _ \/ -_) _\` / _/ _ \ ' \ "
echo "/_/ \_\_| |_|_\|___/ |___/\___\__,_\__\___/_||_| "
echo -e " Linux/Android APRS Multi-Profile Beacon Setup Wizard${C_RESET}\n"
echo "----------------------------------------------------------------"
echo "This wizard will help you configure your APRS beacon as a"
echo "background service and manage it via the control panel."
echo "----------------------------------------------------------------\n"
# Check and install Python3
if ! command -v python3 &> /dev/null; then
echo -e "${C_YELLOW}[!] Python3 not found on the system. Installing...${C_RESET}"
if command -v apt-get &> /dev/null; then
sudo apt-get update && sudo apt-get install -y python3
else
echo -e "${C_RED}[!] Error: Python3 could not be installed automatically. Please install it manually.${C_RESET}"
exit 1
fi
fi
INSTALL_DIR="$HOME/.aprs-beacon"
PROFILES_DIR="$INSTALL_DIR/profiles"
LOGS_DIR="$INSTALL_DIR/logs"
mkdir -p "$PROFILES_DIR" "$LOGS_DIR"
echo "$(pwd)" > "$INSTALL_DIR/.repo_path"
# GUI Dependencies Installation (for Linux)
HAS_GUI=true
# Graphic environment check
if [ -z "$DISPLAY" ]; then
HAS_GUI=false
echo -e "${C_YELLOW}[!] Display environment (DISPLAY) not detected. Performing headless install.${C_RESET}"
fi
if [ "$HAS_GUI" = true ]; then
echo -e "${C_BLUE}[i] Checking GUI, System Tray, and Image libraries (pystray, tkinter, pillow)...${C_RESET}"
if ! python3 -c "import tkinter; import pystray; import PIL" &>/dev/null; then
echo -e "${C_YELLOW}[!] Required GUI packages are missing. Installing...${C_RESET}"
if command -v apt-get &> /dev/null; then
echo -e "${C_BLUE}[i] Administrative privileges (sudo) may be requested:${C_RESET}"
sudo apt-get update && sudo apt-get install -y python3-tk python3-pystray python3-pil
else
echo -e "${C_RED}[!] Error: Package manager (apt-get) not found. Please install python3-tk, python3-pystray, and python3-pil manually.${C_RESET}"
fi
else
echo -e "${C_GREEN}[+] Required GUI packages are ready.${C_RESET}"
fi
fi
# 0. Profile Name
echo -e "\n=== 0. Profile Configuration ==="
while true; do
read -p "Profile Name to Install (e.g. mobile, qth, default) [Default: default]: " PROFILE_NAME
PROFILE_NAME=$(echo "$PROFILE_NAME" | tr 'A-Z' 'a-z' | xargs)
if [ -z "$PROFILE_NAME" ]; then
PROFILE_NAME="default"
fi
if [[ "$PROFILE_NAME" =~ ^[a-z0-9_-]+$ ]]; then
break
fi
echo -e "${C_RED}Error: Profile name can only contain lowercase letters, numbers, hyphens, or underscores!${C_RESET}"
done
# 1. Callsign
while true; do
read -p "1. Callsign (e.g. N0CALL-9): " CALLSIGN
CALLSIGN=$(echo "$CALLSIGN" | tr 'a-z' 'A-Z' | xargs)
if [ -n "$CALLSIGN" ]; then
break
fi
echo -e "${C_RED}Error: Callsign cannot be empty!${C_RESET}"
done
# 2. APRS-IS Passcode
read -p "2. Password (APRS-IS Passcode) [Press Enter to calculate automatically]: " PASSCODE
PASSCODE=$(echo "$PASSCODE" | xargs)
if [ -z "$PASSCODE" ]; then
echo -e "${C_BLUE}[i] Calculating passcode automatically from callsign...${C_RESET}"
PASSCODE=$(python3 -c "
callsign = '${CALLSIGN}'.split('-')[0]
hash_val = 0x73e2
for i in range(0, len(callsign), 2):
char1 = ord(callsign[i]) << 8
char2 = ord(callsign[i+1]) if (i + 1 < len(callsign)) else 0
hash_val ^= (char1 + char2)
print(hash_val & 0x7fff)
")
echo -e "${C_GREEN}[+] Calculated Passcode: $PASSCODE${C_RESET}"
fi
# 3. Status Comment
echo -e "\n3. Status Comment Setting:"
echo -e " ${C_YELLOW}Tip: Add frequency and tone info at start of message (e.g. 145.550MHz T088)${C_RESET}"
echo -e " ${C_YELLOW}Tip: Add 'https://' to show a clickable link on the map (e.g. https://example.com)${C_RESET}"
read -p "Status Comment [Default: APRS Background Beacon]: " COMMENT
COMMENT=$(echo "$COMMENT" | xargs)
if [ -z "$COMMENT" ]; then
COMMENT="APRS Background Beacon"
fi
# 4. Symbol
echo -e "\n4. Select Symbol to Display on Map:"
echo " 1) Helicopter (X) [Default]"
echo " 2) Car / Vehicle (>)"
echo " 3) Pedestrian / Hiker ([)"
echo " 4) House / QTH Station (-)"
echo " 5) Fixed Radio / Station (#)"
echo " 6) Other (Enter your own character)"
read -p "Choice [1-6]: " SYM_CHOICE
SYM_CHOICE=$(echo "$SYM_CHOICE" | xargs)
SYMBOL_TABLE="/"
SYMBOL_CODE="X"
case "$SYM_CHOICE" in
2) SYMBOL_CODE=">" ;;
3) SYMBOL_CODE="[" ;;
4) SYMBOL_CODE="-" ;;
5) SYMBOL_CODE="#" ;;
6)
read -p "Enter Symbol Character (e.g. > or [ or X): " CUSTOM_SYM
SYMBOL_CODE=$(echo "$CUSTOM_SYM" | xargs)
if [ -z "$SYMBOL_CODE" ]; then
SYMBOL_CODE="X"
fi
;;
*) SYMBOL_CODE="X" ;;
esac
LATITUDE=""
LONGITUDE=""
# 5. Coordinates
read -p "5. Do you want to automatically detect your coordinates via IP? [Y/n]: " AUTO_LOC
AUTO_LOC=$(echo "$AUTO_LOC" | tr 'A-Z' 'a-z' | xargs)
if [ "$AUTO_LOC" != "n" ]; then
echo -e "${C_BLUE}[i] Detecting coordinates via IP...${C_RESET}"
IP_LOC=$(python3 -c "
import urllib.request, json
urls = ['http://ip-api.com/json', 'https://ipapi.co/json/']
for url in urls:
try:
req = urllib.request.Request(url, headers={'User-Agent': 'Mozilla/5.0'})
with urllib.request.urlopen(req, timeout=4) as r:
d = json.loads(r.read().decode('utf-8'))
if d.get('status') == 'success' or 'latitude' in d:
lat = d.get('lat') or d.get('latitude')
lon = d.get('lon') or d.get('longitude')
city = d.get('city') or 'Unknown'
country = d.get('country_name') or d.get('country') or 'Unknown'
print(f'{lat},{lon},{city},{country}')
break
except:
continue
")
if [ -n "$IP_LOC" ]; then
IFS=',' read -r LAT LON CITY COUNTRY <<< "$IP_LOC"
echo -e "${C_GREEN}[+] Automatically Detected Location: $CITY, $COUNTRY ($LAT, $LON)${C_RESET}"
LATITUDE="$LAT"
LONGITUDE="$LON"
else
echo -e "${C_RED}[!] IP location detection failed.${C_RESET}"
fi
fi
if [ -z "$LATITUDE" ] || [ -z "$LONGITUDE" ]; then
echo -e "${C_BLUE}[i] Opening OpenStreetMap in browser to help find coordinates...${C_RESET}"
python3 -m webbrowser "https://www.openstreetmap.org" &>/dev/null &
echo -e "${C_YELLOW}[!] Please enter coordinates manually (copy latitude/longitude from map):${C_RESET}"
while true; do
read -p " Latitude (e.g. 41.037002): " LATITUDE
LATITUDE=$(echo "$LATITUDE" | xargs)
if python3 -c "float('$LATITUDE')" &>/dev/null; then
break
fi
echo -e "${C_RED}Error: Invalid latitude value!${C_RESET}"
done
while true; do
read -p " Longitude (e.g. 28.985012): " LONGITUDE
LONGITUDE=$(echo "$LONGITUDE" | xargs)
if python3 -c "float('$LONGITUDE')" &>/dev/null; then
break
fi
echo -e "${C_RED}Error: Invalid longitude value!${C_RESET}"
done
fi
# 6. Interval
while true; do
read -p "6. How often should beacons be sent (minutes)? [Default: 5]: " INTERVAL_MINUTES
INTERVAL_MINUTES=$(echo "$INTERVAL_MINUTES" | xargs)
if [ -z "$INTERVAL_MINUTES" ]; then
INTERVAL_MINUTES=5
break
fi
if python3 -c "int('$INTERVAL_MINUTES') >= 1" &>/dev/null; then
break
fi
echo -e "${C_RED}Error: Interval must be at least 1 minute!${C_RESET}"
done
# 6.5 APRS Thursday
read -p "6.5 Join APRS Thursday event? (ANSRVR) [y/N]: " OPT_THURSDAY
OPT_THURSDAY=$(echo "$OPT_THURSDAY" | tr 'A-Z' 'a-z' | xargs)
APRS_THURSDAY="false"
if [ "$OPT_THURSDAY" = "y" ]; then
APRS_THURSDAY="true"
fi
# Save Configuration
cat <<EOF > "$PROFILES_DIR/$PROFILE_NAME.json"
{
"callsign": "$CALLSIGN",
"passcode": $PASSCODE,
"latitude": $LATITUDE,
"longitude": $LONGITUDE,
"use_termux_gps": false,
"symbol_table": "$SYMBOL_TABLE",
"symbol_code": "$SYMBOL_CODE",
"comment": "$COMMENT",
"interval_minutes": $INTERVAL_MINUTES,
"aprs_thursday": $APRS_THURSDAY,
"server": "rotate.aprs2.net",
"port": 14580
}
EOF
echo -e "\n${C_GREEN}[+] Configuration file saved: $PROFILES_DIR/$PROFILE_NAME.json${C_RESET}"
# Copy / Download files
echo -e "${C_BLUE}[i] Installing application scripts...${C_RESET}"
if [ -f "./aprs_beacon.py" ]; then
cp "./aprs_beacon.py" "$INSTALL_DIR/aprs_beacon.py"
else
curl -sL -o "$INSTALL_DIR/aprs_beacon.py" "https://raw.githubusercontent.com/mcturan/aprs/main/aprs_beacon.py"
fi
chmod +x "$INSTALL_DIR/aprs_beacon.py"
if [ -f "./aprs_manager.py" ]; then
cp "./aprs_manager.py" "$INSTALL_DIR/aprs_manager.py"
else
curl -sL -o "$INSTALL_DIR/aprs_manager.py" "https://raw.githubusercontent.com/mcturan/aprs/main/aprs_manager.py"
fi
chmod +x "$INSTALL_DIR/aprs_manager.py"
# Backward compatibility (migration of old single config)
if [ -f "$INSTALL_DIR/config.json" ]; then
mv "$INSTALL_DIR/config.json" "$PROFILES_DIR/default.json" 2>/dev/null
mv "$INSTALL_DIR/aprs_beacon.log" "$LOGS_DIR/default.log" 2>/dev/null
fi
# Send Test Beacon
echo -e "\n${C_BLUE}[i] Sending test beacon to verify settings...${C_RESET}"
python3 "$INSTALL_DIR/aprs_beacon.py" --profile "$PROFILE_NAME" --once
if [ $? -eq 0 ]; then
echo -e "${C_GREEN}[+] Test Successful! Position packet transmitted to APRS-IS.${C_RESET}"
else
echo -e "${C_RED}[!] Test Failed! Could not transmit packet to server.${C_RESET}"
echo -e "${C_YELLOW}[i] For details: cat $LOGS_DIR/$PROFILE_NAME.log${C_RESET}"
read -p "Do you want to proceed anyway? [y/N]: " PROCEED
PROCEED=$(echo "$PROCEED" | tr 'A-Z' 'a-z' | xargs)
if [ "$PROCEED" != "y" ]; then
echo "Setup cancelled."
exit 1
fi
fi
# Linux systemd startup
echo -e "\n7. Startup Settings (Linux):"
read -p "Start this profile automatically on system boot? [Y/n]: " AUTO_START
AUTO_START=$(echo "$AUTO_START" | tr 'A-Z' 'a-z' | xargs)
# Generate systemd user service template
SYSTEMD_USER_DIR="$HOME/.config/systemd/user"
mkdir -p "$SYSTEMD_USER_DIR"
cat <<EOF > "$SYSTEMD_USER_DIR/aprs-beacon@.service"
[Unit]
Description=APRS Background Beacon Service (%i)
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
ExecStart=$(which python3) $INSTALL_DIR/aprs_beacon.py --profile %i
Restart=always
RestartSec=30
WorkingDirectory=$INSTALL_DIR
[Install]
WantedBy=default.target
EOF
systemctl --user daemon-reload
if [ "$AUTO_START" != "n" ]; then
echo -e "${C_BLUE}[i] Enabling and starting daemon service...${C_RESET}"
systemctl --user enable aprs-beacon@$PROFILE_NAME.service
systemctl --user restart aprs-beacon@$PROFILE_NAME.service
loginctl enable-linger "$USER" 2>/dev/null
fi
# Create desktop shortcut launcher (if GUI available)
if [ "$HAS_GUI" = true ]; then
DESKTOP_DIR="$HOME/.local/share/applications"
mkdir -p "$DESKTOP_DIR"
cat <<EOF > "$DESKTOP_DIR/aprs-manager.desktop"
[Desktop Entry]
Type=Application
Name=APRS Multi-Beacon Manager
Comment=APRS Multi-Profile Background Beacon Manager
Exec=$INSTALL_DIR/aprs_manager.py gui
Icon=radio
Terminal=false
Categories=Utility;Network;
EOF
chmod +x "$DESKTOP_DIR/aprs-manager.desktop"
# Add manager to session autostart
AUTOSTART_DIR="$HOME/.config/autostart"
mkdir -p "$AUTOSTART_DIR"
cp "$DESKTOP_DIR/aprs-manager.desktop" "$AUTOSTART_DIR/"
fi
# Post-install info summary
echo -e "\n${C_GREEN}${C_BOLD}================================================================${C_RESET}"
echo -e "${C_GREEN}${C_BOLD} APRS PROFILE ($PROFILE_NAME) SUCCESSFULLY ACTIVATED!${C_RESET}"
echo -e "${C_GREEN}${C_BOLD}================================================================${C_RESET}"
echo -e "${C_BOLD}Profile Name :${C_RESET} $PROFILE_NAME"
echo -e "${C_BOLD}Callsign :${C_RESET} $CALLSIGN"
echo -e "${C_BOLD}Interval :${C_RESET} Every $INTERVAL_MINUTES minute(s)"
echo -e "${C_BOLD}APRS Thursday :${C_RESET} $([ "$APRS_THURSDAY" = "true" ] && echo "Enabled" || echo "Disabled")"
echo -e "${C_BOLD}Autostart on Boot:${C_RESET} Yes"
echo -e "----------------------------------------------------------------"
if [ "$HAS_GUI" = true ]; then
echo -e "${C_CYAN}Desktop Interface :${C_RESET} Launch 'APRS Multi-Beacon Manager' from application menu."
echo -e "${C_CYAN}System Tray Icon :${C_RESET} System tray icon will appear upon launching."
else
echo -e "${C_YELLOW}Note: No graphic display detected. Launch control panel from terminal.${C_RESET}"
fi
echo -e "${C_CYAN}CLI / Terminal Management:${C_RESET}"
echo -e " - Open Interactive Menu: python3 $INSTALL_DIR/aprs_manager.py"
echo -e " - List Beacon Profiles: python3 $INSTALL_DIR/aprs_manager.py list"
echo -e " - Start Profile Daemon: python3 $INSTALL_DIR/aprs_manager.py start $PROFILE_NAME"
echo -e " - Stop Profile Daemon: python3 $INSTALL_DIR/aprs_manager.py stop $PROFILE_NAME"
echo -e "${C_GREEN}${C_BOLD}================================================================${C_RESET}\n"