Beispiel #1
0
    def __init__(
        self,
        show_shell: bool = True,
        show_events: bool = True,
        show_status: bool = True,
        show_modules: Optional[List[str]] = None,
        widgets: Optional[List[Dict[str, Any]]] = None,
        sidebar: Optional[List[Dict[str, Any]]] = None,
        *args: Any,
        **kwargs: Any,
    ):
        """Inits a new GUI.

        Args:
            show_shell: Whether to show the shell page.
            show_events: Whether to show the events page.
            show_modules: If not empty, show only listed modules.
            widgets: List of custom widgets.
            sidebar: List of custom sidebar widgets.
        """

        # init Qt with asyncio
        self._app = QtWidgets.QApplication(sys.argv)
        loop = QEventLoop(self._app)
        asyncio.set_event_loop(loop)

        # init module
        Module.__init__(self, *args, **kwargs)
        self._window: Optional[MainWindow] = None
        self._show_shell = show_shell
        self._show_events = show_events
        self._show_status = show_status
        self._show_modules = show_modules
        self._custom_widgets = widgets
        self._custom_sidebar_widgets = sidebar
Beispiel #2
0
    def __init__(
        self,
        fits_headers: Optional[Dict[str, Any]] = None,
        filenames: str = "/cache/pyobs-{DAY-OBS|date:}-{FRAMENUM|string:04d}.fits.gz",
        fits_namespaces: Optional[List[str]] = None,
        **kwargs: Any,
    ):
        """Creates a new BaseCamera.

        Args:
            fits_headers: Additional FITS headers.
            flip: Whether or not to flip the image along its first axis.
            filenames: Template for file naming.
            fits_namespaces: List of namespaces for FITS headers that this camera should request
        """
        Module.__init__(self, **kwargs)
        SpectrumFitsHeaderMixin.__init__(
            self, fits_namespaces=fits_namespaces, fits_headers=fits_headers, filenames=filenames
        )

        # init camera
        self._exposure: Optional[ExposureInfo] = None
        self._spectrograph_status = ExposureStatus.IDLE

        # multi-threading
        self._expose_lock = asyncio.Lock()
        self.expose_abort = asyncio.Event()

        # check
        if self.comm is None:
            log.warning("No comm module given, will not be able to signal new images!")
Beispiel #3
0
    def __init__(self,
                 tasks: Union[TaskArchive, dict],
                 allowed_late_start: int = 300,
                 allowed_overrun: int = 300,
                 **kwargs: Any):
        """Initialize a new auto focus system.

        Args:
            tasks: Task archive to use
            allowed_late_start: Allowed seconds to start late.
            allowed_overrun: Allowed time for a task to exceed it's window in seconds
        """
        Module.__init__(self, **kwargs)

        # store
        self._allowed_late_start = allowed_late_start
        self._allowed_overrun = allowed_overrun
        self._running = False

        # add thread func
        self.add_background_task(self._run_thread, True)

        # get task archive
        self._task_archive = self.add_child_object(tasks, TaskArchive)

        # observation name and exposure number
        self._task = None
        self._obs = None
        self._exp = None
Beispiel #4
0
    def __init__(self,
                 watchpath: Optional[str] = None,
                 destinations: Optional[List[str]] = None,
                 **kwargs: Any):
        """Create a new image watcher.

        Args:
            watchpath: Path to watch.
            destinations: Filename patterns for destinations.
        """
        Module.__init__(self, **kwargs)

        # test import
        import pyinotify

        # add thread func
        self.add_background_task(self._worker)

        # variables
        self._watchpath = watchpath
        self._notifier = None
        self._queue = asyncio.Queue[str]()

        # filename patterns
        if not destinations:
            raise ValueError(
                "No filename patterns given for the destinations.")
        self._destinations = destinations
Beispiel #5
0
    def __init__(self,
                 token: str,
                 password: str,
                 allow_new_users: bool = True,
                 **kwargs: Any):
        """Initialize a new bot.

        Args:
            token: The telegram API token.
            password: Password for users to log in.
            allow_new_users: Whether new users are allowed to connect.

        """
        Module.__init__(self, **kwargs)
        from telegram.ext import Updater

        # store
        self._token = token
        self._password = password
        self._allow_new_users = allow_new_users
        self._updater: Optional[Updater] = None
        self._message_queue = asyncio.Queue()
        self._loop = None

        # get log levels
        self._log_levels = {
            logging.getLevelName(x): x
            for x in range(1, 101)
            if not logging.getLevelName(x).startswith("Level")
        }

        # thread
        self.add_background_task(self._log_sender_thread)
