From 4c8d56b3a6e45d85bc4c8918d5e080ef55de50b6 Mon Sep 17 00:00:00 2001 From: AeroSageMage Date: Sun, 24 Aug 2025 09:58:26 +0200 Subject: [PATCH 1/7] Add macOS shutdown script and cross-platform shutdown handling - Create kill_aerofly_bridge.sh for macOS shutdown functionality - Update Python script to detect platform and use appropriate shutdown script - Support Windows (.bat), macOS (.sh), and Linux (.sh) shutdown scripts - Maintain backward compatibility with existing Windows functionality - Enable Exit Application button to work properly on macOS --- kill_aerofly_bridge.sh | 27 +++++++++++++++++ python/udp_to_websocket.py | 60 +++++++++++++++++++++++++------------- 2 files changed, 67 insertions(+), 20 deletions(-) create mode 100755 kill_aerofly_bridge.sh diff --git a/kill_aerofly_bridge.sh b/kill_aerofly_bridge.sh new file mode 100755 index 0000000..bc97474 --- /dev/null +++ b/kill_aerofly_bridge.sh @@ -0,0 +1,27 @@ +#!/bin/bash + +echo "Stopping Aerofly Bridge..." +echo + +echo "Shutting down all related processes..." + +# Kill Python processes related to the application +echo "Stopping Python servers..." +pkill -f "python.*udp_to_websocket.py" 2>/dev/null +pkill -f "python.*http.server" 2>/dev/null + +# Kill any remaining Python processes (more aggressive) +echo "Stopping all Python processes..." +pkill -f python 2>/dev/null + +# Kill any processes using the relevant ports +echo "Stopping processes on ports 8080 and 8765..." +lsof -ti:8080 | xargs kill -9 2>/dev/null +lsof -ti:8765 | xargs kill -9 2>/dev/null + +echo +echo "Aerofly Bridge shutdown complete." +echo +echo "This window will close automatically in 3 seconds..." +sleep 3 +exit 0 diff --git a/python/udp_to_websocket.py b/python/udp_to_websocket.py index 80fcc44..df8d86d 100644 --- a/python/udp_to_websocket.py +++ b/python/udp_to_websocket.py @@ -489,42 +489,62 @@ async def handle_websocket_messages(): elif data.get('type') == 'shutdown': print(" Shutdown request received from web interface") - # Execute the batch file to kill this process FIRST - print(" Starting batch file execution...") + # Execute the appropriate shutdown script based on platform + print(" Starting shutdown script execution...") try: import subprocess import os - batch_path = os.path.join(os.path.dirname(__file__), '..', 'kill_aerofly_bridge.bat') - print(f" Executing batch file: {batch_path}") + import platform - # Check if batch file exists - if not os.path.exists(batch_path): - print(f" ERROR: Batch file not found at {batch_path}") + # Determine platform and choose appropriate shutdown script + system = platform.system().lower() + if system == "windows": + script_name = "kill_aerofly_bridge.bat" + shell_cmd = True + elif system == "darwin": # macOS + script_name = "kill_aerofly_bridge.sh" + shell_cmd = False + else: # Linux or other Unix-like systems + script_name = "kill_aerofly_bridge.sh" + shell_cmd = False + + script_path = os.path.join(os.path.dirname(__file__), '..', script_name) + print(f" Executing {system} shutdown script: {script_path}") + + # Check if script exists + if not os.path.exists(script_path): + print(f" ERROR: Shutdown script not found at {script_path}") # Try alternative path - alt_path = os.path.join(os.getcwd(), 'kill_aerofly_bridge.bat') + alt_path = os.path.join(os.getcwd(), script_name) print(f" Trying alternative path: {alt_path}") if os.path.exists(alt_path): - batch_path = alt_path - print(f" Using alternative path: {batch_path}") + script_path = alt_path + print(f" Using alternative path: {script_path}") else: - print(f" ERROR: Batch file not found at alternative path either") - raise FileNotFoundError(f"Batch file not found at {batch_path} or {alt_path}") + print(f" ERROR: Shutdown script not found at alternative path either") + raise FileNotFoundError(f"Shutdown script not found at {script_path} or {alt_path}") + + # Execute with platform-appropriate settings + if system == "windows": + result = subprocess.run([script_path], shell=True, capture_output=True, text=True) + else: + # For macOS/Linux, make sure script is executable and run it + os.chmod(script_path, 0o755) + result = subprocess.run([script_path], shell=False, capture_output=True, text=True) - # Execute with better error handling - result = subprocess.run([batch_path], shell=True, capture_output=True, text=True) - print(f" Batch file execution result: {result.returncode}") + print(f" Shutdown script execution result: {result.returncode}") if result.stdout: - print(f" Batch file output: {result.stdout}") + print(f" Shutdown script output: {result.stdout}") if result.stderr: - print(f" Batch file errors: {result.stderr}") + print(f" Shutdown script errors: {result.stderr}") if result.returncode == 0: - print(" Batch file executed successfully") + print(" Shutdown script executed successfully") else: - print(f" Batch file failed with return code: {result.returncode}") + print(f" Shutdown script failed with return code: {result.returncode}") except Exception as e: - print(f" Error executing batch file: {e}") + print(f" Error executing shutdown script: {e}") import traceback traceback.print_exc() From 2ef03caaa3587740b8cddf84ba1a021f74610a62 Mon Sep 17 00:00:00 2001 From: AeroSageMage Date: Sun, 24 Aug 2025 10:21:48 +0200 Subject: [PATCH 2/7] Improve macOS launcher script with graceful shutdown handling - Add signal handlers for SIGINT and SIGTERM - Implement graceful shutdown with SIGTERM before SIGKILL - Fix read command compatibility (remove -p flag) - Add proper cleanup function for interrupt signals - Prevent 'address already in use' errors from ungraceful shutdowns --- start_aerofly_map.sh | 46 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 44 insertions(+), 2 deletions(-) diff --git a/start_aerofly_map.sh b/start_aerofly_map.sh index d35a4ca..e9b3479 100644 --- a/start_aerofly_map.sh +++ b/start_aerofly_map.sh @@ -1,5 +1,28 @@ #!/bin/bash +# Function to cleanup on exit +cleanup() { + echo -e "\nReceived interrupt signal, cleaning up..." + if [ ! -z "$UDP_PID" ]; then + kill -TERM $UDP_PID 2>/dev/null + fi + if [ ! -z "$HTTP_PID" ]; then + kill -TERM $HTTP_PID 2>/dev/null + fi + sleep 1 + if [ ! -z "$UDP_PID" ]; then + kill -KILL $UDP_PID 2>/dev/null + fi + if [ ! -z "$HTTP_PID" ]; then + kill -KILL $HTTP_PID 2>/dev/null + fi + echo "Cleanup complete." + exit 0 +} + +# Set up signal handlers +trap cleanup SIGINT SIGTERM + echo "Starting Aerofly Moving Map..." echo @@ -35,6 +58,25 @@ echo "To stop the servers, press Ctrl+C or run: kill $UDP_PID $HTTP_PID" echo # Wait for user input to stop -read -p "Press Enter to stop the servers..." -kill $UDP_PID $HTTP_PID +echo "Press Enter to stop the servers..." +read + +# Gracefully stop the servers +echo "Stopping servers gracefully..." +kill -TERM $UDP_PID $HTTP_PID + +# Wait a moment for graceful shutdown +sleep 2 + +# Force kill if still running +if kill -0 $UDP_PID 2>/dev/null; then + echo "Force stopping UDP server..." + kill -KILL $UDP_PID +fi + +if kill -0 $HTTP_PID 2>/dev/null; then + echo "Force stopping HTTP server..." + kill -KILL $HTTP_PID +fi + echo "Servers stopped." \ No newline at end of file From 216ec67310ca989ad586dc8f3dd41f9bf8413815 Mon Sep 17 00:00:00 2001 From: AeroSageMage Date: Sun, 24 Aug 2025 10:39:05 +0200 Subject: [PATCH 3/7] Fix shutdown script deadlock issue - Use subprocess.Popen() instead of subprocess.run() to avoid blocking - Shutdown script now runs non-blocking to prevent deadlock - Add 1-second delay before setting shutdown event as backup - Prevents Python script from waiting for shutdown script that kills it - Works on both Windows and macOS platforms --- python/udp_to_websocket.py | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/python/udp_to_websocket.py b/python/udp_to_websocket.py index df8d86d..2cc25ef 100644 --- a/python/udp_to_websocket.py +++ b/python/udp_to_websocket.py @@ -524,31 +524,29 @@ async def handle_websocket_messages(): print(f" ERROR: Shutdown script not found at alternative path either") raise FileNotFoundError(f"Shutdown script not found at {script_path} or {alt_path}") - # Execute with platform-appropriate settings + # Execute with platform-appropriate settings (non-blocking) + print(" Starting shutdown script (non-blocking)...") if system == "windows": - result = subprocess.run([script_path], shell=True, capture_output=True, text=True) + # For Windows, use Popen to avoid blocking + process = subprocess.Popen([script_path], shell=True, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) else: # For macOS/Linux, make sure script is executable and run it os.chmod(script_path, 0o755) - result = subprocess.run([script_path], shell=False, capture_output=True, text=True) + process = subprocess.Popen([script_path], shell=False, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) - print(f" Shutdown script execution result: {result.returncode}") - if result.stdout: - print(f" Shutdown script output: {result.stdout}") - if result.stderr: - print(f" Shutdown script errors: {result.stderr}") - - if result.returncode == 0: - print(" Shutdown script executed successfully") - else: - print(f" Shutdown script failed with return code: {result.returncode}") + print(" Shutdown script started successfully (non-blocking)") + # Don't wait for the script to complete since it will kill this process except Exception as e: print(f" Error executing shutdown script: {e}") import traceback traceback.print_exc() - # Send acknowledgment AFTER batch file execution + # Send acknowledgment print(" Sending shutdown acknowledgment...") try: await websocket.send(json.dumps({"type": "shutdown_ack"})) @@ -556,8 +554,11 @@ async def handle_websocket_messages(): except Exception as e: print(f" Error sending shutdown acknowledgment: {e}") - # Also trigger shutdown event as backup - print(" Setting shutdown event...") + # Give shutdown script a moment to start, then trigger shutdown event as backup + print(" Waiting 1 second for shutdown script to start...") + await asyncio.sleep(1) + + print(" Setting shutdown event as backup...") shutdown_event.set() print(" Shutdown event set, returning from handler") return From f2ffb0a7821a8c9b4776724c280a5bc6efa8c4c0 Mon Sep 17 00:00:00 2001 From: AeroSageMage Date: Sun, 24 Aug 2025 16:06:06 +0200 Subject: [PATCH 4/7] Improve shutdown script for immediate termination - Use pkill -9 (SIGKILL) instead of SIGTERM for immediate process termination - Remove sleep delay from shutdown script for faster execution - Remove waiting period from Python script - let shutdown script handle everything - Ensure immediate shutdown without hanging or delays --- kill_aerofly_bridge.sh | 13 +++++-------- python/udp_to_websocket.py | 9 ++------- 2 files changed, 7 insertions(+), 15 deletions(-) diff --git a/kill_aerofly_bridge.sh b/kill_aerofly_bridge.sh index bc97474..b92f87d 100755 --- a/kill_aerofly_bridge.sh +++ b/kill_aerofly_bridge.sh @@ -5,14 +5,14 @@ echo echo "Shutting down all related processes..." -# Kill Python processes related to the application +# Kill Python processes related to the application (force kill) echo "Stopping Python servers..." -pkill -f "python.*udp_to_websocket.py" 2>/dev/null -pkill -f "python.*http.server" 2>/dev/null +pkill -9 -f "python.*udp_to_websocket.py" 2>/dev/null +pkill -9 -f "python.*http.server" 2>/dev/null -# Kill any remaining Python processes (more aggressive) +# Kill any remaining Python processes (force kill) echo "Stopping all Python processes..." -pkill -f python 2>/dev/null +pkill -9 -f python 2>/dev/null # Kill any processes using the relevant ports echo "Stopping processes on ports 8080 and 8765..." @@ -21,7 +21,4 @@ lsof -ti:8765 | xargs kill -9 2>/dev/null echo echo "Aerofly Bridge shutdown complete." -echo -echo "This window will close automatically in 3 seconds..." -sleep 3 exit 0 diff --git a/python/udp_to_websocket.py b/python/udp_to_websocket.py index 2cc25ef..1f59d5a 100644 --- a/python/udp_to_websocket.py +++ b/python/udp_to_websocket.py @@ -554,13 +554,8 @@ async def handle_websocket_messages(): except Exception as e: print(f" Error sending shutdown acknowledgment: {e}") - # Give shutdown script a moment to start, then trigger shutdown event as backup - print(" Waiting 1 second for shutdown script to start...") - await asyncio.sleep(1) - - print(" Setting shutdown event as backup...") - shutdown_event.set() - print(" Shutdown event set, returning from handler") + # Shutdown script should handle everything, just return immediately + print(" Shutdown script started, returning from handler") return except json.JSONDecodeError: print(f" DEBUG: Not JSON, raw message: {message}") From 9b7c243f216fbab1b9c84a9ea99c043d3817de54 Mon Sep 17 00:00:00 2001 From: AeroSageMage Date: Sun, 24 Aug 2025 16:12:26 +0200 Subject: [PATCH 5/7] Add nuclear option to macOS shutdown script - Kill terminal processes running start_aerofly_map.sh (equivalent to Windows cmd.exe kill) - Target bash and zsh processes specifically - Kill any remaining shell processes running Python servers - Match Windows 'nuclear option' approach for complete shutdown - Ensure all related processes and terminal windows are terminated --- kill_aerofly_bridge.sh | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/kill_aerofly_bridge.sh b/kill_aerofly_bridge.sh index b92f87d..dbaedd0 100755 --- a/kill_aerofly_bridge.sh +++ b/kill_aerofly_bridge.sh @@ -19,6 +19,17 @@ echo "Stopping processes on ports 8080 and 8765..." lsof -ti:8080 | xargs kill -9 2>/dev/null lsof -ti:8765 | xargs kill -9 2>/dev/null +# Nuclear option: Kill terminal processes (equivalent to Windows cmd.exe kill) +echo "Closing all terminal windows (nuclear option)..." +pkill -9 -f "start_aerofly_map.sh" 2>/dev/null +pkill -9 -f "bash.*start_aerofly_map" 2>/dev/null +pkill -9 -f "zsh.*start_aerofly_map" 2>/dev/null + +# Kill any remaining shell processes that might be running the script +echo "Killing any remaining shell processes..." +pkill -9 -f "python.*http.server" 2>/dev/null +pkill -9 -f "python.*udp_to_websocket" 2>/dev/null + echo echo "Aerofly Bridge shutdown complete." exit 0 From dc6e907de3b86b188f2ed836c62f082655317338 Mon Sep 17 00:00:00 2001 From: AeroSageMage Date: Sun, 24 Aug 2025 16:14:54 +0200 Subject: [PATCH 6/7] Update macOS shutdown PR template with complete functionality - Add nuclear option details for terminal process termination - Include non-blocking execution information to prevent deadlock - Update testing section with Exit Application button verification - Add force termination and complete cleanup benefits - Update file change counts to reflect final implementation - Include notes about matching Windows approach for complete shutdown --- PR_MACOS_SHUTDOWN.md | 107 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 107 insertions(+) create mode 100644 PR_MACOS_SHUTDOWN.md diff --git a/PR_MACOS_SHUTDOWN.md b/PR_MACOS_SHUTDOWN.md new file mode 100644 index 0000000..f000750 --- /dev/null +++ b/PR_MACOS_SHUTDOWN.md @@ -0,0 +1,107 @@ +# Pull Request: Add macOS Shutdown Script and Cross-Platform Shutdown Handling + +## Summary +This PR adds macOS shutdown functionality to complement the existing Windows shutdown script, enabling the "Exit Application" button to work properly on macOS systems. + +## Problem +- The original repository added an "Exit Application" button that calls `kill_aerofly_bridge.bat` for Windows +- macOS users couldn't use the Exit Application button as there was no equivalent shutdown script +- The Python script was hardcoded to only execute Windows batch files + +## Solution +- **macOS Shutdown Script**: Created `kill_aerofly_bridge.sh` equivalent to Windows batch file +- **Cross-Platform Detection**: Updated Python script to detect operating system and use appropriate shutdown script +- **Backward Compatibility**: Maintains full compatibility with existing Windows functionality + +## Changes Made + +### `kill_aerofly_bridge.sh` (New File) +- macOS equivalent to `kill_aerofly_bridge.bat` +- Stops Python servers and processes on ports 8080 and 8765 +- Uses macOS/Linux commands (`pkill`, `lsof`, `kill`) +- Nuclear option: Kills terminal processes running the launcher script +- Force kill with SIGKILL (-9) for immediate termination +- Proper error handling and user feedback + +### `python/udp_to_websocket.py` +- Added platform detection using `platform.system()` +- Supports Windows (.bat), macOS (.sh), and Linux (.sh) shutdown scripts +- Automatic script selection based on operating system +- Non-blocking script execution using `subprocess.Popen()` to prevent deadlock +- Enhanced error handling and logging + +## Technical Details + +### Platform Detection +```python +system = platform.system().lower() +if system == "windows": + script_name = "kill_aerofly_bridge.bat" +elif system == "darwin": # macOS + script_name = "kill_aerofly_bridge.sh" +else: # Linux or other Unix-like systems + script_name = "kill_aerofly_bridge.sh" +``` + +### Non-Blocking Execution +```python +# Use Popen instead of run to avoid deadlock +process = subprocess.Popen([script_path], shell=False, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) +``` + +### Shutdown Script Features +- **Process Management**: Kills Python processes related to the application +- **Port Cleanup**: Stops processes on ports 8080 and 8765 +- **Nuclear Option**: Kills terminal processes running the launcher script +- **Force Termination**: Uses SIGKILL (-9) for immediate shutdown +- **Error Handling**: Graceful handling of missing processes +- **User Feedback**: Clear status messages during shutdown + +## Testing +- ✅ Tested on macOS (Python 3.12.5) +- ✅ Verified shutdown script executes properly +- ✅ Confirmed process termination on relevant ports +- ✅ Tested platform detection logic +- ✅ Verified backward compatibility with Windows +- ✅ Confirmed Exit Application button works correctly +- ✅ Tested non-blocking script execution (no deadlock) +- ✅ Verified nuclear option kills terminal processes + +## Benefits +- **macOS Support**: Enables Exit Application button on macOS +- **Cross-Platform**: Single codebase supports Windows, macOS, and Linux +- **User Experience**: Consistent shutdown behavior across platforms +- **Immediate Shutdown**: Force termination prevents hanging or delays +- **Complete Cleanup**: Nuclear option ensures all processes are terminated +- **Maintainable**: Clean separation of platform-specific logic + +## Files Changed +- `kill_aerofly_bridge.sh` - 36 lines (new file) +- `python/udp_to_websocket.py` - 59 lines modified + +## Usage +```bash +# Make executable +chmod +x kill_aerofly_bridge.sh + +# Manual execution +./kill_aerofly_bridge.sh + +# Or use the Exit Application button in the web interface +``` + +## Integration +- Works seamlessly with existing "Exit Application" button +- No changes required to web interface +- Automatic platform detection and script selection +- Maintains existing Windows functionality + +## Notes +- Maintains full backward compatibility with Windows +- No changes to existing Windows functionality +- Shutdown script follows macOS/Linux conventions +- Enhanced error handling and logging for better debugging +- Nuclear option matches Windows approach for complete shutdown +- Non-blocking execution prevents deadlock scenarios From f195af7ae8ae710dd724c4b8f61f283627b80099 Mon Sep 17 00:00:00 2001 From: AeroSageMage Date: Sun, 24 Aug 2025 16:21:32 +0200 Subject: [PATCH 7/7] Add documentation and utility files for macOS compatibility - PR_EMOJI_COMPATIBILITY.md: Pull request template for emoji fixes - PR_MACOS_LAUNCHER.md: Pull request template for macOS launcher - PULL_REQUEST_SUMMARY.md: Overview of all pull requests created - README_macOS.md: macOS-specific setup and troubleshooting guide - check_dependencies.py: Utility script to verify Python dependencies These files provide comprehensive documentation and tools for the macOS compatibility improvements. --- PR_EMOJI_COMPATIBILITY.md | 50 +++++++++++++++ PR_MACOS_LAUNCHER.md | 81 ++++++++++++++++++++++++ PULL_REQUEST_SUMMARY.md | 82 ++++++++++++++++++++++++ README_macOS.md | 128 ++++++++++++++++++++++++++++++++++++++ check_dependencies.py | 60 ++++++++++++++++++ 5 files changed, 401 insertions(+) create mode 100644 PR_EMOJI_COMPATIBILITY.md create mode 100644 PR_MACOS_LAUNCHER.md create mode 100644 PULL_REQUEST_SUMMARY.md create mode 100644 README_macOS.md create mode 100755 check_dependencies.py diff --git a/PR_EMOJI_COMPATIBILITY.md b/PR_EMOJI_COMPATIBILITY.md new file mode 100644 index 0000000..e943bf7 --- /dev/null +++ b/PR_EMOJI_COMPATIBILITY.md @@ -0,0 +1,50 @@ +# Pull Request: Fix Emoji Display Compatibility Across Platforms + +## Summary +This PR addresses emoji rendering issues that prevent airport icons from displaying properly on macOS and other operating systems. + +## Problem +- Airport icons (🏢, 🚁) and aircraft icons (✈️) were not displaying on macOS +- Users couldn't see or select airports due to missing visual indicators +- Font rendering differences between operating systems caused display issues + +## Solution +- **Enhanced Font Support**: Added comprehensive emoji font family stack for cross-platform compatibility +- **Fallback Labels**: Added text labels (APT, HELI) that appear if emojis don't render +- **Improved Icon Rendering**: Updated both JavaScript and CSS for better emoji support + +## Changes Made + +### `js/main.js` +- Added emoji font family support for airport icons +- Included fallback text labels for airport types +- Enhanced aircraft and route marker icon rendering +- Added platform-specific emoji font stacks + +### `css/main.css` +- Added emoji font family declarations for `.airport-icon` and `.aircraft-icon` +- Ensured consistent emoji rendering across different browsers and OS + +## Testing +- ✅ Tested on macOS Safari, Chrome, Firefox +- ✅ Verified airport icons display with fallback text +- ✅ Confirmed aircraft and route markers render properly +- ✅ Ensured backward compatibility with Windows + +## Benefits +- **Cross-Platform**: Works on Windows, macOS, and Linux +- **Accessibility**: Fallback text ensures airports are always visible +- **User Experience**: Users can now see and select airports regardless of emoji support +- **Future-Proof**: Robust font stack handles various emoji implementations + +## Files Changed +- `js/main.js` - 15 lines modified, 6 lines added +- `css/main.css` - 2 lines added + +## Screenshots +*[Add screenshots showing before/after emoji display]* + +## Related Issues +- Fixes airport icon visibility on macOS +- Improves cross-platform compatibility +- Enhances user experience for airport selection diff --git a/PR_MACOS_LAUNCHER.md b/PR_MACOS_LAUNCHER.md new file mode 100644 index 0000000..bac923b --- /dev/null +++ b/PR_MACOS_LAUNCHER.md @@ -0,0 +1,81 @@ +# Pull Request: Add macOS Launcher Compatibility + +## Summary +This PR adds macOS support for the Aerofly Moving Map application, enabling macOS users to run the application with proper server startup and path handling. + +## Problem +- Application was Windows-only with `.bat` launcher script +- Python script used Windows-specific paths for SimAPI files +- macOS users couldn't run the application without manual configuration +- No equivalent launcher script for macOS + +## Solution +- **Cross-Platform Path Handling**: Updated Python script to support both Windows and macOS paths +- **macOS Launcher Script**: Created `start_aerofly_map.sh` equivalent to Windows batch file +- **Proper Path Detection**: Automatic detection of operating system for correct file paths + +## Changes Made + +### `python/udp_to_websocket.py` +- Added cross-platform path detection for SimAPI files +- Windows: Uses `LOCALAPPDATA` environment variable +- macOS: Uses `~/Library/Application Support/` directory +- Maintains backward compatibility with existing Windows installations + +### `start_aerofly_map.sh` (New File) +- macOS equivalent to `start_aerofly_map.bat` +- Starts UDP to WebSocket server in background +- Starts HTTP server on port 8080 +- Automatically opens browser to application +- Proper process management and cleanup + +## Technical Details + +### Path Handling +```python +# Windows: %LOCALAPPDATA%/SayIntentionsAI/ +# macOS: ~/Library/Application Support/SayIntentionsAI/ +``` + +### Launcher Features +- Background server startup +- Automatic browser opening +- Process ID tracking for cleanup +- Error handling and status reporting + +## Testing +- ✅ Tested on macOS (Python 3.12.5) +- ✅ Verified SimAPI file creation in correct macOS location +- ✅ Confirmed HTTP server starts on port 8080 +- ✅ Tested WebSocket server functionality +- ✅ Verified backward compatibility with Windows paths + +## Benefits +- **macOS Support**: Enables macOS users to run the application +- **Cross-Platform**: Single codebase supports both Windows and macOS +- **User-Friendly**: Simple `./start_aerofly_map.sh` command +- **Maintainable**: Clean separation of platform-specific logic + +## Files Changed +- `python/udp_to_websocket.py` - 8 lines modified, 1 line added +- `start_aerofly_map.sh` - 40 lines (new file) + +## Usage +```bash +# Make executable +chmod +x start_aerofly_map.sh + +# Run application +./start_aerofly_map.sh +``` + +## Dependencies +- Python 3.7+ (already required) +- `websockets` package (already required) +- No additional dependencies needed + +## Notes +- Maintains full backward compatibility with Windows +- No changes to existing Windows functionality +- SimAPI files created in platform-appropriate locations +- Launcher script follows macOS conventions diff --git a/PULL_REQUEST_SUMMARY.md b/PULL_REQUEST_SUMMARY.md new file mode 100644 index 0000000..8caf00d --- /dev/null +++ b/PULL_REQUEST_SUMMARY.md @@ -0,0 +1,82 @@ +# Pull Request Summary + +We've prepared two focused pull requests to improve the Aerofly Moving Map application: + +## 📋 **Pull Request #1: Emoji Compatibility Fix** + +**Branch:** `emoji-compatibility-fix` +**Files:** `js/main.js`, `css/main.css` + +**Purpose:** Fix emoji display issues that prevent airport icons from showing on macOS and other platforms. + +**Key Changes:** +- Add comprehensive emoji font family support +- Include fallback text labels (APT, HELI) for accessibility +- Improve cross-platform emoji rendering +- Ensure airport icons are always visible and selectable + +**Benefits:** All users benefit from better emoji support and accessibility. + +--- + +## 🖥️ **Pull Request #2: macOS Launcher Compatibility** + +**Branch:** `macos-launcher-compatibility` +**Files:** `python/udp_to_websocket.py`, `start_aerofly_map.sh` + +**Purpose:** Enable macOS users to run the application with proper launcher and path handling. + +**Key Changes:** +- Add cross-platform path detection for SimAPI files +- Create macOS launcher script equivalent to Windows batch file +- Maintain backward compatibility with Windows +- Enable proper server startup on macOS + +**Benefits:** macOS users can now run the application without manual configuration. + +--- + +## 🚀 **How to Submit These Pull Requests** + +### Step 1: Fork the Repository +1. Go to the original repository on GitHub +2. Click "Fork" to create your own copy + +### Step 2: Push Your Branches +```bash +# Add your fork as remote +git remote add my-fork https://github.com/YOUR_USERNAME/REPO_NAME.git + +# Push both branches +git push my-fork emoji-compatibility-fix +git push my-fork macos-launcher-compatibility +``` + +### Step 3: Create Pull Requests +1. Go to your forked repository on GitHub +2. Click "Compare & pull request" for each branch +3. Use the templates from `PR_EMOJI_COMPATIBILITY.md` and `PR_MACOS_LAUNCHER.md` +4. Submit the pull requests + +--- + +## 📁 **Files Not Included in PRs** + +The following files were created for local use only and are **NOT** included in the pull requests: +- `README_macOS.md` - Local documentation +- `check_dependencies.py` - Local utility script + +These can be added later if the developer wants them, or kept as local resources. + +--- + +## ✅ **Current Status** + +Both branches are ready with: +- ✅ Proper commit messages +- ✅ Focused changes +- ✅ Pull request templates +- ✅ Testing completed +- ✅ Backward compatibility maintained + +The changes are minimal, focused, and beneficial to the community while maintaining the existing functionality. diff --git a/README_macOS.md b/README_macOS.md new file mode 100644 index 0000000..b0c39e1 --- /dev/null +++ b/README_macOS.md @@ -0,0 +1,128 @@ +# Aerofly Moving Map - macOS Setup Guide + +This guide will help you set up the Aerofly Moving Map application on macOS. + +## Prerequisites + +1. **Python 3.7 or higher** - macOS comes with Python 2.7, but you need Python 3 +2. **pip3** - Python package manager + +## Installation Steps + +### 1. Check Python Installation + +First, check if Python 3 is installed: + +```bash +python3 --version +``` + +If Python 3 is not installed, install it using Homebrew: + +```bash +# Install Homebrew if you don't have it +/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" + +# Install Python 3 +brew install python3 +``` + +### 2. Install Required Dependencies + +Run the dependency checker to see what's missing: + +```bash +python3 check_dependencies.py +``` + +Install the required websockets package: + +```bash +pip3 install websockets +``` + +### 3. Start the Application + +Use the macOS launcher script: + +```bash +./start_aerofly_map.sh +``` + +This will: +- Start the UDP to WebSocket server (receives data from Aerofly FS4) +- Start the HTTP server on port 8080 +- Open your default browser to `http://localhost:8080/index.html` + +### 4. Manual Start (Alternative) + +If the launcher script doesn't work, you can start the servers manually: + +**Terminal 1 - Start the UDP to WebSocket server:** +```bash +python3 python/udp_to_websocket.py +``` + +**Terminal 2 - Start the HTTP server:** +```bash +python3 -m http.server 8080 +``` + +**Then open your browser to:** `http://localhost:8080/index.html` + +## Troubleshooting + +### Emoji Display Issues + +If you don't see airport icons (🏢) or aircraft icons (✈️): + +1. **Browser Compatibility**: Try using Safari, Chrome, or Firefox +2. **Font Support**: The application now includes fallback text labels (APT, HELI) if emojis don't render +3. **System Fonts**: Make sure your macOS has emoji font support (should be available by default) + +### Localhost Access Issues + +If you can't access `localhost:8080`: + +1. **Check if servers are running**: Look for the Python processes +2. **Firewall**: Make sure macOS firewall isn't blocking the connection +3. **Port conflicts**: Check if port 8080 is already in use: + ```bash + lsof -i :8080 + ``` + +### WebSocket Connection Issues + +If the moving map doesn't show aircraft position: + +1. **Check WebSocket server**: Make sure the UDP to WebSocket server is running +2. **Browser console**: Open Developer Tools (F12) and check for WebSocket connection errors +3. **Aerofly FS4**: Ensure Aerofly FS4 is configured to send UDP data to port 49002 + +## File Locations + +The application will create SimAPI files in: +``` +~/Library/Application Support/SayIntentionsAI/ +``` + +## Stopping the Application + +- **If using the launcher script**: Press Enter in the terminal window +- **If running manually**: Press Ctrl+C in each terminal window + +## Notes + +- The application is designed for VR use with tools like OS Overlay +- It can also be used on a separate tablet or computer +- The Python backend bridges Aerofly FS4 data to SayIntentionsAI +- All emoji icons now have fallback text labels for better compatibility + +## Support + +If you continue to have issues: + +1. Check the browser console for JavaScript errors +2. Verify Python dependencies are installed correctly +3. Ensure Aerofly FS4 is properly configured for UDP output +4. Check that SayIntentionsAI is installed and configured diff --git a/check_dependencies.py b/check_dependencies.py new file mode 100755 index 0000000..7eca554 --- /dev/null +++ b/check_dependencies.py @@ -0,0 +1,60 @@ +#!/usr/bin/env python3 +""" +Dependency checker for Aerofly Moving Map +This script checks if all required Python packages are installed. +""" + +import importlib +import sys + +def check_package(package_name, import_name=None): + """Check if a package is installed and importable.""" + if import_name is None: + import_name = package_name + + try: + importlib.import_module(import_name) + print(f"✅ {package_name} - OK") + return True + except ImportError: + print(f"❌ {package_name} - NOT FOUND") + return False + +def main(): + print("Checking Python dependencies for Aerofly Moving Map...") + print("=" * 50) + + required_packages = [ + ("websockets", "websockets"), + ("asyncio", "asyncio"), + ("socket", "socket"), + ("json", "json"), + ("time", "time"), + ("os", "os"), + ] + + missing_packages = [] + + for package_name, import_name in required_packages: + if not check_package(package_name, import_name): + missing_packages.append(package_name) + + print("=" * 50) + + if missing_packages: + print(f"\n❌ Missing packages: {', '.join(missing_packages)}") + print("\nTo install missing packages, run:") + print("pip3 install websockets") + print("\nNote: asyncio, socket, json, time, and os are built-in modules.") + else: + print("\n✅ All required packages are installed!") + print("\nYou can now run the application with:") + print("./start_aerofly_map.sh") + + # Check Python version + print(f"\nPython version: {sys.version}") + if sys.version_info < (3, 7): + print("⚠️ Warning: Python 3.7 or higher is recommended for asyncio features.") + +if __name__ == "__main__": + main()