#!/usr/bin/env python3 # /// script # requires-python = ">=3.8" # dependencies = ["argcomplete"] # /// """ client for UDP camera control Usage: uv run scripts/camera_control.py # Get all camera settings (default) uv run scripts/camera_control.py get-all # Get all camera settings uv run scripts/camera_control.py get-exposure # Get current exposure uv run scripts/camera_control.py set-exposure 10 # Set exposure to 10ms uv run scripts/camera_control.py get-framerate # Get current framerate uv run scripts/camera_control.py set-framerate 30 # Set framerate to 30fps uv run scripts/camera_control.py get-gain # Get current gain uv run scripts/camera_control.py set-gain 50 # Set gain to 50 uv run scripts/camera_control.py get-auto-exposure # Get auto-exposure status uv run scripts/camera_control.py set-auto-exposure 1 # Enable auto-exposure uv run scripts/camera_control.py get-auto-gain # Get auto-gain status uv run scripts/camera_control.py set-auto-gain 1 # Enable auto-gain uv run scripts/camera_control.py get-gain-boost # Get gain boost status uv run scripts/camera_control.py set-gain-boost 1 # Enable gain boost uv run scripts/camera_control.py status # Get pipeline status This script provides control commands for the UDP control interface for the IDS uEye camera. Make sure launch-ids.py is running before executing commands. """ import argparse import socket import time import sys try: import argcomplete except ImportError: argcomplete = None def send_command(command, host="127.0.0.1", port=5001, timeout=1.0): """Send a command and return the response""" sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sock.settimeout(timeout) try: # Send command sock.sendto(command.encode() + b'\n', (host, port)) # Receive response response, _ = sock.recvfrom(1024) return response.decode().strip() except socket.timeout: return "ERROR: Timeout waiting for response (is launch-ids.py running?)" except Exception as e: return f"ERROR: {e}" finally: sock.close() def simple_command(command, description="Command"): """Execute a single command and print the result""" print(f"{description}...") response = send_command(command) print(f"Response: {response}") # Check if response indicates success if response.startswith("OK"): return True elif response.startswith("ERROR"): print(f"Error: {response}") return False else: print(f"Unknown response: {response}") return False def get_all_settings(): """Get all camera settings""" print("=" * 70) print("Camera Settings") print("=" * 70) settings = [ ("Exposure", "GET_EXPOSURE"), ("Exposure Range", "GET_EXPOSURE_RANGE"), ("Framerate", "GET_FRAMERATE"), ("Gain", "GET_GAIN"), ("Auto-Exposure", "GET_AUTO_EXPOSURE"), ("Auto-Gain", "GET_AUTO_GAIN"), ("Gain Boost", "GET_GAIN_BOOST"), ] all_success = True for name, command in settings: response = send_command(command) print(f"{name:20s}: {response}") if response.startswith("ERROR"): all_success = False print("=" * 70) return all_success def main(): """Main function with argument parsing""" parser = argparse.ArgumentParser( description="UDP Exposure Control Client", epilog=""" Examples: %(prog)s # Get all camera settings (default) %(prog)s get-all # Get all camera settings %(prog)s get-exposure # Get current exposure %(prog)s set-exposure 10 # Set exposure to 10ms %(prog)s get-framerate # Get current framerate %(prog)s set-framerate 30 # Set framerate to 30fps %(prog)s get-gain # Get current gain %(prog)s set-gain 50 # Set gain to 50 %(prog)s get-auto-exposure # Get auto-exposure status %(prog)s set-auto-exposure 1 # Enable auto-exposure %(prog)s get-auto-gain # Get auto-gain status %(prog)s set-auto-gain 1 # Enable auto-gain %(prog)s get-gain-boost # Get gain boost status %(prog)s set-gain-boost 1 # Enable gain boost %(prog)s status # Get pipeline status """, formatter_class=argparse.RawDescriptionHelpFormatter ) parser.add_argument('command', nargs='?', choices=['get-all', 'get-exposure', 'get-exposure-range', 'set-exposure', 'get-framerate', 'set-framerate', 'get-gain', 'set-gain', 'get-auto-exposure', 'set-auto-exposure', 'get-auto-gain', 'set-auto-gain', 'get-gain-boost', 'set-gain-boost', 'status'], help='Command to execute') parser.add_argument('value', nargs='?', type=float, help='Value for set commands (exposure in ms, framerate in fps)') parser.add_argument('--host', default='127.0.0.1', help='Host address (default: 127.0.0.1)') parser.add_argument('--port', type=int, default=5001, help='Port number (default: 5001)') # Enable tab completion if argcomplete is available if argcomplete: argcomplete.autocomplete(parser) args = parser.parse_args() # If no command provided, run get-all by default if args.command is None: success = get_all_settings() sys.exit(0 if success else 1) # Handle individual commands if args.command == 'get-all': success = get_all_settings() elif args.command == 'get-exposure': success = simple_command("GET_EXPOSURE", "Getting current exposure") elif args.command == 'get-exposure-range': success = simple_command("GET_EXPOSURE_RANGE", "Getting exposure range") elif args.command == 'set-exposure': if args.value is None: print("Error: set-exposure requires a value (exposure in milliseconds)") parser.print_help() sys.exit(1) success = simple_command(f"SET_EXPOSURE {args.value}", f"Setting exposure to {args.value}ms") elif args.command == 'get-framerate': success = simple_command("GET_FRAMERATE", "Getting current framerate") elif args.command == 'set-framerate': if args.value is None: print("Error: set-framerate requires a value (framerate in fps)") parser.print_help() sys.exit(1) success = simple_command(f"SET_FRAMERATE {args.value}", f"Setting framerate to {args.value}fps") elif args.command == 'get-gain': success = simple_command("GET_GAIN", "Getting current gain") elif args.command == 'set-gain': if args.value is None: print("Error: set-gain requires a value (0-100, 0 for auto)") parser.print_help() sys.exit(1) # Convert to int for gain gain_value = int(args.value) if gain_value < 0 or gain_value > 100: print("Error: Gain must be between 0 and 100 (0 for auto)") sys.exit(1) success = simple_command(f"SET_GAIN {gain_value}", f"Setting gain to {gain_value}") elif args.command == 'get-auto-exposure': success = simple_command("GET_AUTO_EXPOSURE", "Getting auto-exposure status") elif args.command == 'set-auto-exposure': if args.value is None: print("Error: set-auto-exposure requires a value (0=off, 1=on)") parser.print_help() sys.exit(1) # Convert to int ae_value = int(args.value) if ae_value not in [0, 1]: print("Error: Auto-exposure must be 0 (off) or 1 (on)") sys.exit(1) success = simple_command(f"SET_AUTO_EXPOSURE {ae_value}", f"{'Enabling' if ae_value else 'Disabling'} auto-exposure") elif args.command == 'get-auto-gain': success = simple_command("GET_AUTO_GAIN", "Getting auto-gain status") elif args.command == 'set-auto-gain': if args.value is None: print("Error: set-auto-gain requires a value (0=off, 1=on)") parser.print_help() sys.exit(1) # Convert to int ag_value = int(args.value) if ag_value not in [0, 1]: print("Error: Auto-gain must be 0 (off) or 1 (on)") sys.exit(1) success = simple_command(f"SET_AUTO_GAIN {ag_value}", f"{'Enabling' if ag_value else 'Disabling'} auto-gain") elif args.command == 'get-gain-boost': success = simple_command("GET_GAIN_BOOST", "Getting gain boost status") elif args.command == 'set-gain-boost': if args.value is None: print("Error: set-gain-boost requires a value (0=off, 1=on)") parser.print_help() sys.exit(1) # Convert to int gb_value = int(args.value) if gb_value not in [0, 1]: print("Error: Gain boost must be 0 (off) or 1 (on)") sys.exit(1) success = simple_command(f"SET_GAIN_BOOST {gb_value}", f"{'Enabling' if gb_value else 'Disabling'} gain boost") elif args.command == 'status': success = simple_command("STATUS", "Getting pipeline status") # Exit with appropriate code sys.exit(0 if success else 1) if __name__ == "__main__": main()