Beispiel #6
0
    def __init__(self,
                 port: int = 37075,
                 cache_size: int = 25,
                 max_file_size: int = 100,
                 **kwargs: Any):
        """Initializes file cache.

        Args:
            port: Port for HTTP server.
            cache_size: Size of file cache, i.e. number of files to cache.
            max_file_size: Maximum file size in MB.
        """
        Module.__init__(self, **kwargs)

        # store stuff
        self._cache = DataCache(cache_size)
        self._is_listening = False
        self._port = port
        self._cache_size = cache_size
        self._max_file_size = max_file_size * 1024 * 1024

        # define web server
        self._app = web.Application()
        self._app.add_routes([
            web.get("/{filename}", self.download_handler),
            web.post("/", self.upload_handler)
        ])
        self._runner = web.AppRunner(self._app)
        self._site: Optional[web.TCPSite] = None
Beispiel #7
0
    def __init__(self, **kwargs: Any):
        """Initialize a new base roof."""
        Module.__init__(self, **kwargs)

        # init mixins
        WeatherAwareMixin.__init__(self, **kwargs)
        MotionStatusMixin.__init__(self, **kwargs)
Beispiel #8
0
    def __init__(
        self,
        focuser: Union[str, IFocuser],
        camera: Union[str, IImageGrabber],
        series: FocusSeries,
        offset: bool = False,
        filters: Optional[Union[str, IFilters]] = None,
        filter_name: Optional[str] = None,
        binning: Optional[int] = None,
        **kwargs: Any,
    ):
        """Initialize a new auto focus system.

        Args:
            focuser: Name of IFocuser.
            camera: Name of ICamera.
            filters: Name of IFilters, if any.
            filter_name: Name of filter to set.
            offset: If True, offsets are used instead of absolute focus values.
        """
        Module.__init__(self, **kwargs)

        # store focuser and camera
        self._focuser = focuser
        self._camera = camera
        self._filters = filters
        self._offset = offset
        self._abort = threading.Event()

        # create focus series
        self._series: FocusSeries = get_object(series, FocusSeries)

        # init camera settings mixin
        CameraSettingsMixin.__init__(self,
                                     filters=filters,
                                     filter_name=filter_name,
                                     binning=binning,
                                     **kwargs)

        # register exceptions
        if isinstance(camera, str):
            exc.register_exception(
                exc.RemoteError,
                3,
                timespan=600,
                module=camera,
                callback=self._default_remote_error_callback)
        if isinstance(focuser, str):
            exc.register_exception(
                exc.RemoteError,
                3,
                timespan=600,
                module=focuser,
                callback=self._default_remote_error_callback)
Beispiel #9
0
    def __init__(
        self,
        fits_headers: Optional[Dict[str, Any]] = None,
        centre: Optional[Tuple[float, float]] = None,
        rotation: float = 0.0,
        flip: bool = False,
        filenames:
        str = "/cache/pyobs-{DAY-OBS|date:}-{FRAMENUM|string:04d}-{IMAGETYP|type}00.fits.gz",
        fits_namespaces: Optional[List[str]] = None,
        **kwargs: Any,
    ):
        """Creates a new BaseCamera.

        Args:
            fits_headers: Additional FITS headers.
            centre: (x, y) tuple of camera centre.
            rotation: Rotation east of north.
            flip: Whether or not to flip the image along its first axis.
            filenames: Template for file naming.
            fits_namespaces: List of namespaces for FITS headers that this camera should request
        """
        Module.__init__(self, **kwargs)
        ImageFitsHeaderMixin.__init__(
            self,
            fits_namespaces=fits_namespaces,
            fits_headers=fits_headers,
            centre=centre,
            rotation=rotation,
            filenames=filenames,
        )

        # check
        if self.comm is None:
            log.warning(
                "No comm module given, will not be able to signal new images!")

        # store
        self._flip = flip
        self._exposure_time: float = 0.0
        self._image_type = ImageType.OBJECT

        # init camera
        self._exposure: Optional[ExposureInfo] = None
        self._camera_status = ExposureStatus.IDLE

        # multi-threading
        self.expose_abort = asyncio.Event()

        # register exception
        exc.register_exception(exc.GrabImageError,
                               3,
                               timespan=600,
                               callback=self._default_remote_error_callback)
