Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
85 commits
Select commit Hold shift + click to select a range
de42af6
ci: add clam-av scan
dbetm Feb 15, 2026
dbe634e
Add map visualization, background monitors, and improved setup wizard
Tailspin45 Jan 30, 2026
758ea80
UI improvements: move buttons above map, NTDS-style diamond markers
Tailspin45 Jan 30, 2026
04e420b
Fix aircraft icons: diamonds only for transits, airplane emoji for ot…
Tailspin45 Jan 30, 2026
8cf1d55
Fix duplicate flights and bounding box snap-back
Tailspin45 Jan 30, 2026
f0d11e6
Deduplicate flights in UI only, keep all backend data
Tailspin45 Jan 30, 2026
2339c53
Add target emoji column and dual azimuth arrows
Tailspin45 Jan 30, 2026
6d2e46f
Show altitude in arrow popup along with azimuth
Tailspin45 Jan 30, 2026
9d1dd95
Fix aircraft heading, reorder columns, improve formatting
Tailspin45 Jan 30, 2026
5e7f191
Fix aircraft marker check for coordinates at 0
Tailspin45 Jan 30, 2026
02e1142
Improve deduplication: normalize flight IDs, add debug logging
Tailspin45 Jan 30, 2026
4c48a18
Add interactive highlighting between map and table
Tailspin45 Jan 30, 2026
5010bc2
Flash animations: 3x with partial transparency for rows
Tailspin45 Jan 30, 2026
bc9ecfb
Compact UI: single-line header, inline controls, smaller buttons
Tailspin45 Jan 30, 2026
aa471f8
Simplify header, reorder controls for better flow
Tailspin45 Jan 30, 2026
452342c
Simplify tracking status: show "Tracking 🌙" or "No Tracking"
Tailspin45 Jan 30, 2026
2f82088
Show tracking status per target: "Tracking 🌙 | Not tracking ☀️"
Tailspin45 Jan 30, 2026
7125639
Fix marker flash: use filter/drop-shadow instead of transform
Tailspin45 Jan 30, 2026
c1d8099
Update README with new map features and interactions
Tailspin45 Jan 30, 2026
043cdbc
Add Track Mode: Cmd/Ctrl+click for 6-sec live updates
Tailspin45 Jan 30, 2026
120f5af
Track Mode safety: require medium+ probability transit
Tailspin45 Jan 30, 2026
035e66f
Add synthesized sound effects for Track Mode
Tailspin45 Jan 30, 2026
17cbbdb
Fix loadPosition localStorage check
Tailspin45 Jan 30, 2026
b515c48
Remove filter for flights with no destination
Tailspin45 Jan 31, 2026
3b9534f
Add editable minimum horizon altitude field
Tailspin45 Jan 31, 2026
a04a7c4
Add demo mode with guaranteed transit classifications and UI improvem…
Tailspin45 Jan 31, 2026
57e3b12
Fix map marker flash animation and bearing line alignment
Tailspin45 Jan 31, 2026
c9e3b5e
Improve demo data generator and fix altitude conversion bug
Tailspin45 Jan 31, 2026
eb0a54a
Refactor transit algorithm with proper angular separation and test suite
Tailspin45 Jan 31, 2026
f840dbb
Add UI improvements: header redesign, loading spinner, sticky boundin…
Tailspin45 Jan 31, 2026
01911c3
Add altitude display improvements and distance tracking
Tailspin45 Feb 1, 2026
a80b696
Improve plane angle display: always show all columns with color coding
Tailspin45 Feb 1, 2026
d5a231d
Add configurable auto-refresh and change distance units to nautical m…
Tailspin45 Feb 1, 2026
2328e6d
Change UI label from "Min Alt" to "Min angle" for clarity
Tailspin45 Feb 1, 2026
d3006a7
Calculate and display delta angles for all aircraft
Tailspin45 Feb 1, 2026
cbb9f66
Implement altitude profile display for aircraft visualization
Tailspin45 Feb 1, 2026
fa8e16c
Simplify altitude display to thin color-coded lines
Tailspin45 Feb 1, 2026
effb2c5
Align altitude display with map - make them contiguous
Tailspin45 Feb 1, 2026
2b124aa
Add debugging and improve route/track display robustness
Tailspin45 Feb 1, 2026
7adebfb
Remove route from map legend
Tailspin45 Feb 1, 2026
4cb239b
Fix altitude display height to match map exactly
Tailspin45 Feb 1, 2026
48760d8
Prevent altitude lines from extending beyond bounds
Tailspin45 Feb 1, 2026
7a9f9b1
Handle aircraft below zero altitude properly
Tailspin45 Feb 1, 2026
1e709c0
Remove popup data box from aircraft markers
Tailspin45 Feb 1, 2026
067d3e1
Add persistent light highlight for selected aircraft row
Tailspin45 Feb 1, 2026
b270327
Fix selected row highlight to be clearly light blue
Tailspin45 Feb 1, 2026
3274f19
Improve selected row highlight readability by removing background ove…
Tailspin45 Feb 1, 2026
33e7345
Expand transit detection thresholds for 1.0° target diameter
Tailspin45 Feb 1, 2026
80fbaad
Fix track mode to update only tracked aircraft and change button to R…
Tailspin45 Feb 1, 2026
f273ff8
Add speed column in knots to flight table
Tailspin45 Feb 1, 2026
4e6fab1
Refactor API URLs to use centralized constants
Tailspin45 Feb 2, 2026
938c70a
Replace hardcoded HTTP status codes with HTTPStatus enum
Tailspin45 Feb 2, 2026
a666187
Extract haversine distance calculation into reusable function
Tailspin45 Feb 2, 2026
4149e5a
Set default bounding box when missing instead of raising error
Tailspin45 Feb 2, 2026
9be9a3a
improvements from copilot review
dbetm Feb 15, 2026
1e64655
feat: pause when hidden is optional - default is no pausing
dbetm Feb 27, 2026
5147e98
fix: transit prediction algorithm - consider cases when the target is…
dbetm Mar 10, 2026
e5f1378
register target run in Makefile
dbetm Mar 14, 2026
a4dde24
refactor: standarize units for speed and distance, use km unit
dbetm Mar 14, 2026
1516e7b
docs: remove distribution related docs since there's no real distribu…
dbetm Mar 14, 2026
b07cf20
front-end: move repeated inline CSS styles to main.css
dbetm Mar 14, 2026
0f370ec
refactor: take into account comments from #42
dbetm Mar 14, 2026
40249d3
fix: aircraft emoji direction on map
dbetm Mar 16, 2026
8738291
docs: remove MD files related to new changes and obsolete changes
dbetm Mar 16, 2026
171009f
refactor: use km as unit for results - friendly for most people
dbetm Mar 23, 2026
47a6ece
refactor: improve targets handling
dbetm Mar 28, 2026
d107aa6
feat: encapsulate ADSB providers to integrate Airlabs client easier
dbetm Mar 28, 2026
db19f6c
feat: persist bounding box used by user in local storage
dbetm Apr 14, 2026
6c15d1e
feat: only check weather if there's targets in the sky
dbetm Apr 15, 2026
8ea29b4
feat: simplify background transit monitor - multiplatorm
dbetm Apr 25, 2026
a9f1192
refactor: rename menubar_monitor to background_monitor.py
dbetm Apr 25, 2026
c6306a4
feat: show flight id tooltip on plane hover
dbetm Apr 25, 2026
0a2543e
fix: altitude bar had an offset, showing markers in the incorrect pos…
dbetm Apr 26, 2026
2bdac2c
feat: make sure default min altitude is 15 for default
dbetm Apr 26, 2026
9e3faf0
feat: config wizard was simplified and now ask for pushbullet notific…
dbetm Apr 27, 2026
9fca150
refactor: desktop notifications weren't working properly, were delete…
dbetm Apr 28, 2026
5ecec92
refactor: remove active tracking - it isn't realiable for free tier A…
dbetm Apr 28, 2026
319aad0
feat: complete gallery feature: list, upload, update and delete trans…
dbetm Apr 29, 2026
a12c94f
feature: display test emoji when the server is in test mode
dbetm Apr 29, 2026
5d1ce8c
feat: check weather now is optional
dbetm Apr 30, 2026
326cece
refactor: remove outdated/non-used code
dbetm Apr 30, 2026
f0308f0
refactor: format code
dbetm Apr 30, 2026
808da69
docs: update README for Flymoon 2.0
dbetm May 1, 2026
2343310
fix: don't log possible sensitive data (observer coordinates)
dbetm May 1, 2026
acc680a
sec: upgrade dependencies with reported vulnerabilities
dbetm May 1, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 11 additions & 5 deletions .env.mock
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
# ADSB providers
AEROAPI_API_KEY=
AIRLABS_API_KEY=

