{"id":30313897,"url":"https://github.com/judahpaul16/canarygc","last_synced_at":"2026-07-11T22:00:36.942Z","repository":{"id":305259368,"uuid":"828389701","full_name":"judahpaul16/canarygc","owner":"judahpaul16","description":"A web-based ground control station (GCS) for remote autopilot management via the MAVLink protocol.","archived":false,"fork":false,"pushed_at":"2026-07-11T02:44:02.000Z","size":65400,"stargazers_count":12,"open_issues_count":1,"forks_count":2,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-07-11T03:13:22.508Z","etag":null,"topics":["ardupilot","drone","gcs","iot","mavlink","plane","px4","quadcopter","raspberry-pi","rc","rover","sitl","uav"],"latest_commit_sha":null,"homepage":"https://hub.docker.com/r/judahpaul/canarygc","language":"Svelte","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/judahpaul16.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2024-07-14T02:09:53.000Z","updated_at":"2026-07-11T02:43:12.000Z","dependencies_parsed_at":"2025-07-19T07:37:23.186Z","dependency_job_id":"92e6fc72-9309-4581-a784-f79ce3b80cb8","html_url":"https://github.com/judahpaul16/canarygc","commit_stats":null,"previous_names":["judahpaul16/canarygc"],"tags_count":62,"template":false,"template_full_name":null,"purl":"pkg:github/judahpaul16/canarygc","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/judahpaul16%2Fcanarygc","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/judahpaul16%2Fcanarygc/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/judahpaul16%2Fcanarygc/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/judahpaul16%2Fcanarygc/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/judahpaul16","download_url":"https://codeload.github.com/judahpaul16/canarygc/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/judahpaul16%2Fcanarygc/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35376135,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-11T02:00:05.354Z","response_time":104,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ardupilot","drone","gcs","iot","mavlink","plane","px4","quadcopter","raspberry-pi","rc","rover","sitl","uav"],"created_at":"2025-08-17T18:53:25.564Z","updated_at":"2026-07-11T22:00:36.936Z","avatar_url":"https://github.com/judahpaul16.png","language":"Svelte","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n\n\u003cspan style=\"color: red;\"\u003e⚠️ **Warning**: This project is in **early development** and is not yet ready for production use. Use at your own risk! **It is your responsibility** to understand the risks involved as well as the **laws and regulations** governing the use of unmanned aerial vehicles (UAVs) in your area. ⚠️\u003c/span\u003e\n\n\u003cimg src=\"compose/svelte-kit/static/logo.png\" alt=\"Canary Ground Control Logo\" width=\"100\"/\u003e\n\n# 🚁 Canary Ground Control 📡\n\n[![CI/CD](https://github.com/judahpaul16/canarygc/actions/workflows/ci.yml/badge.svg)](https://github.com/judahpaul16/canarygc/actions/workflows/ci.yml)\n![Raspberry Pi Version](https://img.shields.io/badge/Raspberry_Pi-Zero%20%2F%204B-red?style=flat-square\u0026logo=raspberry-pi)\n![Docker Compose Version](https://img.shields.io/badge/Docker%20Compose-v2.27.1-blue?style=flat-square\u0026logo=docker)\n![Latest Docker Image](https://img.shields.io/docker/v/judahpaul/canarygc)\n\nA web-based ground control station (GCS) for remote autopilot management via the [MAVLink protocol](https://en.wikipedia.org/wiki/MAVLink).\n\n\u003cimg src=\"screenshots/dashboard.png\" alt=\"Illustration\" width=\"auto\"/\u003e\n\n\u003c/div\u003e\n\n---\n\n## 🤔 How Does It Work?\n\nUnlike traditional GCS software, Canary Ground Control is a web-based application that runs on a Raspberry Pi, making it a part of the flight stack. This enables you to manage your autopilot from anywhere in the world, as long as you have an internet connection.\n\n![Diagram](screenshots/diagram.png)\n\n---\n\n## ✨ Features\n\n* **Live telemetry \u0026 control** over MAVLink: attitude, position, battery, GPS, flight-mode changes, arm/disarm, and a virtual D-Pad.\n* **ArduPilot and PX4 support.** Flight-mode encoding and decoding is selected per autopilot through a strategy layer, so mode changes and armed-state readouts work on both stacks.\n* **Mission planner** with a 2D map (Leaflet) and a 3D map (MapLibre).\n* **Configurable basemaps.** Light, dark, and hybrid-satellite tiles resolve from a MapTiler key (with keyless fallbacks), and the map swaps to a real dark basemap when the theme toggles. Each mode's tile source is overridable in Integrations with a preset dropdown or a custom XYZ URL.\n* **Cross-autopilot missions.** A plan is stored autopilot-neutral and normalized to the connected stack on upload: ArduPilot runs the full command set, and PX4 substitutes or skips commands it cannot run and reports what changed.\n* **Mission import.** Load QGroundControl `.plan` and Mission Planner `.waypoints` (QGC WPL) files, or the app's own JSON, straight into the planner.\n* **Smart path optimization.** One click routes the mission clear of hazards without changing the waypoint order. It pulls FAA obstacles and OpenStreetMap building heights for the mission area and, where a leg would strike one, raises the leg to clear it when the ceiling allows or routes around it when it is too tall. Restricted airspace is always routed around, and a waypoint inside it is moved out. The map overlays refetch as you pan, and the airspace, hazard, and building lookups are cached per area.\n* **Airspace overlays.** Both the 2D and 3D maps draw restricted and controlled airspace for the mission area, toggled from a map control, with a popup for each zone's class, altitude band, and operating implication. Worldwide coverage comes from [OpenAIP](https://www.openaip.net) with a key; without one it falls back to the FAA's keyless public airspace layers (US).\n* **LAANC ceilings and obstacles.** Two more toggleable overlays from the FAA's keyless layers: the UAS Facility Map grid colored by each square's pre-approved ceiling, and Digital Obstacle File towers and structures colored by height, each with plain-language popups.\n* **Pre-flight safety checks.** Before a mission starts, every waypoint is validated against an altitude ceiling and floor, a home-relative geofence radius, and the fetched airspace, and each leg is checked for passing through a zone. Restricted airspace, or a waypoint past a limit, blocks the launch; controlled airspace prompts for confirmation.\n* **Audible callouts.** Spoken telemetry callouts (arm/disarm, mode changes, battery, GPS, failsafe, link loss) over the browser speech API, with an on/off toggle that defaults on.\n* **Email alerts.** Enable per-event alerts (arm/disarm, mode change, failsafe, low battery, GPS or link loss, and more); each fires an email with the live coordinates and telemetry.\n* **Integrations \u0026 password reset.** In-app settings for SMTP (your own mail server), airspace keys, map tiles, and the operator email, which also backs an emailed, expiring password-reset link.\n* **WebRTC camera feed** from an on-board Raspberry Pi camera via [MediaMTX](https://github.com/bluenviron/mediamtx).\n* **Weather, compass, and stats** widgets on a customizable dashboard.\n* **Build info** at `/version` (release tag, commit, build time).\n\n---\n\n## ❓ Why Not Just Use Mission Planner, QGC, or APM Planner (with Tailscale)?\n\nYou might ask:\n“Why not just run an existing GCS (Mission Planner, QGC, APM Planner), and connect over Tailscale, either from a laptop, or running the GCS directly on the Raspberry Pi?”\n\n\u003e **TL;DR:**\n\u003e Traditional GCS software is designed for *desktop-based, short-range* semi-manual operation.\n\u003e CanaryGC is purpose-built for *embedded, LTE-connected, persistent, remote UAV control*, where every watt and packet counts.\n\n### Running GCS on a laptop (with Tailscale to the drone):\n\n1. **No Always-On Link**\n   The GCS must be running on your laptop. If your laptop disconnects (or sleeps), telemetry is lost.\n   CanaryGC runs *on the drone itself*, providing a persistent link, always available to any browser.\n\n2. **Laptop Required**\n   You must boot a laptop and connect Tailscale. CanaryGC works from any phone, tablet, or computer, no special software needed.\n\n3. **Tailscale Reliability**\n   VPN tunnels can be fragile over LTE or CG-NAT. CanaryGC supports public-IP SIMs or static tunnels with no VPN dependency.\n\n---\n\n### Running GCS **directly on the Pi** (with Tailscale + VNC / RDP):\n\n1. **GUI Overhead**\n   Traditional GCS software (QGC, Mission Planner, APM Planner) is designed as a desktop GUI app (Qt/X11). Running it on the Pi requires installing and running a full desktop environment (X11 server, GPU stack, window manager). This adds CPU and memory load, increases system complexity, and draws more power, reducing flight time.\n\n2. **Remote Desktop Limitations**\n   Accessing the Pi’s GUI remotely (via Tailscale + VNC/RDP) requires constant encoding and streaming of the desktop image, adding CPU load, using bandwidth, and introducing lag. Over LTE links, this results in poor responsiveness and unreliable control, unacceptable for UAV operations.\n\n3. **Battery \u0026 Performance Impact**\n   The additional CPU/GPU usage from running a desktop GCS and streaming remote sessions directly reduces battery life. It also impacts system responsiveness for other critical tasks (LTE modem handling, telemetry routing, camera streaming).\n\n4. **Reliability Risks**\n   Desktop-based GCS apps are not designed for connection interruptions or lossy networks. VNC/RDP sessions can freeze or drop if connectivity is poor. Recovery often requires manual intervention, not ideal for autonomous or long-range flights.\n\n5. **Increased Maintenance**\n   Installing and maintaining a full desktop stack and GUI-based GCS on the Pi adds software complexity, increases boot time, and introduces more failure points. Field systems should be simple and robust.\n\n---\n\n### Why CanaryGC’s Web-Native, Headless Design Is Better\n\nCanaryGC is designed for **headless, remote-first UAV deployments**:\n\n* It runs as a lightweight background service, no X11, no desktop.\n* The Pi can run a minimal OS, saving power and booting faster.\n* Users connect via a web browser, no VNC or desktop tunnels needed.\n* The Pi streams only telemetry and control data, not full-screen images, making it far more efficient over LTE links.\n* The interface gracefully handles network interruptions and reconnects.\n* It works from any device (phone, tablet, laptop) with a browser, ideal for field operations.\n\n---\n\n## 🐚 Setup Script\n\n### Production Deployment\n```bash\ncurl -s https://raw.githubusercontent.com/judahpaul16/canarygc/main/contrib/setup.sh | \\\n    bash -s --\n```\n\n### Local Testing with SITL\n```bash\ncurl -s https://raw.githubusercontent.com/judahpaul16/canarygc/main/contrib/setup.sh | \\\n    bash -s -- --simulation\n```\n\n### Install-Only (Without System Setup)\n```bash\ncurl -s https://raw.githubusercontent.com/judahpaul16/canarygc/main/contrib/setup.sh | \\\n    bash -s -- --install-only\n```\n\n---\n\n## 🧑‍💻 Local Development\n\nThe stack is a single `docker-compose.yml` with two profiles.\n\n**Development** runs the SvelteKit dev server with hot reload against an ArduPilot SITL container:\n\n```bash\ndocker compose --profile development up\n```\n\nThe app is served at `http://localhost:5173`; SITL exposes MAVLink on TCP `5760`. Set a different host port with `APP_DEV_PORT` in a root `.env` if 5173 collides. The first bring-up builds the ArduPilot SITL image from source (Copter 4.5.7), which takes a while; later runs reuse it, and the simulator streams telemetry about a minute after it starts.\n\nOn first run the database is empty, so open `/register` to create the operator account. To reset it later, wipe the dev database and restart:\n\n```bash\ndocker exec canarygc_app sh -c 'rm -f /app/src/data.db*'\ndocker restart canarygc_app\n```\n\nThe schema recreates empty on the next boot, and the app then prompts for first-run operator setup.\n\n**Production** builds the Node server image and runs the WebRTC camera bridge, talking to a real autopilot over UART:\n\n```bash\ndocker compose --profile production up app webrtc\n```\n\nThe app is served at `http://localhost:3000`.\n\n### Gates\n\nFrom `compose/svelte-kit`, mirroring CI:\n\n```bash\nnpm ci                              # install from the lockfile\nnpm run lint                        # eslint\nnpm run check                       # svelte-check\nnpm run build                       # production build\nnpm audit --audit-level=moderate    # dependency audit\n```\n\n---\n\n## ⚙️ Configuration\n\nThe app reads its configuration from environment variables (see `compose/svelte-kit/.env.example`):\n\n| Variable | Purpose |\n| --- | --- |\n| `DATABASE_PATH` | Path to the SQLite database file (migrated on first boot). |\n| `OPENAIP_API_KEY` | [OpenAIP](https://www.openaip.net) key for worldwide airspace. Without it, airspace falls back to the FAA's keyless US layers. |\n| `VITE_ALTITUDE_ANGEL_API_KEY` | Optional key for the Altitude Angel airspace endpoint. |\n| `SMTP_HOST`, `SMTP_PORT`, `SMTP_SECURE`, `SMTP_USER`, `SMTP_PASS`, `MAIL_FROM` | SMTP for password-reset and alert email. |\n\nThe airspace keys and SMTP settings are also editable in-app under **Integrations**, which stores them in the database and takes precedence over the environment.\n\n---\n\n## 📜 License\nThis software is made available under the MIT License. See the [`LICENSE`](LICENSE.md) file for more information.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjudahpaul16%2Fcanarygc","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjudahpaul16%2Fcanarygc","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjudahpaul16%2Fcanarygc/lists"}