Beispiel #10
0
    def __init__(
        self, telescope: Union[str, ITelescope], pointing: Union[Dict[str, Any], SkyFlatsBasePointing], **kwargs: Any
    ):
        """Initialize a new flat field pointing.

        Args:
            telescope: Telescope to point
            pointing: Pointing for calculating coordinates.
        """
        Module.__init__(self, **kwargs)

        # store telescope and pointing
        self._telescope = telescope
        self._pointing = pointing
Beispiel #11
0
    def __init__(
        self,
        tasks: Union[dict, TaskArchive],
        schedule_range: int = 24,
        safety_time: int = 60,
        twilight: str = "astronomical",
        trigger_on_task_started: bool = False,
        trigger_on_task_finished: bool = False,
        **kwargs: Any,
    ):
        """Initialize a new scheduler.

        Args:
            scheduler: Scheduler to use
            schedule_range: Number of hours to schedule into the future
            safety_time: If no ETA for next task to start exists (from current task, weather became good, etc), use
                         this time in seconds to make sure that we don't schedule for a time when the scheduler is
                         still running
            twilight: astronomical or nautical
            trigger_on_task_started: Whether to trigger a re-calculation of schedule, when task has started.
            trigger_on_task_finishes: Whether to trigger a re-calculation of schedule, when task has finished.
        """
        Module.__init__(self, **kwargs)

        # get scheduler
        self._task_archive = self.add_child_object(tasks, TaskArchive)

        # store
        self._schedule_range = schedule_range
        self._safety_time = safety_time
        self._twilight = twilight
        self._running = True
        self._initial_update_done = False
        self._need_update = False
        self._trigger_on_task_started = trigger_on_task_started
        self._trigger_on_task_finished = trigger_on_task_finished

        # time to start next schedule from
        self._schedule_start = None

        # ID of currently running task, and current (or last if finished) block
        self._current_task_id = None
        self._last_task_id = None

        # blocks
        self._blocks: List[ObservingBlock] = []

        # update thread
        self.add_background_task(self._schedule_thread)
        self.add_background_task(self._update_thread)
Beispiel #12
0
    def __init__(
        self,
        alt_range: Tuple[float, float] = (30.0, 85.0),
        num_alt: int = 8,
        az_range: Tuple[float, float] = (0.0, 360.0),
        num_az: int = 24,
        dec_range: Tuple[float, float] = (-80.0, 80.0),
        min_moon_dist: float = 15.0,
        finish: int = 90,
        exp_time: float = 1.0,
        acquisition: str = "acquisition",
        telescope: str = "telescope",
        **kwargs: Any,
    ):
        """Initialize a new auto focus system.

        Args:
            alt_range: Range in degrees to use in altitude.
            num_alt: Number of altitude points to create on grid.
            az_range: Range in degrees to use in azimuth.
            num_az: Number of azimuth points to create on grid.
            dec_range: Range in declination in degrees to use.
            min_moon_dist: Minimum moon distance in degrees.
            finish: When this number in percent of points have been finished, terminate mastermind.
            exp_time: Exposure time in secs.
            acquisition: IAcquisition unit to use.
            telescope: ITelescope unit to use.
        """
        Module.__init__(self, **kwargs)

        # store
        self._alt_range = tuple(alt_range)
        self._num_alt = num_alt
        self._az_range = tuple(az_range)
        self._num_az = num_az
        self._dec_range = dec_range
        self._min_moon_dist = min_moon_dist
        self._finish = 1.0 - finish / 100.0
        self._exp_time = exp_time
        self._acquisition = acquisition
        self._telescope = telescope

        # if Az range is [0, 360], we got north double, so remove one step
        if self._az_range == (0.0, 360.0):
            self._az_range = (0.0, 360.0 - 360.0 / self._num_az)

        # add thread func
        self.add_background_task(self._run_thread, False)
Beispiel #13
0
    def __init__(self, hostname: str, port: int, *args: Any, **kwargs: Any):
        """Initialize a new logger.

        Args:
            hostname: Hostname of server.
            port: Port of server.

        """
        from fluent import sender

        Module.__init__(self, **kwargs)

        # store
        self._hostname = hostname
        self._port = port
        self._fluent: Optional[sender.FluentSender] = None
