Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
164 commits
Select commit Hold shift + click to select a range
86b7873
Phase 3 V.1
carsonmwolfe Mar 23, 2026
60dde6a
pi dimension changes
carsonmwolfe Mar 24, 2026
3b395f1
test2
carsonmwolfe Mar 24, 2026
d6c2ff8
screen fixes
carsonmwolfe Mar 26, 2026
6f110ce
desync issue resolved
carsonmwolfe Mar 26, 2026
8ebf01b
info bar change
carsonmwolfe Mar 26, 2026
fbaa6a1
bug fixes
carsonmwolfe Mar 27, 2026
418a4de
test
carsonmwolfe Mar 27, 2026
ee07cd3
test 2
carsonmwolfe Mar 27, 2026
8578678
test3
carsonmwolfe Mar 27, 2026
c0c650a
settings page changed
carsonmwolfe Mar 28, 2026
cb36573
UI updates, weather fix, window fix, settings resize
carsonmwolfe Mar 28, 2026
e330297
updated rocket atlas
carsonmwolfe Mar 28, 2026
49fc6f7
adding some API fixes and updates.
carsonmwolfe Mar 29, 2026
a99e5e2
Complete Overhaul of API interface, changes to how api is handeled to…
carsonmwolfe Mar 31, 2026
1f36dad
large changes to mission page, and main index page for better visuals.
carsonmwolfe Apr 2, 2026
b4084ba
Add Tianlong3 and Soyuz5 rocket assets
carsonmwolfe Apr 2, 2026
0e7d356
layer changes
carsonmwolfe Apr 2, 2026
6595232
Add .gitignore to exclude data_cache.json
carsonmwolfe Apr 2, 2026
3ef9e00
Fix Tianlong3 asset filename case for Linux
carsonmwolfe Apr 2, 2026
68e419c
Remove Kinetica2 asset reference, fix case issues
carsonmwolfe Apr 2, 2026
8545100
Mockup: VIF (opt2) + background pad (opt1) replacing VAB/MLP
carsonmwolfe Apr 2, 2026
0803ba2
reversion
carsonmwolfe Apr 2, 2026
120c936
changes the main index page and changes to mission orbit page.
carsonmwolfe Apr 3, 2026
f7e51db
rocket positioning and performance fixes.
carsonmwolfe Apr 3, 2026
be5ec66
hopefully final v.2 update
carsonmwolfe Apr 3, 2026
b713cbc
fixed some backend issues.
carsonmwolfe Apr 4, 2026
3c969ad
created an auto updater script to pull from github
carsonmwolfe Apr 4, 2026
f3a57e3
updated update.sh
carsonmwolfe Apr 4, 2026
be8be96
add notify.py and update update.sh
carsonmwolfe Apr 4, 2026
ecce4ec
update.sh pulls from Phase3, add notify.py
carsonmwolfe Apr 4, 2026
d931d6a
health checks on pi
carsonmwolfe Apr 4, 2026
4d3b5f9
health formatting
carsonmwolfe Apr 4, 2026
8bff7e8
updates to health checks
carsonmwolfe Apr 4, 2026
f15e079
updated SS
carsonmwolfe Apr 4, 2026
5e90219
next
carsonmwolfe Apr 4, 2026
27bbec6
positional fixes for falcon9, moon scale fixes, exhaust fixes, health…
carsonmwolfe Apr 6, 2026
bca0157
health checks
carsonmwolfe Apr 6, 2026
503107c
health checks 2
carsonmwolfe Apr 6, 2026
1768d33
remove data_cache.json from tracking
carsonmwolfe Apr 6, 2026
8a07428
health checks 3
carsonmwolfe Apr 6, 2026
bb9688d
health checks 4
carsonmwolfe Apr 6, 2026
921b300
overally process improvements, and performance improvements for publi…
carsonmwolfe Apr 6, 2026
c6a0497
brightness bug fixes
carsonmwolfe Apr 6, 2026
cbc4cab
fixed VAB haze box
carsonmwolfe Apr 6, 2026
fb84d14
wifi page redesign, bug fixes, update.sh quote fix
carsonmwolfe Apr 6, 2026
619bf69
fixed VAB haze
carsonmwolfe Apr 6, 2026
f7af3ae
server updates
carsonmwolfe Apr 6, 2026
60b89f2
wifi changes
carsonmwolfe Apr 7, 2026
3117a03
final bug updates
carsonmwolfe Apr 7, 2026
4ec6a40
updates to fonts
carsonmwolfe Apr 7, 2026
06b4907
update.sh: use hard reset instead of stash to always apply latest
carsonmwolfe Apr 8, 2026
8d048ea
mission: increase orbit pill font size 5px → 7px
carsonmwolfe Apr 8, 2026
9e19a6c
settings: add SITE time option (UTC | SITE | LOCAL) for clock and sky…
carsonmwolfe Apr 8, 2026
cc5ce80
update.sh: clear chromium cache + auto reload on update
carsonmwolfe Apr 8, 2026
ac365ee
settings: 3-col grid, brightness full-width on top, no scrollbar
carsonmwolfe Apr 8, 2026
e461a27
app.js: remove umbilical arms from pad 1
carsonmwolfe Apr 8, 2026
b8a5977
app.js: remove background pad umbilicals, restore main pad umbilicals
carsonmwolfe Apr 8, 2026
db2b261
app.js: fix ReferenceError from missing rocketRightX declaration
carsonmwolfe Apr 8, 2026
a7c8dbf
app.js: add scaled umbilicals to background pad
carsonmwolfe Apr 8, 2026
df632e5
app.js: fix bg pad umbilical x positions to match rocket body
carsonmwolfe Apr 8, 2026
1c9f138
app.js: fix bg pad umbilicals using actual rocket x position
carsonmwolfe Apr 8, 2026
ba4c5f1
app.js: remove bg pad umbilicals, clean up
carsonmwolfe Apr 8, 2026
5a4c88d
bug fixes: wifi net_id validation, infobar null guard, localStorage s…
carsonmwolfe Apr 8, 2026
1103377
hide cursor on all pages
carsonmwolfe Apr 8, 2026
0dc5748
server: route launch fetches through DO relay, ping relay for dashboa…
carsonmwolfe Apr 8, 2026
48be9b8
update.sh: force kill port 5001 before restart
carsonmwolfe Apr 8, 2026
5eb2a4f
server: remove cape-only location filter, show next 5 global launches
carsonmwolfe Apr 8, 2026
c6e4387
settings: always show unit ID field
carsonmwolfe Apr 9, 2026
ef0c4a1
server: try multiple network interfaces for unit ID; remove unit ID i…
carsonmwolfe Apr 9, 2026
5429d52
dashboard: command queue (restart/update/reboot per Pi), fix stale th…
carsonmwolfe Apr 9, 2026
8e1b2b5
settings: remove unit ID input; app: grey umbilical cables
carsonmwolfe Apr 9, 2026
1741da0
update.sh: re-apply execute permission after git reset
carsonmwolfe Apr 9, 2026
d44c929
server: separate 30s command poll thread, fix reboot, remove restart …
carsonmwolfe Apr 9, 2026
75806de
update.sh: set executable bit in git
carsonmwolfe Apr 9, 2026
6fca426
setup.sh: one-command fresh Pi setup script
carsonmwolfe Apr 11, 2026
1f0ccd4
settings: timezone dropdown; server: timezone API endpoint; setup: ti…
carsonmwolfe Apr 11, 2026
1c50fb5
positioner: full rocket positioner with all rockets, sliders, config …
carsonmwolfe Apr 12, 2026
7447e6e
Rocket positioning overhaul — all 25 rockets tuned
carsonmwolfe Apr 12, 2026
f7e42bc
Flame trench overhaul, fleet management improvements, bug fixes
carsonmwolfe Apr 13, 2026
53ad32a
updates
carsonmwolfe Apr 13, 2026
2916f2d
Reduce command poll interval 30s → 5s for near-instant remote commands
carsonmwolfe Apr 13, 2026
095f9e7
Extend Pi notification display from 5s to 15s
carsonmwolfe Apr 13, 2026
01e45bf
Add boot splash page — shows while server starts, auto-redirects when…
carsonmwolfe Apr 13, 2026
0b7cd6e
Update script posts result notification: already up to date or update…
carsonmwolfe Apr 13, 2026
bddcc84
Fix Pi notification missing on update: persist to file to survive ser…
carsonmwolfe Apr 13, 2026
b47f9e6
Restore DATA UPDATED notification on fresh API fetch
carsonmwolfe Apr 13, 2026
188dc3b
Restyle data-updated notification to match app design system
carsonmwolfe Apr 13, 2026
dd58eaf
Persist currentIdx and mid-flight state across page reloads/updates
carsonmwolfe Apr 13, 2026
4b23182
Remove duplicate update notification — only show completion message
carsonmwolfe Apr 13, 2026
ea02a5d
Add RangeTrack logo to boot splash page
carsonmwolfe Apr 13, 2026
2503407
Add server watchdog: redirect to boot page if server goes down mid-se…
carsonmwolfe Apr 13, 2026
64c4fbc
Reduce watchdog poll interval and fix notification surviving page rel…
carsonmwolfe Apr 13, 2026
efb0781
Fix notification bar resetting — deduplicate repeated poll responses
carsonmwolfe Apr 13, 2026
52b7bfe
Fix restart button crashing browser without relaunching
carsonmwolfe Apr 13, 2026
6b139fc
Remove duplicate update notifications
carsonmwolfe Apr 13, 2026
34b74d7
Fix restart button — navigate to / instead of killing Chromium
carsonmwolfe Apr 13, 2026
bc22960
Fix boot.html stuck forever — use no-cors fetch from file:// page
carsonmwolfe Apr 13, 2026
1192bf6
Add robust startup script with supervisor and improve update reliability
carsonmwolfe Apr 13, 2026
dca8a1f
Fix boot.html probe — use image load instead of no-cors fetch
carsonmwolfe Apr 13, 2026
d8250d2
Add T-10 min alert, lock file, and fix script permissions
carsonmwolfe Apr 13, 2026
4d52a4f
Re-apply execute permission to start.sh after updates
carsonmwolfe Apr 13, 2026
3a045ba
Fix supervisor/updater race — check lock file before restarting server
carsonmwolfe Apr 13, 2026
236019e
Fix day/night cycle using wrong timezone and launch-site sunrise/sunset
carsonmwolfe Apr 14, 2026
35581bb
Fix sky always appearing daytime when cloudy/rainy/foggy
carsonmwolfe Apr 14, 2026
63a221b
Fix repeated update notifications and disable Chrome popups
carsonmwolfe Apr 14, 2026
abc232d
Fix health.py racing supervisor and update.sh on server restart
carsonmwolfe Apr 14, 2026
108fb65
Fix setup.sh and start.sh for newer Raspberry Pi OS
carsonmwolfe Apr 18, 2026
f35e4a2
Fix start.sh for newer Pi OS — set DISPLAY, clear Chromium singleton …
carsonmwolfe Apr 18, 2026
607766e
Fix start.sh for Wayland/labwc (Pi OS Bookworm/Trixie)
carsonmwolfe Apr 18, 2026
d724492
Fix Chromium GPU init on Wayland Pi — use --use-angle=gles
carsonmwolfe Apr 18, 2026
b600527
Clear all Chromium singleton files on startup to prevent lock conflicts
carsonmwolfe Apr 18, 2026
cfb9c0a
Fix singleton lock race and supervisor sudo failures
carsonmwolfe Apr 18, 2026
afb20ed
Fix Chromium keyring popup and reboot command
carsonmwolfe Apr 18, 2026
658606a
Launch Chromium with boot.html immediately on startup
carsonmwolfe Apr 18, 2026
0e50432
Auto-detect backlight path, drop sudo for brightness
carsonmwolfe Apr 18, 2026
dca76bd
Performance fixes: version-based reload, no xdotool, wifi timeout
carsonmwolfe Apr 18, 2026
a5c8873
Fix WiFi for Pi OS Trixie (NetworkManager replaces wpa_supplicant)
carsonmwolfe Apr 18, 2026
6e97404
Revamp WiFi page to use native squeekboard keyboard
carsonmwolfe Apr 18, 2026
d71330e
Fix reboot endpoint, optimize BootLOGO, misc
carsonmwolfe Apr 18, 2026
e0d6712
Remove snapshot polling, disable accessibility overhead, add log rota…
carsonmwolfe Apr 19, 2026
7b1768f
Code cleanup: remove dead code, consolidate fetch helpers, fix saveSe…
carsonmwolfe Apr 19, 2026
241578b
Add --enable-wayland-ime for on-screen keyboard on Pi 2
carsonmwolfe Apr 19, 2026
d4caa3c
Hold detection, RTLS booster animation, OSK keyboard, launch transiti…
carsonmwolfe Apr 19, 2026
03ea55e
Replace broken squeekboard D-Bus OSK with self-contained JS keyboard …
carsonmwolfe Apr 19, 2026
c1ef4af
Add RTLS booster return banner at bottom of canvas
carsonmwolfe Apr 19, 2026
682a222
Fix LAUNCHED + cooldown banner layout and readability
carsonmwolfe Apr 19, 2026
a571eb6
Fix testRTLS() to start at frame 80, skipping pre-delay
carsonmwolfe Apr 19, 2026
cb7560f
Fix RTLS banner not rendering — missing ctx.beginPath() before roundR…
carsonmwolfe Apr 19, 2026
b63c0b6
Rewrite RTLS banner to avoid path state issues
carsonmwolfe Apr 19, 2026
d193735
Remove RTLS banner
carsonmwolfe Apr 19, 2026
9df8a21
Add /api/notify polling so update notifications actually appear
carsonmwolfe Apr 19, 2026
9a546ee
Redesign wifi.html layout: top half info, bottom half keyboard
carsonmwolfe Apr 19, 2026
87f60ca
Increase keyboard font size 8px → 12px
carsonmwolfe Apr 19, 2026
887c83f
Add Pi nickname support to dashboard
carsonmwolfe Apr 19, 2026
6022549
Fix update reload on Wayland Pi: kill Chromium instead of version poll
carsonmwolfe Apr 19, 2026
f2f5e5b
Fix setup.sh: detect labwc vs lxsession, add wallpaper + taskbar config
carsonmwolfe Apr 19, 2026
909cdd2
Fix setup.sh for labwc/Wayland: correct wallpaper session, kill taskbar
carsonmwolfe Apr 19, 2026
16e9bbe
fix chromium package detection
carsonmwolfe Apr 19, 2026
247bf83
setup.sh: fix wallpaper reconfigure, taskbar autohide=1, remove boot …
carsonmwolfe Apr 19, 2026
ac101e4
setup.sh: revert autostart to match working Pi 2 config
carsonmwolfe Apr 19, 2026
a8c1a84
setup.sh: add default pcmanfm profile for wallpaper on Pi OS Trixie
carsonmwolfe Apr 19, 2026
93e3466
setup.sh: clean rewrite with all confirmed working fixes
carsonmwolfe Apr 19, 2026
3a3d768
setup.sh: hide desktop icons via .hidden file
carsonmwolfe Apr 19, 2026
d0d31f2
add New Glenn milestones from Blue Origin flight profile
carsonmwolfe Apr 20, 2026
bdc84d5
fix /api/device: try multiple network interfaces for MAC address
carsonmwolfe Apr 20, 2026
f6f9c59
fix LAUNCHED banner: center text to match box bounds
carsonmwolfe Apr 20, 2026
6f2201b
add T-1hr amber alert and auto-dim at night (10pm-6am)
carsonmwolfe Apr 20, 2026
6293156
readability pass: milestone fonts/contrast, info bar layout, weather …
carsonmwolfe Apr 22, 2026
b257094
fix weather panel: space out WIND/MPH/CLOUD labels
carsonmwolfe Apr 22, 2026
b86e232
fix weather number alignment and left panel spacing
carsonmwolfe Apr 22, 2026
72e1de3
readability polish: info bar layout, milestone position, t10 flash, e…
carsonmwolfe Apr 22, 2026
2ebe9b5
draw umbilicals behind rocket
carsonmwolfe Apr 22, 2026
81c37a7
numerous readability changes.
carsonmwolfe Apr 22, 2026
ee66879
UI polish, settings page overhaul, bug fixes, and health monitoring i…
carsonmwolfe Apr 23, 2026
158f9dc
settings changes
carsonmwolfe Apr 25, 2026
128bce1
Bump health.py screenshot timeout from 30s to 60s for slow Pi headles…
carsonmwolfe Apr 25, 2026
255714d
Fix headless Chromium screenshots on Pi: add --no-zygote flag, bump v…
carsonmwolfe Apr 25, 2026
f6e98c7
Disable gnome-keyring on Pi to prevent 'choose password' dialog on fi…
carsonmwolfe Apr 25, 2026
45304d4
Implement force update from Mission Control via /api/update endpoint
carsonmwolfe Apr 25, 2026
a95fd82
health: rate-limit alerts, rotate log, auto-provision on update
carsonmwolfe Apr 26, 2026
e3d7647
launches: larger card text, fix name truncation, fix weather spam
carsonmwolfe Apr 29, 2026
d9b8e68
feat: track launch T0 slips and display on card
carsonmwolfe Apr 30, 2026
af10fe6
launches: DELAYED badge + strikethrough original date on slipped laun…
carsonmwolfe Apr 30, 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
Binary file modified .DS_Store
Binary file not shown.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
website/
159 changes: 159 additions & 0 deletions api.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
import requests, time, threading
from flask import Flask, jsonify, request

