pyobs-core 2.0.0.dev21__tar.gz → 2.0.0.dev24__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.
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/PKG-INFO +1 -1
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/comm/comm.py +31 -9
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/comm/proxy.py +29 -1
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/comm/xmpp/xmppclient.py +1 -1
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/comm/xmpp/xmppcomm.py +25 -11
- pyobs_core-2.0.0.dev24/pyobs/interfaces/IDataSequence.py +51 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/interfaces/__init__.py +3 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/mixins/motionstatus.py +13 -1
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/modules/camera/basecamera.py +66 -2
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/modules/camera/basespectrograph.py +11 -1
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/modules/camera/pipelinecamera.py +11 -2
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/modules/flatfield/flatfield.py +6 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/modules/focus/focusmodel.py +14 -3
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/modules/pointing/autoguiding.py +5 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/modules/pointing/scienceframeguiding.py +5 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/modules/roof/baseroof.py +1 -14
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/modules/telescope/_dummytelescopebase.py +12 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/modules/telescope/dummysolartelescope.py +12 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/modules/utils/dummymode.py +1 -2
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/robotic/utils/skyflats/flatfielder.py +7 -1
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyproject.toml +1 -1
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/.gitignore +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/LICENSE +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/__init__.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/application.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/background_task.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/cli/__init__.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/cli/_cli.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/cli/pyobs.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/cli/pyobsd.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/cli/pyobsw.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/comm/__init__.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/comm/commlogging.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/comm/dummy/__init__.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/comm/dummy/dummycomm.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/comm/local/__init__.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/comm/local/localcomm.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/comm/local/localnetwork.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/comm/xmpp/__init__.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/comm/xmpp/rpc.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/comm/xmpp/serializer.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/comm/xmpp/xep_0009/__init__.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/comm/xmpp/xep_0009/binding.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/comm/xmpp/xep_0009/rpc.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/comm/xmpp/xep_0009_timeout/__init__.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/comm/xmpp/xep_0009_timeout/rpc.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/comm/xmpp/xep_0009_timeout/stanza/RPC.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/comm/xmpp/xep_0009_timeout/stanza/__init__.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/events/__init__.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/events/badweather.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/events/event.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/events/exposurestatuschanged.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/events/filterchanged.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/events/focusfound.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/events/goodweather.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/events/log.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/events/modechanged.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/events/moduleclosed.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/events/moduleopened.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/events/motionstatuschanged.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/events/move.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/events/newimage.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/events/newspectrum.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/events/offsets.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/events/roofclosing.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/events/roofopened.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/events/taskfailed.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/events/taskfinished.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/events/taskstarted.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/events/testevent.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/images/__init__.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/images/image.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/images/meta/__init__.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/images/meta/altazoffsets.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/images/meta/exptime.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/images/meta/genericoffset.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/images/meta/onskydistance.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/images/meta/pixeloffsets.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/images/meta/radecoffsets.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/images/meta/skyoffsets.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/images/processor.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/images/processors/__init__.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/images/processors/_daobackgroundremover.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/images/processors/annotation/__init__.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/images/processors/annotation/_pillow.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/images/processors/annotation/circle.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/images/processors/annotation/crosshair.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/images/processors/annotation/text.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/images/processors/astrometry/__init__.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/images/processors/astrometry/_dotnet_request.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/images/processors/astrometry/_dotnet_request_builder.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/images/processors/astrometry/_dotnet_request_logger.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/images/processors/astrometry/_dotnet_response_saver.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/images/processors/astrometry/astrometry.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/images/processors/astrometry/dotnet.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/images/processors/calibration/__init__.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/images/processors/calibration/_calibration_cache.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/images/processors/calibration/_ccddata_calibrator.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/images/processors/calibration/calibration.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/images/processors/detection/__init__.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/images/processors/detection/_pysep_stats_calculator.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/images/processors/detection/_source_catalog.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/images/processors/detection/daophot.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/images/processors/detection/pysep.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/images/processors/detection/simpledisk.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/images/processors/detection/sourcedetection.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/images/processors/exptime/__init__.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/images/processors/exptime/exptime.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/images/processors/exptime/star.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/images/processors/image/__init__.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/images/processors/image/addfitsheaders.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/images/processors/image/download.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/images/processors/image/flip.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/images/processors/image/grayscale.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/images/processors/image/httpserver.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/images/processors/image/normalize.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/images/processors/image/save.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/images/processors/image/saveimage.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/images/processors/image/smooth.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/images/processors/image/softbin.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/images/processors/misc/__init__.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/images/processors/misc/addmask.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/images/processors/misc/catalogcircularmask.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/images/processors/misc/circularmask.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/images/processors/misc/createfilename.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/images/processors/misc/imagesourcefilter.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/images/processors/misc/removebackground.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/images/processors/modules/__init__.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/images/processors/modules/getfitsheaders.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/images/processors/offsets/__init__.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/images/processors/offsets/astrometry.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/images/processors/offsets/brighteststar.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/images/processors/offsets/brighteststar_guiding.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/images/processors/offsets/dummyoffsets.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/images/processors/offsets/dummyskyoffsets.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/images/processors/offsets/fitsheader.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/images/processors/offsets/offsets.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/images/processors/offsets/pixeloffsets.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/images/processors/offsets/projected.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/images/processors/offsets/spilled_light.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/images/processors/photometry/__init__.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/images/processors/photometry/_photometry_calculator.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/images/processors/photometry/_photutil_aperture_photometry.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/images/processors/photometry/_sep_aperture_photometry.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/images/processors/photometry/aperture_photometry.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/images/processors/photometry/photometry.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/images/processors/photometry/photutil.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/images/processors/photometry/pysep.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/images/processors/wcs/__init__.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/images/processors/wcs/solarhelioprojective.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/interfaces/IAbortable.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/interfaces/IAcquisition.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/interfaces/IAutoFocus.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/interfaces/IAutoGuiding.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/interfaces/IAutonomous.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/interfaces/IBinning.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/interfaces/ICalibrate.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/interfaces/ICamera.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/interfaces/IConfig.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/interfaces/ICooling.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/interfaces/IData.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/interfaces/IDome.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/interfaces/IExposure.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/interfaces/IExposureTime.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/interfaces/IFilters.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/interfaces/IFitsHeaderAfter.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/interfaces/IFitsHeaderBefore.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/interfaces/IFlatField.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/interfaces/IFocusModel.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/interfaces/IFocuser.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/interfaces/IGain.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/interfaces/IImageFormat.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/interfaces/IImageType.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/interfaces/IMode.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/interfaces/IModule.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/interfaces/IMotion.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/interfaces/IMultiFiber.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/interfaces/IOffsetsAltAz.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/interfaces/IOffsetsRaDec.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/interfaces/IPointingAltAz.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/interfaces/IPointingBody.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/interfaces/IPointingHeliocentricPolar.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/interfaces/IPointingHeliographicStonyhurst.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/interfaces/IPointingHelioprojective.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/interfaces/IPointingOrbitalElements.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/interfaces/IPointingRaDec.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/interfaces/IPointingSeries.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/interfaces/IReady.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/interfaces/IRoof.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/interfaces/IRotation.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/interfaces/IRunnable.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/interfaces/IRunning.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/interfaces/IScriptRunner.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/interfaces/ISpectrograph.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/interfaces/IStartStop.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/interfaces/IStructuredConfig.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/interfaces/ISyncTarget.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/interfaces/ITelescope.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/interfaces/ITemperatures.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/interfaces/ITrackingMode.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/interfaces/ITrackingRate.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/interfaces/IVideo.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/interfaces/IWeather.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/interfaces/IWindow.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/interfaces/interface.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/mixins/__init__.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/mixins/camerasettings.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/mixins/fitsheader.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/mixins/fitsnamespace.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/mixins/follow.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/mixins/pipeline.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/mixins/waitformotion.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/mixins/weatheraware.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/modules/__init__.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/modules/camera/__init__.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/modules/camera/adaptive.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/modules/camera/basevideo.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/modules/camera/dummycamera.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/modules/camera/dummyspectrograph.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/modules/camera/dummyvideo.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/modules/flatfield/__init__.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/modules/flatfield/pointing.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/modules/flatfield/scheduler.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/modules/focus/__init__.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/modules/focus/dummyautofocus.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/modules/focus/focusseries.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/modules/image/__init__.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/modules/image/imagewatcher.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/modules/image/imagewriter.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/modules/image/pipeline.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/modules/image/seeing.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/modules/module.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/modules/pointing/__init__.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/modules/pointing/_base.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/modules/pointing/_baseguiding.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/modules/pointing/acquisition.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/modules/pointing/dummyacquisition.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/modules/pointing/dummyguiding.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/modules/pointing/guidingstatistics/__init__.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/modules/pointing/guidingstatistics/guidingstatistics.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/modules/pointing/guidingstatistics/pixeloffset.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/modules/pointing/guidingstatistics/skyoffsets.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/modules/pointing/guidingstatistics/uptime.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/modules/robotic/__init__.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/modules/robotic/mastermind.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/modules/robotic/pointing.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/modules/robotic/scheduler.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/modules/robotic/scriptrunner.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/modules/roof/__init__.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/modules/roof/basedome.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/modules/roof/dummyroof.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/modules/telescope/__init__.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/modules/telescope/basetelescope.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/modules/telescope/dummyaltaztelescope.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/modules/telescope/dummyradectelescope.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/modules/test/__init__.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/modules/test/standalone.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/modules/utils/__init__.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/modules/utils/fluentlogger.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/modules/utils/httpfilecache.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/modules/utils/kiosk.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/modules/utils/matrix.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/modules/utils/stellarium.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/modules/utils/telegram.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/modules/utils/trigger.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/modules/weather/__init__.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/modules/weather/mockweather.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/modules/weather/weather.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/modules/weather/weather_api.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/modules/weather/weather_state.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/object.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/py.typed +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/robotic/__init__.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/robotic/observation.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/robotic/scheduler/__init__.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/robotic/scheduler/astroplanscheduler.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/robotic/scheduler/constraints/__init__.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/robotic/scheduler/constraints/airmassconstraint.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/robotic/scheduler/constraints/constraint.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/robotic/scheduler/constraints/moonilluminationconstraint.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/robotic/scheduler/constraints/moonseparationconstraint.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/robotic/scheduler/constraints/solarelevationconstraint.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/robotic/scheduler/constraints/timeconstraint.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/robotic/scheduler/dataprovider.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/robotic/scheduler/merits/__init__.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/robotic/scheduler/merits/aftertime.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/robotic/scheduler/merits/beforetime.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/robotic/scheduler/merits/constant.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/robotic/scheduler/merits/follow.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/robotic/scheduler/merits/interval.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/robotic/scheduler/merits/merit.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/robotic/scheduler/merits/pernight.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/robotic/scheduler/merits/random.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/robotic/scheduler/merits/timewindow.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/robotic/scheduler/merits/transit.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/robotic/scheduler/observationarchiveevolution.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/robotic/scheduler/ondemandscheduler.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/robotic/scheduler/targets/__init__.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/robotic/scheduler/targets/dynamictarget.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/robotic/scheduler/targets/heliocentricpolartarget.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/robotic/scheduler/targets/helioprojectivetarget.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/robotic/scheduler/targets/picker/__init__.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/robotic/scheduler/targets/picker/csvpicker.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/robotic/scheduler/targets/picker/picker.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/robotic/scheduler/targets/siderealtarget.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/robotic/scheduler/targets/target.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/robotic/scheduler/taskscheduler.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/robotic/scripts/__init__.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/robotic/scripts/calibration/__init__.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/robotic/scripts/calibration/darkbias.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/robotic/scripts/calibration/pointing.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/robotic/scripts/calibration/skyflats.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/robotic/scripts/control/__init__.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/robotic/scripts/control/cases.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/robotic/scripts/control/conditional.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/robotic/scripts/control/parallel.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/robotic/scripts/control/selector.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/robotic/scripts/control/sequential.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/robotic/scripts/imaging/__init__.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/robotic/scripts/imaging/autofocus.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/robotic/scripts/imaging/imaging.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/robotic/scripts/imaging/transitimaging.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/robotic/scripts/script.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/robotic/scripts/utils/__init__.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/robotic/scripts/utils/callmodule.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/robotic/scripts/utils/debugtrigger.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/robotic/scripts/utils/log.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/robotic/storage/__init__.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/robotic/storage/backend/__init__.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/robotic/storage/backend/observationarchive.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/robotic/storage/backend/taskarchive.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/robotic/storage/filesystem/__init__.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/robotic/storage/filesystem/observationarchive.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/robotic/storage/filesystem/taskarchive.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/robotic/storage/lco/__init__.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/robotic/storage/lco/_portal.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/robotic/storage/lco/_schedulereader.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/robotic/storage/lco/_schedulewriter.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/robotic/storage/lco/configdb.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/robotic/storage/lco/mockobservationarchive.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/robotic/storage/lco/observationarchive.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/robotic/storage/lco/scripts/__init__.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/robotic/storage/lco/scripts/autofocus.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/robotic/storage/lco/scripts/default.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/robotic/storage/lco/scripts/script.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/robotic/storage/lco/task.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/robotic/storage/lco/taskarchive.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/robotic/storage/lco/taskrunner.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/robotic/storage/memory/__init__.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/robotic/storage/memory/observationarchive.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/robotic/storage/memory/taskarchive.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/robotic/storage/observationarchive.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/robotic/storage/taskarchive.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/robotic/task.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/robotic/taskrunner.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/robotic/utils/__init__.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/robotic/utils/archive/__init__.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/robotic/utils/archive/archive.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/robotic/utils/archive/local_archive.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/robotic/utils/archive/pyobs_archive.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/robotic/utils/exptime/__init__.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/robotic/utils/exptime/exptime.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/robotic/utils/exptime/stellarexptime.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/robotic/utils/skyflats/__init__.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/robotic/utils/skyflats/exptimeeval.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/robotic/utils/skyflats/pointing/__init__.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/robotic/utils/skyflats/pointing/base.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/robotic/utils/skyflats/pointing/static.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/robotic/utils/skyflats/priorities/__init__.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/robotic/utils/skyflats/priorities/archive.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/robotic/utils/skyflats/priorities/base.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/robotic/utils/skyflats/priorities/const.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/robotic/utils/skyflats/scheduler.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/utils/__init__.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/utils/average.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/utils/cache.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/utils/config.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/utils/config_schema.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/utils/coordinates.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/utils/curvefit.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/utils/enums.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/utils/exceptions.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/utils/fits.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/utils/focusseries/__init__.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/utils/focusseries/base.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/utils/focusseries/photometry.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/utils/focusseries/projection.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/utils/grids/__init__.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/utils/grids/filters.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/utils/grids/grid.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/utils/grids/gridnode.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/utils/grids/pipeline.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/utils/gui/__init__.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/utils/gui/camera/__init__.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/utils/gui/camera/binningwidget.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/utils/gui/camera/datadisplaywidget.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/utils/gui/camera/exposewidget.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/utils/gui/camera/exposuretimewidget.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/utils/gui/camera/imageformatwidget.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/utils/gui/camera/listpickerdialog.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/utils/gui/camera/windowingwidget.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/utils/http.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/utils/influxdb.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/utils/logger.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/utils/logging/__init__.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/utils/logging/context.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/utils/logging/resolvableerror.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/utils/modulegui.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/utils/offsets/__init__.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/utils/offsets/applyaltazoffsets.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/utils/offsets/applyoffsets.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/utils/offsets/applyradecoffsets.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/utils/parallel.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/utils/pipeline/__init__.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/utils/pipeline/night.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/utils/pipeline/pipeline.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/utils/publisher/__init__.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/utils/publisher/csv.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/utils/publisher/http.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/utils/publisher/log.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/utils/publisher/multi.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/utils/publisher/publisher.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/utils/serialization.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/utils/shellcommand.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/utils/threads/__init__.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/utils/threads/lockwithabort.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/utils/time.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/utils/units.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/version.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/vfs/__init__.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/vfs/archivefile.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/vfs/bufferedfile.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/vfs/file.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/vfs/filelists/__init__.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/vfs/filelists/filelist.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/vfs/filelists/testing.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/vfs/httpfile.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/vfs/localfile.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/vfs/memfile.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/vfs/sftpfile.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/vfs/smbfile.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/vfs/sshfile.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/vfs/tempfile.py +0 -0
- {pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/vfs/vfs.py +0 -0
|
@@ -133,16 +133,14 @@ class Comm:
|
|
|
133
133
|
except IndexError:
|
|
134
134
|
return None
|
|
135
135
|
|
|
136
|
-
#
|
|
137
|
-
|
|
136
|
+
# create new proxy
|
|
137
|
+
proxy = Proxy(self, client, interfaces)
|
|
138
|
+
|
|
139
|
+
# fetch capabilities in the background, so a peer that isn't fully up yet doesn't block
|
|
140
|
+
# proxy construction -- Proxy.wait_for_capabilities() can be used to wait for the result
|
|
138
141
|
for interface in interfaces:
|
|
139
142
|
if interface.capabilities is not None:
|
|
140
|
-
|
|
141
|
-
if cap is not None:
|
|
142
|
-
capabilities[interface] = cap
|
|
143
|
-
|
|
144
|
-
# create new proxy
|
|
145
|
-
proxy = Proxy(self, client, interfaces, capabilities)
|
|
143
|
+
asyncio.create_task(self._fetch_and_update_capabilities(client, interface, proxy))
|
|
146
144
|
|
|
147
145
|
# subscribe to state
|
|
148
146
|
for interface in interfaces:
|
|
@@ -151,9 +149,14 @@ class Comm:
|
|
|
151
149
|
|
|
152
150
|
self._proxies[client] = proxy
|
|
153
151
|
|
|
154
|
-
# return proxy
|
|
155
152
|
return self._proxies[client]
|
|
156
153
|
|
|
154
|
+
async def _fetch_and_update_capabilities(self, client: str, interface: type[Interface], proxy: Proxy) -> None:
|
|
155
|
+
"""Fetch capabilities for a single interface and push them into the given proxy once available."""
|
|
156
|
+
cap = await self._get_capabilities(client, interface)
|
|
157
|
+
if cap is not None:
|
|
158
|
+
proxy.update_capabilities(interface, cap)
|
|
159
|
+
|
|
157
160
|
async def _resolve_proxy(
|
|
158
161
|
self, name_or_object: str | object, obj_type: type[ProxyType] | None = None
|
|
159
162
|
) -> Any | ProxyType:
|
|
@@ -445,6 +448,25 @@ class Comm:
|
|
|
445
448
|
if not event_class.local:
|
|
446
449
|
await self._register_events(event_classes, handler)
|
|
447
450
|
|
|
451
|
+
async def unregister_event(
|
|
452
|
+
self, event_class: type[Event], handler: Callable[[Event, str], Coroutine[Any, Any, bool]]
|
|
453
|
+
) -> None:
|
|
454
|
+
"""Remove a handler previously added via register_event().
|
|
455
|
+
|
|
456
|
+
Leaves the event type itself registered (other handlers may still be interested in it,
|
|
457
|
+
and the module may still want to advertise/receive it), only stops calling this handler.
|
|
458
|
+
|
|
459
|
+
Args:
|
|
460
|
+
event_class: Class of event that was registered.
|
|
461
|
+
handler: The exact handler that was passed to register_event().
|
|
462
|
+
"""
|
|
463
|
+
|
|
464
|
+
# same derived-events expansion as register_event(), so this mirrors exactly what was added
|
|
465
|
+
for ev in self._get_derived_events(event_class):
|
|
466
|
+
handlers = self._event_handlers.get(ev)
|
|
467
|
+
if handlers is not None and handler in handlers:
|
|
468
|
+
handlers.remove(handler)
|
|
469
|
+
|
|
448
470
|
async def _register_events(
|
|
449
471
|
self, events: list[type[Event]], handler: Callable[[Event, str], Coroutine[Any, Any, bool]] | None = None
|
|
450
472
|
) -> None:
|
|
@@ -62,6 +62,7 @@ class Proxy:
|
|
|
62
62
|
# store state and capabilities
|
|
63
63
|
self._state: dict[type[Interface], Any] = {}
|
|
64
64
|
self._capabilities: dict[type[Interface], Any] = capabilities if capabilities is not None else {}
|
|
65
|
+
self._capabilities_events: dict[type[Interface], asyncio.Event] = {}
|
|
65
66
|
|
|
66
67
|
@property
|
|
67
68
|
def name(self) -> str:
|
|
@@ -175,8 +176,18 @@ class Proxy:
|
|
|
175
176
|
"""Latest known state for the given interface, or None if nothing has arrived yet."""
|
|
176
177
|
return self._state.get(interface)
|
|
177
178
|
|
|
179
|
+
def update_capabilities(self, interface: type[Interface], capabilities: Any) -> None:
|
|
180
|
+
"""Called by Comm once capabilities for an interface arrive.
|
|
181
|
+
|
|
182
|
+
Not intended to be called directly by module code.
|
|
183
|
+
"""
|
|
184
|
+
self._capabilities[interface] = capabilities
|
|
185
|
+
event = self._capabilities_events.get(interface)
|
|
186
|
+
if event is not None:
|
|
187
|
+
event.set()
|
|
188
|
+
|
|
178
189
|
def get_capabilities(self, interface: type[Interface]) -> Any | None:
|
|
179
|
-
"""Capabilities for the given interface,
|
|
190
|
+
"""Capabilities for the given interface, or None if not (yet) fetched."""
|
|
180
191
|
return self._capabilities.get(interface)
|
|
181
192
|
|
|
182
193
|
async def wait_for_state(
|
|
@@ -203,6 +214,23 @@ class Proxy:
|
|
|
203
214
|
|
|
204
215
|
return self._state.get(interface)
|
|
205
216
|
|
|
217
|
+
async def wait_for_capabilities(
|
|
218
|
+
self,
|
|
219
|
+
interface: type[Interface],
|
|
220
|
+
timeout: float = 10.0,
|
|
221
|
+
) -> Any | None:
|
|
222
|
+
"""Return capabilities immediately if available, otherwise wait for the background fetch to complete."""
|
|
223
|
+
if self._capabilities.get(interface) is not None:
|
|
224
|
+
return self._capabilities[interface]
|
|
225
|
+
|
|
226
|
+
event = self._capabilities_events.setdefault(interface, asyncio.Event())
|
|
227
|
+
try:
|
|
228
|
+
await asyncio.wait_for(event.wait(), timeout=timeout)
|
|
229
|
+
except TimeoutError:
|
|
230
|
+
pass
|
|
231
|
+
|
|
232
|
+
return self._capabilities.get(interface)
|
|
233
|
+
|
|
206
234
|
|
|
207
235
|
class _ProxyContext(Generic[ProxyType]):
|
|
208
236
|
"""Returned by Comm.proxy() / Object.proxy() / Comm.safe_proxy(). Must be used as:
|
|
@@ -48,7 +48,7 @@ class XmppClient(slixmpp.ClientXMPP):
|
|
|
48
48
|
self.register_plugin("xep_0199") # XMPP Ping
|
|
49
49
|
|
|
50
50
|
# enable keep alive pings
|
|
51
|
-
self["xep_0199"].enable_keepalive()
|
|
51
|
+
self.plugin["xep_0199"].enable_keepalive()
|
|
52
52
|
|
|
53
53
|
# handle session_start and message events
|
|
54
54
|
self.add_event_handler("session_start", self.session_start)
|
|
@@ -909,20 +909,34 @@ class XmppComm(Comm):
|
|
|
909
909
|
return self._capabilities.get(interface)
|
|
910
910
|
|
|
911
911
|
async def _get_capabilities(self, module: str, interface: type[Interface]) -> Any | None:
|
|
912
|
-
"""Fetch and deserialize capabilities for a remote module's interface.
|
|
912
|
+
"""Fetch and deserialize capabilities for a remote module's interface.
|
|
913
|
+
|
|
914
|
+
Retries a few times, since this may run right as the peer is still starting up and hasn't
|
|
915
|
+
published its capabilities yet.
|
|
916
|
+
"""
|
|
913
917
|
if interface.capabilities is None:
|
|
914
918
|
return None
|
|
915
|
-
# Use full JID (with resource) if we know it — bare JID may not route correctly
|
|
916
|
-
full_jid = next(
|
|
917
|
-
(jid for jid in self._online_clients if jid.startswith(f"{module}@")),
|
|
918
|
-
f"{module}@{self._domain}",
|
|
919
|
-
)
|
|
920
|
-
jid = full_jid
|
|
921
919
|
ns = f"urn:pyobs:capabilities:{interface.__name__}:{interface.version}"
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
920
|
+
|
|
921
|
+
result = None
|
|
922
|
+
last_error: BaseException | None = None
|
|
923
|
+
for attempt in range(3):
|
|
924
|
+
# Use full JID (with resource) if we know it — bare JID may not route correctly
|
|
925
|
+
full_jid = next(
|
|
926
|
+
(jid for jid in self._online_clients if jid.startswith(f"{module}@")),
|
|
927
|
+
f"{module}@{self._domain}",
|
|
928
|
+
)
|
|
929
|
+
try:
|
|
930
|
+
result = await asyncio.wait_for(
|
|
931
|
+
self.client.plugin["xep_0030"].get_info(jid=JID(full_jid)), timeout=10.0
|
|
932
|
+
)
|
|
933
|
+
break
|
|
934
|
+
except (TimeoutError, Exception) as e:
|
|
935
|
+
last_error = e
|
|
936
|
+
if attempt < 2:
|
|
937
|
+
await asyncio.sleep(2)
|
|
938
|
+
else:
|
|
939
|
+
log.warning("Failed to get capabilities for %s from %s: %s", interface.__name__, module, last_error)
|
|
926
940
|
return None
|
|
927
941
|
log.debug("get_capabilities disco result XML: %s", ET.tostring(result.xml).decode()[:500])
|
|
928
942
|
# result.xml is the <iq> — the <query> is its child, capabilities are grandchildren
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from abc import ABCMeta, abstractmethod
|
|
4
|
+
from dataclasses import dataclass, field
|
|
5
|
+
from typing import Any
|
|
6
|
+
|
|
7
|
+
from ..utils.time import Time
|
|
8
|
+
from .IAbortable import IAbortable
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@dataclass
|
|
12
|
+
class DataSequenceState:
|
|
13
|
+
count_total: int # 0 when idle / no sequence running
|
|
14
|
+
count_left: int
|
|
15
|
+
time: Time = field(default_factory=Time.now)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class IDataSequence(IAbortable, metaclass=ABCMeta):
|
|
19
|
+
"""The module can grab a counted sequence of data (images, spectra, ...)."""
|
|
20
|
+
|
|
21
|
+
__module__ = "pyobs.interfaces"
|
|
22
|
+
|
|
23
|
+
state = DataSequenceState
|
|
24
|
+
|
|
25
|
+
@abstractmethod
|
|
26
|
+
async def grab_sequence(self, count: int, broadcast: bool = True, **kwargs: Any) -> None:
|
|
27
|
+
"""Start a sequence of `count` grabs. Returns immediately; progress is available via
|
|
28
|
+
the pushed DataSequenceState.
|
|
29
|
+
|
|
30
|
+
Args:
|
|
31
|
+
count: Number of grabs to take.
|
|
32
|
+
broadcast: Broadcast existence of each grab.
|
|
33
|
+
|
|
34
|
+
Raises:
|
|
35
|
+
GrabImageError: If the device is already busy (exposing or already running a
|
|
36
|
+
sequence).
|
|
37
|
+
"""
|
|
38
|
+
...
|
|
39
|
+
|
|
40
|
+
@abstractmethod
|
|
41
|
+
async def abort_sequence(self, **kwargs: Any) -> None:
|
|
42
|
+
"""Stop the sequence after the current grab. The grab currently in progress, if any,
|
|
43
|
+
finishes normally; no further grabs in the sequence are started.
|
|
44
|
+
|
|
45
|
+
This is the graceful counterpart to IAbortable.abort(), which remains the hard-stop
|
|
46
|
+
path: it cancels the running grab immediately *and* the remaining sequence count.
|
|
47
|
+
"""
|
|
48
|
+
...
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
__all__ = ["IDataSequence", "DataSequenceState"]
|
|
@@ -23,6 +23,7 @@ from .ICamera import ICamera
|
|
|
23
23
|
from .IConfig import ConfigCapabilities, ConfigScalar, ConfigValue, IConfig
|
|
24
24
|
from .ICooling import CoolingState, ICooling
|
|
25
25
|
from .IData import IData
|
|
26
|
+
from .IDataSequence import DataSequenceState, IDataSequence
|
|
26
27
|
from .IDome import IDome
|
|
27
28
|
from .IExposure import ExposureState, IExposure
|
|
28
29
|
from .IExposureTime import ExposureTimeState, IExposureTime
|
|
@@ -94,6 +95,8 @@ __all__ = [
|
|
|
94
95
|
"ConfigValue",
|
|
95
96
|
"ICooling",
|
|
96
97
|
"CoolingState",
|
|
98
|
+
"IDataSequence",
|
|
99
|
+
"DataSequenceState",
|
|
97
100
|
"IDome",
|
|
98
101
|
"IExposure",
|
|
99
102
|
"ExposureState",
|
|
@@ -4,7 +4,7 @@ import logging
|
|
|
4
4
|
from typing import Any
|
|
5
5
|
|
|
6
6
|
from pyobs.events import MotionStatusChangedEvent
|
|
7
|
-
from pyobs.interfaces import IMotion, MotionState
|
|
7
|
+
from pyobs.interfaces import IMotion, IReady, MotionState, ReadyState
|
|
8
8
|
from pyobs.modules import Module
|
|
9
9
|
from pyobs.utils.enums import MotionStatus
|
|
10
10
|
|
|
@@ -31,6 +31,7 @@ class MotionStatusMixin:
|
|
|
31
31
|
if isinstance(self, Module) and self._comm:
|
|
32
32
|
await self.comm.register_event(MotionStatusChangedEvent)
|
|
33
33
|
await self.comm.set_state(IMotion, MotionState(status=self.__motion_status))
|
|
34
|
+
await self.comm.set_state(IReady, ReadyState(ready=self._is_ready()))
|
|
34
35
|
|
|
35
36
|
async def _change_motion_status(self, status: MotionStatus, interface: str | None = None) -> None:
|
|
36
37
|
"""Change motion status and send event,
|
|
@@ -88,6 +89,7 @@ class MotionStatusMixin:
|
|
|
88
89
|
MotionStatusChangedEvent(status=this.__motion_status, interfaces=this.__motion_status_single)
|
|
89
90
|
)
|
|
90
91
|
await self.comm.set_state(IMotion, MotionState(status=this.__motion_status))
|
|
92
|
+
await self.comm.set_state(IReady, ReadyState(ready=self._is_ready()))
|
|
91
93
|
|
|
92
94
|
def _combine_motion_status(self) -> MotionStatus:
|
|
93
95
|
"""Method for combining motion statuses for individual interfaces into the global one. Can be overriden."""
|
|
@@ -111,6 +113,16 @@ class MotionStatusMixin:
|
|
|
111
113
|
# otherwise just take status of first interface
|
|
112
114
|
return self.__motion_status_single[self.__motion_status_interfaces[0]]
|
|
113
115
|
|
|
116
|
+
def _is_ready(self) -> bool:
|
|
117
|
+
"""Whether the device is ready, for publishing as `IReady` state. Override for device-specific criteria."""
|
|
118
|
+
return self.motion_status() not in [
|
|
119
|
+
MotionStatus.PARKED,
|
|
120
|
+
MotionStatus.INITIALIZING,
|
|
121
|
+
MotionStatus.PARKING,
|
|
122
|
+
MotionStatus.ERROR,
|
|
123
|
+
MotionStatus.UNKNOWN,
|
|
124
|
+
]
|
|
125
|
+
|
|
114
126
|
def motion_status(self, device: str | None = None) -> MotionStatus:
|
|
115
127
|
"""Returns current motion status (synchronous, for internal use).
|
|
116
128
|
|
|
@@ -9,12 +9,14 @@ from typing import Any, NamedTuple
|
|
|
9
9
|
import numpy as np
|
|
10
10
|
from astropy.io import fits
|
|
11
11
|
|
|
12
|
-
from pyobs.events import ExposureStatusChangedEvent, NewImageEvent
|
|
12
|
+
from pyobs.events import BadWeatherEvent, Event, ExposureStatusChangedEvent, NewImageEvent
|
|
13
13
|
from pyobs.images import Image
|
|
14
14
|
from pyobs.interfaces import (
|
|
15
|
+
DataSequenceState,
|
|
15
16
|
ExposureState,
|
|
16
17
|
ExposureTimeState,
|
|
17
18
|
ICamera,
|
|
19
|
+
IDataSequence,
|
|
18
20
|
IExposure,
|
|
19
21
|
IExposureTime,
|
|
20
22
|
IImageType,
|
|
@@ -44,7 +46,7 @@ async def calc_expose_timeout(camera: BaseCamera, *args: Any, **kwargs: Any) ->
|
|
|
44
46
|
return camera._exposure_time + 30
|
|
45
47
|
|
|
46
48
|
|
|
47
|
-
class BaseCamera(Module, ImageFitsHeaderMixin, ICamera, IExposureTime, IImageType, metaclass=ABCMeta):
|
|
49
|
+
class BaseCamera(Module, ImageFitsHeaderMixin, ICamera, IExposureTime, IImageType, IDataSequence, metaclass=ABCMeta):
|
|
48
50
|
"""Base class for all camera modules."""
|
|
49
51
|
|
|
50
52
|
__module__ = "pyobs.modules.camera"
|
|
@@ -102,6 +104,11 @@ class BaseCamera(Module, ImageFitsHeaderMixin, ICamera, IExposureTime, IImageTyp
|
|
|
102
104
|
# multi-threading
|
|
103
105
|
self.expose_abort = asyncio.Event()
|
|
104
106
|
|
|
107
|
+
# grab_sequence() state -- count_left > 0 means a sequence is currently running
|
|
108
|
+
# (also between individual grabs, while _camera_status is briefly IDLE again)
|
|
109
|
+
self._sequence_count_left = 0
|
|
110
|
+
self._sequence_task: asyncio.Task[None] | None = None
|
|
111
|
+
|
|
105
112
|
# register exception
|
|
106
113
|
exc.register_exception(exc.GrabImageError, 3, timespan=600, callback=self._default_remote_error_callback)
|
|
107
114
|
|
|
@@ -113,6 +120,7 @@ class BaseCamera(Module, ImageFitsHeaderMixin, ICamera, IExposureTime, IImageTyp
|
|
|
113
120
|
if self._comm:
|
|
114
121
|
await self.comm.register_event(NewImageEvent)
|
|
115
122
|
await self.comm.register_event(ExposureStatusChangedEvent)
|
|
123
|
+
await self.comm.register_event(BadWeatherEvent, self._abort_weather)
|
|
116
124
|
|
|
117
125
|
# publish initial states
|
|
118
126
|
await self.comm.set_state(IExposureTime, ExposureTimeState(exposure_time=self._exposure_time))
|
|
@@ -125,6 +133,7 @@ class BaseCamera(Module, ImageFitsHeaderMixin, ICamera, IExposureTime, IImageTyp
|
|
|
125
133
|
exposure_time_left=0.0,
|
|
126
134
|
),
|
|
127
135
|
)
|
|
136
|
+
await self.comm.set_state(IDataSequence, DataSequenceState(count_total=0, count_left=0))
|
|
128
137
|
|
|
129
138
|
async def set_exposure_time(self, exposure_time: float, **kwargs: Any) -> None:
|
|
130
139
|
"""Set the exposure time in seconds.
|
|
@@ -361,6 +370,55 @@ class BaseCamera(Module, ImageFitsHeaderMixin, ICamera, IExposureTime, IImageTyp
|
|
|
361
370
|
# return filename
|
|
362
371
|
return filename
|
|
363
372
|
|
|
373
|
+
async def grab_sequence(self, count: int, broadcast: bool = True, **kwargs: Any) -> None:
|
|
374
|
+
"""Start a sequence of `count` images. Returns immediately; progress is available via
|
|
375
|
+
the pushed DataSequenceState.
|
|
376
|
+
|
|
377
|
+
Args:
|
|
378
|
+
count: Number of images to take.
|
|
379
|
+
broadcast: Broadcast existence of each image.
|
|
380
|
+
|
|
381
|
+
Raises:
|
|
382
|
+
CameraException: If camera is already busy (exposing or already running a sequence).
|
|
383
|
+
"""
|
|
384
|
+
if count < 1:
|
|
385
|
+
raise ValueError("count must be >= 1.")
|
|
386
|
+
|
|
387
|
+
# already running a sequence, or mid-exposure outside of one?
|
|
388
|
+
if self._sequence_count_left > 0 or self._camera_status != ExposureStatus.IDLE:
|
|
389
|
+
raise CameraException("Cannot start new sequence because camera is not idle.")
|
|
390
|
+
|
|
391
|
+
log.info("Starting sequence of %d images...", count)
|
|
392
|
+
self._sequence_count_left = count
|
|
393
|
+
await self.comm.set_state(IDataSequence, DataSequenceState(count_total=count, count_left=count))
|
|
394
|
+
self._sequence_task = asyncio.create_task(self._run_sequence(count, broadcast))
|
|
395
|
+
|
|
396
|
+
async def _run_sequence(self, count_total: int, broadcast: bool) -> None:
|
|
397
|
+
"""Runs a sequence of grab_data() calls, started by grab_sequence()."""
|
|
398
|
+
try:
|
|
399
|
+
while self._sequence_count_left > 0:
|
|
400
|
+
try:
|
|
401
|
+
await self.grab_data(broadcast=broadcast)
|
|
402
|
+
except exc.PyObsError:
|
|
403
|
+
log.exception("Grab failed during sequence, aborting sequence.")
|
|
404
|
+
break
|
|
405
|
+
self._sequence_count_left -= 1
|
|
406
|
+
await self.comm.set_state(
|
|
407
|
+
IDataSequence, DataSequenceState(count_total=count_total, count_left=self._sequence_count_left)
|
|
408
|
+
)
|
|
409
|
+
finally:
|
|
410
|
+
log.info("Finished sequence.")
|
|
411
|
+
self._sequence_count_left = 0
|
|
412
|
+
self._sequence_task = None
|
|
413
|
+
await self.comm.set_state(IDataSequence, DataSequenceState(count_total=0, count_left=0))
|
|
414
|
+
|
|
415
|
+
async def abort_sequence(self, **kwargs: Any) -> None:
|
|
416
|
+
"""Stop the sequence after the current image. The image currently exposing, if any,
|
|
417
|
+
finishes normally; no further images in the sequence are started.
|
|
418
|
+
"""
|
|
419
|
+
log.info("Aborting sequence after current image...")
|
|
420
|
+
self._sequence_count_left = 0
|
|
421
|
+
|
|
364
422
|
async def _abort_exposure(self) -> None:
|
|
365
423
|
"""Abort the running exposure. Should be implemented by derived class.
|
|
366
424
|
|
|
@@ -379,6 +437,7 @@ class BaseCamera(Module, ImageFitsHeaderMixin, ICamera, IExposureTime, IImageTyp
|
|
|
379
437
|
# set abort event
|
|
380
438
|
log.info("Aborting current image and sequence...")
|
|
381
439
|
self.expose_abort.set()
|
|
440
|
+
self._sequence_count_left = 0
|
|
382
441
|
|
|
383
442
|
# do camera-specific abort
|
|
384
443
|
await self._abort_exposure()
|
|
@@ -387,6 +446,11 @@ class BaseCamera(Module, ImageFitsHeaderMixin, ICamera, IExposureTime, IImageTyp
|
|
|
387
446
|
while self._camera_status == ExposureStatus.EXPOSING:
|
|
388
447
|
await asyncio.sleep(0.1)
|
|
389
448
|
|
|
449
|
+
async def _abort_weather(self, event: Event, sender: str, **kwargs: Any) -> bool:
|
|
450
|
+
"""Abort on bad weather."""
|
|
451
|
+
await self.abort()
|
|
452
|
+
return True
|
|
453
|
+
|
|
390
454
|
@staticmethod
|
|
391
455
|
def set_biassec_trimsec(hdr: fits.Header, left: int, top: int, width: int, height: int) -> None:
|
|
392
456
|
"""Calculates and sets the BIASSEC and TRIMSEC areas.
|
|
@@ -9,7 +9,7 @@ from typing import Any, NamedTuple
|
|
|
9
9
|
from astropy.io import fits
|
|
10
10
|
|
|
11
11
|
from pyobs.events import ExposureStatusChangedEvent, NewSpectrumEvent
|
|
12
|
-
from pyobs.interfaces import ISpectrograph
|
|
12
|
+
from pyobs.interfaces import ExposureState, IExposure, ISpectrograph
|
|
13
13
|
from pyobs.mixins.fitsheader import SpectrumFitsHeaderMixin
|
|
14
14
|
from pyobs.modules import Module, timeout
|
|
15
15
|
from pyobs.utils.enums import ExposureStatus
|
|
@@ -60,6 +60,15 @@ class BaseSpectrograph(Module, SpectrumFitsHeaderMixin, ISpectrograph, metaclass
|
|
|
60
60
|
if self._comm is None:
|
|
61
61
|
log.warning("No comm module given, will not be able to signal new images!")
|
|
62
62
|
|
|
63
|
+
async def open(self) -> None:
|
|
64
|
+
"""Open module."""
|
|
65
|
+
await Module.open(self)
|
|
66
|
+
|
|
67
|
+
# publish initial state
|
|
68
|
+
await self.comm.set_state(
|
|
69
|
+
IExposure, ExposureState(status=self._spectrograph_status, progress=0.0, exposure_time_left=0.0)
|
|
70
|
+
)
|
|
71
|
+
|
|
63
72
|
@abstractmethod
|
|
64
73
|
async def _expose(self, abort_event: asyncio.Event) -> fits.HDUList:
|
|
65
74
|
"""Actually do the exposure, should be implemented by derived classes.
|
|
@@ -192,6 +201,7 @@ class BaseSpectrograph(Module, SpectrumFitsHeaderMixin, ISpectrograph, metaclass
|
|
|
192
201
|
|
|
193
202
|
# set it
|
|
194
203
|
self._spectrograph_status = status
|
|
204
|
+
await self.comm.set_state(IExposure, ExposureState(status=status, progress=0.0, exposure_time_left=0.0))
|
|
195
205
|
|
|
196
206
|
async def abort(self, **kwargs: Any) -> None:
|
|
197
207
|
"""Aborts the current exposure.
|
|
@@ -3,11 +3,11 @@ from typing import Any
|
|
|
3
3
|
|
|
4
4
|
from pyobs.events import NewImageEvent
|
|
5
5
|
from pyobs.images import Image
|
|
6
|
-
from pyobs.interfaces import ICamera
|
|
6
|
+
from pyobs.interfaces import ExposureState, ICamera, IExposure
|
|
7
7
|
from pyobs.mixins import ImageFitsHeaderMixin
|
|
8
8
|
from pyobs.mixins.pipeline import PipelineMixin
|
|
9
9
|
from pyobs.modules import Module
|
|
10
|
-
from pyobs.utils.enums import ImageType
|
|
10
|
+
from pyobs.utils.enums import ExposureStatus, ImageType
|
|
11
11
|
from pyobs.utils.exceptions import GrabImageError
|
|
12
12
|
|
|
13
13
|
log = logging.getLogger(__name__)
|
|
@@ -24,6 +24,15 @@ class PipelineCamera(Module, ICamera, ImageFitsHeaderMixin, PipelineMixin):
|
|
|
24
24
|
PipelineMixin.__init__(self, **kwargs)
|
|
25
25
|
ImageFitsHeaderMixin.__init__(self, **kwargs)
|
|
26
26
|
|
|
27
|
+
async def open(self) -> None:
|
|
28
|
+
"""Open module."""
|
|
29
|
+
await Module.open(self)
|
|
30
|
+
|
|
31
|
+
# publish initial state
|
|
32
|
+
await self.comm.set_state(
|
|
33
|
+
IExposure, ExposureState(status=ExposureStatus.IDLE, progress=0.0, exposure_time_left=0.0)
|
|
34
|
+
)
|
|
35
|
+
|
|
27
36
|
async def grab_data(self, broadcast: bool = True, **kwargs: Any) -> str:
|
|
28
37
|
"""Grabs an image and returns reference.
|
|
29
38
|
|
|
@@ -11,13 +11,16 @@ from pyobs.interfaces import (
|
|
|
11
11
|
ICamera,
|
|
12
12
|
IFilters,
|
|
13
13
|
IFlatField,
|
|
14
|
+
IMotion,
|
|
14
15
|
IReady,
|
|
15
16
|
ITelescope,
|
|
17
|
+
MotionState,
|
|
16
18
|
ReadyState,
|
|
17
19
|
)
|
|
18
20
|
from pyobs.modules import Module, timeout
|
|
19
21
|
from pyobs.robotic.utils.skyflats import FlatFielder
|
|
20
22
|
from pyobs.utils import exceptions as exc
|
|
23
|
+
from pyobs.utils.enums import MotionStatus
|
|
21
24
|
from pyobs.utils.publisher import CsvPublisher
|
|
22
25
|
|
|
23
26
|
log = logging.getLogger(__name__)
|
|
@@ -121,6 +124,9 @@ class FlatField(Module, IFlatField, IBinning, IFilters):
|
|
|
121
124
|
if self._filter is not None:
|
|
122
125
|
await self.comm.set_state(IFilters, FilterState(filter=self._filter))
|
|
123
126
|
await self.comm.set_state(IReady, ReadyState(ready=True))
|
|
127
|
+
# IFilters extends IMotion, but FlatField isn't itself a moving device -- publish a
|
|
128
|
+
# static state so the pubsub node exists for anything that subscribes to it
|
|
129
|
+
await self.comm.set_state(IMotion, MotionState(status=MotionStatus.IDLE))
|
|
124
130
|
|
|
125
131
|
async def close(self) -> None:
|
|
126
132
|
"""Close module."""
|
|
@@ -156,7 +156,10 @@ class FocusModel(Module, IFocusModel):
|
|
|
156
156
|
await self._calc_focus_model()
|
|
157
157
|
|
|
158
158
|
# publish initial states
|
|
159
|
-
|
|
159
|
+
try:
|
|
160
|
+
await self.comm.set_state(IFocusModel, OptimalFocusState(focus=await self._get_optimal_focus()))
|
|
161
|
+
except ValueError as e:
|
|
162
|
+
log.warning("Could not publish initial focus model state: %s", e)
|
|
160
163
|
|
|
161
164
|
async def _update(self) -> None:
|
|
162
165
|
# wait a little
|
|
@@ -170,7 +173,12 @@ class FocusModel(Module, IFocusModel):
|
|
|
170
173
|
continue
|
|
171
174
|
|
|
172
175
|
# update states
|
|
173
|
-
|
|
176
|
+
try:
|
|
177
|
+
await self.comm.set_state(IFocusModel, OptimalFocusState(focus=await self._get_optimal_focus()))
|
|
178
|
+
except ValueError as e:
|
|
179
|
+
log.warning("Could not update focus model state: %s", e)
|
|
180
|
+
await asyncio.sleep(self._interval)
|
|
181
|
+
continue
|
|
174
182
|
|
|
175
183
|
# get focuser
|
|
176
184
|
if not await self.has_proxy(self._focuser, IFocuser):
|
|
@@ -282,7 +290,10 @@ class FocusModel(Module, IFocusModel):
|
|
|
282
290
|
|
|
283
291
|
# get temperatures
|
|
284
292
|
async with self.proxy(cfg["module"], ITemperatures) as proxy:
|
|
285
|
-
|
|
293
|
+
try:
|
|
294
|
+
temp_state = await proxy.wait_for_state(ITemperatures)
|
|
295
|
+
except TimeoutError:
|
|
296
|
+
raise ValueError(f"Timeout waiting for temperatures from module {cfg['module']}.")
|
|
286
297
|
module_temps[cfg["module"]] = (
|
|
287
298
|
{r.name: r.value for r in temp_state.readings} if temp_state is not None else {}
|
|
288
299
|
)
|
|
@@ -41,6 +41,11 @@ class AutoGuiding(BaseGuiding, CameraSettingsMixin):
|
|
|
41
41
|
# add thread func
|
|
42
42
|
self.add_background_task(self._auto_guiding)
|
|
43
43
|
|
|
44
|
+
async def open(self) -> None:
|
|
45
|
+
"""Open module."""
|
|
46
|
+
await BaseGuiding.open(self)
|
|
47
|
+
await self.comm.set_state(IExposureTime, ExposureTimeState(exposure_time=self._default_exposure_time))
|
|
48
|
+
|
|
44
49
|
async def set_exposure_time(self, exposure_time: float, **kwargs: Any) -> None:
|
|
45
50
|
"""Set the exposure time in seconds.
|
|
46
51
|
|
{pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/modules/pointing/scienceframeguiding.py
RENAMED
|
@@ -4,6 +4,7 @@ from typing import Any
|
|
|
4
4
|
|
|
5
5
|
from pyobs.events import Event, NewImageEvent
|
|
6
6
|
from pyobs.images import Image
|
|
7
|
+
from pyobs.interfaces import ExposureTimeState, IExposureTime
|
|
7
8
|
|
|
8
9
|
from ._baseguiding import BaseGuiding
|
|
9
10
|
|
|
@@ -33,6 +34,10 @@ class ScienceFrameAutoGuiding(BaseGuiding):
|
|
|
33
34
|
log.info("Subscribing to new image events...")
|
|
34
35
|
await self.comm.register_event(NewImageEvent, self.add_image)
|
|
35
36
|
|
|
37
|
+
# exposure time is dictated by incoming science frames, not settable -- but IAutoGuiding
|
|
38
|
+
# requires IExposureTime, so publish a placeholder state for the pubsub node to exist
|
|
39
|
+
await self.comm.set_state(IExposureTime, ExposureTimeState(exposure_time=0.0))
|
|
40
|
+
|
|
36
41
|
async def set_exposure_time(self, exposure_time: float, **kwargs: Any) -> None:
|
|
37
42
|
"""Set the exposure time for the auto-guider.
|
|
38
43
|
|
|
@@ -4,7 +4,7 @@ import logging
|
|
|
4
4
|
from abc import ABCMeta
|
|
5
5
|
from typing import Any
|
|
6
6
|
|
|
7
|
-
from pyobs.interfaces import FitsHeaderEntry, IFitsHeaderBefore,
|
|
7
|
+
from pyobs.interfaces import FitsHeaderEntry, IFitsHeaderBefore, IRoof
|
|
8
8
|
from pyobs.mixins import MotionStatusMixin, WeatherAwareMixin
|
|
9
9
|
from pyobs.modules import Module
|
|
10
10
|
from pyobs.utils.enums import MotionStatus
|
|
@@ -32,9 +32,6 @@ class BaseRoof(WeatherAwareMixin, MotionStatusMixin, IRoof, IFitsHeaderBefore, M
|
|
|
32
32
|
await WeatherAwareMixin.open(self)
|
|
33
33
|
await MotionStatusMixin.open(self)
|
|
34
34
|
|
|
35
|
-
# publish initial ready state
|
|
36
|
-
await self.comm.set_state(IReady, ReadyState(ready=self._is_ready()))
|
|
37
|
-
|
|
38
35
|
async def get_fits_header_before(
|
|
39
36
|
self, namespaces: list[str] | None = None, **kwargs: Any
|
|
40
37
|
) -> dict[str, FitsHeaderEntry]:
|
|
@@ -53,15 +50,5 @@ class BaseRoof(WeatherAwareMixin, MotionStatusMixin, IRoof, IFitsHeaderBefore, M
|
|
|
53
50
|
)
|
|
54
51
|
}
|
|
55
52
|
|
|
56
|
-
def _is_ready(self) -> bool:
|
|
57
|
-
"""The roof is ready if it is open (not parked, initializing, parking, error, or unknown)."""
|
|
58
|
-
return self.motion_status() not in [
|
|
59
|
-
MotionStatus.PARKED,
|
|
60
|
-
MotionStatus.INITIALIZING,
|
|
61
|
-
MotionStatus.PARKING,
|
|
62
|
-
MotionStatus.ERROR,
|
|
63
|
-
MotionStatus.UNKNOWN,
|
|
64
|
-
]
|
|
65
|
-
|
|
66
53
|
|
|
67
54
|
__all__ = ["BaseRoof"]
|
{pyobs_core-2.0.0.dev21 → pyobs_core-2.0.0.dev24}/pyobs/modules/telescope/_dummytelescopebase.py
RENAMED
|
@@ -12,6 +12,7 @@ from astropy.coordinates import SkyCoord
|
|
|
12
12
|
|
|
13
13
|
from pyobs.events import FilterChangedEvent
|
|
14
14
|
from pyobs.interfaces import (
|
|
15
|
+
AltAzState,
|
|
15
16
|
FiltersCapabilities,
|
|
16
17
|
FilterState,
|
|
17
18
|
FitsHeaderEntry,
|
|
@@ -137,6 +138,14 @@ class _DummyTelescopeBase(
|
|
|
137
138
|
def _position_radec(self) -> tuple[float, float] | None:
|
|
138
139
|
return float(self._position.ra.degree), float(self._position.dec.degree)
|
|
139
140
|
|
|
141
|
+
async def _publish_altaz(self) -> None:
|
|
142
|
+
"""Publish the current position as IPointingAltAz state, derived from RA/Dec and the observer location."""
|
|
143
|
+
if self._observer is not None:
|
|
144
|
+
altaz = self.observer.altaz(Time.now(), self._position)
|
|
145
|
+
await self.comm.set_state(
|
|
146
|
+
IPointingAltAz, AltAzState(alt=float(altaz.alt.degree), az=float(altaz.az.degree))
|
|
147
|
+
)
|
|
148
|
+
|
|
140
149
|
async def _sim_change_status(self, status: MotionStatus) -> None:
|
|
141
150
|
if status != self._sim_status:
|
|
142
151
|
self._sim_status = status
|
|
@@ -168,6 +177,7 @@ class _DummyTelescopeBase(
|
|
|
168
177
|
dec=float(self._position.dec.degree),
|
|
169
178
|
),
|
|
170
179
|
)
|
|
180
|
+
await self._publish_altaz()
|
|
171
181
|
else:
|
|
172
182
|
dra = vra / length * self._speed / np.cos(np.radians(self._position.dec.degree)) * u.deg
|
|
173
183
|
ddec = vdec / length * self._speed * u.deg
|
|
@@ -182,6 +192,7 @@ class _DummyTelescopeBase(
|
|
|
182
192
|
IPointingRaDec,
|
|
183
193
|
RaDecState(ra=float(self._position.ra.degree), dec=float(self._position.dec.degree)),
|
|
184
194
|
)
|
|
195
|
+
await self._publish_altaz()
|
|
185
196
|
|
|
186
197
|
drift_ra = random.gauss(self._drift_rate[0], max(self._drift_rate[0] / 10.0, 1e-9))
|
|
187
198
|
drift_dec = random.gauss(self._drift_rate[1], max(self._drift_rate[1] / 10.0, 1e-9))
|
|
@@ -224,6 +235,7 @@ class _DummyTelescopeBase(
|
|
|
224
235
|
dec=float(self._position.dec.degree),
|
|
225
236
|
),
|
|
226
237
|
)
|
|
238
|
+
await self._publish_altaz()
|
|
227
239
|
await self.comm.set_capabilities(ITrackingMode, TrackingModeCapabilities(modes=self._tracking_modes))
|
|
228
240
|
await self.comm.set_capabilities(ITrackingRate, TrackingRateCapabilities(min_update_interval=0.0))
|
|
229
241
|
await self.comm.set_state(ITrackingMode, TrackingModeState(mode=self._tracking_mode))
|