citrascope 0.5.1__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.
Files changed (52) hide show
  1. citrascope-0.5.1/.devcontainer/devcontainer.json +22 -0
  2. citrascope-0.5.1/.flake8 +3 -0
  3. citrascope-0.5.1/.github/copilot-instructions.md +105 -0
  4. citrascope-0.5.1/.github/dependabot.yml +12 -0
  5. citrascope-0.5.1/.github/workflows/pypi-publish.yml +24 -0
  6. citrascope-0.5.1/.github/workflows/pytest.yml +37 -0
  7. citrascope-0.5.1/.gitignore +139 -0
  8. citrascope-0.5.1/.pre-commit-config.yaml +33 -0
  9. citrascope-0.5.1/.python-version +1 -0
  10. citrascope-0.5.1/.vscode/launch.json +25 -0
  11. citrascope-0.5.1/LICENSE +21 -0
  12. citrascope-0.5.1/PKG-INFO +199 -0
  13. citrascope-0.5.1/README.md +149 -0
  14. citrascope-0.5.1/citrascope/__init__.py +0 -0
  15. citrascope-0.5.1/citrascope/__main__.py +23 -0
  16. citrascope-0.5.1/citrascope/api/abstract_api_client.py +30 -0
  17. citrascope-0.5.1/citrascope/api/citra_api_client.py +142 -0
  18. citrascope-0.5.1/citrascope/citra_scope_daemon.py +315 -0
  19. citrascope-0.5.1/citrascope/constants.py +23 -0
  20. citrascope-0.5.1/citrascope/hardware/abstract_astro_hardware_adapter.py +239 -0
  21. citrascope-0.5.1/citrascope/hardware/adapter_registry.py +94 -0
  22. citrascope-0.5.1/citrascope/hardware/indi_adapter.py +730 -0
  23. citrascope-0.5.1/citrascope/hardware/kstars_dbus_adapter.py +179 -0
  24. citrascope-0.5.1/citrascope/hardware/nina_adv_http_adapter.py +622 -0
  25. citrascope-0.5.1/citrascope/hardware/nina_adv_http_survey_template.json +328 -0
  26. citrascope-0.5.1/citrascope/logging/__init__.py +4 -0
  27. citrascope-0.5.1/citrascope/logging/_citrascope_logger.py +114 -0
  28. citrascope-0.5.1/citrascope/logging/web_log_handler.py +75 -0
  29. citrascope-0.5.1/citrascope/settings/__init__.py +0 -0
  30. citrascope-0.5.1/citrascope/settings/citrascope_settings.py +134 -0
  31. citrascope-0.5.1/citrascope/settings/settings_file_manager.py +126 -0
  32. citrascope-0.5.1/citrascope/tasks/runner.py +291 -0
  33. citrascope-0.5.1/citrascope/tasks/scope/base_telescope_task.py +220 -0
  34. citrascope-0.5.1/citrascope/tasks/scope/static_telescope_task.py +24 -0
  35. citrascope-0.5.1/citrascope/tasks/scope/tracking_telescope_task.py +28 -0
  36. citrascope-0.5.1/citrascope/tasks/task.py +43 -0
  37. citrascope-0.5.1/citrascope/web/__init__.py +1 -0
  38. citrascope-0.5.1/citrascope/web/app.py +594 -0
  39. citrascope-0.5.1/citrascope/web/server.py +132 -0
  40. citrascope-0.5.1/citrascope/web/static/api.js +82 -0
  41. citrascope-0.5.1/citrascope/web/static/app.js +729 -0
  42. citrascope-0.5.1/citrascope/web/static/config.js +601 -0
  43. citrascope-0.5.1/citrascope/web/static/img/citra.png +0 -0
  44. citrascope-0.5.1/citrascope/web/static/img/favicon.png +0 -0
  45. citrascope-0.5.1/citrascope/web/static/style.css +152 -0
  46. citrascope-0.5.1/citrascope/web/static/websocket.js +127 -0
  47. citrascope-0.5.1/citrascope/web/templates/dashboard.html +490 -0
  48. citrascope-0.5.1/pyproject.toml +100 -0
  49. citrascope-0.5.1/tests/unit/test_api_client.py +31 -0
  50. citrascope-0.5.1/tests/unit/test_hardware_adapter.py +76 -0
  51. citrascope-0.5.1/tests/unit/test_task_manager.py +299 -0
  52. citrascope-0.5.1/tests/unit/utils.py +72 -0