app = Flask(__name__)

_cache = {}
_cache_lock = threading.Lock()
CACHE_TTL = 300 # 5 minutes

LL2_BASE = "https://ll.thespacedevs.com/2.2.0"
WEATHER_BASE = "https://api.open-meteo.com/v1"

SITES = {
'cape': {'lat': 28.5623, 'lon': -80.5774},
'vandenberg': {'lat': 34.7420, 'lon': -120.5724},
}

def _fetch_launches():
try:
r = requests.get(f"{LL2_BASE}/launch/upcoming/",
params={'limit': 10, 'format': 'json'},
timeout=15)
return r.json().get('results', [])
except Exception as e:
print(f"Launch fetch error: {e}")
return None

def _fetch_weather(lat, lon):
try:
r = requests.get(f"{WEATHER_BASE}/forecast", params={
'latitude': lat, 'longitude': lon,
'current': 'temperature_2m,windspeed_10m,cloudcover,weathercode',
'daily': 'sunrise,sunset',
'timezone': 'auto', 'forecast_days': 1
}, timeout=10)
return r.json()
except Exception as e:
print(f"Weather fetch error: {e}")
return None

def _refresh():
with _cache_lock:
now = time.time()
if now - _cache.get('_fetched_at', 0) < CACHE_TTL:
return
launches = _fetch_launches()
if launches is not None:
_cache['launches'] = launches
for site_id, site in SITES.items():
wx = _fetch_weather(site['lat'], site['lon'])
if wx:
_cache[f'weather_{site_id}'] = wx
_cache['_fetched_at'] = now
print(f"Cache refreshed at {time.strftime('%H:%M:%S')}")