# BOUNDING BOX OF AREA TO CHECK
# lower left
LAT_LOWER_LEFT=21.659
LONG_LOWER_LEFT=-105.22
LAT_LOWER_LEFT=
LONG_LOWER_LEFT=
# upper right
LAT_UPPER_RIGHT=24.803
LONG_UPPER_RIGHT=-102.194
LAT_UPPER_RIGHT=
LONG_UPPER_RIGHT=

# Push notifications
PUSH_BULLET_API_KEY=
PUSH_BULLET_API_KEY=

# Weather checking
OPENWEATHER_API_KEY=
CLOUD_COVER_THRESHOLD=85
53 changes: 53 additions & 0 deletions .github/workflows/clamav-scan.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
name: ClamAV-Scan

on:
pull_request:
branches: [main, dev]

jobs:
clamav-scan:
runs-on: ubuntu-latest
steps:
- name: Checkout code from PR
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Install ClamAV
run: |
sudo apt-get update
sudo apt-get install -y clamav clamav-daemon

- name: Update hashes database
run: |
sudo systemctl stop clamav-freshclam || true
sudo freshclam

- name: Get files added or updated
id: changed
run: |
git fetch origin ${{ github.base_ref }} --depth=1
git diff --name-only origin/${{ github.base_ref }}...HEAD > changed-files.txt
cat changed-files.txt