Beispiel #14
0
    def __init__(self,
                 message: str = "Hello world",
                 interval: int = 10,
                 **kwargs: Any):
        """Creates a new StandAlone object.

        Args:
            message: Message to log in the given interval.
            interval: Interval between messages.
        """
        Module.__init__(self, **kwargs)

        # add thread func
        self.add_background_task(self._message_func)

        # store
        self._message = message
        self._interval = interval
Beispiel #15
0
    def __init__(self,
                 filename: str = "/archive/{FNAME}",
                 sources: Optional[Union[str, List[str]]] = None,
                 **kwargs: Any):
        """Creates a new image writer.

        Args:
            filename: Pattern for filename to store images at.
            sources: List of sources (e.g. cameras) to process images from or None for all.
        """
        Module.__init__(self, **kwargs)

        # add thread func
        self.add_background_task(self._worker, True)

        # variables
        self._filename = filename
        self._sources = [sources] if isinstance(sources, str) else sources
        self._queue = asyncio.Queue()
Beispiel #16
0
    def __init__(self, triggers: List[Dict[str, Any]], **kwargs: Any):
        """Initialize a new trigger module.

        Args:
            triggers: List of dictionaries defining the trigger. Must contain fields for event, module and method,
                      may contain a sender.

        """
        Module.__init__(self, **kwargs)

        # store
        self._running = False

        # store triggers and convert event strings to actual classes
        self._triggers = triggers
        for trigger in self._triggers:
            # get class and store it
            kls = get_class_from_string(trigger["event"])
            trigger["event"] = kls
Beispiel #17
0
    def __init__(
        self,
        fits_headers: Optional[Dict[str, Any]] = None,
        min_altitude: float = 10,
        wait_for_dome: Optional[str] = None,
        **kwargs: Any,
    ):
        """Initialize a new base telescope.

        Args:
            fits_headers: Additional FITS headers to send.
            min_altitude: Minimal altitude for telescope.
            wait_for_dome: Name of dome module to wait for.
        """
        Module.__init__(self, **kwargs)

        # store
        self._fits_headers = fits_headers if fits_headers is not None else {}
        self._min_altitude = min_altitude

        # some multi-threading stuff
        self._lock_moving = asyncio.Lock()
        self._abort_move = asyncio.Event()

        # celestial status
        self._celestial_headers: Dict[str, Any] = {}

        # add thread func
        self.add_background_task(self._celestial, True)

        # init mixins
        WeatherAwareMixin.__init__(self, **kwargs)
        MotionStatusMixin.__init__(self, **kwargs)
        WaitForMotionMixin.__init__(
            self,
            wait_for_modules=None if wait_for_dome is None else [wait_for_dome],
            wait_for_timeout=60000,
            wait_for_states=[MotionStatus.POSITIONED, MotionStatus.TRACKING],
        )

        # register exception
        exc.register_exception(exc.MotionError, 3, timespan=600, callback=self._default_remote_error_callback)
Beispiel #18
0
    def __init__(
        self,
        warn_sound: str,
        warn_interval: float = 1,
        start_sound: Optional[str] = None,
        started_sound: Optional[str] = None,
        stop_sound: Optional[str] = None,
        stopped_sound: Optional[str] = None,
        player: str = "mpg123",
        trigger_file: Optional[str] = None,
        **kwargs: Any,
    ):
        """Initialize a new warning.

        Args:
            warn_sound: Name of file to play.
            warn_interval: Interval in seconds between sounds.
            start_sound: Sound to play when starting systems.
            started_sound: Sound to play when systems started.
            stop_sound: Sound to play when stopping systems.
            stopped_sound: Sound to play when systems stopped.
            trigger_file: File, which triggers to switch on-off and vice versa, when created.
                Will be deleted afterwards.
        """
        Module.__init__(self, **kwargs)

        # store
        self._warn_sound = warn_sound
        self._warn_interval = warn_interval
        self._start_sound = start_sound
        self._started_sound = started_sound
        self._stop_sound = stop_sound
        self._stopped_sound = stopped_sound
        self._trigger_file = trigger_file
        self._player = player
        self._autonomous = False

        # threads
        self.add_background_task(self._heartbeat)
        self.add_background_task(self._check_autonomous)
        self.add_background_task(self._check_trigger)