@@ -0,0 +1,22 @@
1
+ // For format details, see https://aka.ms/devcontainer.json. For config options, see the
2
+ // README at: https://github.com/devcontainers/templates/tree/main/src/python
3
+ {
4
+ "name": "Python 3",
5
+ // Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile
6
+ "image": "mcr.microsoft.com/devcontainers/python:1-3.12-bullseye",
7
+
8
+ // Features to add to the dev container. More info: https://containers.dev/features.
9
+ // "features": {},
10
+
11
+ // Use 'forwardPorts' to make a list of ports inside the container available locally.
12
+ // "forwardPorts": [],
13
+
14
+ // Use 'postCreateCommand' to run commands after the container is created.
15
+ "postCreateCommand": "sudo apt-get update && sudo apt-get install -y cmake libdbus-1-dev && python3 -m pip install --upgrade pip && pip3 install pre-commit && pip3 install ."
16
+
17
+ // Configure tool-specific properties.
18
+ // "customizations": {},
19
+
20
+ // Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root.
21
+ // "remoteUser": "root"
22
+ }
@@ -0,0 +1,3 @@
1
+ [flake8]
2
+ max-line-length = 120
3
+ extend-ignore = E203, W503
@@ -0,0 +1,105 @@
1
+ # Copilot Instructions for CitraScope
2
+
3
+ ## Overview
4
+ This project is a Python package for interacting with astronomical data and services. It includes modules for API clients, INDI client integration, logging, settings management, and task execution. Tests are located in the `tests/` directory.
5
+
6
+ ## Coding Guidelines
7
+ - Follow PEP8 for Python code style.
8
+ - Use type hints for all public functions and methods.
9
+ - Write docstrings for all modules, classes, and functions.
10
+ - Prefer logging via the custom logger in `citrascope/logging/` over print statements.
11
+ - Organize code into logical modules as per the existing structure.
12
+
13
+ ## Directory Structure
14
+ - `citrascope/api/`: API client code
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.)
19
+ - `citrascope/logging/`: Logging utilities
20
+ - `citrascope/settings/`: Settings and configuration
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
27
+ - `tests/`: Unit and integration tests
28
+
29
+ ## Testing
30
+ - All new features and bug fixes should include corresponding tests in `tests/`.
31
+ - Use pytest for running tests.
32
+ - Test files should be named `test_*.py`.
33
+
34
+ ## Copilot Usage
35
+ - When implementing new features, follow the module structure and add tests.
36
+ - For bug fixes, describe the issue and expected behavior in comments or commit messages.
37
+ - For refactoring, ensure no breaking changes and all tests pass.
38
+ - Use Copilot to suggest code, refactor, and generate tests, but always review suggestions for correctness and style.
39
+
40
+ ## Common Tasks
41
+ - Add new API integrations in `citrascope/api/`.
42
+ - Extend or add hardware adapters:
43
+ - Create new adapter class implementing `AbstractAstroHardwareAdapter` in `citrascope/hardware/`
44
+ - Register it in `citrascope/hardware/adapter_registry.py` by adding an entry to `REGISTERED_ADAPTERS`
45
+ - All adapter discovery and instantiation flows from this registry
46
+ - Update logging logic in `citrascope/logging/`.
47
+ - Change settings in `citrascope/settings/`.
48
+ - Add or modify tasks in `citrascope/tasks/`.
49
+ - Enhance web interface in `citrascope/web/`.
50
+ - Write or update tests in `tests/`.
51
+
52
+ ## Web Interface Guidelines
53
+
54
+ The web interface provides real-time monitoring and configuration for telescope operations. When working on web-related features:
55
+
56
+ ### Design Principles
57
+ - **Dark theme required**: All UI elements must use dark colors suitable for nighttime telescope operations to preserve night vision
58
+ - **Real-time updates**: Use WebSocket connections for live status, logs, and telemetry
59
+ - **Mobile-friendly**: The interface should be responsive and usable on tablets/phones in the field
60
+ - **Minimal distractions**: Reduce visual clutter; prioritize essential telescope and task information
61
+
62
+ ### Architecture
63
+ - **FastAPI backend** (`web/app.py`): RESTful API endpoints and WebSocket handlers
64
+ - **Separate thread**: Web server runs in daemon thread with its own event loop (`web/server.py`)
65
+ - **Log streaming**: Custom `WebLogHandler` broadcasts logs to web clients in real-time
66
+ - **Static files**: HTML, CSS, and JavaScript are served from `web/templates/` and `web/static/`
67
+
68
+ ### Development Notes
69
+ - Keep web-specific code isolated in the `citrascope/web/` directory
70
+ - The daemon should only call `web_server.start()` - all web complexity stays in `web/server.py`
71
+ - Filter out noise from web logs (HTTP requests, WebSocket events, Uvicorn messages)
72
+ - Use thread-safe mechanisms when accessing daemon state from web handlers
73
+ - Port 24872 (CITRA on phone keypad) is the default web interface port
74
+
75
+ ## Important Packages
76
+
77
+ This project relies on several key Python packages. Below are some of the most important ones and their roles:
78
+
79
+ - **Click**: Used for building the command-line interface (CLI). The main entry point for the application (`python -m citrascope`) is implemented using Click.
80
+ - **Pydantic-Settings**: Manages configuration and settings, ensuring type safety and validation for environment variables.
81
+ - **Requests** and **HTTPX**: Handle HTTP requests for interacting with the Citra.space API.
82
+ - **Python-Dateutil**: Provides robust date and time parsing utilities.
83
+ - **PyINDI-Client**: Interfaces with INDI telescope hardware, enabling communication with telescope and camera devices.
84
+ - **Skyfield**: Used for astronomical calculations, such as determining celestial positions.
85
+ - **Pytest** and **Pytest-Cov**: Facilitate unit testing and code coverage analysis.
86
+
87
+ ### Development Dependencies
88
+ - **Black**: Ensures consistent code formatting.
89
+ - **Pre-Commit**: Runs code quality checks automatically before commits.
90
+ - **Isort**: Sorts imports to maintain a clean and organized structure.
91
+ - **Mypy**: Performs static type checking.
92
+ - **Flake8**: Enforces code style and linting rules.
93
+ - **Sphinx**: Generates project documentation.
94
+
95
+ ### Web Interface Dependencies
96
+ - **FastAPI**: Modern async web framework for the monitoring interface
97
+ - **Uvicorn**: ASGI server for running the web application
98
+ - **WebSockets**: Real-time bidirectional communication for live updates
99
+
100
+ For a complete list of dependencies, refer to the `pyproject.toml` file.
101
+
102
+ ## Additional Notes
103
+ - Keep dependencies minimal and update `pyproject.toml` as needed.
104
+ - Documentation is maintained in the [citra-space/docs](https://github.com/citra-space/docs) repository under `docs/citrascope/`.
105
+ - Use pre-commit hooks for code quality.
@@ -0,0 +1,12 @@
1
+ # To get started with Dependabot version updates, you'll need to specify which
2
+ # package ecosystems to update and where the package manifests are located.
3
+ # Please see the documentation for more information:
4
+ # https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
5
+ # https://containers.dev/guide/dependabot
6
+
7
+ version: 2
8
+ updates:
9
+ - package-ecosystem: "devcontainers"
10
+ directory: "/"
11
+ schedule:
12
+ interval: weekly
@@ -0,0 +1,24 @@
1
+ name: Publish Python Package
2
+
3
+ on:
4
+ release:
5
+ types: [published]
6
+
7
+ jobs:
8
+ build-and-publish:
9
+ runs-on: ubuntu-latest
10
+ steps:
11
+ - uses: actions/checkout@v4
12
+ - name: Set up Python
13
+ uses: actions/setup-python@v5
14
+ with:
15
+ python-version: '3.12'
16
+ - name: Install build tools
17
+ run: pip install build twine
18
+ - name: Build package
19
+ run: python -m build
20
+ - name: Publish to PyPI
21
+ env:
22
+ TWINE_USERNAME: __token__
23
+ TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }}
24
+ run: twine upload dist/*
@@ -0,0 +1,37 @@
1
+ name: Pytest
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ jobs:
10
+ test:
11
+ runs-on: ubuntu-latest
12
+ strategy:
13
+ fail-fast: false
14
+ matrix:
15
+ python-version: ['3.10', '3.11', '3.12']
16
+ steps:
17
+ - name: Checkout code
18
+ uses: actions/checkout@v4
19
+ - name: Set up Python ${{ matrix.python-version }}
20
+ uses: actions/setup-python@v5
21
+ with:
22
+ python-version: ${{ matrix.python-version }}
23
+ - name: Install project prerequisites
24
+ run: sudo apt-get update && sudo apt-get install -y libglib2.0-dev libdbus-1-dev libjpeg-dev zlib1g-dev
25
+ - name: Install dependencies
26
+ run: |
27
+ pip install --upgrade pip
28
+ pip install .[dev,test,indi,all]
29
+ - name: Run pytest with coverage
30
+ run: |
31
+ pytest -m "not integration" --cov=citrascope --cov-report=term-missing --cov-report=xml --cov-branch
32
+ - name: Upload coverage report
33
+ uses: actions/upload-artifact@v4
34
+ if: matrix.python-version == '3.12'
35
+ with:
36
+ name: coverage-xml
37
+ path: coverage.xml
@@ -0,0 +1,139 @@
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+
6
+ # C extensions
7
+ *.so
8
+
9
+ # Distribution / packaging
10
+ .Python
11
+ build/
12
+ develop-eggs/
13
+ dist/
14
+ downloads/
15
+ eggs/
16
+ .eggs/
17
+ lib/
18
+ lib64/
19
+ parts/
20
+ sdist/
21
+ var/
22
+ wheels/
23
+ pip-wheel-metadata/
24
+ share/python-wheels/
25
+ *.egg-info/
26
+ .installed.cfg
27
+ *.egg
28
+ MANIFEST
29
+
30
+ # PyInstaller
31
+ # Usually these files are written by a python script from a template
32
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
33
+ *.manifest
34
+ *.spec
35
+
36
+ # Installer logs
37
+ pip-log.txt
38
+ pip-delete-this-directory.txt
39
+
40
+ # Unit test / coverage reports
41
+ htmlcov/
42
+ .tox/
43
+ .nox/
44
+ .coverage
45
+ .coverage.*
46
+ .cache
47
+ nosetests.xml
48
+ coverage.xml
49
+ *.cover
50
+ *.py,cover
51
+ .hypothesis/
52
+ .pytest_cache/
53
+
54
+ # Translations
55
+ *.mo
56
+ *.pot
57
+
58
+ # Django stuff:
59
+ *.log
60
+ local_settings.py
61
+ db.sqlite3
62
+ db.sqlite3-journal
63
+
64
+ # Flask stuff:
65
+ instance/
66
+ .webassets-cache
67
+
68
+ # Scrapy stuff:
69
+ .scrapy
70
+
71
+ # PyBuilder
72
+ target/
73
+
74
+ # Jupyter Notebook
75
+ .ipynb_checkpoints
76
+
77
+ # IPython
78
+ profile_default/
79
+ ipython_config.py
80
+
81
+ # pipenv
82
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
83
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
84
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
85
+ # install all needed dependencies.
86
+ #Pipfile.lock
87
+
88
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow
89
+ __pypackages__/
90
+
91
+ # Celery stuff
92
+ celerybeat-schedule
93
+ celerybeat.pid
94
+
95
+ # SageMath parsed files
96
+ *.sage.py
97
+
98
+ # Environments
99
+ prod.env
100
+ .env.prod
101
+ .env
102
+ .venv
103
+ env/
104
+ venv/
105
+ ENV/
106
+ env.bak/
107
+ venv.bak/
108
+
109
+ # Spyder project settings
110
+ .spyderproject
111
+ .spyproject
112
+
113
+ # Rope project settings
114
+ .ropeproject
115
+
116
+ # mkdocs documentation
117
+ /site
118
+
119
+ # mypy
120
+ .mypy_cache/
121
+ .dmypy.json
122
+ dmypy.json
123
+
124
+ # Pyre type checker
125
+ .pyre/
126
+ .vscode/extensions.json
127
+ .vscode/settings.json
128
+ .vscode/tasks.json
129
+
130
+ as_headers/
131
+
132
+ certs/
133
+ de421.bsp
134
+ citra_image.fits
135
+ /images/*
136
+ .DS_Store
137
+ hip_main.dat
138
+ nina_sequence_*.json
139
+ nina_focus_positions.json
@@ -0,0 +1,33 @@
1
+ repos:
2
+
3
+ - repo: https://github.com/pre-commit/pre-commit-hooks
4
+ rev: v6.0.0
5
+ hooks:
6
+ - id: check-added-large-files
7
+ exclude: data
8
+ - id: check-case-conflict
9
+ - id: check-yaml
10
+ - id: debug-statements
11
+ - id: end-of-file-fixer
12
+ exclude: data
13
+ - id: trailing-whitespace
14
+ exclude: data
15
+
16
+ - repo: https://github.com/pycqa/isort
17
+ rev: 7.0.0
18
+ hooks:
19
+ - id: isort
20
+
21
+ - repo: https://github.com/psf/black
22
+ rev: 25.9.0
23
+ hooks:
24
+ - id: black
25
+
26
+ - repo: local
27
+ hooks:
28
+ - id: pytest
29
+ name: pytest
30
+ entry: pytest
31
+ language: system
32
+ types: [python]
33
+ pass_filenames: false
@@ -0,0 +1 @@
1
+ 3.12
@@ -0,0 +1,25 @@
1
+ {
2
+ // Use IntelliSense to learn about possible attributes.
3
+ // Hover to view descriptions of existing attributes.
4
+ "version": "0.2.0",
5
+ "configurations": [
6
+ {
7
+ "name": "Python: citrascope",
8
+ "type": "debugpy",
9
+ "request": "launch",
10
+ "module": "citrascope",
11
+ "args": [],
12
+ "console": "integratedTerminal",
13
+ "justMyCode": false
14
+ },
15
+ {
16
+ "name": "Python: citrascope (custom port)",
17
+ "type": "debugpy",
18
+ "request": "launch",
19
+ "module": "citrascope",
20
+ "args": ["--web-port", "8080"],
21
+ "console": "integratedTerminal",
22
+ "justMyCode": false
23
+ }
24
+ ]
25
+ }
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Citra Space
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,199 @@
1
+ Metadata-Version: 2.4
2
+ Name: citrascope
3
+ Version: 0.5.1
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: Patrick McDavid <patrick@citra.space>
6
+ License: MIT
7
+ License-File: LICENSE
8
+ Requires-Python: <3.13,>=3.10
9
+ Requires-Dist: click
10
+ Requires-Dist: fastapi>=0.104.0
11
+ Requires-Dist: httpx
12
+ Requires-Dist: platformdirs>=4.0.0
13
+ Requires-Dist: python-dateutil
14
+ Requires-Dist: requests
15
+ Requires-Dist: skyfield
16
+ Requires-Dist: uvicorn[standard]>=0.24.0
17
+ Requires-Dist: websockets>=12.0
18
+ Provides-Extra: all
19
+ Requires-Dist: dbus-python; extra == 'all'
20
+ Requires-Dist: pixelemon; extra == 'all'
21
+ Requires-Dist: plotly; extra == 'all'
22
+ Requires-Dist: pyindi-client; extra == 'all'
23
+ Provides-Extra: build
24
+ Requires-Dist: build; extra == 'build'
25
+ Provides-Extra: deploy
26
+ Requires-Dist: twine; extra == 'deploy'
27
+ Provides-Extra: dev
28
+ Requires-Dist: black; extra == 'dev'
29
+ Requires-Dist: bump-my-version; extra == 'dev'
30
+ Requires-Dist: flake8; extra == 'dev'
31
+ Requires-Dist: flake8-pytest-style; extra == 'dev'
32
+ Requires-Dist: isort; extra == 'dev'
33
+ Requires-Dist: mockito; extra == 'dev'
34
+ Requires-Dist: mypy; extra == 'dev'
35
+ Requires-Dist: pre-commit; extra == 'dev'
36
+ Requires-Dist: pytest; extra == 'dev'
37
+ Requires-Dist: pytest-cov; extra == 'dev'
38
+ Requires-Dist: types-python-dateutil; extra == 'dev'
39
+ Provides-Extra: indi
40
+ Requires-Dist: pixelemon; extra == 'indi'
41
+ Requires-Dist: plotly; extra == 'indi'
42
+ Requires-Dist: pyindi-client; extra == 'indi'
43
+ Provides-Extra: kstars
44
+ Requires-Dist: dbus-python; extra == 'kstars'
45
+ Provides-Extra: test
46
+ Requires-Dist: mockito; extra == 'test'
47
+ Requires-Dist: pytest; extra == 'test'
48
+ Requires-Dist: pytest-cov; extra == 'test'
49
+ Description-Content-Type: text/markdown
50
+
51
+ # CitraScope
52
+ [![Pytest](https://github.com/citra-space/citrascope/actions/workflows/pytest.yml/badge.svg)](https://github.com/citra-space/citrascope/actions/workflows/pytest.yml) [![Publish Python Package](https://github.com/citra-space/citrascope/actions/workflows/pypi-publish.yml/badge.svg)](https://github.com/citra-space/citrascope/actions/workflows/pypi-publish.yml) [![PyPI version](https://badge.fury.io/py/citrascope.svg)](https://pypi.org/project/citrascope/) [![PyPI - Downloads](https://img.shields.io/pypi/dm/citrascope)](https://pypi.org/project/citrascope/) [![License](https://img.shields.io/github/license/citra-space/citrascope)](https://github.com/citra-space/citrascope/blob/main/LICENSE)
53
+
54
+ Remotely control a telescope while it polls for tasks, collects observations, and delivers data for further processing.
55
+
56
+ ## Features
57
+ - Offers a web UI to configure hardware and connect to Citra.space's api
58
+ - Connects to Citra.space's API and identifies itself as an online telescope
59
+ - Connects to configured telescope and camera hardware
60
+ - Acts as a task daemon carrying out and remitting photography tasks
61
+
62
+ ## Documentation
63
+
64
+ Full documentation is available at [docs.citra.space](https://docs.citra.space/citrascope/).
65
+
66
+ Documentation source is maintained in the [citra-space/docs](https://github.com/citra-space/docs) repository.
67
+
68
+ ## Installation
69
+
70
+ **Important:** CitraScope requires Python 3.10, 3.11, or 3.12.
71
+
72
+ ### Check Your Python Version
73
+
74
+ ```sh
75
+ python3 --version
76
+ ```
77
+
78
+ If you don't have a compatible version, install one with [pyenv](https://github.com/pyenv/pyenv):
79
+
80
+ ```sh
81
+ pyenv install 3.12.0
82
+ pyenv local 3.12.0 # Sets Python 3.12.0 for the current directory
83
+ ```
84
+
85
+ ### Install CitraScope
86
+
87
+ **Recommended: Using pip in a virtual environment**
88
+
89
+ ```sh
90
+ python3 -m venv citrascope-env
91
+ source citrascope-env/bin/activate # On Windows: citrascope-env\Scripts\activate
92
+ pip install citrascope
93
+ ```
94
+
95
+ ### Optional Dependencies
96
+
97
+ For Linux-based telescope control (INDI):
98
+
99
+ ```sh
100
+ pip install citrascope[indi]
101
+ ```
102
+
103
+ This provides the `citrascope` command-line tool. To see available commands:
104
+
105
+ ```sh
106
+ citrascope --help
107
+ ```
108
+
109
+ ## Usage
110
+
111
+ ### Starting the Daemon
112
+
113
+ Run the daemon with:
114
+
115
+ ```sh
116
+ citrascope
117
+ ```
118
+
119
+ By default, this starts the web interface on `http://localhost:24872`. You can customize the port:
120
+
121
+ ```sh
122
+ citrascope --web-port 8080
123
+ ```
124
+
125
+ ## Developer Setup
126
+
127
+ 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.
128
+
129
+ By opening this project in VS Code and choosing "Reopen in Container" (or using the Dev Containers extension), you can develop and run the project seamlessly, regardless of your host OS.
130
+
131
+ The devcontainer also ensures all required system dependencies (like `cmake`) are installed automatically.
132
+
133
+ ### Python Version
134
+
135
+ 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.
136
+
137
+ ### If not using the dev container:
138
+ ```sh
139
+ python -m venv .venv
140
+ source .venv/bin/activate
141
+ ```
142
+
143
+ ### Installing Development Dependencies
144
+
145
+ To install development dependencies (for code style, linting, and pre-commit hooks):
146
+
147
+ ```sh
148
+ pip install '.[dev]'
149
+ ```
150
+
151
+ ### Setting up Pre-commit Hooks
152
+
153
+ This project uses [pre-commit](https://pre-commit.com/) to run code quality checks (like Flake8, Black, isort, etc.) automatically before each commit.
154
+
155
+ After installing the dev dependencies, enable the hooks with:
156
+
157
+ ```sh
158
+ pre-commit install
159
+ ```
160
+
161
+ You can manually run all pre-commit checks on all files with:
162
+
163
+ ```sh
164
+ pre-commit run --all-files
165
+ ```
166
+
167
+ This ensures code style and quality checks are enforced for all contributors.
168
+
169
+ ### Releasing a New Version
170
+
171
+ To bump the version and create a release:
172
+
173
+ ```sh
174
+ bump-my-version bump patch # 0.1.3 → 0.1.4
175
+ bump-my-version bump minor # 0.1.3 → 0.2.0
176
+ bump-my-version bump major # 0.1.3 → 1.0.0
177
+ git push && git push --tags
178
+ ```
179
+
180
+ Then create a release in the GitHub UI from the new tag. This triggers automatic PyPI publishing.
181
+
182
+ ### Running and Debugging with VS Code
183
+
184
+ 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`:
185
+
186
+ - **Python: citrascope** — Runs the daemon with default settings
187
+ - **Python: citrascope (custom port)** — Runs with web interface on port 8080
188
+
189
+ To use these, open the Run and Debug panel in VS Code, select the desired configuration, and click the Run or Debug button.
190
+
191
+ ## Running Tests
192
+
193
+ This project uses [pytest](https://pytest.org/) for unit testing. All tests are located in the `tests/` directory.
194
+
195
+ To run unit tests within your devcontainer:
196
+
197
+ ```bash
198
+ pytest
199
+ ```