A Python implementation of the RTS2 (Remote Telescope System 2nd Version) device drivers framework. This project provides a complete Python-based alternative to the C++ RTS2 components, focusing on ease of development and extensibility while maintaining full protocol compatibility with the original system.
RTS2 (Remote Telescope System 2nd Version) is an open-source observatory control system designed for robotic observatories. This Python implementation provides:
- Complete RTS2 device driver (daemon) network protocol support
- Unified configuration system with command line, config files, and environment variables
- Device abstraction framework with mixin architecture for multi-function devices
- Type-safe value system with automatic network distribution
- Command handling with automatic registration and dispatch
- Device-to-device communication with automatic connection management
- Production-ready implementations for filter wheels, focusers, and GRB detection
The framework is designed to work seamlessly within existing RTS2 installations, connecting to centrald and communicating with other RTS2 components.
pip install rtspy# Clone the repository
git clone https://github.com/yourusername/rts2-python.git
cd rtspy
# Install in development mode
pip install -e .For better system stability, it's recommended to use system packages instead of pip auto-installing dependencies. This prevents conflicts with system-managed Python packages:
# Clone the repository
git clone https://github.com/yourusername/rts2-python.git
cd rtspy
# First, install dependencies via apt (preferred on Ubuntu/Debian)
sudo apt install python3-psycopg2 python3-astropy python3-serial \
python3-certifi python3-confluent-kafka
# Install rtspy without auto-installing dependencies
pip install -e . --no-deps --break-system-packages
# Install remaining dependencies not available via apt (or if apt versions are too old)
pip install gcn-kafka --break-system-packagesThis approach prioritizes system packages, which are better integrated with your OS and less likely to cause version conflicts. Note that confluent_kafka in particular can cause issues when pip-installed, so using the apt package python3-confluent-kafka is highly recommended.
If you need to use the old flat structure:
# Clone the repository
git clone https://github.com/yourusername/rts2-python.git
cd rtspy
# Install dependencies manually
pip install psycopg2-binary gcn-kafka astropy pyserialRun the example dummy filter wheel to test the system:
# After pip installation, use entry points:
rtspy-filterd-dummy -d W0 -p 0 --filters "J:H:K:R:G:B"
# Or in development mode without pip install:
python rtspy/drivers/filterd_dummy.py -d W0 -p 0 --filters "J:H:K:R:G:B"After installation with pip, the following commands are available:
Production Daemons:
rtspy-grbd- GRB detection daemon with GCN Kafka interfacertspy-queue-selector- Queue-based target selectorrtspy-watcher- Device monitoring daemon
Test/Dummy Devices:
rtspy-filterd-dummy- Simulated filter wheelrtspy-focusd-dummy- Simulated focuserrtspy-sensor-temp- Example temperature sensor
Hardware Drivers:
rtspy-filterd-ovis- OVIS spectrograph filter wheel driver
CLI Utilities:
rts2-value- Get/set device values via network protocolrts2-grbinfo- Query GRB information from databaserts2-queue-manual- Manual queue management
RTS2 Ecosystem Integration (Shell Wrappers):
rts2-gcnkafka- Daemon wrapper for rtspy-grbdrts2-queuer- Daemon wrapper for rtspy-queue-selectorrts2-filterd-ovis- Daemon wrapper for rtspy-filterd-ovis
These wrappers provide daemon management (forking, PID files) compatible with rts2-start/rts2-stop.
All commands support --help for detailed usage information.
The experimental/ directory contains work-in-progress components that are not included in the package:
teld/- Telescope drivers (incomplete)imgprocd*.py- Image processing daemon variants (experimental)
The system is built around several core components:
- App: Application framework handling configuration, command line parsing, and device lifecycle
- Device: Base device class with integrated network communication and configuration
- DeviceConfig: Unified configuration system supporting multiple sources with proper precedence
- NetworkManager: Handles all network communication, authentication, and automatic device discovery
- Value: Type-safe values with change tracking, callbacks, and automatic distribution
- Mixins: Reusable device functionality components for filters, focusers, and other instruments
- FilterMixin: Complete filter wheel functionality as a mixin class
- Filterd: Standalone filter wheel base class
- DummyFilter: Simulated filter wheel for testing
- OvisMultiFunction: Real hardware driver for OVIS spectrograph (combines filter + focuser)
- FocuserMixin: Complete focuser functionality with temperature compensation
- Focusd: Standalone focuser base class with position control and limits
- DummyFocuser: Simulated focuser with gradual movement simulation
- GrbDaemon: Production GRB detection daemon with modern GCN Kafka interface
- TemperatureSensor: Example environmental monitoring device
- WatcherDevice: Device monitoring and inter-device communication example
The mixin architecture allows combining multiple instrument types in a single device:
class MultiInstrument(Device, FilterMixin, FocuserMixin):
def setup_config(self, config):
self.setup_filter_config(config)
self.setup_focuser_config(config)
def apply_config(self, config):
super().apply_config(config)
self.apply_filter_config(config)
self.apply_focuser_config(config)The unified configuration system supports multiple sources with proper precedence:
- Built-in defaults
- System config files (
/etc/rts2/rts2.conf) - User config files (
~/.rts2/rts2.conf) - Explicit config files (
--config myconfig.conf) - Environment variables (
RTS2_DEVICE_VARIABLE) - Command line arguments (highest priority)
Example device with custom configuration:
class MyDevice(Device, DeviceConfig):
def setup_config(self, config):
config.add_argument('--my-option', help='Custom option')
config.add_argument('--my-port', type=int, default=8080,
section='hardware', help='Hardware port')
def apply_config(self, config):
super().apply_config(config)
self.my_option = config.get('my_option')
self.my_port = config.get('my_port')Devices can automatically establish connections and monitor other devices:
# Monitor another device's values
self.network.register_interest_in_value(
device_name="TEMP",
value_name="temperature",
callback=self._on_temperature_update
)
# Monitor device state changes
self.network.register_state_interest(
device_name="CCD1",
state_callback=self._on_ccd_state_changed
)Connections are established automatically when centrald provides device information, with automatic reconnection on failure.
The included GRB daemon provides production-ready gamma-ray burst detection:
- Modern GCN Kafka interface replacing legacy socket protocols
- Robust VOEvent XML parsing with mission-specific handlers
- PostgreSQL database integration with RTS2 target system
- Automatic observation triggering with configurable constraints
- Comprehensive monitoring and statistics
python grbd.py --gcn-client-id YOUR_ID --gcn-client-secret YOUR_SECRETExtend the appropriate base class or use mixins:
from filterd import Filterd
class MyFilterWheel(Filterd):
def setup_config(self, config):
super().setup_config(config)
config.add_argument('--serial-port', help='Serial port device')
def set_filter_num(self, new_filter):
# Implement hardware-specific movement
return 0 # Success
def get_filter_num(self):
# Read current position from hardware
return self.current_position
if __name__ == "__main__":
app = App(description='My Filter Wheel Driver')
app.register_device_options(MyFilterWheel)
args = app.parse_args()
device = app.create_device(MyFilterWheel)
app.run()- Full RTS2 Compatibility: Seamless integration with existing RTS2 installations
- Modern Python Architecture: Type hints, dataclasses, and proper error handling
- Unified Configuration: Single system handling all configuration sources
- Mixin Architecture: Reusable components for multi-function devices
- Automatic Device Discovery: Zero-configuration device-to-device communication
- Production Ready: Used in real observatory environments
The system uses RTS2-compatible logging with proper formatting:
2024-05-04T12:34:56.789 UTC DEVICENAME I Log message here
All network communication and device interactions are logged for debugging and monitoring.
Contributions are welcome! The codebase follows modern Python practices with comprehensive type hints and documentation.
This project is licensed under the GNU General Public License v3.0.
This project is inspired by the original RTS2 system by Petr Kubanek et al. The OVIS filter wheel implementation was developed as part of the "Otevřená Věda" program of the Academy of Sciences of the Czech Republic, with contributions from high school students and university collaborators.