def _bg_refresh():
while True:
try:
_refresh()
except Exception as e:
print(f"BG refresh error: {e}")
time.sleep(60)

@app.route('/api/launches')
def launches():
_refresh()
return jsonify(_cache.get('launches', []))

@app.route('/api/weather')
def weather():
site = request.args.get('site', 'cape')
_refresh()
return jsonify(_cache.get(f'weather_{site}', {}))

@app.route('/api/health')
def health():
return jsonify({'ok': True, 'cached_at': _cache.get('_fetched_at', 0)})

# ── Unit tracking ──────────────────────────────────────────────────────────────

_units = {}
_commands = {} # unit_id -> list of pending command dicts
_acks = {} # unit_id -> list of {command, ts}
_cmd_lock = threading.Lock()

UNIT_TTL = 3600 # drop units not seen in 1h

@app.route('/api/unit/ping', methods=['POST'])
def unit_ping():
data = request.get_json() or {}
unit_id = data.get('unit_id', 'unknown')
now = time.time()
# Expire stale units
stale = [k for k, v in _units.items() if now - v.get('last_seen', 0) > UNIT_TTL]
for k in stale:
del _units[k]
_units[unit_id] = {**data, 'last_seen': now}
return jsonify({'ok': True})

@app.route('/api/units')
def units():
now = time.time()
active = {k: v for k, v in _units.items() if now - v.get('last_seen', 0) < UNIT_TTL}
return jsonify(active)

