citrascope 0.1.0__tar.gz → 0.3.0__tar.gz
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-0.1.0 → citrascope-0.3.0}/.github/copilot-instructions.md +42 -2
- citrascope-0.1.0/.github/workflows/publish.yml → citrascope-0.3.0/.github/workflows/pypi-publish.yml +1 -1
- {citrascope-0.1.0 → citrascope-0.3.0}/.github/workflows/pytest.yml +9 -4
- {citrascope-0.1.0 → citrascope-0.3.0}/.gitignore +2 -3
- citrascope-0.3.0/.python-version +1 -0
- {citrascope-0.1.0 → citrascope-0.3.0}/.vscode/launch.json +11 -2
- {citrascope-0.1.0 → citrascope-0.3.0}/PKG-INFO +68 -36
- {citrascope-0.1.0 → citrascope-0.3.0}/README.md +49 -31
- citrascope-0.3.0/citrascope/__main__.py +26 -0
- {citrascope-0.1.0 → citrascope-0.3.0}/citrascope/api/abstract_api_client.py +7 -0
- {citrascope-0.1.0 → citrascope-0.3.0}/citrascope/api/citra_api_client.py +30 -1
- citrascope-0.3.0/citrascope/citra_scope_daemon.py +243 -0
- {citrascope-0.1.0 → citrascope-0.3.0}/citrascope/hardware/abstract_astro_hardware_adapter.py +70 -2
- citrascope-0.3.0/citrascope/hardware/adapter_registry.py +94 -0
- citrascope-0.3.0/citrascope/hardware/indi_adapter.py +730 -0
- citrascope-0.3.0/citrascope/hardware/kstars_dbus_adapter.py +179 -0
- citrascope-0.3.0/citrascope/hardware/nina_adv_http_adapter.py +593 -0
- citrascope-0.3.0/citrascope/hardware/nina_adv_http_survey_template.json +328 -0
- citrascope-0.3.0/citrascope/logging/__init__.py +4 -0
- citrascope-0.3.0/citrascope/logging/_citrascope_logger.py +114 -0
- citrascope-0.3.0/citrascope/logging/web_log_handler.py +74 -0
- citrascope-0.3.0/citrascope/settings/citrascope_settings.py +145 -0
- citrascope-0.3.0/citrascope/settings/settings_file_manager.py +126 -0
- citrascope-0.3.0/citrascope/tasks/runner.py +252 -0
- {citrascope-0.1.0 → citrascope-0.3.0}/citrascope/tasks/scope/base_telescope_task.py +25 -10
- citrascope-0.3.0/citrascope/tasks/scope/static_telescope_task.py +24 -0
- citrascope-0.3.0/citrascope/web/__init__.py +1 -0
- citrascope-0.3.0/citrascope/web/app.py +470 -0
- citrascope-0.3.0/citrascope/web/server.py +123 -0
- citrascope-0.3.0/citrascope/web/static/api.js +82 -0
- citrascope-0.3.0/citrascope/web/static/app.js +500 -0
- citrascope-0.3.0/citrascope/web/static/config.js +362 -0
- citrascope-0.3.0/citrascope/web/static/img/citra.png +0 -0
- citrascope-0.3.0/citrascope/web/static/img/favicon.png +0 -0
- citrascope-0.3.0/citrascope/web/static/style.css +120 -0
- citrascope-0.3.0/citrascope/web/static/websocket.js +127 -0
- citrascope-0.3.0/citrascope/web/templates/dashboard.html +354 -0
- {citrascope-0.1.0 → citrascope-0.3.0}/pyproject.toml +29 -5
- {citrascope-0.1.0/tests → citrascope-0.3.0/tests/unit}/test_hardware_adapter.py +23 -0
- citrascope-0.3.0/tests/unit/test_task_manager.py +299 -0
- {citrascope-0.1.0/tests → citrascope-0.3.0/tests/unit}/utils.py +4 -0
- citrascope-0.1.0/.env.example +0 -8
- citrascope-0.1.0/.github/workflows/docker-publish.yml +0 -29
- citrascope-0.1.0/Dockerfile +0 -30
- citrascope-0.1.0/citrascope/__main__.py +0 -23
- citrascope-0.1.0/citrascope/citra_scope_daemon.py +0 -90
- citrascope-0.1.0/citrascope/hardware/indi_adapter.py +0 -290
- citrascope-0.1.0/citrascope/logging/__init__.py +0 -3
- citrascope-0.1.0/citrascope/logging/_citrascope_logger.py +0 -35
- citrascope-0.1.0/citrascope/settings/_citrascope_settings.py +0 -42
- citrascope-0.1.0/citrascope/tasks/runner.py +0 -156
- citrascope-0.1.0/citrascope/tasks/scope/static_telescope_task.py +0 -16
- {citrascope-0.1.0 → citrascope-0.3.0}/.devcontainer/devcontainer.json +0 -0
- {citrascope-0.1.0 → citrascope-0.3.0}/.flake8 +0 -0
- {citrascope-0.1.0 → citrascope-0.3.0}/.github/dependabot.yml +0 -0
- {citrascope-0.1.0 → citrascope-0.3.0}/.pre-commit-config.yaml +0 -0
- {citrascope-0.1.0 → citrascope-0.3.0}/citrascope/__init__.py +0 -0
- {citrascope-0.1.0 → citrascope-0.3.0}/citrascope/settings/__init__.py +0 -0
- {citrascope-0.1.0 → citrascope-0.3.0}/citrascope/tasks/scope/tracking_telescope_task.py +0 -0
- {citrascope-0.1.0 → citrascope-0.3.0}/citrascope/tasks/task.py +0 -0
- {citrascope-0.1.0 → citrascope-0.3.0}/docs/index.md +0 -0
- {citrascope-0.1.0/tests → citrascope-0.3.0/tests/unit}/test_api_client.py +0 -0
|
@@ -12,10 +12,18 @@ This project is a Python package for interacting with astronomical data and serv
|
|
|
12
12
|
|
|
13
13
|
## Directory Structure
|
|
14
14
|
- `citrascope/api/`: API client code
|
|
15
|
-
- `citrascope/
|
|
15
|
+
- `citrascope/hardware/`: Hardware adapter implementations and registry
|
|
16
|
+
- `adapter_registry.py`: Central registry for all hardware adapters (add new adapters here)
|
|
17
|
+
- `abstract_astro_hardware_adapter.py`: Base class all adapters must implement
|
|
18
|
+
- Individual adapter implementations (indi_adapter.py, nina_adv_http_adapter.py, etc.)
|
|
16
19
|
- `citrascope/logging/`: Logging utilities
|
|
17
20
|
- `citrascope/settings/`: Settings and configuration
|
|
18
21
|
- `citrascope/tasks/`: Task runner and definitions
|
|
22
|
+
- `citrascope/web/`: Web interface for monitoring and configuration
|
|
23
|
+
- `citrascope/web/app.py`: FastAPI application and routes
|
|
24
|
+
- `citrascope/web/server.py`: Web server management and threading
|
|
25
|
+
- `citrascope/web/templates/`: HTML templates
|
|
26
|
+
- `citrascope/web/static/`: CSS and JavaScript files
|
|
19
27
|
- `tests/`: Unit and integration tests
|
|
20
28
|
- `docs/`: Project documentation
|
|
21
29
|
|
|
@@ -32,12 +40,39 @@ This project is a Python package for interacting with astronomical data and serv
|
|
|
32
40
|
|
|
33
41
|
## Common Tasks
|
|
34
42
|
- Add new API integrations in `citrascope/api/`.
|
|
35
|
-
- Extend
|
|
43
|
+
- Extend or add hardware adapters:
|
|
44
|
+
- Create new adapter class implementing `AbstractAstroHardwareAdapter` in `citrascope/hardware/`
|
|
45
|
+
- Register it in `citrascope/hardware/adapter_registry.py` by adding an entry to `REGISTERED_ADAPTERS`
|
|
46
|
+
- All adapter discovery and instantiation flows from this registry
|
|
36
47
|
- Update logging logic in `citrascope/logging/`.
|
|
37
48
|
- Change settings in `citrascope/settings/`.
|
|
38
49
|
- Add or modify tasks in `citrascope/tasks/`.
|
|
50
|
+
- Enhance web interface in `citrascope/web/`.
|
|
39
51
|
- Write or update tests in `tests/`.
|
|
40
52
|
|
|
53
|
+
## Web Interface Guidelines
|
|
54
|
+
|
|
55
|
+
The web interface provides real-time monitoring and configuration for telescope operations. When working on web-related features:
|
|
56
|
+
|
|
57
|
+
### Design Principles
|
|
58
|
+
- **Dark theme required**: All UI elements must use dark colors suitable for nighttime telescope operations to preserve night vision
|
|
59
|
+
- **Real-time updates**: Use WebSocket connections for live status, logs, and telemetry
|
|
60
|
+
- **Mobile-friendly**: The interface should be responsive and usable on tablets/phones in the field
|
|
61
|
+
- **Minimal distractions**: Reduce visual clutter; prioritize essential telescope and task information
|
|
62
|
+
|
|
63
|
+
### Architecture
|
|
64
|
+
- **FastAPI backend** (`web/app.py`): RESTful API endpoints and WebSocket handlers
|
|
65
|
+
- **Separate thread**: Web server runs in daemon thread with its own event loop (`web/server.py`)
|
|
66
|
+
- **Log streaming**: Custom `WebLogHandler` broadcasts logs to web clients in real-time
|
|
67
|
+
- **Static files**: HTML, CSS, and JavaScript are served from `web/templates/` and `web/static/`
|
|
68
|
+
|
|
69
|
+
### Development Notes
|
|
70
|
+
- Keep web-specific code isolated in the `citrascope/web/` directory
|
|
71
|
+
- The daemon should only call `web_server.start()` - all web complexity stays in `web/server.py`
|
|
72
|
+
- Filter out noise from web logs (HTTP requests, WebSocket events, Uvicorn messages)
|
|
73
|
+
- Use thread-safe mechanisms when accessing daemon state from web handlers
|
|
74
|
+
- Port 24872 (CITRA on phone keypad) is the default web interface port
|
|
75
|
+
|
|
41
76
|
## Important Packages
|
|
42
77
|
|
|
43
78
|
This project relies on several key Python packages. Below are some of the most important ones and their roles:
|
|
@@ -58,6 +93,11 @@ This project relies on several key Python packages. Below are some of the most i
|
|
|
58
93
|
- **Flake8**: Enforces code style and linting rules.
|
|
59
94
|
- **Sphinx**: Generates project documentation.
|
|
60
95
|
|
|
96
|
+
### Web Interface Dependencies
|
|
97
|
+
- **FastAPI**: Modern async web framework for the monitoring interface
|
|
98
|
+
- **Uvicorn**: ASGI server for running the web application
|
|
99
|
+
- **WebSockets**: Real-time bidirectional communication for live updates
|
|
100
|
+
|
|
61
101
|
For a complete list of dependencies, refer to the `pyproject.toml` file.
|
|
62
102
|
|
|
63
103
|
## Additional Notes
|
|
@@ -9,24 +9,29 @@ on:
|
|
|
9
9
|
jobs:
|
|
10
10
|
test:
|
|
11
11
|
runs-on: ubuntu-latest
|
|
12
|
+
strategy:
|
|
13
|
+
fail-fast: false
|
|
14
|
+
matrix:
|
|
15
|
+
python-version: ['3.10', '3.11', '3.12']
|
|
12
16
|
steps:
|
|
13
17
|
- name: Checkout code
|
|
14
18
|
uses: actions/checkout@v4
|
|
15
|
-
- name: Set up Python
|
|
19
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
16
20
|
uses: actions/setup-python@v5
|
|
17
21
|
with:
|
|
18
|
-
python-version:
|
|
22
|
+
python-version: ${{ matrix.python-version }}
|
|
19
23
|
- name: Install project prerequisites
|
|
20
24
|
run: sudo apt-get update && sudo apt-get install -y libglib2.0-dev libdbus-1-dev libjpeg-dev zlib1g-dev
|
|
21
25
|
- name: Install dependencies
|
|
22
26
|
run: |
|
|
23
27
|
pip install --upgrade pip
|
|
24
|
-
pip install .[dev,test]
|
|
28
|
+
pip install .[dev,test,indi,all]
|
|
25
29
|
- name: Run pytest with coverage
|
|
26
30
|
run: |
|
|
27
|
-
pytest --cov=citrascope --cov-report=term-missing --cov-report=xml --cov-branch
|
|
31
|
+
pytest -m "not integration" --cov=citrascope --cov-report=term-missing --cov-report=xml --cov-branch
|
|
28
32
|
- name: Upload coverage report
|
|
29
33
|
uses: actions/upload-artifact@v4
|
|
34
|
+
if: matrix.python-version == '3.12'
|
|
30
35
|
with:
|
|
31
36
|
name: coverage-xml
|
|
32
37
|
path: coverage.xml
|
|
@@ -81,9 +81,6 @@ target/
|
|
|
81
81
|
profile_default/
|
|
82
82
|
ipython_config.py
|
|
83
83
|
|
|
84
|
-
# pyenv
|
|
85
|
-
.python-version
|
|
86
|
-
|
|
87
84
|
# pipenv
|
|
88
85
|
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
|
89
86
|
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
|
@@ -141,3 +138,5 @@ citra_image.fits
|
|
|
141
138
|
/images/*
|
|
142
139
|
.DS_Store
|
|
143
140
|
hip_main.dat
|
|
141
|
+
nina_sequence_*.json
|
|
142
|
+
nina_focus_positions.json
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.12
|
|
@@ -5,16 +5,25 @@
|
|
|
5
5
|
"configurations": [
|
|
6
6
|
{
|
|
7
7
|
"name": "Python: citrascope dev start",
|
|
8
|
-
"type": "
|
|
8
|
+
"type": "debugpy",
|
|
9
9
|
"request": "launch",
|
|
10
10
|
"module": "citrascope",
|
|
11
11
|
"args": ["--dev", "start"],
|
|
12
12
|
"console": "integratedTerminal",
|
|
13
13
|
"justMyCode": false
|
|
14
14
|
},
|
|
15
|
+
{
|
|
16
|
+
"name": "Python: citrascope dev start, keep images",
|
|
17
|
+
"type": "debugpy",
|
|
18
|
+
"request": "launch",
|
|
19
|
+
"module": "citrascope",
|
|
20
|
+
"args": ["--dev", "--keep-images", "start"],
|
|
21
|
+
"console": "integratedTerminal",
|
|
22
|
+
"justMyCode": false
|
|
23
|
+
},
|
|
15
24
|
{
|
|
16
25
|
"name": "Python: citrascope dev start DEBUG logging",
|
|
17
|
-
"type": "
|
|
26
|
+
"type": "debugpy",
|
|
18
27
|
"request": "launch",
|
|
19
28
|
"module": "citrascope",
|
|
20
29
|
"args": ["--dev", "--log-level", "DEBUG", "start"],
|
|
@@ -1,27 +1,35 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: citrascope
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.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
|
-
Author-email:
|
|
5
|
+
Author-email: Patrick McDavid <patrick@citra.space>
|
|
6
6
|
License-Expression: MIT
|
|
7
|
-
Requires-Python:
|
|
7
|
+
Requires-Python: <3.13,>=3.10
|
|
8
8
|
Requires-Dist: click
|
|
9
|
+
Requires-Dist: fastapi>=0.104.0
|
|
9
10
|
Requires-Dist: httpx
|
|
10
|
-
Requires-Dist:
|
|
11
|
+
Requires-Dist: platformdirs>=4.0.0
|
|
11
12
|
Requires-Dist: pydantic-settings
|
|
12
|
-
Requires-Dist: pyindi-client
|
|
13
13
|
Requires-Dist: pytest-cov
|
|
14
14
|
Requires-Dist: python-dateutil
|
|
15
15
|
Requires-Dist: python-json-logger
|
|
16
16
|
Requires-Dist: requests
|
|
17
17
|
Requires-Dist: skyfield
|
|
18
18
|
Requires-Dist: types-python-dateutil
|
|
19
|
+
Requires-Dist: uvicorn[standard]>=0.24.0
|
|
20
|
+
Requires-Dist: websockets>=12.0
|
|
21
|
+
Provides-Extra: all
|
|
22
|
+
Requires-Dist: dbus-python; extra == 'all'
|
|
23
|
+
Requires-Dist: pixelemon; extra == 'all'
|
|
24
|
+
Requires-Dist: plotly; extra == 'all'
|
|
25
|
+
Requires-Dist: pyindi-client; extra == 'all'
|
|
19
26
|
Provides-Extra: build
|
|
20
27
|
Requires-Dist: build; extra == 'build'
|
|
21
28
|
Provides-Extra: deploy
|
|
22
29
|
Requires-Dist: twine; extra == 'deploy'
|
|
23
30
|
Provides-Extra: dev
|
|
24
31
|
Requires-Dist: black; extra == 'dev'
|
|
32
|
+
Requires-Dist: bump-my-version; extra == 'dev'
|
|
25
33
|
Requires-Dist: flake8; extra == 'dev'
|
|
26
34
|
Requires-Dist: flake8-pytest-style; extra == 'dev'
|
|
27
35
|
Requires-Dist: isort; extra == 'dev'
|
|
@@ -34,6 +42,12 @@ Provides-Extra: docs
|
|
|
34
42
|
Requires-Dist: sphinx; extra == 'docs'
|
|
35
43
|
Requires-Dist: sphinx-autodoc-typehints; extra == 'docs'
|
|
36
44
|
Requires-Dist: sphinx-markdown-builder; extra == 'docs'
|
|
45
|
+
Provides-Extra: indi
|
|
46
|
+
Requires-Dist: pixelemon; extra == 'indi'
|
|
47
|
+
Requires-Dist: plotly; extra == 'indi'
|
|
48
|
+
Requires-Dist: pyindi-client; extra == 'indi'
|
|
49
|
+
Provides-Extra: kstars
|
|
50
|
+
Requires-Dist: dbus-python; extra == 'kstars'
|
|
37
51
|
Provides-Extra: test
|
|
38
52
|
Requires-Dist: mockito; extra == 'test'
|
|
39
53
|
Requires-Dist: pytest; extra == 'test'
|
|
@@ -41,24 +55,44 @@ Requires-Dist: pytest-cov; extra == 'test'
|
|
|
41
55
|
Description-Content-Type: text/markdown
|
|
42
56
|
|
|
43
57
|
# CitraScope
|
|
44
|
-
[](https://github.com/citra-space/citrascope/actions/workflows/pytest.yml) [](https://github.com/citra-space/citrascope/actions/workflows/pytest.yml) [](https://github.com/citra-space/citrascope/actions/workflows/pypi-publish.yml)
|
|
45
59
|
|
|
46
60
|
Remotely control a telescope while it polls for tasks, collects observations, and delivers data for further processing.
|
|
47
61
|
|
|
48
62
|
## Features
|
|
49
|
-
|
|
63
|
+
- Offers a web UI to configure hardware and connect to Citra.space's api
|
|
50
64
|
- Connects to Citra.space's API and identifies itself as an online telescope
|
|
51
|
-
- Connects to configured
|
|
65
|
+
- Connects to configured telescope and camera hardware
|
|
52
66
|
- Acts as a task daemon carrying out and remitting photography tasks
|
|
53
67
|
|
|
54
68
|
## Installation
|
|
55
69
|
|
|
56
|
-
Install
|
|
70
|
+
### Install with pipx
|
|
71
|
+
|
|
72
|
+
[pipx](https://pipx.pypa.io/) installs the CLI tool in an isolated environment while making it globally available:
|
|
57
73
|
|
|
58
74
|
```sh
|
|
59
|
-
|
|
75
|
+
pipx install citrascope
|
|
60
76
|
```
|
|
61
77
|
|
|
78
|
+
### Optional Dependencies
|
|
79
|
+
|
|
80
|
+
CitraScope supports different hardware adapters through optional dependency groups:
|
|
81
|
+
|
|
82
|
+
- **INDI adapter** (for Linux-based telescope control):
|
|
83
|
+
```sh
|
|
84
|
+
pipx install citrascope[indi]
|
|
85
|
+
# or with pip: pip install citrascope[indi]
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
- **All optional dependencies**:
|
|
89
|
+
```sh
|
|
90
|
+
pipx install citrascope[all]
|
|
91
|
+
# or with pip: pip install citrascope[all]
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
The base installation without optional dependencies supports the NINA adapter, which works via HTTP API calls and does not require additional Python packages.
|
|
95
|
+
|
|
62
96
|
This provides the `citrascope` command-line tool. To see available commands:
|
|
63
97
|
|
|
64
98
|
```sh
|
|
@@ -79,31 +113,6 @@ To connect to the Citra Dev server:
|
|
|
79
113
|
citrascope start --dev
|
|
80
114
|
```
|
|
81
115
|
|
|
82
|
-
## Configuration
|
|
83
|
-
|
|
84
|
-
Settings are managed via environment variables with the prefix `CITRASCOPE_`. You must configure your personal access token and telescope ID, as well as INDI server details. You can set these variables in your shell or in a `.env` file at the project root.
|
|
85
|
-
|
|
86
|
-
Example `.env` file:
|
|
87
|
-
|
|
88
|
-
```env
|
|
89
|
-
CITRASCOPE_PERSONAL_ACCESS_TOKEN=citra_pat_xxx
|
|
90
|
-
CITRASCOPE_TELESCOPE_ID=xxx
|
|
91
|
-
# CITRASCOPE_INDI_SERVER_URL=127.0.0.1
|
|
92
|
-
CITRASCOPE_INDI_SERVER_URL=host.docker.internal # use with devcontainer for accessing a localhost indi server
|
|
93
|
-
CITRASCOPE_INDI_SERVER_PORT=7624
|
|
94
|
-
CITRASCOPE_INDI_TELESCOPE_NAME=Telescope Simulator
|
|
95
|
-
```
|
|
96
|
-
|
|
97
|
-
**Variable descriptions:**
|
|
98
|
-
|
|
99
|
-
- `CITRASCOPE_PERSONAL_ACCESS_TOKEN`: Your CitraScope personal access token (required)
|
|
100
|
-
- `CITRASCOPE_TELESCOPE_ID`: Your telescope ID (required)
|
|
101
|
-
- `CITRASCOPE_INDI_SERVER_URL`: Hostname or IP address of the INDI server (default: `host.docker.internal` for devcontainers, or `127.0.0.1` for local)
|
|
102
|
-
- `CITRASCOPE_INDI_SERVER_PORT`: Port for the INDI server (default: `7624`)
|
|
103
|
-
- `CITRASCOPE_INDI_TELESCOPE_NAME`: Name of the INDI telescope device (default: `Telescope Simulator`)
|
|
104
|
-
|
|
105
|
-
You can copy `.env.example` to `.env` and tweak your values.
|
|
106
|
-
|
|
107
116
|
## Developer Setup
|
|
108
117
|
|
|
109
118
|
If you are developing on macOS or Windows, use the provided [VS Code Dev Container](https://code.visualstudio.com/docs/devcontainers/containers) setup. The devcontainer provides a full Linux environment, which is required for the `pyindi-client` dependency to work. This is necessary because `pyindi-client` only works on Linux, and will not function natively on Mac or Windows.
|
|
@@ -112,6 +121,16 @@ By opening this project in VS Code and choosing "Reopen in Container" (or using
|
|
|
112
121
|
|
|
113
122
|
The devcontainer also ensures all required system dependencies (like `cmake`) are installed automatically.
|
|
114
123
|
|
|
124
|
+
### Python Version
|
|
125
|
+
|
|
126
|
+
This project requires Python 3.10 or higher, up to Python 3.12. A `.python-version` file is included specifying Python 3.12 as the recommended version. If you use [pyenv](https://github.com/pyenv/pyenv), it will automatically use this version when you enter the project directory.
|
|
127
|
+
|
|
128
|
+
### If not using the dev container:
|
|
129
|
+
```sh
|
|
130
|
+
python -m venv .venv
|
|
131
|
+
source .venv/bin/activate
|
|
132
|
+
```
|
|
133
|
+
|
|
115
134
|
### Installing Development Dependencies
|
|
116
135
|
|
|
117
136
|
To install development dependencies (for code style, linting, and pre-commit hooks):
|
|
@@ -138,6 +157,19 @@ pre-commit run --all-files
|
|
|
138
157
|
|
|
139
158
|
This ensures code style and quality checks are enforced for all contributors.
|
|
140
159
|
|
|
160
|
+
### Releasing a New Version
|
|
161
|
+
|
|
162
|
+
To bump the version and create a release:
|
|
163
|
+
|
|
164
|
+
```sh
|
|
165
|
+
bump-my-version bump patch # 0.1.3 → 0.1.4
|
|
166
|
+
bump-my-version bump minor # 0.1.3 → 0.2.0
|
|
167
|
+
bump-my-version bump major # 0.1.3 → 1.0.0
|
|
168
|
+
git push && git push --tags
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
Then create a release in the GitHub UI from the new tag. This triggers automatic PyPI publishing.
|
|
172
|
+
|
|
141
173
|
### Running and Debugging with VS Code
|
|
142
174
|
|
|
143
175
|
If you are using Visual Studio Code, you can run or debug the project directly using the pre-configured launch options in `.vscode/launch.json`:
|
|
@@ -151,7 +183,7 @@ To use these, open the Run and Debug panel in VS Code, select the desired config
|
|
|
151
183
|
|
|
152
184
|
This project uses [pytest](https://pytest.org/) for unit testing. All tests are located in the `tests/` directory.
|
|
153
185
|
|
|
154
|
-
To run tests
|
|
186
|
+
To run unit tests within your devcontainer:
|
|
155
187
|
|
|
156
188
|
```bash
|
|
157
189
|
pytest
|
|
@@ -1,22 +1,42 @@
|
|
|
1
1
|
# CitraScope
|
|
2
|
-
[](https://github.com/citra-space/citrascope/actions/workflows/pytest.yml) [](https://github.com/citra-space/citrascope/actions/workflows/pytest.yml) [](https://github.com/citra-space/citrascope/actions/workflows/pypi-publish.yml)
|
|
3
3
|
|
|
4
4
|
Remotely control a telescope while it polls for tasks, collects observations, and delivers data for further processing.
|
|
5
5
|
|
|
6
6
|
## Features
|
|
7
|
-
|
|
7
|
+
- Offers a web UI to configure hardware and connect to Citra.space's api
|
|
8
8
|
- Connects to Citra.space's API and identifies itself as an online telescope
|
|
9
|
-
- Connects to configured
|
|
9
|
+
- Connects to configured telescope and camera hardware
|
|
10
10
|
- Acts as a task daemon carrying out and remitting photography tasks
|
|
11
11
|
|
|
12
12
|
## Installation
|
|
13
13
|
|
|
14
|
-
Install
|
|
14
|
+
### Install with pipx
|
|
15
|
+
|
|
16
|
+
[pipx](https://pipx.pypa.io/) installs the CLI tool in an isolated environment while making it globally available:
|
|
15
17
|
|
|
16
18
|
```sh
|
|
17
|
-
|
|
19
|
+
pipx install citrascope
|
|
18
20
|
```
|
|
19
21
|
|
|
22
|
+
### Optional Dependencies
|
|
23
|
+
|
|
24
|
+
CitraScope supports different hardware adapters through optional dependency groups:
|
|
25
|
+
|
|
26
|
+
- **INDI adapter** (for Linux-based telescope control):
|
|
27
|
+
```sh
|
|
28
|
+
pipx install citrascope[indi]
|
|
29
|
+
# or with pip: pip install citrascope[indi]
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
- **All optional dependencies**:
|
|
33
|
+
```sh
|
|
34
|
+
pipx install citrascope[all]
|
|
35
|
+
# or with pip: pip install citrascope[all]
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
The base installation without optional dependencies supports the NINA adapter, which works via HTTP API calls and does not require additional Python packages.
|
|
39
|
+
|
|
20
40
|
This provides the `citrascope` command-line tool. To see available commands:
|
|
21
41
|
|
|
22
42
|
```sh
|
|
@@ -37,31 +57,6 @@ To connect to the Citra Dev server:
|
|
|
37
57
|
citrascope start --dev
|
|
38
58
|
```
|
|
39
59
|
|
|
40
|
-
## Configuration
|
|
41
|
-
|
|
42
|
-
Settings are managed via environment variables with the prefix `CITRASCOPE_`. You must configure your personal access token and telescope ID, as well as INDI server details. You can set these variables in your shell or in a `.env` file at the project root.
|
|
43
|
-
|
|
44
|
-
Example `.env` file:
|
|
45
|
-
|
|
46
|
-
```env
|
|
47
|
-
CITRASCOPE_PERSONAL_ACCESS_TOKEN=citra_pat_xxx
|
|
48
|
-
CITRASCOPE_TELESCOPE_ID=xxx
|
|
49
|
-
# CITRASCOPE_INDI_SERVER_URL=127.0.0.1
|
|
50
|
-
CITRASCOPE_INDI_SERVER_URL=host.docker.internal # use with devcontainer for accessing a localhost indi server
|
|
51
|
-
CITRASCOPE_INDI_SERVER_PORT=7624
|
|
52
|
-
CITRASCOPE_INDI_TELESCOPE_NAME=Telescope Simulator
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
**Variable descriptions:**
|
|
56
|
-
|
|
57
|
-
- `CITRASCOPE_PERSONAL_ACCESS_TOKEN`: Your CitraScope personal access token (required)
|
|
58
|
-
- `CITRASCOPE_TELESCOPE_ID`: Your telescope ID (required)
|
|
59
|
-
- `CITRASCOPE_INDI_SERVER_URL`: Hostname or IP address of the INDI server (default: `host.docker.internal` for devcontainers, or `127.0.0.1` for local)
|
|
60
|
-
- `CITRASCOPE_INDI_SERVER_PORT`: Port for the INDI server (default: `7624`)
|
|
61
|
-
- `CITRASCOPE_INDI_TELESCOPE_NAME`: Name of the INDI telescope device (default: `Telescope Simulator`)
|
|
62
|
-
|
|
63
|
-
You can copy `.env.example` to `.env` and tweak your values.
|
|
64
|
-
|
|
65
60
|
## Developer Setup
|
|
66
61
|
|
|
67
62
|
If you are developing on macOS or Windows, use the provided [VS Code Dev Container](https://code.visualstudio.com/docs/devcontainers/containers) setup. The devcontainer provides a full Linux environment, which is required for the `pyindi-client` dependency to work. This is necessary because `pyindi-client` only works on Linux, and will not function natively on Mac or Windows.
|
|
@@ -70,6 +65,16 @@ By opening this project in VS Code and choosing "Reopen in Container" (or using
|
|
|
70
65
|
|
|
71
66
|
The devcontainer also ensures all required system dependencies (like `cmake`) are installed automatically.
|
|
72
67
|
|
|
68
|
+
### Python Version
|
|
69
|
+
|
|
70
|
+
This project requires Python 3.10 or higher, up to Python 3.12. A `.python-version` file is included specifying Python 3.12 as the recommended version. If you use [pyenv](https://github.com/pyenv/pyenv), it will automatically use this version when you enter the project directory.
|
|
71
|
+
|
|
72
|
+
### If not using the dev container:
|
|
73
|
+
```sh
|
|
74
|
+
python -m venv .venv
|
|
75
|
+
source .venv/bin/activate
|
|
76
|
+
```
|
|
77
|
+
|
|
73
78
|
### Installing Development Dependencies
|
|
74
79
|
|
|
75
80
|
To install development dependencies (for code style, linting, and pre-commit hooks):
|
|
@@ -96,6 +101,19 @@ pre-commit run --all-files
|
|
|
96
101
|
|
|
97
102
|
This ensures code style and quality checks are enforced for all contributors.
|
|
98
103
|
|
|
104
|
+
### Releasing a New Version
|
|
105
|
+
|
|
106
|
+
To bump the version and create a release:
|
|
107
|
+
|
|
108
|
+
```sh
|
|
109
|
+
bump-my-version bump patch # 0.1.3 → 0.1.4
|
|
110
|
+
bump-my-version bump minor # 0.1.3 → 0.2.0
|
|
111
|
+
bump-my-version bump major # 0.1.3 → 1.0.0
|
|
112
|
+
git push && git push --tags
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Then create a release in the GitHub UI from the new tag. This triggers automatic PyPI publishing.
|
|
116
|
+
|
|
99
117
|
### Running and Debugging with VS Code
|
|
100
118
|
|
|
101
119
|
If you are using Visual Studio Code, you can run or debug the project directly using the pre-configured launch options in `.vscode/launch.json`:
|
|
@@ -109,7 +127,7 @@ To use these, open the Run and Debug panel in VS Code, select the desired config
|
|
|
109
127
|
|
|
110
128
|
This project uses [pytest](https://pytest.org/) for unit testing. All tests are located in the `tests/` directory.
|
|
111
129
|
|
|
112
|
-
To run tests
|
|
130
|
+
To run unit tests within your devcontainer:
|
|
113
131
|
|
|
114
132
|
```bash
|
|
115
133
|
pytest
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import click
|
|
2
|
+
|
|
3
|
+
from citrascope.citra_scope_daemon import CitraScopeDaemon
|
|
4
|
+
from citrascope.settings.citrascope_settings import CitraScopeSettings
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
@click.group()
|
|
8
|
+
@click.option("--dev", is_flag=True, default=False, help="Use the development API (dev.app.citra.space)")
|
|
9
|
+
@click.option("--log-level", default="INFO", help="Set logging level (DEBUG, INFO, WARNING, ERROR, CRITICAL)")
|
|
10
|
+
@click.option("--keep-images", is_flag=True, default=False, help="Keep image files after upload (do not delete)")
|
|
11
|
+
@click.pass_context
|
|
12
|
+
def cli(ctx, dev, log_level, keep_images):
|
|
13
|
+
ctx.obj = {"settings": CitraScopeSettings(dev=dev, log_level=log_level, keep_images=keep_images)}
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@cli.command("start")
|
|
17
|
+
@click.option("--web-host", default="0.0.0.0", help="Web server host address (default: 0.0.0.0)")
|
|
18
|
+
@click.option("--web-port", default=24872, type=int, help="Web server port (default: 24872)")
|
|
19
|
+
@click.pass_context
|
|
20
|
+
def start(ctx, web_host, web_port):
|
|
21
|
+
daemon = CitraScopeDaemon(ctx.obj["settings"], enable_web=True, web_host=web_host, web_port=web_port)
|
|
22
|
+
daemon.run()
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
if __name__ == "__main__":
|
|
26
|
+
cli()
|
|
@@ -6,6 +6,20 @@ from .abstract_api_client import AbstractCitraApiClient
|
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
class CitraApiClient(AbstractCitraApiClient):
|
|
9
|
+
def put_telescope_status(self, body):
|
|
10
|
+
"""
|
|
11
|
+
PUT to /telescopes to report online status.
|
|
12
|
+
"""
|
|
13
|
+
try:
|
|
14
|
+
response = self._request("PUT", "/telescopes", json=body)
|
|
15
|
+
if self.logger:
|
|
16
|
+
self.logger.debug(f"PUT /telescopes: {response}")
|
|
17
|
+
return response
|
|
18
|
+
except Exception as e:
|
|
19
|
+
if self.logger:
|
|
20
|
+
self.logger.error(f"Failed PUT /telescopes: {e}")
|
|
21
|
+
return None
|
|
22
|
+
|
|
9
23
|
def __init__(self, host: str, token: str, use_ssl: bool = True, logger=None):
|
|
10
24
|
self.base_url = ("https" if use_ssl else "http") + "://" + host
|
|
11
25
|
self.token = token
|
|
@@ -57,8 +71,10 @@ class CitraApiClient(AbstractCitraApiClient):
|
|
|
57
71
|
|
|
58
72
|
def upload_image(self, task_id, telescope_id, filepath):
|
|
59
73
|
"""Upload an image file for a given task."""
|
|
74
|
+
file_size = os.path.getsize(filepath)
|
|
60
75
|
signed_url_response = self._request(
|
|
61
|
-
"POST",
|
|
76
|
+
"POST",
|
|
77
|
+
f"/my/images?filename=citra_task_{task_id}_image.fits&telescope_id={telescope_id}&task_id={task_id}&file_size={file_size}",
|
|
62
78
|
)
|
|
63
79
|
if not signed_url_response or "uploadUrl" not in signed_url_response:
|
|
64
80
|
if self.logger:
|
|
@@ -99,3 +115,16 @@ class CitraApiClient(AbstractCitraApiClient):
|
|
|
99
115
|
if self.logger:
|
|
100
116
|
self.logger.error(f"Failed to mark task {task_id} as complete: {e}")
|
|
101
117
|
return None
|
|
118
|
+
|
|
119
|
+
def mark_task_failed(self, task_id):
|
|
120
|
+
"""Mark a task as failed using the API."""
|
|
121
|
+
try:
|
|
122
|
+
body = {"status": "Failed"}
|
|
123
|
+
response = self._request("PUT", f"/tasks/{task_id}", json=body)
|
|
124
|
+
if self.logger:
|
|
125
|
+
self.logger.debug(f"Marked task {task_id} as failed: {response}")
|
|
126
|
+
return response
|
|
127
|
+
except Exception as e:
|
|
128
|
+
if self.logger:
|
|
129
|
+
self.logger.error(f"Failed to mark task {task_id} as failed: {e}")
|
|
130
|
+
return None
|