Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
b195e5b
Merge pull request #32 from accius/Staging
MichaelWheeley Apr 2, 2026
2092e2c
add station altitude, minimum elevation settings
MichaelWheeley Apr 3, 2026
f84b472
consume station altitude
MichaelWheeley Apr 3, 2026
c23de1a
Merge pull request #33 from accius/Staging
MichaelWheeley Apr 3, 2026
39a4091
Merge branch 'feature/thai-language-dev' into feature/sat_predict_dev
MichaelWheeley Apr 3, 2026
7aa6c90
Merge pull request #34 from accius/Staging
MichaelWheeley Apr 3, 2026
080f59e
is visible only when exceeds min elevation
MichaelWheeley Apr 3, 2026
00a192e
satellite footprint disable green when elevation not exceeding minimum
MichaelWheeley Apr 3, 2026
9957a58
satellite details reorder and add subtle colored boxing
MichaelWheeley Apr 3, 2026
61c1478
minor correction to input variables
MichaelWheeley Apr 3, 2026
07d00c5
Merge pull request #35 from accius/Staging
MichaelWheeley Apr 4, 2026
1db9a8b
Merge branch 'feature/thai-language-dev' into feature/sat_predict_dev
MichaelWheeley Apr 4, 2026
2df9780
style highliting green background when satellite is visible
MichaelWheeley Apr 4, 2026
0ecd4b4
orbit predict
MichaelWheeley Apr 4, 2026
e1c967b
adjust table columns
MichaelWheeley Apr 4, 2026
6603c7b
make satellite details with scrollable by blocking propagation of mou…
MichaelWheeley Apr 5, 2026
67b3029
add time from now column
MichaelWheeley Apr 5, 2026
ed9cb3f
updates table every minute
MichaelWheeley Apr 5, 2026
52a5a0c
wire global variables to satellite prediction
MichaelWheeley Apr 5, 2026
840c60e
remove dead code in useSatelliteLayer.js, this appears to be unutiliz…
MichaelWheeley Apr 5, 2026
b13b635
satellite prediction modal updated every 1s however satellite passes …
MichaelWheeley Apr 5, 2026
5897abc
move ./src/plugins/layers/satelliteOrbit.js to ./src/utils/orbit.js
MichaelWheeley Apr 5, 2026
b075109
enhance table countdown, add ACTIVE, and drop passes ended
MichaelWheeley Apr 6, 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
7 changes: 7 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
"axios": "^1.6.2",
"compression": "^1.7.4",
"cors": "^2.8.5",
"dayjs": "^1.11.20",
"dotenv": "^16.3.1",
"express": "^4.21.2",
"express-rate-limit": "^7.5.0",
Expand Down
2 changes: 1 addition & 1 deletion src/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,7 @@ const App = () => {

const propagation = usePropagation(config.location, dxLocation, config.propagation);
const mySpots = useMySpots(config.callsign);
const satellites = useSatellites(config.location);
const satellites = useSatellites(config.location, config.satellite);
const localWeather = useWeather(config.location, config.allUnits);
const dxWeather = useWeather(dxLocation, config.allUnits);
const localAlerts = useWeatherAlerts(config.location);
Expand Down
76 changes: 75 additions & 1 deletion src/components/SettingsPanel.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ export const SettingsPanel = ({
const [gridSquare, setGridSquare] = useState(config?.locator || '');
const [lat, setLat] = useState(config?.location?.lat ?? 0);
const [lon, setLon] = useState(config?.location?.lon ?? 0);
const [stationAlt, setStationAlt] = useState(config?.location?.stationAlt ?? 100);
const [minElev, setMinElev] = useState(config?.satellite?.minElev ?? 5.0);
const [layout, setLayout] = useState(config?.layout || 'modern');
const [mouseZoom, setMouseZoom] = useState(config?.mouseZoom || 50);
const [timezone, setTimezone] = useState(config?.timezone || '');
Expand Down Expand Up @@ -179,6 +181,8 @@ export const SettingsPanel = ({
setheaderSize(config.headerSize || 1.0);
setLat(config.location?.lat ?? 0);
setLon(config.location?.lon ?? 0);
setStationAlt(config.location?.stationAlt ?? 100);
setMinElev(config.satellite?.minElev ?? 5.0);
setLayout(config.layout || 'modern');
setMouseZoom(config.mouseZoom || 50);
setTimezone(config.timezone || '');
Expand Down Expand Up @@ -419,7 +423,8 @@ export const SettingsPanel = ({
headerSize: headerSize,
swapHeaderClocks,
showMutualReception,
location: { lat: parseFloat(lat), lon: parseFloat(lon) },
location: { lat: parseFloat(lat) || 0, lon: parseFloat(lon) || 0, stationAlt: parseInt(stationAlt) || 100 },
satellite: { minElev: parseFloat(minElev) || 5.0 },
theme,
customTheme,
layout,
Expand Down Expand Up @@ -3360,6 +3365,75 @@ export const SettingsPanel = ({
Footprints
</label>
</div>

{/* station altitude and minimum elevation inputs */}
<div
style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '12px', marginBottom: '12px' }}
>
<div>
<label
style={{
display: 'block',
marginBottom: '6px',
color: 'var(--text-muted)',
fontSize: '11px',
textTransform: 'uppercase',
}}
>
Station Altitude [m]
</label>
<input
type="number"
step="1"
value={isNaN(stationAlt) ? '' : stationAlt}
onChange={(e) => setStationAlt(e.target.valueAsNumber ?? 100)}
style={{
width: '100%',
padding: '10px',
background: 'var(--bg-tertiary)',
border: '1px solid var(--border-color)',
borderRadius: '6px',
color: 'var(--text-primary)',
fontSize: '14px',
fontFamily: 'JetBrains Mono, monospace',
boxSizing: 'border-box',
}}
/>
</div>
<div>
<label
style={{
display: 'block',
marginBottom: '6px',
color: 'var(--text-muted)',
fontSize: '11px',
textTransform: 'uppercase',
}}
>
Minimum Elevation [°]
</label>
<input
type="number"
step="0.1"
min="-89.0"
max="89.0"
value={isNaN(minElev) ? '' : minElev}
onChange={(e) => setMinElev(e.target.valueAsNumber ?? 5.0)}
style={{
width: '100%',
padding: '10px',
background: 'var(--bg-tertiary)',
border: '1px solid var(--border-color)',
borderRadius: '6px',
color: 'var(--text-primary)',
fontSize: '14px',
fontFamily: 'JetBrains Mono, monospace',
boxSizing: 'border-box',
}}
/>
</div>
</div>

{/* Lead Time Slider WIP
<div style={{ marginTop: '8px' }}>
<label style={{
Expand Down
15 changes: 10 additions & 5 deletions src/hooks/useSatellites.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ function round(value, decimals) {
return Math.round(value * factor) / factor;
}

export const useSatellites = (observerLocation) => {
export const useSatellites = (observerLocation, satelliteConfig) => {
const [data, setData] = useState([]);
const [loading, setLoading] = useState(true);
const [tleData, setTleData] = useState({});
Expand Down Expand Up @@ -51,7 +51,7 @@ export const useSatellites = (observerLocation) => {
const observerGd = {
longitude: satellite.degreesToRadians(observerLocation.lon),
latitude: satellite.degreesToRadians(observerLocation.lat),
height: 0.1, // km above sea level
height: (observerLocation.stationAlt || 100) / 1000, // above sea level [km], stationAlt is [m]), defaults to 100m
};

Object.entries(tleData).forEach(([name, tle]) => {
Expand Down Expand Up @@ -82,10 +82,13 @@ export const useSatellites = (observerLocation) => {
const elevation = satellite.radiansToDegrees(lookAngles.elevation);
const rangeSat = lookAngles.rangeSat;

// Calculate range-rate and doppler factor, only if satellite is above horizon
const isVisible = elevation >= satelliteConfig.minElev; // visible only if above minimum elevation

// Calculate range-rate and doppler factor, only if satellite is visible
let dopplerFactor = 1;
let rangeRate = 0;
if (elevation > 0) {

if (isVisible) {
const observerEcf = satellite.geodeticToEcf(observerGd);
const velocityEcf = satellite.eciToEcf(velocityEci, gmst);
dopplerFactor = satellite.dopplerFactor(observerEcf, positionEcf, velocityEcf);
Expand Down Expand Up @@ -125,6 +128,8 @@ export const useSatellites = (observerLocation) => {

positions.push({
name: tle.name || name,
tle1: line1,
tle2: line2,
lat,
lon,
alt: round(alt, 1),
Expand All @@ -134,7 +139,7 @@ export const useSatellites = (observerLocation) => {
range: round(rangeSat, 1),
rangeRate: round(rangeRate, 3),
dopplerFactor: round(dopplerFactor, 9),
isVisible: elevation > 0,
isVisible, // visible if above minimum elevation
isPopular: tle.priority <= 2,
track,
footprintRadius: Math.round(footprintRadius),
Expand Down
Loading
Loading