- name: Scan files
run: |
cat changed-files.txt | xargs -r clamscan --infected --alert-broken \
2>&1 | tee scan-results.txt

- name: Verify results
run: |
if grep -q "Infected files: 0" scan-results.txt; then
echo "✅ No threats found"
else
echo "🚨 Infected files were detected!"
grep "FOUND" scan-results.txt || true
exit 1
fi

- name: Upload report (when it has failed)
if: failure()
uses: actions/upload-artifact@v4
with:
name: virus-scan-report
path: scan-results.txt
10 changes: 9 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -164,9 +164,17 @@ cython_debug/
# data
de421.bsp
notes.txt
dev-notes.txt
data/possible-transits/*.csv
data/possible-transits/log-backup.txt
static/gallery/**/*

# tests
tests/test_results.json

# misc
exp.ipynb
*.DS_Store
*.DS_Store

# VSCode
.vscode/*
17 changes: 17 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Changelog

## Flymoon 2.0
Released May 2026

Special thanks to **Tom Harnish** for his contributions, ideas, and feedback that shaped several features in this release.

**What's new:**
1. Transit algorithm uses angular separation for a more accurate possibility level
2. Dual target tracking
3. Non-transit values now shown in the table
4. Optional weather check
5. Setup wizard
6. Headless monitor mode (no browser required)
7. Map view — aircraft positions, direction, and altitude
8. Support for Airlabs as an alternative ADS-B provider (1,000 free API calls/month)
9. Personal gallery to organize transit photos
8 changes: 8 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,12 @@ create-env:
@$(CMD_CHECK_ENV)


run:
@( \
$(CMD_ACTIVATE_VENV) || exit 1; \
python3 app.py; \
)



setup: create-env install
158 changes: 70 additions & 88 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,147 +1,129 @@
# Flymoon

A web app to run locally on a LAN network that checks for possible transits over the Moon or the Sun (up to 15 minutes ahead).
A web app to run locally on a LAN network that checks for possible transits over the Moon or the Sun (up to several minutes ahead).

Get flight data from an existing API.
Get flight data from an existing ADSB provider API.

You need to set coordinates for an area to check flights as a bounding box, input your position, choose a target (Moon or Sun), and then the app will compute future flight positions and check intersections with the target, which is called a transit.
![](data/assets/transit_example.jpg)

![](data/assets/flymoon2.png)
You need to set coordinates for an area to check flights as a bounding box, input your position, choose a target (Moon, Sun or both), and then the app will compute future flight positions and check intersections with the target, which is called a transit.

![](data/assets/flymoon2-0-0.png)

The results show the difference in alt-azimuthal coordinates. Typically, you can expect a likely transit when there's no change in elevation and the difference in altitude (alt diff) and azimuth (az diff) is less than a few grades for both. In such cases, the row of results will be highlighted. Yellow 🟡: Low possibility; Orange 🟠: Medium possibility; Green 🟢: High possibility.
The results show the future and minimum angular separation from aircraft and the chosen target. Typically, you can expect a likely transit when there's expected a lower angular separation, no change in elevation and the difference in altitude (alt diff) and azimuth (az diff, both not in all cases) is less than a few degrees for both. In such cases, the row of results will be highlighted:

| Color | Possibility |
|---|---|
| 🟡 Yellow | Low |
| 🟠 Orange | Medium |
| 🟢 Green | High |


**Main features**
1. Check transits on demand (user click on _Check_ button)
2. Check transits on Auto mode (each X chosen minutes the app checks, send push notification and sounds alert)
3. Display aircrafts over a map (position, direction and altitude, highlighed when a transit is predicted)
4. Display results, ordered by more probable transits to less probable ones
5. Check weather, min altitude and targets above horizon before getting API flight data
6. Personal gallery (you can organize your own collection of transits)
7. Background monitor (run Flymoon in auto mode without a browser, only the Terminal is required)
--------


## Setup
## Setup & Configuration

**Pre-requisites**
See [SETUP.md](SETUP.md) for full installation and configuration instructions (interactive wizard and manual setup).

- Python +3.9
- Download or clone this project from GitHub (if you download a zip file, please extract it first, please).

**Linux distros and MacOS**
--------

1) Run setup, this will create a virtual environment and install required python libraries.

```shell
make setup
```
## Usage

2) Activate virtual env.
### Web app

```shell
source .venv/bin/activate
```

**Windows**
Activate venv and launch the server:

1) Open the CMD and move to the project path
2) Run this command to create the `.env` file:
```shell
copy .env.mock .env
```
3) Create a virtual environment:
```shell
python -m venv .venv
```
4) Activate the virtual environment:
```shell
.venv\Scripts\activate
```
5) Install all the required python dependencies:
```shell
pip install -r requirements.txt
```

**Configuration**
# macOS/Linux
source .venv/bin/activate && python3 app.py

Open the `.env` file. You may need to display the hidden files.

In Windows, if you don't have a text editor to open the `.env` file, you can download and install [Notepad++](https://notepad-plus-plus.org/downloads/)
# Windows
.venv\Scripts\activate && python app.py
```

1) Set `AEROAPI_API_KEY`. Sign up on [FlightAware AeroAPI](https://www.flightaware.com/commercial/aeroapi/) and use the [Personal free tier](https://www.flightaware.com/aeroapi/signup/personal) to generate an API KEY.
Access it from any device on the same network (the LAN address is printed on startup):
- From another device: `http://192.168.x.x:8000`
- From the host: `http://localhost:8000`

2) Set the area of flights to check. I strong suggest to cover a 15 min area. This must be a bounding box, using latitudes and longitudes. Set `LAT_LOWER_LEFT`, `LONG_LOWER_LEFT`, `LAT_UPPER_RIGHT`, and `LONG_UPPER_RIGHT` appropriately.
Enter your latitude, longitude and elevation (saved in local storage). Use [MAPS.ie](https://www.maps.ie/coordinates.html) or Google Maps to get your coordinates.

3) (Optional) When using the auto mode If you want to receive notifications in your smartphone, you can get an API KEY from [Pushbucket platform](https://www.pushbullet.com/) and then set `PUSH_BULLET_API_KEY`. To get it, create an account, install the app in your phone and go to *Settings* > *Create Access Token*.
**Key controls:**
- **Check** — compute transits now
- **Auto** — repeat every X minutes; plays a sound and sends a push notification on medium/high probability transits
- **Target icon** — toggle between Moon, Sun, and Auto mode (tracks whichever is above the horizon)
- **Map button** — interactive map with your position, bounding box, azimuth arrows, and aircraft (◆ = predicted transit)

Click a table row or map aircraft to cross-highlight between them.

![](data/assets/bounding-box-example.png)
**Weather filtering:** if `OPENWEATHER_API_KEY` is set in `.env`, cloud cover is checked before each run (threshold: `CLOUD_COVER_THRESHOLD`, default 85%).


--------


## Usage
## Background Monitor

Run Flymoon in auto mode from the terminal, no browser needed.

**Activate venv**

**macOS/Linux**
```shell
source .venv/bin/activate
python3 monitor.py --lat <LAT> --long <LONG> --elev <ELEV> [options]
```

For Windows you can use:
```shell
.venv\Scripts\activate
```

Launch the web server from a terminal.

```shell
python3 app.py
```

Windows:
**Windows**
```shell
python app.py
python windows_monitor.py
```

The IP address in LAN network will be displayed, use it to access from any device inside the same network.

Example: `http://192.168.3.199:8000`

**Input your position (coordinates)**

I suggest using [MAPS.ie](https://www.maps.ie/coordinates.html#google_vignette) or [Google Maps](https://maps.google.com/). The values will be saved in local storage, so you won't need to type them again next time if you're in the same location.

**Options for `monitor.py`:**

**Compute possible transits**

Click on Go! button to display results. Each row will include differences in alt-azimuthal coordinates only if it’s a possible transit. If the difference is enough small, the row will be highlighted in yellow, orange or green color (less probable to more probable).

**Compute possible transits every X minutes**

Click on Auto button, which will require a time in minutes, then the web app will check for transits every X minutes, it there's at leat one possible transit then a sound alert will be played along the sending of a push notification if it was configured (only medium to high probable flighs are notified).

**Change target**

Tap into the target icon and it'll toggle between Sun and Moon.
| Argument | Default | Description |
|---|---|---|
| `--lat` | required | Observer latitude |
| `--long` | required | Observer longitude |
| `--elev` | required | Observer elevation (meters) |
| `--target` | `auto` | `moon`, `sun`, or `auto` |
| `--interval` | `12` | Check interval in minutes |
| `--adsb` | `flightaware-aeroapi` | ADS-B provider (`flightaware-aeroapi` or `airlabs`) |
| `--min-alt` | `15` | Minimum target altitude (degrees) |
| `--notify` | off | Send push notifications |
| `--weather` | off | Check weather before each run |
| `--test` | off | Test mode |


--------


## Limitations

1) Computing the moment when there is a minimum difference between a plane and the target in alt-azimuthal coordinates is a numerical approach. Perhaps there could be an analytical way to optimize it.
1) Computing the moment when there is a minimum angular separation between a plane and the target is a numerical approach. Perhaps there could be an analytical way to optimize it.

2) The app assumes that airplanes maintain a constant speed and direction. However, changes to these factors within the 15-minute observation window can alter the ETA and potentially disrupt the predicted transit.
2) The app assumes that airplanes maintain a constant speed and direction. However, changes to these factors within a several-minute observation window can alter the ETA and potentially disrupt the predicted transit.


--------


## Contribute

This web app is still under active testing. If you want to fix something, improve it, or make a suggestion, feel free to open a Pull Request or an issue.
This web app is still under active testing. If you want to fix something, improve it, or make a suggestion, feel free to open a Pull Request or an issue. Please, don't forget testing proposal code before opening a PR.


**Share your epic picture!**
-------

See [CHANGELOG.md](CHANGELOG.md) for release history.

I'd love to watch some transit picture taken with the help of this tool. So, post it on this [issue](https://github.com/dbetm/flymoon/issues/21).

Pro-tip: You can use the Fightradar24 app to complement this web app.
**Share your epic picture!**

I'd love to watch some transit picture taken with the help of this tool. So, post it on this [issue](https://github.com/dbetm/flymoon/issues/21).
Loading
Loading