@app.route('/api/unit/<unit_id>', methods=['DELETE'])
def delete_unit(unit_id):
_units.pop(unit_id, None)
return jsonify({'ok': True})

# ── Command queue ──────────────────────────────────────────────────────────────

@app.route('/api/unit/command', methods=['POST'])
def send_command():
"""Dashboard posts a command for a specific unit."""
data = request.get_json() or {}
unit_id = data.get('unit_id')
cmd = data.get('command') # 'restart', 'update', 'reboot'
if not unit_id or not cmd:
return jsonify({'ok': False, 'error': 'unit_id and command required'}), 400
with _cmd_lock:
if unit_id not in _commands:
_commands[unit_id] = []
_commands[unit_id].append({'command': cmd, 'queued_at': time.time()})
print(f"Command '{cmd}' queued for {unit_id}")
return jsonify({'ok': True})

@app.route('/api/unit/commands/<unit_id>')
def get_commands(unit_id):
"""Pi polls this to get pending commands."""
with _cmd_lock:
cmds = _commands.pop(unit_id, [])
return jsonify(cmds)

@app.route('/api/unit/ack', methods=['POST'])
def unit_ack():
"""Pi confirms a command was received and is executing."""
data = request.get_json() or {}
unit_id = data.get('unit_id')
cmd = data.get('command')
if unit_id and cmd:
_acks.setdefault(unit_id, []).append({'command': cmd, 'ts': time.time()})
return jsonify({'ok': True})

