diff --git a/.env b/.env new file mode 100644 index 0000000..8a75e01 --- /dev/null +++ b/.env @@ -0,0 +1,3 @@ +POSTGRES_DB=spacecom +POSTGRES_USER=spacecom +POSTGRES_PASSWORD=spacecom \ No newline at end of file diff --git a/backend/Dockerfile b/backend/Dockerfile new file mode 100644 index 0000000..f274166 --- /dev/null +++ b/backend/Dockerfile @@ -0,0 +1,8 @@ +FROM python:3.11-slim + +WORKDIR /app +COPY . . + +RUN pip install fastapi uvicorn + +CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"] diff --git a/backend/app/__pycache__/main.cpython-311.pyc b/backend/app/__pycache__/main.cpython-311.pyc new file mode 100644 index 0000000..2de66ad Binary files /dev/null and b/backend/app/__pycache__/main.cpython-311.pyc differ diff --git a/backend/app/main.py b/backend/app/main.py new file mode 100644 index 0000000..f906b11 --- /dev/null +++ b/backend/app/main.py @@ -0,0 +1,65 @@ +# backend/main.py + +from fastapi import FastAPI +from fastapi.responses import JSONResponse +from fastapi.middleware.cors import CORSMiddleware + +app = FastAPI() + + +app.add_middleware( + CORSMiddleware, + allow_origins=[ + "http://aegis.sbln.bxl.skynav.cloud:8080" + ], + allow_credentials=True, + allow_methods=["*"], + allow_headers=["*"], +) + + + +@app.get("/czml/test") +def get_dummy_czml(): + czml = [ + { + "id": "document", + "name": "Dummy orbit test", + "version": "1.0" + }, + { + "id": "sat1", + "name": "TestSat-001", + "availability": "2025-06-29T00:00:00Z/2025-06-29T00:04:00Z", + "position": { + "interpolationAlgorithm": "LAGRANGE", + "interpolationDegree": 5, + "referenceFrame": "INERTIAL", + "epoch": "2025-06-29T00:00:00Z", + "cartesian": [ + 0, 7000000, 0, 0, + 60, 7050000, 20000, 0, + 120, 7100000, 40000, 0, + 180, 7150000, 60000, 0, + 240, 7200000, 80000, 0 + ] + }, + "point": { + "pixelSize": 10, + "color": { + "rgba": [0, 255, 255, 255] + } + }, + "label": { + "text": "TestSat-001", + "font": "12pt sans-serif", + "style": "FILL", + "outlineWidth": 2, + "verticalOrigin": "BOTTOM", + "pixelOffset": { + "cartesian2": [0, -20] + } + } + } + ] + return JSONResponse(content=czml) diff --git a/db/schema.sql b/db/schema.sql new file mode 100644 index 0000000..6d2699e --- /dev/null +++ b/db/schema.sql @@ -0,0 +1,44 @@ +-- Enable extensions +CREATE EXTENSION IF NOT EXISTS postgis; +CREATE EXTENSION IF NOT EXISTS timescaledb; + +-- Main object catalog (replaces 'satellites') +CREATE TABLE objects ( + id SERIAL PRIMARY KEY, + name TEXT NOT NULL, + norad_id INT UNIQUE NOT NULL, + intl_designator TEXT, + launch_date DATE, + orbit_type TEXT +); + +CREATE TABLE orbits ( + object_id INT REFERENCES objects(id), + ts TIMESTAMPTZ NOT NULL, + position GEOGRAPHY(POINT, 4326), + altitude_km DOUBLE PRECISION, + velocity_kms DOUBLE PRECISION, + PRIMARY KEY (object_id, ts) +); +SELECT create_hypertable('orbits', 'ts', if_not_exists => TRUE); + +-- Conjunction Data Messages / alerts +CREATE TABLE conjunctions ( + id SERIAL PRIMARY KEY, + primary_object INT REFERENCES objects(id), + secondary_object INT, + tca TIMESTAMPTZ, -- Time of Closest Approach + miss_distance_km DOUBLE PRECISION, + risk_level TEXT, + poc DOUBLE PRECISION -- Probability of Collision +); + +-- Re-entry prediction windows and footprints +CREATE TABLE reentry_predictions ( + id SERIAL PRIMARY KEY, + object_id INT REFERENCES objects(id), + window_start TIMESTAMPTZ, + window_end TIMESTAMPTZ, + footprint GEOGRAPHY(POLYGON, 4326), + notes TEXT +); diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..dd61a17 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,43 @@ +version: '3.8' + +services: + frontend: + image: nginx:alpine + container_name: spacecom-frontend + volumes: + - ./frontend/public:/usr/share/nginx/html:ro + ports: + - "8080:80" + restart: unless-stopped + + backend: + build: ./backend + container_name: spacecom-backend + ports: + - "8000:8000" + depends_on: + - db + environment: + - DB_URL=postgresql://spacecom:spacecom@db:5432/spacecom + volumes: + - ./backend:/app + restart: unless-stopped + + + db: + image: timescaledev/timescaledb-ha:pg17 + container_name: spacecom-db + ports: + - "5432:5432" + environment: + POSTGRES_DB: spacecom + POSTGRES_USER: spacecom + POSTGRES_PASSWORD: uCV4@YUCuR9kX.MQaxp2 + volumes: + - pgdata:/var/lib/postgresql/data + - ./db/schema.sql:/docker-entrypoint-initdb.d/schema.sql:ro + restart: unless-stopped + + +volumes: + pgdata: diff --git a/frontend/public/app.js b/frontend/public/app.js new file mode 100644 index 0000000..631298c --- /dev/null +++ b/frontend/public/app.js @@ -0,0 +1,56 @@ +// app.js +import { API_BASE_URL } from "./config.js"; + +console.log('🔥 app.js loaded'); + +// Optional: set Ion token (if using Ion) +Cesium.Ion.defaultAccessToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJkZjk0MDM3OC1kZDE1LTRhMjItODg3NC1iMjUzNmI1NzUwMjgiLCJpZCI6MzE2ODE3LCJpYXQiOjE3NTEyMzM5OTh9.UDLPRYrMOcLAjuCWAZa2f159W0bULWSMNv3iiQcAAP8'; + + + +// Create empty viewer with no base layer +const viewer = new Cesium.Viewer("cesiumContainer", { + imageryProvider: false, + baseLayerPicker: false, + terrainProvider: new Cesium.EllipsoidTerrainProvider() +}); + +console.log('✅ Viewer created:', viewer); + +// Create OSM imagery layer +const osmLayer = new Cesium.ImageryLayer( + new Cesium.UrlTemplateImageryProvider({ + url: "https://a.tile.openstreetmap.org/{z}/{x}/{y}.png", + credit: "© OpenStreetMap contributors" + }) +); + +// Add imagery layer manually +viewer.imageryLayers.add(osmLayer); + +console.log('✅ OSM Layer Added:', osmLayer); +console.log('✅ Imagery Layers:', viewer.imageryLayers.length); + + + +// Load CZML from FastAPI endpoint +fetch(`${API_BASE_URL}/czml/test`) + .then(response => { + if (!response.ok) { + throw new Error("Network response was not ok"); + } + return response.json(); + }) + .then(czmlData => { + // Load the CZML data into a Cesium data source + const czmlSource = new Cesium.CzmlDataSource(); + czmlSource.load(czmlData).then(() => { + viewer.dataSources.add(czmlSource); + viewer.zoomTo(czmlSource); + }); + }) + .catch(error => { + console.error("Failed to load CZML:", error); + }); + + diff --git a/frontend/public/config.js b/frontend/public/config.js new file mode 100644 index 0000000..a09dbb3 --- /dev/null +++ b/frontend/public/config.js @@ -0,0 +1,2 @@ +// config.js +export const API_BASE_URL = "http://aegis.sbln.bxl.skynav.cloud:8000"; diff --git a/frontend/public/index.html b/frontend/public/index.html new file mode 100644 index 0000000..b073e73 --- /dev/null +++ b/frontend/public/index.html @@ -0,0 +1,69 @@ + + + + + SkyNav SpaceCom + + + + + + + + + + + + +
+

🛰️ SkyNav SpaceCom

+

Real-Time Orbit & Re-entry Monitoring Platform

+
+ +
+ + + + + diff --git a/worker/fetch.py b/worker/fetch.py new file mode 100644 index 0000000..e992ae4 --- /dev/null +++ b/worker/fetch.py @@ -0,0 +1,2 @@ +# Placeholder for TLE or CDM ingestion logic +print("Worker fetch script ready. Implement data polling here.") \ No newline at end of file