-
-
Notifications
You must be signed in to change notification settings - Fork 9
Expand file tree
/
Copy pathsatellite-link.html
More file actions
286 lines (267 loc) · 12.6 KB
/
Copy pathsatellite-link.html
File metadata and controls
286 lines (267 loc) · 12.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
<!DOCTYPE html>
<html lang="en-GB">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Satellite link — OscarWatch Help</title>
<link rel="stylesheet" href="styles.css" />
</head>
<body>
<div class="wrap">
<header>
<div class="brand">
<a href="index.html" class="brand-home" title="Home"><img src="oscarwatch-icon.png" alt="" class="brand-icon" width="56" height="56" /></a>
<div class="brand-text">
<h1>Satellite link</h1>
<p class="tagline">Broadcast focused satellite data to logging applications over WebSocket</p>
</div>
</div>
<nav aria-label="Help topics">
<ul>
<li><a href="quick-start.html">Quick start</a></li>
<li><a href="map-and-sidebar.html">Map & sidebar</a></li>
<li><a href="frequencies.html">Frequencies</a></li>
<li><a href="satellites.html">Satellites & TLEs</a></li>
<li><a href="passes.html">Pass planning</a></li>
<li><a href="radio-rotator.html">Radio & rotator</a></li>
<li><a href="settings.html">Settings</a></li>
<li><a href="keyboard-shortcuts.html">Shortcuts</a></li>
<li><a href="troubleshooting.html">Problems?</a></li>
</ul>
</nav>
</header>
<main>
<h2>Overview</h2>
<p>
<strong>Satellite link</strong> is OscarWatch’s replacement for the legacy SatPC32 DDE interface.
When enabled, OscarWatch runs a small WebSocket server on your PC that sends JSON messages about the
<strong>focused</strong> satellite: name, NORAD ID, uplink and downlink frequencies and modes, ADIF bands,
azimuth, elevation, range, and more. Logging applications can subscribe and pre-fill QSO fields automatically.
When you log a QSO in <strong>QSO Logbook</strong>, OscarWatch also broadcasts a <code>qsoLogged</code> event
(and <code>qsoUpdated</code> / <code>qsoDeleted</code> when you edit or remove entries) so external tools can
mirror your log in real time.
</p>
<p>
Each message also includes a <code>wispDde</code> string in the old Wisp32/GSC format for adapters that
still expect SatPC32-style text.
</p>
<h2>Settings</h2>
<p>
Open <strong>Settings → Integrations → Satellite link</strong>. Press <strong>Save</strong> when finished.
See also <a href="settings.html#satellite-link">Settings (Integrations)</a>.
</p>
<ul>
<li><strong>Enable Satellite link WebSocket server</strong> — master switch.</li>
<li><strong>Port</strong> — default <strong>7373</strong> (1024–65535).</li>
<li><strong>Allow connections from local network</strong> — when off, only this PC (<code>127.0.0.1</code>). When on, OscarWatch listens on your LAN IP addresses (shown in the connection URL box). On Windows, allow OscarWatch when the system firewall prompt appears.</li>
<li><strong>Only broadcast when satellite is above horizon</strong> — when on, payloads below 0° elevation send <code>** NO SATELLITE **</code> (SatPC32-style).</li>
<li><strong>Update interval (ms)</strong> — minimum time between identical payloads (default 1000). Focus and mode changes are sent immediately.</li>
<li><strong>Test port</strong> — checks that OscarWatch can bind to the port (no client required).</li>
<li><strong>Open help</strong> — opens this page.</li>
</ul>
<h2 id="status-bar">Status bar</h2>
<p>
When Satellite link is enabled, the <a href="map-and-sidebar.html#status-bar">main window status bar</a>
shows a <strong>Sat link</strong> label to the left of the map-time buttons:
</p>
<ul>
<li><strong>amber</strong> — waiting for clients (port open, none connected yet)</li>
<li><strong>green</strong> — one or more clients connected (hover for port and client count)</li>
<li><strong>red</strong> — could not start (port in use, permissions, etc.)</li>
</ul>
<p>The indicator is hidden when Satellite link is disabled in Settings.</p>
<h2 id="api">For developers</h2>
<p>
Protocol version <strong>1</strong>. Connect with a standard WebSocket client to:
</p>
<p><code>ws://127.0.0.1:<port>/</code> (this PC only)</p>
<p>or, when LAN access is enabled:</p>
<p><code>ws://<this PC IP>:<port>/</code></p>
<p>
There is no authentication in v1 — use localhost or a trusted LAN only.
On connect, OscarWatch sends the latest satellite snapshot immediately, then broadcasts updates when focus,
mode, frequencies, or tracking data change (throttled by the update interval). QSO events are sent
immediately when you add, edit, or delete a contact in QSO Logbook (not replayed to new clients on connect).
</p>
<h3>Satellite status messages</h3>
<p>Live tracking payloads use <code>type: "satelliteStatus"</code>:</p>
<pre><code>{
"type": "satelliteStatus",
"version": 1,
"timestampUtc": "2026-07-07T11:04:00.000Z",
"inRange": true,
"satellite": {
"name": "SO-50",
"noradId": "27607",
"modeType": "FM VOICE"
},
"frequencies": {
"uplinkHz": 435300000,
"downlinkHz": 145850000,
"uplinkMode": "FM",
"downlinkMode": "FM",
"nominalUplinkKHz": 435300,
"nominalDownlinkKHz": 145850,
"isBeaconOnly": false
},
"bands": { "tx": "70cm", "rx": "2m" },
"tracking": {
"azimuthDeg": 91.7,
"elevationDeg": 1.9,
"rangeKm": 2100.5,
"rangeRateKmPerSec": -4.92,
"isSunlit": true
},
"dopplerStrategy": "full",
"wispDde": "SO-50 AZ91,7 EL1,9 UP435300000 UFM DN145850000 DFM MA0,0 RR-4,92"
}</code></pre>
<p>When no satellite is in range (or none focused):</p>
<pre><code>{
"type": "satelliteStatus",
"version": 1,
"timestampUtc": "...",
"inRange": false,
"satellite": null,
"wispDde": "** NO SATELLITE **"
}</code></pre>
<h3>QSO logbook messages</h3>
<p>
When a contact is saved in <a href="qso-logbook.html">QSO Logbook</a>, OscarWatch broadcasts a separate JSON
frame to all connected clients. These events are independent of satellite status updates and are always sent
immediately (not throttled). Clients that connect later do <strong>not</strong> receive a backlog — only
events that occur while they are connected.
</p>
<h4><code>qsoLogged</code></h4>
<p>Emitted when a new QSO is added:</p>
<pre><code>{
"type": "qsoLogged",
"version": 1,
"timestampUtc": "2026-07-11T14:30:05.000Z",
"logbook": {
"id": 3,
"name": "Field day",
"myCallsign": "G0ABC",
"myGridSquare": "IO91"
},
"qso": {
"id": 42,
"qsoUtc": "2026-07-11T14:30:00.000Z",
"call": "DL1ABC",
"rstSent": "59",
"rstRcvd": "59",
"gridSquare": "JO62",
"name": "",
"comment": "",
"satellite": {
"name": "SO-50",
"noradId": "27607"
},
"frequencies": {
"uplinkHz": 435300000,
"downlinkHz": 145850000,
"uplinkMode": "FM",
"downlinkMode": "FM"
},
"bands": { "tx": "70cm", "rx": "2m" },
"propMode": "SAT"
}
}</code></pre>
<h4><code>qsoUpdated</code></h4>
<p>Same shape as <code>qsoLogged</code>, emitted when an existing QSO is saved after editing.</p>
<h4><code>qsoDeleted</code></h4>
<p>Emitted when a QSO is removed from the logbook:</p>
<pre><code>{
"type": "qsoDeleted",
"version": 1,
"timestampUtc": "2026-07-11T14:35:00.000Z",
"logbook": {
"id": 3,
"name": "Field day",
"myCallsign": "G0ABC",
"myGridSquare": "IO91"
},
"qso": {
"id": 42,
"call": "DL1ABC"
}
}</code></pre>
<h4>QSO field notes</h4>
<ul>
<li><code>logbook</code> — the active logbook at the time of the event.</li>
<li><code>qso.id</code> — stable OscarWatch database ID; use for deduplication across <code>qsoUpdated</code> / <code>qsoDeleted</code>.</li>
<li><code>qso.qsoUtc</code> — contact time in UTC (ISO-8601), matching ADIF <code>QSO_DATE</code> + <code>TIME_ON</code>.</li>
<li><code>qso.satellite.name</code> — LoTW-style name captured at log time (same as ADIF <code>SAT_NAME</code>).</li>
<li><code>qso.satellite.noradId</code> — focused satellite NORAD ID when logged; omitted on edit/delete if unknown.</li>
<li><code>qso.frequencies.uplinkHz</code> / <code>downlinkHz</code> — TX/RX at log time (Hz). Omitted when zero.</li>
<li><code>qso.bands.tx</code> / <code>rx</code> — ADIF band labels (e.g. <code>70cm</code>, <code>2m</code>).</li>
<li><code>qso.propMode</code> — always <code>SAT</code> for satellite QSOs in OscarWatch.</li>
<li>Empty optional strings are omitted (<code>null</code> absent from JSON) rather than sent as <code>""</code>.</li>
</ul>
<h3>Field notes (satellite status)</h3>
<ul>
<li><code>satellite.name</code> — OscarWatch / LoTW naming (same as Cloudlog <code>sat_name</code>).</li>
<li><code>frequencies.uplinkHz</code> / <code>downlinkHz</code> — radio-corrected Hz (what CAT uses), not raw catalogue nominals.</li>
<li><code>dopplerStrategy</code> — <code>full</code>, <code>downlinkOnly</code>, or <code>uplinkOnly</code>.</li>
<li><code>wispDde</code> — European decimal commas; SatPC32 field order for legacy parsers.</li>
<li>Ignore unknown future JSON fields (forward-compatible).</li>
</ul>
<h3>Minimal Python client</h3>
<pre><code>import asyncio
import json
import websockets
async def main():
async with websockets.connect("ws://127.0.0.1:7373/") as ws:
while True:
msg = json.loads(await ws.recv())
kind = msg.get("type")
if kind == "satelliteStatus":
if msg.get("inRange"):
sat = msg["satellite"]["name"]
rx = msg["frequencies"]["downlinkHz"]
print(f"{sat} RX {rx} Hz")
else:
print("No satellite")
elif kind == "qsoLogged":
qso = msg["qso"]
print(f"Logged {qso['call']} on {qso['satellite']['name']}")
elif kind == "qsoUpdated":
print(f"Updated QSO {msg['qso']['id']}")
elif kind == "qsoDeleted":
print(f"Deleted QSO {msg['qso']['id']}")
asyncio.run(main())</code></pre>
<h3>Minimal C# client</h3>
<pre><code>using System.Net.WebSockets;
using System.Text;
using System.Text.Json;
using var ws = new ClientWebSocket();
await ws.ConnectAsync(new Uri("ws://127.0.0.1:7373/"), CancellationToken.None);
var buffer = new byte[8192];
while (ws.State == WebSocketState.Open)
{
var result = await ws.ReceiveAsync(buffer, CancellationToken.None);
var json = Encoding.UTF8.GetString(buffer, 0, result.Count);
using var doc = JsonDocument.Parse(json);
var root = doc.RootElement;
switch (root.GetProperty("type").GetString())
{
case "satelliteStatus" when root.GetProperty("inRange").GetBoolean():
Console.WriteLine(root.GetProperty("satellite").GetProperty("name").GetString());
break;
case "qsoLogged":
Console.WriteLine($"Logged {root.GetProperty("qso").GetProperty("call").GetString()}");
break;
}
}</code></pre>
<h2>Troubleshooting</h2>
<ul>
<li><strong>Windows Firewall</strong> — when LAN access is first enabled, Windows should prompt to allow OscarWatch. Choose <strong>Allow access</strong> on private networks. If you previously blocked it, open <strong>Windows Security → Firewall & network protection → Allow an app through firewall</strong> and enable OscarWatch for Private.</li>
<li><strong>Port in use</strong> — another program (or a second OscarWatch instance) may already use the port. Change the port or stop the other program. Use <strong>Test port</strong> in Settings.</li>
<li><strong>LAN clients cannot connect</strong> — enable <strong>Allow connections from local network</strong>, allow the port in Windows Firewall, and use this PC’s LAN IP address.</li>
<li><strong>Always <code>** NO SATELLITE **</code></strong> — check <strong>Only broadcast when satellite is above horizon</strong>, focus a satellite on the map, and ensure a transponder mode is selected in the frequency panel.</li>
<li><strong>No clients shown in status bar</strong> — the server can be waiting (amber) with zero clients; connect your logging app and the label should turn green.</li>
</ul>
</main>
<footer><a href="index.html">Back to help home</a></footer>
</div>
</body>
</html>