base sys done. shift to vs code

This commit is contained in:
Duncan Auld
2025-06-30 05:17:50 +00:00
parent 05f87e04f9
commit 2c49d7cd5c
10 changed files with 292 additions and 0 deletions

3
.env Normal file
View File

@@ -0,0 +1,3 @@
POSTGRES_DB=spacecom
POSTGRES_USER=spacecom
POSTGRES_PASSWORD=spacecom

8
backend/Dockerfile Normal file
View File

@@ -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"]

Binary file not shown.

65
backend/app/main.py Normal file
View File

@@ -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)

44
db/schema.sql Normal file
View File

@@ -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
);

43
docker-compose.yml Normal file
View File

@@ -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:

56
frontend/public/app.js Normal file
View File

@@ -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);
});

View File

@@ -0,0 +1,2 @@
// config.js
export const API_BASE_URL = "http://aegis.sbln.bxl.skynav.cloud:8000";

View File

@@ -0,0 +1,69 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>SkyNav SpaceCom</title>
<!-- CesiumJS -->
<script src="https://cesium.com/downloads/cesiumjs/releases/1.110/Build/Cesium/Cesium.js"></script>
<link href="https://cesium.com/downloads/cesiumjs/releases/1.110/Build/Cesium/Widgets/widgets.css" rel="stylesheet">
<!-- Google Font (Montserrat) -->
<link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@400;600&display=swap" rel="stylesheet">
<style>
html, body {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
overflow: hidden;
font-family: 'Montserrat', sans-serif;
background-color: #000;
}
#branding {
height: 6em;
background: linear-gradient(to right, #1e124f, #2e1a6d); /* SkyNav deep purple gradient */
color: #fff;
padding: 1em;
text-align: center;
border-bottom: 2px solid #352f66;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.5);
}
#branding h1 {
margin: 0;
font-size: 1.8em;
font-weight: 600;
letter-spacing: 1px;
}
#branding p {
margin: 0.3em 0 0;
font-size: 1em;
color: #ccc;
}
#cesiumContainer {
position: absolute;
top: 8em;
left: 0;
right: 0;
bottom: 0;
}
</style>
</head>
<body>
<header id="branding">
<h1>🛰️ SkyNav SpaceCom</h1>
<p>Real-Time Orbit & Re-entry Monitoring Platform</p>
</header>
<div id="cesiumContainer"></div>
<script type="module" src="app.js"></script>
</body>
</html>

2
worker/fetch.py Normal file
View File

@@ -0,0 +1,2 @@
# Placeholder for TLE or CDM ingestion logic
print("Worker fetch script ready. Implement data polling here.")