Beispiel #19
0
    def __init__(self,
                 camera: Union[ICamera, str],
                 port: int = 37077,
                 **kwargs: Any):
        """Initializes file cache.

        Args:
            camera: Camera to use for kiosk mode.
            port: Port for HTTP server.
        """
        Module.__init__(self, **kwargs)

        # add thread funcs
        self.add_background_task(self._camera_thread)

        # store stuff
        self._is_listening = False
        self._camera = camera
        self._port = port
        self._exp_time = 2
        self._running = False
        self._image: Optional[bytes] = None

        # create empty image
        from PIL import Image, ImageDraw

        img = Image.new("RGB", (300, 300), color=(0, 0, 0))
        d = ImageDraw.Draw(img)
        d.text((110, 150), "No image taken yet", fill=(255, 255, 255))

        # create image from data array
        with io.BytesIO() as bio:
            img.save(bio, format="jpeg")
            self._empty = bio.getvalue()

        # define web server
        self._app = web.Application()
        self._app.add_routes([web.get("/image.jpg", self.image_handler)])
        self._runner = web.AppRunner(self._app)
        self._site: Optional[web.TCPSite] = None
Beispiel #20
0
 def __init__(self, **kwargs: Any):
     Module.__init__(self, **kwargs)
     self._running = False
Beispiel #21
0
    def __init__(
        self,
        telescope: Union[str, ITelescope],
        camera: Union[str, ICamera],
        flat_fielder: Optional[Union[Dict[str, Any], FlatFielder]],
        filters: Optional[Union[str, IFilters]] = None,
        log_file: Optional[str] = None,
        **kwargs: Any,
    ):
        """Initialize a new flat fielder.

        Args:
            telescope: Name of ITelescope.
            camera: Name of ICamera.
            flat_fielder: Flat field object to use.
            filters: Name of IFilters, if any.
            log_file: Name of file to store flat field log in.
        """
        Module.__init__(self, **kwargs)

        # store telescope, camera, and filters
        self._telescope = telescope
        self._camera = camera
        self._filter_wheel = filters
        self._abort = asyncio.Event()
        self._running = False

        # flat fielder
        self._flat_fielder = self.get_object(flat_fielder,
                                             FlatFielder,
                                             callback=self.callback)

        # init log file
        self._publisher = None if log_file is None else CsvPublisher(log_file)

        # init binning and filter
        self._binning = (1, 1)
        self._filter: Optional[str] = None

        # need to add IFilters interface?
        if self._filter_wheel is not None:
            # check filters
            if not self._flat_fielder.has_filters:
                raise ValueError(
                    "Filter wheel module given in config, but no filters in functions."
                )

            # add it
            # self.__class__ = type('FlatFieldFilter', (FlatField, IFilters), {})

        # register exceptions
        if isinstance(camera, str):
            exc.register_exception(
                exc.RemoteError,
                3,
                timespan=600,
                module=camera,
                callback=self._default_remote_error_callback)
        if isinstance(telescope, str):
            exc.register_exception(
                exc.RemoteError,
                3,
                timespan=600,
                module=telescope,
                callback=self._default_remote_error_callback)
        if isinstance(filters, str):
            exc.register_exception(
                exc.RemoteError,
                3,
                timespan=600,
                module=filters,
                callback=self._default_remote_error_callback)
