added SkyCAT support
This commit is contained in:
@@ -8,7 +8,7 @@
|
||||
import PolarPlot from './components/PolarPlot.svelte'
|
||||
import { Go, onWailsEvent } from './lib/wails.js'
|
||||
import { get } from 'svelte/store'
|
||||
import { satPositions, satList, trackedSat, trackedPosition, passes, tleAge, tleLoaded, flexConnected, rotorConnected, settings, watchlist, soundEnabled, passesAllCache } from './stores/satstore.js'
|
||||
import { satPositions, satList, trackedSat, trackedPosition, passes, tleAge, tleLoaded, flexConnected, rotorConnected, skycatConnected, settings, watchlist, soundEnabled, passesAllCache } from './stores/satstore.js'
|
||||
|
||||
let activeTab = 'map'
|
||||
let cleanups = []
|
||||
@@ -43,6 +43,15 @@
|
||||
await Go.SetRotorAzOnly(s.rotorAzOnly ?? true)
|
||||
}
|
||||
}
|
||||
if (s.autoConnectSkycat && s.radioType === 'skycat') {
|
||||
const res = await Go.ConnectSkyCAT(s.skycatHost, s.skycatPort)
|
||||
if (res === 'OK') {
|
||||
skycatConnected.set(true)
|
||||
await Go.SetSkyCATMode(s.skycatSatMode || 'Duplex')
|
||||
}
|
||||
}
|
||||
// Sync radio type to backend on startup
|
||||
if (s.radioType) await Go.SetRadioType(s.radioType)
|
||||
|
||||
const names = await Go.GetSatelliteList()
|
||||
if (names) satList.set(names)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script>
|
||||
import { settings, flexConnected, rotorConnected, soundEnabled } from '../stores/satstore.js'
|
||||
import { settings, flexConnected, rotorConnected, soundEnabled, skycatConnected } from '../stores/satstore.js'
|
||||
import { Go } from '../lib/wails.js'
|
||||
import { maidenheadToLatLon, latLonToMaidenhead } from '../lib/maidenhead.js'
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
let availableVoices = []
|
||||
let selectedVoiceName = ''
|
||||
|
||||
let skycatStatus = ''
|
||||
|
||||
// Load slice config on mount
|
||||
import { onMount } from 'svelte'
|
||||
onMount(async () => {
|
||||
@@ -48,6 +50,28 @@
|
||||
flexStatus = `Slices: RX=Slice ${'ABCDEFGH'[rxSlice]}, TX=Slice ${'ABCDEFGH'[txSlice]}`
|
||||
}
|
||||
|
||||
async function connectSkycat() {
|
||||
skycatStatus = 'Connecting…'
|
||||
settings.update(s => ({ ...s, skycatHost: local.skycatHost, skycatPort: local.skycatPort, skycatSatMode: local.skycatSatMode }))
|
||||
const res = await Go.ConnectSkyCAT(local.skycatHost, local.skycatPort)
|
||||
if (res === 'OK') {
|
||||
skycatConnected.set(true)
|
||||
skycatStatus = 'Connected ✓'
|
||||
await Go.SetSkyCATMode(local.skycatSatMode || 'Duplex')
|
||||
} else { skycatStatus = res || 'Error' }
|
||||
}
|
||||
|
||||
async function disconnectSkycat() {
|
||||
await Go.DisconnectSkyCAT()
|
||||
skycatConnected.set(false)
|
||||
skycatStatus = 'Disconnected'
|
||||
}
|
||||
|
||||
async function saveRadioType() {
|
||||
settings.update(s => ({ ...s, radioType: local.radioType }))
|
||||
await Go.SetRadioType(local.radioType)
|
||||
}
|
||||
|
||||
function saveVoice() {
|
||||
settings.update(s => ({ ...s, ttsVoiceName: selectedVoiceName }))
|
||||
}
|
||||
@@ -163,6 +187,58 @@
|
||||
</button>
|
||||
</section>
|
||||
|
||||
<!-- Radio Backend Selector -->
|
||||
<section class="card">
|
||||
<h3>📻 Radio Backend</h3>
|
||||
<div class="fg">
|
||||
<label>Active backend</label>
|
||||
<select bind:value={local.radioType} on:change={saveRadioType}>
|
||||
<option value="flex">FlexRadio 8600 (direct TCP)</option>
|
||||
<option value="skycat">SkyCAT / rigctld (universal)</option>
|
||||
</select>
|
||||
</div>
|
||||
<p class="hint">
|
||||
{#if local.radioType === 'skycat'}
|
||||
SkyCAT mode: connect skycatd.exe or rigctld.exe for your radio, then connect below.
|
||||
{:else}
|
||||
FlexRadio mode: direct TCP connection to SmartSDR API port 4992.
|
||||
{/if}
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<!-- SkyCAT -->
|
||||
{#if local.radioType === 'skycat'}
|
||||
<section class="card">
|
||||
<div class="card-head">
|
||||
<h3>🛰 SkyCAT / rigctld</h3>
|
||||
<span class="badge {$skycatConnected ? 'ok' : 'off'}">{$skycatConnected ? 'CONNECTED' : 'OFFLINE'}</span>
|
||||
</div>
|
||||
<div class="fg">
|
||||
<label>Host / IP</label>
|
||||
<input type="text" bind:value={local.skycatHost} placeholder="127.0.0.1" />
|
||||
<label>TCP Port</label>
|
||||
<input type="number" bind:value={local.skycatPort} placeholder="4532" />
|
||||
<label>Sat Mode</label>
|
||||
<select bind:value={local.skycatSatMode}>
|
||||
<option value="Duplex">Duplex (RX≠TX freq)</option>
|
||||
<option value="Split">Split VFO</option>
|
||||
<option value="Simplex">Simplex</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="btn-row">
|
||||
{#if $skycatConnected}
|
||||
<button class="btn-danger" on:click={disconnectSkycat}>Disconnect</button>
|
||||
{:else}
|
||||
<button class="btn-primary" on:click={connectSkycat}>Connect</button>
|
||||
{/if}
|
||||
{#if skycatStatus}
|
||||
<span class="status {skycatStatus.includes('✓') ? 'ok-txt' : 'err-txt'}">{skycatStatus}</span>
|
||||
{/if}
|
||||
</div>
|
||||
<p class="hint">Start skycatd.exe first: <code>skycatd -m IC-9700 -r COM9 -t 4532</code></p>
|
||||
</section>
|
||||
{/if}
|
||||
|
||||
<!-- FlexRadio -->
|
||||
<section class="card">
|
||||
<div class="card-head">
|
||||
@@ -308,7 +384,7 @@
|
||||
<!-- About -->
|
||||
<section class="card">
|
||||
<h3>ℹ️ About</h3>
|
||||
<p><strong>SatMaster v1.0</strong> — F4BPO</p>
|
||||
<p><strong>SatMaster v0.2</strong> — F4BPO</p>
|
||||
<p>Amateur satellite tracking · FlexRadio Doppler correction · PstRotator control</p>
|
||||
<p class="hint">SGP4 via akhenakh/sgp4 · Go + Wails + Svelte</p>
|
||||
</section>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script>
|
||||
import { trackedSat, trackedPosition, flexConnected, rotorConnected, tleAge, settings, dopplerEnabled, rotorEnabled, soundEnabled } from '../stores/satstore.js'
|
||||
import { trackedSat, trackedPosition, flexConnected, rotorConnected, skycatConnected, tleAge, settings, dopplerEnabled, rotorEnabled, soundEnabled } from '../stores/satstore.js'
|
||||
import { formatFreq, formatShift, formatRange, computeDopplerShift } from '../lib/utils.js'
|
||||
import { onMount, onDestroy } from 'svelte'
|
||||
|
||||
@@ -58,7 +58,7 @@
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{#if $flexConnected}
|
||||
{#if ($settings.radioType === 'skycat' && $skycatConnected) || ($settings.radioType !== 'skycat' && $flexConnected)}
|
||||
<button class="doppler-toggle {$dopplerEnabled ? 'don' : 'doff'}" on:click={() => dopplerEnabled.update(v => !v)} title={$dopplerEnabled ? 'Doppler ON — click to disable' : 'Doppler OFF — click to enable'}>
|
||||
<span>⟳ DOPPLER {$dopplerEnabled ? 'ON' : 'OFF'}</span>
|
||||
</button>
|
||||
@@ -72,10 +72,17 @@
|
||||
<span>🔊 SOUND {$soundEnabled ? 'ON' : 'OFF'}</span>
|
||||
</button>
|
||||
<div class="conn-group">
|
||||
<div class="conn {$flexConnected ? 'on' : 'off'}">
|
||||
<span class="conn-dot"></span>
|
||||
<span>FLEX</span>
|
||||
</div>
|
||||
{#if $settings.radioType === 'skycat'}
|
||||
<div class="conn {$skycatConnected ? 'on' : 'off'}">
|
||||
<span class="conn-dot"></span>
|
||||
<span>SKYCAT</span>
|
||||
</div>
|
||||
{:else}
|
||||
<div class="conn {$flexConnected ? 'on' : 'off'}">
|
||||
<span class="conn-dot"></span>
|
||||
<span>FLEX</span>
|
||||
</div>
|
||||
{/if}
|
||||
<div class="conn {$rotorConnected ? 'on' : 'off'}">
|
||||
<span class="conn-dot"></span>
|
||||
<span>ROTOR</span>
|
||||
|
||||
@@ -51,6 +51,12 @@ export const Go = {
|
||||
SetSatelliteMode: (mode) => wailsCall('main.App.SetSatelliteMode', mode),
|
||||
SetTrackFreqMode: (v) => wailsCall('main.App.SetTrackFreqMode', v),
|
||||
SetTrackAzimuth: (v) => wailsCall('main.App.SetTrackAzimuth', v),
|
||||
// SkyCAT / rigctld
|
||||
ConnectSkyCAT: (host, port) => wailsCall('main.App.ConnectSkyCAT', host, port),
|
||||
DisconnectSkyCAT: () => wailsCall('main.App.DisconnectSkyCAT'),
|
||||
GetSkyCATStatus: () => wailsCall('main.App.GetSkyCATStatus'),
|
||||
SetRadioType: (type) => wailsCall('main.App.SetRadioType', type),
|
||||
SetSkyCATMode: (mode) => wailsCall('main.App.SetSkyCATMode', mode),
|
||||
}
|
||||
|
||||
// Wails event listener wrapper
|
||||
|
||||
@@ -35,6 +35,7 @@ trackedSat.subscribe(name => {
|
||||
|
||||
// Connection states
|
||||
export const flexConnected = writable(false)
|
||||
export const skycatConnected = writable(false)
|
||||
export const dopplerEnabled = writable(true)
|
||||
|
||||
// Passes panel state — persisted in memory so tab switches don't reset filters
|
||||
@@ -55,22 +56,27 @@ const DEFAULT_SETTINGS = {
|
||||
qthLat: 48.7,
|
||||
qthLon: 2.55,
|
||||
qthAlt: 100,
|
||||
radioType: 'flex', // 'flex' | 'skycat'
|
||||
flexHost: '192.168.1.100',
|
||||
flexPort: 4992,
|
||||
skycatHost: '127.0.0.1',
|
||||
skycatPort: 4532,
|
||||
skycatSatMode: 'Duplex', // 'Duplex' | 'Split' | 'Simplex'
|
||||
autoConnectSkycat: false,
|
||||
rotorHost: '127.0.0.1',
|
||||
rotorPort: 12000,
|
||||
rotorAzOnly: true, // true = azimuth only, false = az+el
|
||||
rotorAzOnly: true,
|
||||
downlinkHz: 145800000,
|
||||
uplinkHz: 145200000,
|
||||
minElFilter: 5,
|
||||
autoConnectFlex: false,
|
||||
autoConnectRotor: false,
|
||||
rxSlice: 0, // Slice A = RX downlink
|
||||
txSlice: 1, // Slice B = TX uplink
|
||||
rxSlice: 0,
|
||||
txSlice: 1,
|
||||
}
|
||||
|
||||
// Settings version — bump this to force reset of specific fields
|
||||
const SETTINGS_VERSION = 3
|
||||
const SETTINGS_VERSION = 4
|
||||
|
||||
// Load persisted settings from localStorage
|
||||
function loadSettings() {
|
||||
@@ -85,6 +91,10 @@ function loadSettings() {
|
||||
...parsed,
|
||||
rxSlice: DEFAULT_SETTINGS.rxSlice,
|
||||
txSlice: DEFAULT_SETTINGS.txSlice,
|
||||
radioType: DEFAULT_SETTINGS.radioType,
|
||||
skycatHost: DEFAULT_SETTINGS.skycatHost,
|
||||
skycatPort: DEFAULT_SETTINGS.skycatPort,
|
||||
skycatSatMode: DEFAULT_SETTINGS.skycatSatMode,
|
||||
_version: SETTINGS_VERSION,
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user