@app.route('/api/unit/acks/<unit_id>')
def get_acks(unit_id):
"""Dashboard polls this; clears on read."""
return jsonify(_acks.pop(unit_id, []))

@app.after_request
def add_cors(r):
r.headers['Access-Control-Allow-Origin'] = '*'
r.headers['Access-Control-Allow-Headers'] = 'Content-Type'
r.headers['Access-Control-Allow-Methods'] = 'GET, POST, OPTIONS'
return r

if __name__ == '__main__':
threading.Thread(target=_bg_refresh, daemon=True).start()
app.run(host='0.0.0.0', port=5000)
Binary file modified launch-timer/.DS_Store
Binary file not shown.
Binary file modified launch-timer/Phase2/.DS_Store
Binary file not shown.
15 changes: 15 additions & 0 deletions launch-timer/Phase2/.claude/settings.local.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"permissions": {
"allow": [
"Bash(curl -s http://localhost:5001/api/data)",
"Bash(python3 -m json.tool)",
"Bash(curl -s \"https://ll.thespacedevs.com/2.3.0/launches/upcoming/?limit=3&format=json\")",
"Bash(curl -s -X POST http://localhost:5001/api/launches/invalidate)",
"Bash(curl -v http://localhost:5000/)",
"Bash(python3 -c \":*)",
"Bash(git add:*)",
"Bash(git commit:*)",
"Bash(git push:*)"
]
}
}
3 changes: 3 additions & 0 deletions launch-timer/Phase2/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
data_cache.json
__pycache__/
*.pyc
Loading