Beispiel #22
0
    def __init__(
        self,
        focuser: Optional[str] = None,
        weather: Optional[str] = None,
        interval: int = 300,
        temperatures: Optional[Dict[str, Dict[str, float]]] = None,
        model: Optional[str] = None,
        coefficients: Optional[Dict[str, float]] = None,
        update: bool = False,
        log_file: Optional[str] = None,
        min_measurements: int = 10,
        enabled: bool = True,
        temp_sensor: str = "average.temp",
        default_filter: Optional[str] = None,
        filter_offsets: Optional[Dict[str, float]] = None,
        filter_wheel: Optional[str] = None,
        **kwargs: Any,
    ):
        """Initialize a focus model.

        Args:
            focuser: Name of focuser.
            weather: Name of weather station.
            interval: Interval for setting focus or None, if no regular setting of focus is required.
            model: Focus model to use.
            coefficients: Coefficients in model, mainly used when updating it.
            update: Whether to update the model on new focus values.
            log_file: Path to file containing all focus measurements.
            min_measurements: Minimum number of measurements to update model.
            enabled: If False, no focus is set.
            temp_sensor: Name of sensor at weather station to provide ambient temperature.
            default_filter: Name of default filter. If None, filters are ignored.
            filter_offsets: Offsets for different filters. If None, they are not modeled.
            filter_wheel: Name of filter wheel module to use for fetching filter before setting focus.
        """
        Module.__init__(self, **kwargs)

        # check import
        import lmfit

        log.info(f"Found lmfit {lmfit.__version__}.")

        # add thread func
        if interval is not None and interval > 0:
            self.add_background_task(self._update)

        # store
        self._focuser = focuser
        self._weather = weather
        self._interval = interval
        self._temperatures: Dict[str, Dict[
            str, float]] = {} if temperatures is None else temperatures
        self._focuser_ready = True
        self._coefficients = {} if coefficients is None else coefficients
        self._update_model = update
        self._min_measurements = min_measurements
        self._enabled = enabled
        self._temp_station, sensor = temp_sensor.split(".")
        self._temp_sensor = WeatherSensors(sensor)
        self._default_filter = default_filter
        self._filter_offsets = filter_offsets
        self._filter_wheel = filter_wheel
        log.info("Going to fetch temperature from sensor %s at station %s.",
                 self._temp_sensor, self._temp_station)

        # model
        parser = Parser()
        log.info("Parsing model: %s", model)
        self._model = parser.parse(model)

        # coefficients
        if self._coefficients is not None and len(self._coefficients) > 0:
            log.info(
                "Found coefficients: %s", ", ".join([
                    "%s=%.3f" % (k, v) for k, v in self._coefficients.items()
                ]))

        # variables
        variables = self._model.variables()
        for c in self._coefficients.keys():
            variables.remove(c)
        log.info("Found variables: %s", ", ".join(variables))

        # init log file
        self._publisher = None if log_file is None else CsvPublisher(log_file)

        # update model now?
        if update:
            self._calc_focus_model()
Beispiel #23
0
    def __init__(
        self,
        http_port: int = 37077,
        interval: float = 0.5,
        video_path: str = "/webcam/video.mjpg",
        filenames:
        str = "/webcam/pyobs-{DAY-OBS|date:}-{FRAMENUM|string:04d}.fits",
        fits_namespaces: Optional[List[str]] = None,
        fits_headers: Optional[Dict[str, Any]] = None,
        centre: Optional[Tuple[float, float]] = None,
        rotation: float = 0.0,
        cache_size: int = 5,
        live_view: bool = True,
        flip: bool = False,
        sleep_time: int = 600,
        **kwargs: Any,
    ):
        """Creates a new BaseWebcam.

        On the receiving end, a VFS root with a HTTPFile must exist with the same name as in image_path and video_path,
        i.e. "webcam" in the default settings.

        Args:
            http_port: HTTP port for webserver.
            exposure_time: Initial exposure time.
            interval: Min interval for grabbing images.
            video_path: VFS path to video.
            filename: Filename pattern for FITS images.
            fits_namespaces: List of namespaces for FITS headers that this camera should request.
            fits_headers: Additional FITS headers.
            centre: (x, y) tuple of camera centre.
            rotation: Rotation east of north.
            cache_size: Size of cache for previous images.
            live_view: If True, live view is served via web server.
            flip: Whether to flip around Y axis.
            sleep_time: Time in s with inactivity after which the camera should go to sleep.
        """
        Module.__init__(self, **kwargs)
        ImageFitsHeaderMixin.__init__(
            self,
            fits_namespaces=fits_namespaces,
            fits_headers=fits_headers,
            centre=centre,
            rotation=rotation,
            filenames=filenames,
        )

        # store
        self._is_listening = False
        self._port = http_port
        self._interval = interval
        self._new_image_event = asyncio.Event()
        self._video_path = video_path
        self._frame_num = 0
        self._live_view = live_view
        self._image_type = ImageType.OBJECT
        self._image_request_lock = asyncio.Lock()
        self._image_requests: List[ImageRequest] = []
        self._next_image: Optional[NextImage] = None
        self._last_image: Optional[LastImage] = None
        self._last_time = 0.0
        self._flip = flip
        self._sleep_time = sleep_time

        # active
        self._active = False
        self._active_time = 0.0
        self.add_background_task(self._active_update)

        # image cache
        self._cache = DataCache(cache_size)

        # define web server
        self._app = web.Application()
        self._app.add_routes([
            web.get("/", self.web_handler),
            web.get("/video.mjpg", self.video_handler),
            web.get("/{filename}", self.image_handler),
        ])
        self._runner = web.AppRunner(self._app)
        self._site: Optional[web.TCPSite] = None
Beispiel #24
0
    def __init__(self, **kwargs: Any):
        """Create a new dummy acquisition."""
        Module.__init__(self, **kwargs)

        # store
        self._is_running = False