citrascope 0.7.0__py3-none-any.whl → 0.9.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- citrascope/api/abstract_api_client.py +14 -0
- citrascope/api/citra_api_client.py +41 -0
- citrascope/citra_scope_daemon.py +75 -0
- citrascope/hardware/abstract_astro_hardware_adapter.py +97 -2
- citrascope/hardware/adapter_registry.py +15 -3
- citrascope/hardware/devices/__init__.py +17 -0
- citrascope/hardware/devices/abstract_hardware_device.py +79 -0
- citrascope/hardware/devices/camera/__init__.py +13 -0
- citrascope/hardware/devices/camera/abstract_camera.py +114 -0
- citrascope/hardware/devices/camera/rpi_hq_camera.py +353 -0
- citrascope/hardware/devices/camera/usb_camera.py +407 -0
- citrascope/hardware/devices/camera/ximea_camera.py +756 -0
- citrascope/hardware/devices/device_registry.py +273 -0
- citrascope/hardware/devices/filter_wheel/__init__.py +7 -0
- citrascope/hardware/devices/filter_wheel/abstract_filter_wheel.py +73 -0
- citrascope/hardware/devices/focuser/__init__.py +7 -0
- citrascope/hardware/devices/focuser/abstract_focuser.py +78 -0
- citrascope/hardware/devices/mount/__init__.py +7 -0
- citrascope/hardware/devices/mount/abstract_mount.py +115 -0
- citrascope/hardware/direct_hardware_adapter.py +805 -0
- citrascope/hardware/dummy_adapter.py +202 -0
- citrascope/hardware/filter_sync.py +94 -0
- citrascope/hardware/indi_adapter.py +6 -2
- citrascope/hardware/kstars_dbus_adapter.py +46 -37
- citrascope/hardware/nina_adv_http_adapter.py +13 -11
- citrascope/settings/citrascope_settings.py +6 -0
- citrascope/tasks/runner.py +2 -0
- citrascope/tasks/scope/static_telescope_task.py +17 -12
- citrascope/tasks/task.py +3 -0
- citrascope/time/__init__.py +14 -0
- citrascope/time/time_health.py +103 -0
- citrascope/time/time_monitor.py +186 -0
- citrascope/time/time_sources.py +261 -0
- citrascope/web/app.py +260 -60
- citrascope/web/static/app.js +121 -731
- citrascope/web/static/components.js +136 -0
- citrascope/web/static/config.js +259 -420
- citrascope/web/static/filters.js +55 -0
- citrascope/web/static/formatters.js +129 -0
- citrascope/web/static/store-init.js +204 -0
- citrascope/web/static/style.css +44 -0
- citrascope/web/templates/_config.html +175 -0
- citrascope/web/templates/_config_hardware.html +208 -0
- citrascope/web/templates/_monitoring.html +242 -0
- citrascope/web/templates/dashboard.html +109 -377
- {citrascope-0.7.0.dist-info → citrascope-0.9.0.dist-info}/METADATA +18 -1
- citrascope-0.9.0.dist-info/RECORD +69 -0
- citrascope-0.7.0.dist-info/RECORD +0 -41
- {citrascope-0.7.0.dist-info → citrascope-0.9.0.dist-info}/WHEEL +0 -0
- {citrascope-0.7.0.dist-info → citrascope-0.9.0.dist-info}/entry_points.txt +0 -0
- {citrascope-0.7.0.dist-info → citrascope-0.9.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -8,14 +8,17 @@
|
|
|
8
8
|
<link rel="icon" type="image/png" href="/static/img/favicon.png">
|
|
9
9
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/css/bootstrap.min.css" rel="stylesheet"
|
|
10
10
|
integrity="sha384-sRIl4kxILFvY47J16cr9ZwB07vP4J8+LH7qKQnuqkuIAvNWLzeN8tE5YBujZqJLB" crossorigin="anonymous">
|
|
11
|
+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css">
|
|
11
12
|
<link href="/static/style.css" rel="stylesheet">
|
|
12
13
|
</head>
|
|
13
14
|
|
|
14
|
-
<body data-bs-theme="dark">
|
|
15
|
+
<body data-bs-theme="dark" x-data>
|
|
15
16
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/js/bootstrap.bundle.min.js"
|
|
16
17
|
integrity="sha384-FKyoEForCGlyvwx9Hj09JcYn3nv7wiPVlz7YYwJrWVcXK/BmnVDxM+D2scQbITxI"
|
|
17
18
|
crossorigin="anonymous"></script>
|
|
18
|
-
|
|
19
|
+
<script type="module" src="/static/store-init.js"></script>
|
|
20
|
+
<script defer src="https://cdn.jsdelivr.net/npm/@alpinejs/persist@3.x.x/dist/cdn.min.js"></script>
|
|
21
|
+
<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.14.3/dist/cdn.min.js"></script>
|
|
19
22
|
|
|
20
23
|
<div class="container">
|
|
21
24
|
<header class="d-flex flex-wrap justify-content-center py-3 mb-4 border-bottom align-items-center">
|
|
@@ -24,365 +27,38 @@
|
|
|
24
27
|
<img src="/static/img/citra.png" alt="CitraScope Logo" class="logo-img" />
|
|
25
28
|
CitraScope
|
|
26
29
|
<small class="text-muted" style="font-size: 0.875rem;">
|
|
27
|
-
<span
|
|
28
|
-
|
|
30
|
+
<span style="cursor: pointer; user-select: none;" data-bs-toggle="tooltip" data-bs-placement="bottom" title="Click to check for updates"
|
|
31
|
+
@click="$store.citrascope.showVersionModal()" x-text="$store.citrascope.version || 'v...'"></span>
|
|
32
|
+
<span class="badge bg-info text-dark ms-1" style="font-size: 0.7rem;"
|
|
33
|
+
x-show="$store.citrascope.updateIndicator"
|
|
34
|
+
x-text="$store.citrascope.updateIndicator"
|
|
35
|
+
@click="$store.citrascope.showVersionModal()"></span>
|
|
29
36
|
</small>
|
|
30
37
|
</span>
|
|
31
38
|
</span>
|
|
32
39
|
|
|
33
40
|
<ul class="nav" id="mainNav">
|
|
34
|
-
<li class="nav-item"><a href="#" class="nav-link px-2 text-white
|
|
35
|
-
aria-current="page"
|
|
36
|
-
|
|
41
|
+
<li class="nav-item"><a href="#monitoring" class="nav-link px-2" :class="$store.citrascope.currentSection === 'monitoring' ? 'text-white' : ''"
|
|
42
|
+
:aria-current="$store.citrascope.currentSection === 'monitoring' ? 'page' : null"
|
|
43
|
+
data-section="monitoring" @click.prevent="$store.citrascope.currentSection = 'monitoring'; window.location.hash = 'monitoring'">Monitoring</a></li>
|
|
44
|
+
<li class="nav-item"><a href="#config" class="nav-link px-2" :class="$store.citrascope.currentSection === 'config' ? 'text-white' : ''"
|
|
45
|
+
:aria-current="$store.citrascope.currentSection === 'config' ? 'page' : null"
|
|
46
|
+
data-section="config" @click.prevent="$store.citrascope.currentSection = 'config'; window.location.hash = 'config'">Config</a></li>
|
|
37
47
|
<li class="nav-item"><a href="https://docs.citra.space/citrascope/" class="nav-link px-2" target="_blank">Docs</a></li>
|
|
38
|
-
<li class="nav-item"><a href="#" class="nav-link bg-success text-white btn"
|
|
39
|
-
id="taskScopeButton" target="_blank"
|
|
48
|
+
<li class="nav-item"><a href="#" class="nav-link bg-success text-white btn"
|
|
49
|
+
id="taskScopeButton" target="_blank"
|
|
50
|
+
x-show="$store.citrascope.status?.ground_station_url"
|
|
51
|
+
:href="$store.citrascope.status?.ground_station_url || '#'">Task my Scope</a></li>
|
|
40
52
|
</ul>
|
|
41
53
|
</header>
|
|
42
54
|
|
|
43
|
-
<!-- Template for connection status badge -->
|
|
44
|
-
<template id="connectionStatusTemplate">
|
|
45
|
-
<span class="badge rounded-pill connection-status-badge" data-bs-toggle="tooltip" data-bs-placement="bottom">
|
|
46
|
-
<span class="status-text"></span>
|
|
47
|
-
</span>
|
|
48
|
-
</template>
|
|
49
55
|
</div>
|
|
50
56
|
|
|
51
|
-
<div id="monitoringSection">
|
|
52
|
-
<div class="container">
|
|
53
|
-
<div class="row g-3 mb-3">
|
|
54
|
-
<div class="col-12 col-md-6">
|
|
55
|
-
<div class="card bg-dark text-light border-secondary h-100">
|
|
56
|
-
<div class="card-header">
|
|
57
|
-
System Status
|
|
58
|
-
</div>
|
|
59
|
-
<div class="card-body">
|
|
60
|
-
<div class="row mb-2">
|
|
61
|
-
<div class="col-6 fw-semibold">Daemon</div>
|
|
62
|
-
<div class="col-6" id="wsStatus"><span class="badge rounded-pill bg-secondary" data-bs-toggle="tooltip" data-bs-placement="bottom" title="Dashboard connection status">Connecting...</span></div>
|
|
63
|
-
</div>
|
|
64
|
-
<div class="row mb-2">
|
|
65
|
-
<div class="col-6 fw-semibold">Telescope</div>
|
|
66
|
-
<div class="col-6" id="telescopeConnected"><span class="badge rounded-pill bg-secondary">Unknown</span></div>
|
|
67
|
-
</div>
|
|
68
|
-
<div class="row mb-2">
|
|
69
|
-
<div class="col-6 fw-semibold">Camera</div>
|
|
70
|
-
<div class="col-6" id="cameraConnected"><span class="badge rounded-pill bg-secondary">Unknown</span></div>
|
|
71
|
-
</div>
|
|
72
|
-
<div class="row">
|
|
73
|
-
<div class="col-6 fw-semibold">Task Processing</div>
|
|
74
|
-
<div class="col-6 d-flex align-items-center gap-2">
|
|
75
|
-
<span id="processingStatus"><span class="badge rounded-pill bg-success">Active</span></span>
|
|
76
|
-
<button id="toggleProcessingButton" class="btn btn-sm btn-secondary" title="Pause task processing">
|
|
77
|
-
<span id="processingButtonIcon">Pause</span>
|
|
78
|
-
</button>
|
|
79
|
-
</div>
|
|
80
|
-
</div>
|
|
81
|
-
</div>
|
|
82
|
-
</div>
|
|
83
|
-
</div>
|
|
84
|
-
<div class="col-12 col-md-6">
|
|
85
|
-
<div class="card bg-dark text-light border-secondary h-100">
|
|
86
|
-
<div class="card-header">
|
|
87
|
-
Telescope
|
|
88
|
-
</div>
|
|
89
|
-
<div class="card-body">
|
|
90
|
-
<div class="row mb-2">
|
|
91
|
-
<div class="col-6 fw-semibold">Adapter</div>
|
|
92
|
-
<div class="col-6" id="hardwareAdapter">-</div>
|
|
93
|
-
</div>
|
|
94
|
-
<div class="row mb-2">
|
|
95
|
-
<div class="col-6 fw-semibold">Right Ascension</div>
|
|
96
|
-
<div class="col-6" id="telescopeRA">-</div>
|
|
97
|
-
</div>
|
|
98
|
-
<div class="row mb-2">
|
|
99
|
-
<div class="col-6 fw-semibold">Declination</div>
|
|
100
|
-
<div class="col-6" id="telescopeDEC">-</div>
|
|
101
|
-
</div>
|
|
102
|
-
<div class="row">
|
|
103
|
-
<div class="col-6 fw-semibold">Ground Station</div>
|
|
104
|
-
<div class="col-6" id="groundStationName">-</div>
|
|
105
|
-
</div>
|
|
106
|
-
</div>
|
|
107
|
-
</div>
|
|
108
|
-
</div>
|
|
109
57
|
|
|
110
|
-
|
|
111
|
-
</div>
|
|
112
|
-
<div class="container">
|
|
113
|
-
<div class="row g-3 mb-3">
|
|
114
|
-
<div class="col-12">
|
|
115
|
-
<div class="card bg-dark text-light border-secondary">
|
|
116
|
-
<div class="card-header">
|
|
117
|
-
Current Task
|
|
118
|
-
</div>
|
|
119
|
-
<div class="card-body">
|
|
120
|
-
<div id="currentTaskDisplay">
|
|
121
|
-
<p class="text-muted-dark">No active task</p>
|
|
122
|
-
</div>
|
|
123
|
-
</div>
|
|
124
|
-
</div>
|
|
58
|
+
{% include '_monitoring.html' %}
|
|
125
59
|
|
|
126
|
-
|
|
127
|
-
<template id="activeTaskTemplate">
|
|
128
|
-
<div class="d-flex align-items-center gap-2 mb-2">
|
|
129
|
-
<div class="spinner-border spinner-border-sm text-success" role="status">
|
|
130
|
-
<span class="visually-hidden">Loading...</span>
|
|
131
|
-
</div>
|
|
132
|
-
<div class="fw-bold task-target-name" style="font-size: 1.3em;"></div>
|
|
133
|
-
</div>
|
|
134
|
-
<div class="text-secondary small">
|
|
135
|
-
<span class="task-id-text"></span>
|
|
136
|
-
</div>
|
|
137
|
-
</template>
|
|
138
|
-
</div>
|
|
139
|
-
</div>
|
|
140
|
-
<div class="row g-3 mb-3">
|
|
141
|
-
<div class="col-12">
|
|
142
|
-
<div class="card bg-dark text-light border-secondary">
|
|
143
|
-
<div class="card-header d-flex align-items-center justify-content-between">
|
|
144
|
-
<span>Task Queue</span>
|
|
145
|
-
<span class="small text-secondary"><span id="tasksPending">0</span> pending</span>
|
|
146
|
-
</div>
|
|
147
|
-
<div class="card-body p-0">
|
|
148
|
-
<div id="taskList" class="table-responsive">
|
|
149
|
-
<p class="p-3 text-muted-dark">Loading tasks...</p>
|
|
150
|
-
</div>
|
|
151
|
-
</div>
|
|
152
|
-
</div>
|
|
60
|
+
{% include '_config.html' %}
|
|
153
61
|
|
|
154
|
-
<!-- Template for task queue rows -->
|
|
155
|
-
<template id="taskRowTemplate">
|
|
156
|
-
<tr class="task-row">
|
|
157
|
-
<td class="fw-semibold task-target"></td>
|
|
158
|
-
<td class="text-secondary small task-start"></td>
|
|
159
|
-
<td class="text-secondary small task-end"></td>
|
|
160
|
-
<td><span class="badge rounded-pill task-status"></span></td>
|
|
161
|
-
</tr>
|
|
162
|
-
</template>
|
|
163
|
-
</div>
|
|
164
|
-
</div>
|
|
165
|
-
</div>
|
|
166
|
-
</div>
|
|
167
|
-
|
|
168
|
-
<div class="container my-4" id="configSection" style="display: none;">
|
|
169
|
-
<form id="configForm">
|
|
170
|
-
<div class="row g-3 mb-3">
|
|
171
|
-
<!-- API Configuration Card -->
|
|
172
|
-
<div class="col-12">
|
|
173
|
-
<div class="card bg-dark text-light border-secondary">
|
|
174
|
-
<div class="card-header">
|
|
175
|
-
<h5 class="mb-0">API Configuration</h5>
|
|
176
|
-
</div>
|
|
177
|
-
<div class="card-body">
|
|
178
|
-
<div class="row g-3">
|
|
179
|
-
<div class="col-12">
|
|
180
|
-
<label for="apiEndpoint" class="form-label">API Endpoint</label>
|
|
181
|
-
<select id="apiEndpoint" class="form-select">
|
|
182
|
-
<option value="production">Production (api.citra.space)</option>
|
|
183
|
-
<option value="development">Development (dev.api.citra.space)</option>
|
|
184
|
-
<option value="custom">Custom</option>
|
|
185
|
-
</select>
|
|
186
|
-
</div>
|
|
187
|
-
<div class="col-12" id="customHostContainer" style="display: none;">
|
|
188
|
-
<label for="customHost" class="form-label">Custom API Host</label>
|
|
189
|
-
<input type="text" id="customHost" class="form-control" placeholder="api.example.com">
|
|
190
|
-
<div class="row g-2 mt-2">
|
|
191
|
-
<div class="col-6">
|
|
192
|
-
<label for="customPort" class="form-label small">Port</label>
|
|
193
|
-
<input type="number" id="customPort" class="form-control" value="443" placeholder="443">
|
|
194
|
-
</div>
|
|
195
|
-
<div class="col-6 d-flex align-items-end">
|
|
196
|
-
<div class="form-check">
|
|
197
|
-
<input class="form-check-input" type="checkbox" id="customUseSsl" checked>
|
|
198
|
-
<label class="form-check-label" for="customUseSsl">
|
|
199
|
-
Use SSL
|
|
200
|
-
</label>
|
|
201
|
-
</div>
|
|
202
|
-
</div>
|
|
203
|
-
</div>
|
|
204
|
-
</div>
|
|
205
|
-
<div class="col-12 col-md-6">
|
|
206
|
-
<label for="personal_access_token" class="form-label">Personal Access Token <span class="text-danger">*</span></label>
|
|
207
|
-
<input type="password" id="personal_access_token" class="form-control" placeholder="Enter your Citra API token" required>
|
|
208
|
-
<small class="text-muted">Get your token and telescope ID from <a href="" id="appUrlLink" target="_blank"></a></small>
|
|
209
|
-
</div>
|
|
210
|
-
<div class="col-12 col-md-6">
|
|
211
|
-
<label for="telescopeId" class="form-label">Telescope ID <span class="text-danger">*</span></label>
|
|
212
|
-
<input type="text" id="telescopeId" class="form-control" placeholder="Enter telescope ID" required>
|
|
213
|
-
</div>
|
|
214
|
-
</div>
|
|
215
|
-
</div>
|
|
216
|
-
</div>
|
|
217
|
-
</div>
|
|
218
|
-
|
|
219
|
-
<!-- Hardware Configuration Card -->
|
|
220
|
-
<div class="col-12">
|
|
221
|
-
<div class="card bg-dark text-light border-secondary">
|
|
222
|
-
<div class="card-header">
|
|
223
|
-
<h5 class="mb-0">Hardware Configuration</h5>
|
|
224
|
-
</div>
|
|
225
|
-
<div class="card-body">
|
|
226
|
-
<div class="row g-3 mb-3">
|
|
227
|
-
<div class="col-12">
|
|
228
|
-
<label for="hardwareAdapterSelect" class="form-label">Hardware Adapter <span class="text-danger">*</span></label>
|
|
229
|
-
<select id="hardwareAdapterSelect" class="form-select" required>
|
|
230
|
-
<option value="">-- Select Hardware Adapter --</option>
|
|
231
|
-
<!-- Options populated dynamically from API -->
|
|
232
|
-
</select>
|
|
233
|
-
</div>
|
|
234
|
-
</div>
|
|
235
|
-
|
|
236
|
-
<!-- Dynamic Adapter Settings Container -->
|
|
237
|
-
<div id="adapter-settings-container"></div>
|
|
238
|
-
|
|
239
|
-
<!-- Filter Configuration Section (shown when adapter supports filters) -->
|
|
240
|
-
<div id="filterConfigSection" style="display: none; margin-top: 1.5rem;">
|
|
241
|
-
<hr class="border-secondary">
|
|
242
|
-
<h5 class="mb-3">Filter Configuration</h5>
|
|
243
|
-
<p id="filterAdapterChangeMessage" class="text-muted mb-3" style="display: none;">
|
|
244
|
-
Save configuration to edit filter settings for this adapter
|
|
245
|
-
</p>
|
|
246
|
-
<div class="row">
|
|
247
|
-
<!-- Filter List Column -->
|
|
248
|
-
<div class="col-12 col-md-6">
|
|
249
|
-
<h6 class="mb-2">Filters</h6>
|
|
250
|
-
<div id="filterTableContainer">
|
|
251
|
-
<table class="table table-dark table-sm">
|
|
252
|
-
<thead>
|
|
253
|
-
<tr>
|
|
254
|
-
<th>Enabled</th>
|
|
255
|
-
<th>Name</th>
|
|
256
|
-
<th>Focus Position</th>
|
|
257
|
-
</tr>
|
|
258
|
-
</thead>
|
|
259
|
-
<tbody id="filterTableBody">
|
|
260
|
-
<!-- Filter rows will be populated by JavaScript -->
|
|
261
|
-
</tbody>
|
|
262
|
-
</table>
|
|
263
|
-
<div id="noFiltersMessage" class="text-muted small" style="display: none;">
|
|
264
|
-
No filters configured. Connect to hardware to discover filters.
|
|
265
|
-
</div>
|
|
266
|
-
</div>
|
|
267
|
-
</div>
|
|
268
|
-
|
|
269
|
-
<!-- Autofocus Column -->
|
|
270
|
-
<div class="col-12 col-md-6">
|
|
271
|
-
<h6 class="mb-2">Autofocus</h6>
|
|
272
|
-
<div class="mb-3">
|
|
273
|
-
<button type="button" class="btn btn-sm btn-outline-primary w-100" id="runAutofocusButton">
|
|
274
|
-
<span id="autofocusButtonText">Run Autofocus</span>
|
|
275
|
-
<span id="autofocusButtonSpinner" class="spinner-border spinner-border-sm ms-2" style="display: none;" role="status"></span>
|
|
276
|
-
</button>
|
|
277
|
-
</div>
|
|
278
|
-
<div class="mb-3">
|
|
279
|
-
<label class="form-label small text-muted">Last Autofocus</label>
|
|
280
|
-
<div id="lastAutofocusDisplay" class="text-light">Never</div>
|
|
281
|
-
</div>
|
|
282
|
-
<div class="mb-3">
|
|
283
|
-
<div class="form-check">
|
|
284
|
-
<input class="form-check-input" type="checkbox" id="scheduled_autofocus_enabled">
|
|
285
|
-
<label class="form-check-label" for="scheduled_autofocus_enabled">
|
|
286
|
-
Enable Scheduled Autofocus
|
|
287
|
-
</label>
|
|
288
|
-
</div>
|
|
289
|
-
</div>
|
|
290
|
-
<div class="mb-3">
|
|
291
|
-
<label for="autofocus_interval_minutes" class="form-label small">Autofocus Interval</label>
|
|
292
|
-
<select id="autofocus_interval_minutes" class="form-select form-select-sm">
|
|
293
|
-
<option value="30">30 minutes</option>
|
|
294
|
-
<option value="60" selected>60 minutes</option>
|
|
295
|
-
<option value="120">120 minutes (2 hours)</option>
|
|
296
|
-
<option value="180">180 minutes (3 hours)</option>
|
|
297
|
-
</select>
|
|
298
|
-
</div>
|
|
299
|
-
<div id="nextAutofocusDisplay" class="small text-muted" style="display: none;">
|
|
300
|
-
Next autofocus in: <span id="nextAutofocusTime">--</span>
|
|
301
|
-
</div>
|
|
302
|
-
</div>
|
|
303
|
-
</div>
|
|
304
|
-
</div>
|
|
305
|
-
</div>
|
|
306
|
-
</div>
|
|
307
|
-
</div>
|
|
308
|
-
|
|
309
|
-
<!-- Logging Settings Card -->
|
|
310
|
-
<div class="col-12">
|
|
311
|
-
<div class="card bg-dark text-light border-secondary">
|
|
312
|
-
<div class="card-header">
|
|
313
|
-
<h5 class="mb-0">Logging Settings</h5>
|
|
314
|
-
</div>
|
|
315
|
-
<div class="card-body">
|
|
316
|
-
<div class="row g-3">
|
|
317
|
-
<div class="col-12 col-md-6">
|
|
318
|
-
<label for="logLevel" class="form-label">Log Level</label>
|
|
319
|
-
<select id="logLevel" class="form-select">
|
|
320
|
-
<option value="DEBUG">DEBUG</option>
|
|
321
|
-
<option value="INFO">INFO</option>
|
|
322
|
-
<option value="WARNING">WARNING</option>
|
|
323
|
-
<option value="ERROR">ERROR</option>
|
|
324
|
-
</select>
|
|
325
|
-
</div>
|
|
326
|
-
<div class="col-12 col-md-6">
|
|
327
|
-
<div class="form-check mt-4">
|
|
328
|
-
<input class="form-check-input" type="checkbox" id="file_logging_enabled">
|
|
329
|
-
<label class="form-check-label" for="file_logging_enabled">
|
|
330
|
-
Enable file logging
|
|
331
|
-
</label>
|
|
332
|
-
</div>
|
|
333
|
-
</div>
|
|
334
|
-
<div class="col-12">
|
|
335
|
-
<small class="text-muted">
|
|
336
|
-
Log file: <span id="logFilePath" class="text-secondary">Loading...</span>
|
|
337
|
-
</small>
|
|
338
|
-
</div>
|
|
339
|
-
</div>
|
|
340
|
-
</div>
|
|
341
|
-
</div>
|
|
342
|
-
</div>
|
|
343
|
-
|
|
344
|
-
<!-- Task Settings Card -->
|
|
345
|
-
<div class="col-12">
|
|
346
|
-
<div class="card bg-dark text-light border-secondary">
|
|
347
|
-
<div class="card-header">
|
|
348
|
-
<h5 class="mb-0">Task Settings</h5>
|
|
349
|
-
</div>
|
|
350
|
-
<div class="card-body">
|
|
351
|
-
<div class="row g-3">
|
|
352
|
-
<div class="col-12 col-md-6">
|
|
353
|
-
<div class="form-check mt-2">
|
|
354
|
-
<input class="form-check-input" type="checkbox" id="keep_images">
|
|
355
|
-
<label class="form-check-label" for="keep_images">
|
|
356
|
-
Keep captured images
|
|
357
|
-
</label>
|
|
358
|
-
</div>
|
|
359
|
-
<small class="text-muted ms-4">By default, images are deleted after upload unless this is enabled</small>
|
|
360
|
-
</div>
|
|
361
|
-
<div class="col-12">
|
|
362
|
-
<small class="text-muted">
|
|
363
|
-
Images directory: <span id="imagesDirPath" class="text-secondary">Loading...</span>
|
|
364
|
-
</small>
|
|
365
|
-
</div>
|
|
366
|
-
</div>
|
|
367
|
-
</div>
|
|
368
|
-
</div>
|
|
369
|
-
</div>
|
|
370
|
-
</div>
|
|
371
|
-
|
|
372
|
-
<!-- Save Button -->
|
|
373
|
-
<div class="row">
|
|
374
|
-
<div class="col">
|
|
375
|
-
<button type="submit" class="btn btn-primary" id="saveConfigButton">
|
|
376
|
-
<span id="saveButtonText">Save Configuration</span>
|
|
377
|
-
<span id="saveButtonSpinner" class="spinner-border spinner-border-sm ms-2" style="display: none;" role="status"></span>
|
|
378
|
-
</button>
|
|
379
|
-
<small class="text-muted ms-3">
|
|
380
|
-
Config file: <span id="configFilePath" class="text-secondary">Loading...</span>
|
|
381
|
-
</small>
|
|
382
|
-
</div>
|
|
383
|
-
</div>
|
|
384
|
-
</form>
|
|
385
|
-
</div>
|
|
386
62
|
|
|
387
63
|
<!-- Setup Wizard Modal -->
|
|
388
64
|
<div class="modal fade" id="setupWizard" data-bs-backdrop="static" data-bs-keyboard="false" tabindex="-1" aria-hidden="true">
|
|
@@ -399,9 +75,6 @@
|
|
|
399
75
|
<li>Your telescope ID</li>
|
|
400
76
|
<li>Information about your hardware adapter (INDI, N.I.N.A., or KStars)</li>
|
|
401
77
|
</ul>
|
|
402
|
-
<div class="alert alert-info">
|
|
403
|
-
<strong>Note:</strong> The configuration screen is available in the "Config" tab at the top of the page.
|
|
404
|
-
</div>
|
|
405
78
|
</div>
|
|
406
79
|
<div class="modal-footer border-secondary">
|
|
407
80
|
<button type="button" class="btn btn-primary" onclick="showConfigSection()">Configure Now</button>
|
|
@@ -418,7 +91,18 @@
|
|
|
418
91
|
<button class="accordion-button collapsed bg-secondary text-light log-accordion-button" type="button"
|
|
419
92
|
data-bs-toggle="collapse" data-bs-target="#logAccordionCollapse" aria-expanded="false"
|
|
420
93
|
aria-controls="logAccordionCollapse">
|
|
421
|
-
<span
|
|
94
|
+
<span class="log-latest-line">
|
|
95
|
+
<template x-if="!$store.citrascope.latestLog">
|
|
96
|
+
<span>Log Terminal</span>
|
|
97
|
+
</template>
|
|
98
|
+
<template x-if="$store.citrascope.latestLog">
|
|
99
|
+
<span>
|
|
100
|
+
<span class="log-timestamp" x-text="new Date($store.citrascope.latestLog.timestamp).toLocaleTimeString()"></span>
|
|
101
|
+
<span class="log-level" :class="'log-level-' + $store.citrascope.latestLog.level" x-text="$store.citrascope.latestLog.level"></span>
|
|
102
|
+
<span x-text="($store.citrascope.stripAnsiCodes($store.citrascope.latestLog.message) || '').substring(0, 150) + (($store.citrascope.latestLog.message || '').length > 150 ? '...' : '')"></span>
|
|
103
|
+
</span>
|
|
104
|
+
</template>
|
|
105
|
+
</span>
|
|
422
106
|
<div class="accordion-social-links">
|
|
423
107
|
<a href="https://github.com/citra-space/citrascope/issues/new" target="_blank" class="social-link" title="Report an Issue" onclick="event.stopPropagation();">
|
|
424
108
|
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor" viewBox="0 0 16 16">
|
|
@@ -441,29 +125,21 @@
|
|
|
441
125
|
<div id="logAccordionCollapse" class="accordion-collapse collapse" aria-labelledby="logAccordionHeader"
|
|
442
126
|
data-bs-parent="#logAccordion">
|
|
443
127
|
<div class="accordion-body p-0 log-accordion-body">
|
|
444
|
-
<div class="log-container p-3" id="logContainer">
|
|
445
|
-
<p class="text-muted-dark">
|
|
128
|
+
<div class="log-container p-3" id="logContainer" x-ref="logContainer">
|
|
129
|
+
<p class="text-muted-dark" x-show="$store.citrascope.logs.length === 0">No logs available</p>
|
|
130
|
+
<template x-for="(log, index) in $store.citrascope.logs" :key="index">
|
|
131
|
+
<div x-data="logEntry(log)" class="log-entry">
|
|
132
|
+
<span class="log-timestamp" x-text="timestamp"></span>
|
|
133
|
+
<span class="log-level" :class="levelClass" x-text="log.level"></span>
|
|
134
|
+
<span class="log-message" x-text="strippedMessage"></span>
|
|
135
|
+
</div>
|
|
136
|
+
</template>
|
|
446
137
|
</div>
|
|
447
138
|
</div>
|
|
448
139
|
</div>
|
|
449
140
|
</div>
|
|
450
141
|
</div>
|
|
451
142
|
|
|
452
|
-
<!-- Templates for log display -->
|
|
453
|
-
<template id="logEntryTemplate">
|
|
454
|
-
<div class="log-entry">
|
|
455
|
-
<span class="log-timestamp"></span>
|
|
456
|
-
<span class="log-level"></span>
|
|
457
|
-
<span class="log-message"></span>
|
|
458
|
-
</div>
|
|
459
|
-
</template>
|
|
460
|
-
|
|
461
|
-
<template id="latestLogLineTemplate">
|
|
462
|
-
<span class="log-timestamp"></span>
|
|
463
|
-
<span class="log-level"></span>
|
|
464
|
-
<span class="log-message"></span>
|
|
465
|
-
</template>
|
|
466
|
-
|
|
467
143
|
</div>
|
|
468
144
|
|
|
469
145
|
|
|
@@ -476,34 +152,34 @@
|
|
|
476
152
|
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Close"></button>
|
|
477
153
|
</div>
|
|
478
154
|
<div class="modal-body">
|
|
479
|
-
<div
|
|
155
|
+
<div x-show="$store.citrascope.versionCheckState === 'loading'" style="text-align: center;">
|
|
480
156
|
<div class="spinner-border text-primary" role="status">
|
|
481
157
|
<span class="visually-hidden">Checking...</span>
|
|
482
158
|
</div>
|
|
483
159
|
<p class="mt-2">Checking for updates...</p>
|
|
484
160
|
</div>
|
|
485
|
-
<div
|
|
161
|
+
<div x-show="$store.citrascope.versionCheckState === 'up-to-date'">
|
|
486
162
|
<p class="text-success">✓ You're up to date!</p>
|
|
487
163
|
<p>
|
|
488
|
-
<strong>Current version:</strong> <span
|
|
164
|
+
<strong>Current version:</strong> <span x-text="$store.citrascope.versionCheckResult?.currentVersion === 'development' ? 'development' : 'v' + ($store.citrascope.versionCheckResult?.currentVersion || '-')"></span>
|
|
489
165
|
</p>
|
|
490
166
|
</div>
|
|
491
|
-
<div
|
|
167
|
+
<div x-show="$store.citrascope.versionCheckState === 'update-available'">
|
|
492
168
|
<p class="text-warning">A new version of CitraScope is available!</p>
|
|
493
169
|
<p class="mb-3">
|
|
494
|
-
<strong>Current:</strong> <span
|
|
495
|
-
<strong>Latest:</strong> <span
|
|
170
|
+
<strong>Current:</strong> <span x-text="'v' + ($store.citrascope.versionCheckResult?.currentVersion || '-')"></span><br>
|
|
171
|
+
<strong>Latest:</strong> <span x-text="$store.citrascope.versionCheckResult?.latestVersion || '-'"></span>
|
|
496
172
|
</p>
|
|
497
173
|
<p class="mb-2">To upgrade, run:</p>
|
|
498
174
|
<pre class="bg-secondary p-2 rounded"><code>pip install -U citrascope</code></pre>
|
|
499
175
|
<p class="mb-0">
|
|
500
|
-
<a href="#"
|
|
176
|
+
<a :href="$store.citrascope.versionCheckResult?.releaseUrl || '#'" target="_blank" class="text-info">View release notes on GitHub →</a>
|
|
501
177
|
</p>
|
|
502
178
|
</div>
|
|
503
|
-
<div
|
|
179
|
+
<div x-show="$store.citrascope.versionCheckState === 'error'">
|
|
504
180
|
<p class="text-muted">Unable to check for updates. You may be offline or GitHub is unreachable.</p>
|
|
505
181
|
<p>
|
|
506
|
-
<strong>Current version:</strong> <span
|
|
182
|
+
<strong>Current version:</strong> <span x-text="$store.citrascope.versionCheckResult?.currentVersion === 'development' ? 'development' : ($store.citrascope.versionCheckResult?.currentVersion || '-')"></span>
|
|
507
183
|
</p>
|
|
508
184
|
</div>
|
|
509
185
|
</div>
|
|
@@ -514,6 +190,62 @@
|
|
|
514
190
|
</div>
|
|
515
191
|
</div>
|
|
516
192
|
|
|
193
|
+
<!-- Camera Control Modal -->
|
|
194
|
+
<div class="modal fade" id="cameraControlModal" tabindex="-1" aria-labelledby="cameraControlModalLabel" aria-hidden="true">
|
|
195
|
+
<div class="modal-dialog modal-lg modal-dialog-centered">
|
|
196
|
+
<div class="modal-content bg-dark text-light border-secondary">
|
|
197
|
+
<div class="modal-header border-secondary">
|
|
198
|
+
<h5 class="modal-title" id="cameraControlModalLabel"><i class="bi bi-camera"></i> Camera Control</h5>
|
|
199
|
+
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Close"></button>
|
|
200
|
+
</div>
|
|
201
|
+
<div class="modal-body">
|
|
202
|
+
<div class="row g-3">
|
|
203
|
+
<div class="col-12">
|
|
204
|
+
<label for="exposureDuration" class="form-label">Exposure Duration (seconds)</label>
|
|
205
|
+
<input type="number" class="form-control" x-model.number="$store.citrascope.exposureDuration" min="0.001" max="300" step="0.001">
|
|
206
|
+
<small class="text-muted">Range: 0.001 to 300 seconds</small>
|
|
207
|
+
</div>
|
|
208
|
+
</div>
|
|
209
|
+
|
|
210
|
+
<!-- Capture Result Area -->
|
|
211
|
+
<div x-show="$store.citrascope.captureResult" class="mt-3">
|
|
212
|
+
<hr class="border-secondary">
|
|
213
|
+
<h6>Latest Capture</h6>
|
|
214
|
+
<div class="alert alert-success mb-2">
|
|
215
|
+
<strong>Filename:</strong> <span x-text="$store.citrascope.captureResult?.filename"></span><br>
|
|
216
|
+
<strong>Format:</strong> <span x-text="$store.citrascope.captureResult?.format || 'Unknown'"></span>
|
|
217
|
+
</div>
|
|
218
|
+
|
|
219
|
+
<!-- Image Preview (only for PNG/JPG) -->
|
|
220
|
+
<div x-show="$store.citrascope.captureResult && ['PNG', 'JPG', 'JPEG'].includes($store.citrascope.captureResult.format)" class="mt-3">
|
|
221
|
+
<img :src="'/images/' + $store.citrascope.captureResult?.filename"
|
|
222
|
+
alt="Captured image"
|
|
223
|
+
class="img-fluid rounded border border-secondary"
|
|
224
|
+
style="max-height: 400px; width: auto; display: block; margin: 0 auto;">
|
|
225
|
+
</div>
|
|
226
|
+
</div>
|
|
227
|
+
|
|
228
|
+
<!-- Images Directory -->
|
|
229
|
+
<div class="mt-3">
|
|
230
|
+
<hr class="border-secondary">
|
|
231
|
+
<h6>Images Directory</h6>
|
|
232
|
+
<p class="text-muted small mb-1">All captured images are saved to:</p>
|
|
233
|
+
<p><a :href="'file://' + ($store.citrascope.config?.images_dir_path || '#')" x-text="$store.citrascope.config?.images_dir_path || 'Not set'" class="text-break"></a></p>
|
|
234
|
+
</div>
|
|
235
|
+
</div>
|
|
236
|
+
<div class="modal-footer border-secondary">
|
|
237
|
+
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
|
|
238
|
+
<button type="button" class="btn btn-primary" :disabled="$store.citrascope.isCapturing" @click="$store.citrascope.captureImage()">
|
|
239
|
+
<span x-text="$store.citrascope.isCapturing ? 'Capturing...' : 'Capture'"></span>
|
|
240
|
+
<span x-show="$store.citrascope.isCapturing" class="spinner-border spinner-border-sm ms-2" role="status">
|
|
241
|
+
<span class="visually-hidden">Capturing...</span>
|
|
242
|
+
</span>
|
|
243
|
+
</button>
|
|
244
|
+
</div>
|
|
245
|
+
</div>
|
|
246
|
+
</div>
|
|
247
|
+
</div>
|
|
248
|
+
|
|
517
249
|
<!-- Toast Container for Notifications -->
|
|
518
250
|
<div class="toast-container position-fixed top-0 end-0 p-3" style="z-index: 9999;" id="toastContainer"></div>
|
|
519
251
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: citrascope
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.9.0
|
|
4
4
|
Summary: Remotely control a telescope while it polls for tasks, collects and edge processes data, and delivers results and data for further processing.
|
|
5
5
|
Project-URL: Homepage, https://citra.space
|
|
6
6
|
Project-URL: Documentation, https://docs.citra.space/citrascope/
|
|
@@ -25,6 +25,8 @@ Requires-Python: <3.13,>=3.10
|
|
|
25
25
|
Requires-Dist: click
|
|
26
26
|
Requires-Dist: fastapi>=0.104.0
|
|
27
27
|
Requires-Dist: httpx
|
|
28
|
+
Requires-Dist: jinja2>=3.1.0
|
|
29
|
+
Requires-Dist: ntplib>=0.4.0
|
|
28
30
|
Requires-Dist: platformdirs>=4.0.0
|
|
29
31
|
Requires-Dist: python-dateutil
|
|
30
32
|
Requires-Dist: requests
|
|
@@ -36,6 +38,14 @@ Requires-Dist: dbus-python; extra == 'all'
|
|
|
36
38
|
Requires-Dist: pixelemon; extra == 'all'
|
|
37
39
|
Requires-Dist: plotly; extra == 'all'
|
|
38
40
|
Requires-Dist: pyindi-client; extra == 'all'
|
|
41
|
+
Provides-Extra: all-hardware
|
|
42
|
+
Requires-Dist: cv2-enumerate-cameras>=1.0.0; extra == 'all-hardware'
|
|
43
|
+
Requires-Dist: opencv-python>=4.8.0; extra == 'all-hardware'
|
|
44
|
+
Requires-Dist: picamera2>=0.3.12; extra == 'all-hardware'
|
|
45
|
+
Requires-Dist: pixelemon; extra == 'all-hardware'
|
|
46
|
+
Requires-Dist: plotly; extra == 'all-hardware'
|
|
47
|
+
Requires-Dist: pyindi-client; extra == 'all-hardware'
|
|
48
|
+
Requires-Dist: ximea-api>=1.0.0; extra == 'all-hardware'
|
|
39
49
|
Provides-Extra: build
|
|
40
50
|
Requires-Dist: build; extra == 'build'
|
|
41
51
|
Provides-Extra: deploy
|
|
@@ -58,10 +68,17 @@ Requires-Dist: plotly; extra == 'indi'
|
|
|
58
68
|
Requires-Dist: pyindi-client; extra == 'indi'
|
|
59
69
|
Provides-Extra: kstars
|
|
60
70
|
Requires-Dist: dbus-python; extra == 'kstars'
|
|
71
|
+
Provides-Extra: rpi
|
|
72
|
+
Requires-Dist: picamera2>=0.3.12; extra == 'rpi'
|
|
61
73
|
Provides-Extra: test
|
|
62
74
|
Requires-Dist: mockito; extra == 'test'
|
|
63
75
|
Requires-Dist: pytest; extra == 'test'
|
|
64
76
|
Requires-Dist: pytest-cov; extra == 'test'
|
|
77
|
+
Provides-Extra: usb-camera
|
|
78
|
+
Requires-Dist: cv2-enumerate-cameras>=1.0.0; extra == 'usb-camera'
|
|
79
|
+
Requires-Dist: opencv-python>=4.8.0; extra == 'usb-camera'
|
|
80
|
+
Provides-Extra: ximea
|
|
81
|
+
Requires-Dist: ximea-api>=1.0.0; extra == 'ximea'
|
|
65
82
|
Description-Content-Type: text/markdown
|
|
66
83
|
|
|
67
84
|
# CitraScope
|