diff --git a/CHANGELOG.md b/CHANGELOG.md index 9434d90..a3b1294 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,8 @@ ### 🚀 New -* [#29](https://vscode.dev/github/sdss/lvmecp/pull/29) Add a new engineering mode that can be used to bypass the heartbeat and to allow the dome to open during daytime. +* [#29](https://github.com/sdss/lvmecp/pull/29) Add a new engineering mode that can be used to bypass the heartbeat and to allow the dome to open during daytime. +* [#30](https://github.com/sdss/lvmecp/pull/30) Prevent the dome from opening during daytime. Close if daytime is detected. ### ✨ Improved @@ -13,7 +14,7 @@ ### 🏷️ Changed -* [#28](https://vscode.dev/github/sdss/lvmecp/pull/28) Removed the automatic setting of the heartbeat variable. Added a `heartbeat` command that will be triggered by a heartbeat middleware. +* [#28](https://github.com/sdss/lvmecp/pull/28) Removed the automatic setting of the heartbeat variable. Added a `heartbeat` command that will be triggered by a heartbeat middleware. ### 🔧 Fixed diff --git a/codecov.yml b/codecov.yml index 3c97002..f415c96 100644 --- a/codecov.yml +++ b/codecov.yml @@ -8,7 +8,7 @@ coverage: target: 85% if_not_found: success if_ci_failed: error - informational: false + informational: true only_pulls: true patch: default: diff --git a/pyproject.toml b/pyproject.toml index 76f9846..36f887f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -16,7 +16,7 @@ dependencies = [ "click-default-group>=1.2.2", "pyserial-asyncio>=0.6", "pymodbus>=3.6.0,<3.7", - "lvmopstools>=0.2.0" + "lvmopstools[ephemeris]>=0.5.2", ] [project.urls] diff --git a/python/lvmecp/__main__.py b/python/lvmecp/__main__.py index ebefee3..77cdcc0 100644 --- a/python/lvmecp/__main__.py +++ b/python/lvmecp/__main__.py @@ -75,6 +75,7 @@ async def actor(ctx, with_simulator: bool = False): schema_rel = ecp_config["actor"]["schema"] ecp_config["actor"]["schema"] = str(pathlib.Path(__file__).parent / schema_rel) + config.load(ecp_config) # Update internal configuration actor_obj = ECPActor.from_config(ecp_config) if ctx.obj["verbose"]: diff --git a/python/lvmecp/actor/actor.py b/python/lvmecp/actor/actor.py index dfbf355..1f4f93c 100644 --- a/python/lvmecp/actor/actor.py +++ b/python/lvmecp/actor/actor.py @@ -64,6 +64,7 @@ def __init__( self.semaphore = asyncio.Semaphore(5) self._emit_status_task: asyncio.Task | None = None + self._monitor_dome_task: asyncio.Task | None = None self._engineering_mode: bool = False self._engineering_mode_task: asyncio.Task | None = None @@ -81,6 +82,7 @@ async def start(self, **kwargs): await self.plc.start_modules() self._emit_status_task = asyncio.create_task(self.emit_status()) + self._monitor_dome_task = asyncio.create_task(self.monitor_dome()) return self @@ -88,6 +90,8 @@ async def stop(self, **kwargs): """Stops the actor.""" self._emit_status_task = await cancel_task(self._emit_status_task) + self._monitor_dome_task = await cancel_task(self._monitor_dome_task) + self._engineering_mode_task = await cancel_task(self._engineering_mode_task) await super().stop(**kwargs) @@ -102,6 +106,18 @@ async def emit_status(self, delay: float = 30.0): await self.send_command(self.name, "status", internal=True) await asyncio.sleep(delay) + async def monitor_dome(self, delay: float = 30.0): + """Monitors the dome and closes during daytime.""" + + while True: + await asyncio.sleep(delay) + + if self._engineering_mode: + pass + elif self.plc.dome.is_daytime(): + self.write("w", text="Dome found open during daytime. Closing.") + await self.plc.dome.close() + async def engineering_mode( self, enable: bool, diff --git a/python/lvmecp/dome.py b/python/lvmecp/dome.py index 6b6133a..2b80175 100644 --- a/python/lvmecp/dome.py +++ b/python/lvmecp/dome.py @@ -13,7 +13,10 @@ from time import time from types import SimpleNamespace -from lvmecp import log +from astropy.time import Time +from lvmopstools.ephemeris import get_ephemeris_summary + +from lvmecp import config, log from lvmecp.exceptions import DomeError, ECPWarning from lvmecp.maskbits import DomeStatus from lvmecp.module import PLCModule @@ -145,6 +148,9 @@ async def _move(self, open: bool, force: bool = False): async def open(self, force: bool = False): """Open the dome.""" + if not self.is_allowed(): + raise DomeError("Dome cannot be opened during daytime.") + await self._move(True, force=force) async def close(self, force: bool = False): @@ -172,3 +178,47 @@ async def reset(self): await self.modbus["rolloff_error_reset"].set(1) await asyncio.sleep(1) + + def is_allowed(self): + """Returns whether the dome is allowed to move. + + Currently the only check performed is to confirm that it is not daytime, + but this method could be expanded in the future. + + """ + + is_daytime: bool | None + if not config["dome.daytime_allowed"]: + is_daytime = self.is_daytime() + else: + is_daytime = None + + if not is_daytime: + return True + + if self.plc._actor and self.plc._actor._engineering_mode: + self.plc._actor.write( + "w", + text="Daytime detected but engineering mode is active. " + "Allowing to open the dome.", + ) + return True + + return False + + def is_daytime(self): # pragma: no cover + """Returns whether it is daytime.""" + + daytime_tolerance = config["dome.daytime_tolerance"] or 0.0 + + ephemeris = get_ephemeris_summary() + sunset = ephemeris["sunset"] - daytime_tolerance / 86400 + sunrise = ephemeris["sunrise"] + daytime_tolerance / 86400 + + now = Time.now().jd + assert isinstance(now, float) + + if now < sunset or now > sunrise: + return True + + return False diff --git a/python/lvmecp/etc/lvmecp.yml b/python/lvmecp/etc/lvmecp.yml index 6281bfb..a51f596 100644 --- a/python/lvmecp/etc/lvmecp.yml +++ b/python/lvmecp/etc/lvmecp.yml @@ -172,6 +172,10 @@ safety: override_local_mode: False o2_threshold: 19.5 +dome: + daytime_allowed: false + daytime_tolerance: 600 + hvac: host: 10.8.38.49 port: 502 diff --git a/python/lvmecp/plc.py b/python/lvmecp/plc.py index 333643e..36e4ad1 100644 --- a/python/lvmecp/plc.py +++ b/python/lvmecp/plc.py @@ -69,6 +69,8 @@ def __init__( self.config = config self.modbus = Modbus(config=config["modbus"]) + self._actor = actor + self.dome = DomeController( "dome", self, diff --git a/tests/test_command_dome.py b/tests/test_command_dome.py new file mode 100644 index 0000000..bccc791 --- /dev/null +++ b/tests/test_command_dome.py @@ -0,0 +1,111 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +# @Author: José Sánchez-Gallego (gallegoj@uw.edu) +# @Date: 2024-12-24 +# @Filename: test_command_dome.py +# @License: BSD 3-clause (http://www.opensource.org/licenses/BSD-3-Clause) + +from __future__ import annotations + +import asyncio + +from typing import TYPE_CHECKING + +import lvmecp.dome +from lvmecp.maskbits import DomeStatus + + +if TYPE_CHECKING: + from pytest_mock import MockerFixture + + from lvmecp.actor import ECPActor + + +async def test_command_dome_open(actor: ECPActor, mocker: MockerFixture): + mocker.patch.object(actor.plc.dome, "is_daytime", return_value=False) + mocker.patch.object(actor.plc.dome, "_move", return_value=True) + + mocker.patch.object(actor.plc.dome, "status", return_value=DomeStatus.OPEN) + + cmd = await actor.invoke_mock_command("dome open") + await cmd + + assert cmd.status.did_succeed + + +async def test_command_dome_close(actor: ECPActor, mocker: MockerFixture): + mocker.patch.object(actor.plc.dome, "_move", return_value=True) + + mocker.patch.object(actor.plc.dome, "status", return_value=DomeStatus.CLOSED) + + cmd = await actor.invoke_mock_command("dome close") + await cmd + + assert cmd.status.did_succeed + + +async def test_command_dome_daytime(actor: ECPActor, mocker: MockerFixture): + mocker.patch.object(actor.plc.dome, "is_daytime", return_value=True) + mocker.patch.object(actor.plc.dome, "_move", return_value=True) + + cmd = await actor.invoke_mock_command("dome open") + await cmd + + assert cmd.status.did_fail + + +async def test_command_dome_daytime_allowed(actor: ECPActor, mocker: MockerFixture): + mocker.patch.object( + lvmecp.dome, + "config", + return_value={"dome": {"daytime_allowed": True}}, + ) + mocker.patch.object(actor.plc.dome, "is_daytime", return_value=True) + mocker.patch.object(actor.plc.dome, "_move", return_value=True) + + mocker.patch.object(actor.plc.dome, "status", return_value=DomeStatus.OPEN) + + cmd = await actor.invoke_mock_command("dome open") + await cmd + + assert cmd.status.did_succeed + + +async def test_command_dome_daytime_eng_mode(actor: ECPActor, mocker: MockerFixture): + mocker.patch.object(actor.plc.dome, "is_daytime", return_value=True) + mocker.patch.object(actor.plc.dome, "_move", return_value=True) + mocker.patch.object(actor, "_engineering_mode", return_value=True) + + mocker.patch.object(actor.plc.dome, "status", return_value=DomeStatus.OPEN) + + cmd = await actor.invoke_mock_command("dome open") + await cmd + + assert cmd.status.did_succeed + + +async def test_actor_daytime_task(actor: ECPActor, mocker: MockerFixture): + mocker.patch.object(actor.plc.dome, "is_daytime", return_value=True) + dome_close_mock = mocker.patch.object(actor.plc.dome, "close") + + task = asyncio.create_task(actor.monitor_dome(delay=0.1)) + await asyncio.sleep(0.2) + + dome_close_mock.assert_called_once() + + task.cancel() + + +async def test_actor_daytime_task_eng_mode(actor: ECPActor, mocker: MockerFixture): + mocker.patch.object(actor.plc.dome, "is_daytime", return_value=True) + mocker.patch.object(actor, "_engineering_mode", return_value=True) + + dome_close_mock = mocker.patch.object(actor.plc.dome, "close") + + task = asyncio.create_task(actor.monitor_dome(delay=0.1)) + await asyncio.sleep(0.2) + + dome_close_mock.assert_not_called() + + task.cancel() diff --git a/tests/test_command_engineering_mode.py b/tests/test_command_engineering_mode.py index 6705ee0..95af87f 100644 --- a/tests/test_command_engineering_mode.py +++ b/tests/test_command_engineering_mode.py @@ -3,7 +3,7 @@ # # @Author: José Sánchez-Gallego (gallegoj@uw.edu) # @Date: 2024-12-24 -# @Filename: test_command_heartbeat.py +# @Filename: test_command_engineering_mode.py # @License: BSD 3-clause (http://www.opensource.org/licenses/BSD-3-Clause) from __future__ import annotations diff --git a/uv.lock b/uv.lock index ed9e908..6369aae 100644 --- a/uv.lock +++ b/uv.lock @@ -161,6 +161,63 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/a9/37/3fa718aaadd36e073891138dc3ebd919a71bafd4881c97d8a133265af191/argcomplete-3.5.2-py3-none-any.whl", hash = "sha256:036d020d79048a5d525bc63880d7a4b8d1668566b8a76daf1144c0bbe0f63472", size = 43506 }, ] +[[package]] +name = "astroplan" +version = "0.10.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "astropy" }, + { name = "numpy" }, + { name = "pytz" }, + { name = "six" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/48/80/1be3af06717245a51adaf6994b682b3ee25ace9bfe5d443d440209d627df/astroplan-0.10.1.tar.gz", hash = "sha256:39d97c3377e1630abff3a94d8c956980f77a3e809e27a0376dd7d30abe3b6959", size = 140603 } + +[[package]] +name = "astropy" +version = "7.0.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "astropy-iers-data" }, + { name = "numpy" }, + { name = "packaging" }, + { name = "pyerfa" }, + { name = "pyyaml" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/6a/12/d6ad68d5acd751e3827d54a64333e0dd789bcc747fe9528f5758b35421f8/astropy-7.0.0.tar.gz", hash = "sha256:e92d7c9fee86eb3df8714e5dd41bbf9f163d343e1a183d95bf6bd09e4313c940", size = 7130087 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d6/54/de05566563bb3327d7878cec81507ad5677801f5739eb7623dffef6f6a39/astropy-7.0.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:0ada206f13b1e9c9c07ae0fce55e3090d694c555107c23c30b271a58fea1732b", size = 6664940 }, + { url = "https://files.pythonhosted.org/packages/e3/b4/308bcffcde4c971245f75a8805a6b7606d150090ff9e94317b818808e0ca/astropy-7.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d5f5657a1443421b0ab8ae6afa85fc7934f5e384648b7acef21aca5918acfca8", size = 6540264 }, + { url = "https://files.pythonhosted.org/packages/79/3d/54c4c3773d10f8a6010ab60619c0b0a39c058d2f58abacb3895fac461478/astropy-7.0.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b47d7af967e51dc612fd8440ed65ad371c0c2bbf5d739ef4aa147bcd2fbe6b13", size = 10605227 }, + { url = "https://files.pythonhosted.org/packages/34/4c/ec389497ae4305dce4a35062b2851065c535d792f91231f5c290b5c25725/astropy-7.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:74c6df5c68cc4acb86e343db6d4b96419d585c7ba5fd41fe3023f47ee9f5dbc9", size = 10663688 }, + { url = "https://files.pythonhosted.org/packages/21/90/3e2563e37df91c36b1e8e03d2ef49561b6eeb86abac39ee8f66fcf652fb5/astropy-7.0.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:9fcfb92043994dfbd1a267b893398aab8f680b0587b4333dacbfa034a3159aa0", size = 10696004 }, + { url = "https://files.pythonhosted.org/packages/51/52/a1a5d365d34c6b933db759960fa7451ae3f076e9d020dfa9c5b6fa8dd359/astropy-7.0.0-cp311-cp311-win32.whl", hash = "sha256:1ad4483712effdd691c085e7b58805c01a54cebf8f4c6955973ceccd60bd36ed", size = 6391060 }, + { url = "https://files.pythonhosted.org/packages/38/76/c7165f1729c98273c9af6a756e0c1f95893b7ff7eea939cb9a72e2699c0f/astropy-7.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:f8a00fcb30c2317b111d8b6a99eb60a81e8292c24dce65e986ee4610ea16b8d2", size = 6522031 }, + { url = "https://files.pythonhosted.org/packages/83/cf/3356a9b3428b37a895c9f23b6a844814a18dd486e1d3358925bf6222d3eb/astropy-7.0.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:b103516dd54a90f9b9652dff3dd47ad6d43436c61ed800023943a562b7ea9712", size = 6669091 }, + { url = "https://files.pythonhosted.org/packages/1c/08/e6d55b98514720e6d574647385570e9602414c49c1b6b48903c3cec9415a/astropy-7.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:3ced126597ea2d2876a341821d76ba20fb895c2eef117b447b6b3182993794df", size = 6545597 }, + { url = "https://files.pythonhosted.org/packages/96/d2/a64c3ca06b010cb228f78d9ffc0a41b0c26bcfe7323b60a41f66cfb534b6/astropy-7.0.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:733be30f52e7ed5ace7fc5ab9bbfbf1f2f604661682141f177ea356893b58cc4", size = 10646328 }, + { url = "https://files.pythonhosted.org/packages/01/5f/aa4c1a6b1769b0a48d289b9293aaf92b51f190d2ef5da3b4a2090411010d/astropy-7.0.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:14bb14bce6e7cc41066037d8a168b26a5fe6722a9201e9fae8da22a4c34c8780", size = 10728865 }, + { url = "https://files.pythonhosted.org/packages/01/76/79f2fcf90800d98abfb37928589f54fdf06621d029e2ba6093661c6951d4/astropy-7.0.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:5c14ca39b607af23273ee2b86cecee782a4feb4220b8f7a93b1dc3fe07582779", size = 10741642 }, + { url = "https://files.pythonhosted.org/packages/e6/75/eae5d114fed94248e1ff83eb798aeb3c67f985bbbdf1312ee690dc723ae4/astropy-7.0.0-cp312-cp312-win32.whl", hash = "sha256:6f2ee5872b0fffd8b9c4d9ce9af51c69f24cdad0d2f4fffbabfcfd4debd303f8", size = 6390205 }, + { url = "https://files.pythonhosted.org/packages/0a/f6/627fe5592c1f903f8d8d707486e30e2d13eda3fe3e903bd4e35eba5e1b5c/astropy-7.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:62d62d3603bb8b243f6bac21f02341f963418ccf6f299be1d45d8c3918e64c91", size = 6520322 }, + { url = "https://files.pythonhosted.org/packages/47/1d/6c02cc24248897f07cc417c8583f0c1ae4a80d50f6b45b2e889f331b511c/astropy-7.0.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:0e5adeb8f955242da5cb4fe58df2f1483d81c10b2b73f089c91fc87dd3b63e1e", size = 6660947 }, + { url = "https://files.pythonhosted.org/packages/85/66/bbb28b73eaa4469be1be88e302f133f3ff2b3b295f80ca4bc6e10269973e/astropy-7.0.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:31614b6451436163eed3744b90edd89dd357bf223c482fa944e627be86a47349", size = 6537491 }, + { url = "https://files.pythonhosted.org/packages/1e/5f/9cfd728e903972f0bcf6f0048f813d225e67447cab01889571fd25a060a0/astropy-7.0.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b7b28a144165e4e7f4f0467fb6d8ed079f320fc99969a907614d98b18c7cea99", size = 10547602 }, + { url = "https://files.pythonhosted.org/packages/bd/0c/11e0cd93a8235627e154aeda1cf083e8bebd0ff72a27fea3390d2b2df1c2/astropy-7.0.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:db36b632989060ce4f7c3058ffc860af38df5c8ee7ee7ef2daad1f441c416c12", size = 10635466 }, + { url = "https://files.pythonhosted.org/packages/de/25/19f515e7f7ad4800b1bc4d642f40f7872b39476c1d8e9ab690b7e702bf30/astropy-7.0.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:c6a14810e596b9d437fbfe40733d61afccc9d4b7b9f7504228ba492f545d197f", size = 10652309 }, + { url = "https://files.pythonhosted.org/packages/17/02/be4a0d3f6add53c3ebfbf7d4f2704030ea04f06963abb0a9286528a8ab27/astropy-7.0.0-cp313-cp313-win32.whl", hash = "sha256:446931f9c260294ddc8646684ab2413e1a5eb14dcd4ff1e8a0532fa143b0844e", size = 6387551 }, + { url = "https://files.pythonhosted.org/packages/fa/3a/cf06361685f72b50b3fb69247b95b66a6d2edb1b1947e6403c168f01eecc/astropy-7.0.0-cp313-cp313-win_amd64.whl", hash = "sha256:7ecaaeeb017cceb02512d5505c43e162b3e26d951cece2b021e786f4c0af17a7", size = 6516991 }, +] + +[[package]] +name = "astropy-iers-data" +version = "0.2024.12.23.0.33.24" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/46/6f/e425652becd72edeb6b4b320f835c3629e6cc8b048d31e9849ca2faac54e/astropy_iers_data-0.2024.12.23.0.33.24.tar.gz", hash = "sha256:f9bb8f676233f5bb564fdffa4b81af28160e3040a796dcaf0a9436f842fee951", size = 1887154 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e8/4d/565740d9ac54640c09d2fdd22ef3583103438fb97305a9cfb66595a4b259/astropy_iers_data-0.2024.12.23.0.33.24-py3-none-any.whl", hash = "sha256:40d3c6b6a5cf4dc6ad91b92b7e0f949e5366234e3c4440302247429fc8294302", size = 1940192 }, +] + [[package]] name = "asttokens" version = "3.0.0" @@ -725,6 +782,12 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/28/97/c5bba66496547df744ff7093325cfff27f2161e6123b289acc9542690d86/lvmopstools-0.5.2-py3-none-any.whl", hash = "sha256:a16a81da8432ec682b2d62aa2c337e1afe2611519d883ce014dbc1725135069e", size = 138875 }, ] +[package.optional-dependencies] +ephemeris = [ + { name = "astroplan" }, + { name = "astropy" }, +] + [[package]] name = "makefun" version = "1.15.6" @@ -1210,6 +1273,24 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/51/b2/b2b50d5ecf21acf870190ae5d093602d95f66c9c31f9d5de6062eb329ad1/pydantic_core-2.27.2-cp313-cp313-win_arm64.whl", hash = "sha256:ac4dbfd1691affb8f48c2c13241a2e3b60ff23247cbcf981759c768b6633cf8b", size = 1885186 }, ] +[[package]] +name = "pyerfa" +version = "2.0.1.5" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "numpy" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/71/39/63cc8291b0cf324ae710df41527faf7d331bce573899199d926b3e492260/pyerfa-2.0.1.5.tar.gz", hash = "sha256:17d6b24fe4846c65d5e7d8c362dcb08199dc63b30a236aedd73875cc83e1f6c0", size = 818430 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7d/d9/3448a57cb5bd19950de6d6ab08bd8fbb3df60baa71726de91d73d76c481b/pyerfa-2.0.1.5-cp39-abi3-macosx_10_9_x86_64.whl", hash = "sha256:b282d7c60c4c47cf629c484c17ac504fcb04abd7b3f4dfcf53ee042afc3a5944", size = 341818 }, + { url = "https://files.pythonhosted.org/packages/11/4a/31a363370478b63c6289a34743f2ba2d3ae1bd8223e004d18ab28fb92385/pyerfa-2.0.1.5-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:be1aeb70390dd03a34faf96749d5cabc58437410b4aab7213c512323932427df", size = 329370 }, + { url = "https://files.pythonhosted.org/packages/cb/96/b6210fc624123c8ae13e1eecb68fb75e3f3adff216d95eee1c7b05843e3e/pyerfa-2.0.1.5-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b0603e8e1b839327d586c8a627cdc634b795e18b007d84f0cda5500a0908254e", size = 692794 }, + { url = "https://files.pythonhosted.org/packages/e5/e0/050018d855d26d3c0b4a7d1b2ed692be758ce276d8289e2a2b44ba1014a5/pyerfa-2.0.1.5-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0e43c7194e3242083f2350b46c09fd4bf8ba1bcc0ebd1460b98fc47fe2389906", size = 738711 }, + { url = "https://files.pythonhosted.org/packages/b9/f5/ff91ee77308793ae32fa1e1de95e9edd4551456dd888b4e87c5938657ca5/pyerfa-2.0.1.5-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:07b80cd70701f5d066b1ac8cce406682cfcd667a1186ec7d7ade597239a6021d", size = 722966 }, + { url = "https://files.pythonhosted.org/packages/2c/56/b22b35c8551d2228ff8d445e63787112927ca13f6dc9e2c04f69d742c95b/pyerfa-2.0.1.5-cp39-abi3-win32.whl", hash = "sha256:d30b9b0df588ed5467e529d851ea324a67239096dd44703125072fd11b351ea2", size = 339955 }, + { url = "https://files.pythonhosted.org/packages/b4/11/97233cf23ad5411ac6f13b1d6ee3888f90ace4f974d9bf9db887aa428912/pyerfa-2.0.1.5-cp39-abi3-win_amd64.whl", hash = "sha256:66292d437dcf75925b694977aa06eb697126e7b86553e620371ed3e48b5e0ad0", size = 349410 }, +] + [[package]] name = "pygments" version = "2.18.0" @@ -1324,6 +1405,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/4b/72/2f30cf26664fcfa0bd8ec5ee62ec90c03bd485e4a294d92aabc76c5203a5/python_json_logger-3.2.1-py3-none-any.whl", hash = "sha256:cdc17047eb5374bd311e748b42f99d71223f3b0e186f4206cc5d52aefe85b090", size = 14924 }, ] +[[package]] +name = "pytz" +version = "2024.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/3a/31/3c70bf7603cc2dca0f19bdc53b4537a797747a58875b552c8c413d963a3f/pytz-2024.2.tar.gz", hash = "sha256:2aa355083c50a0f93fa581709deac0c9ad65cca8a9e9beac660adcbd493c798a", size = 319692 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/11/c3/005fcca25ce078d2cc29fd559379817424e94885510568bc1bc53d7d5846/pytz-2024.2-py2.py3-none-any.whl", hash = "sha256:31c7c1817eb7fae7ca4b8c7ee50c72f93aa2dd863de768e1ef4245d426aa0725", size = 508002 }, +] + [[package]] name = "pyyaml" version = "6.0.2" @@ -1560,7 +1650,7 @@ version = "0.8.5a0" source = { editable = "." } dependencies = [ { name = "click-default-group" }, - { name = "lvmopstools" }, + { name = "lvmopstools", extra = ["ephemeris"] }, { name = "pymodbus" }, { name = "pyserial-asyncio" }, { name = "sdss-clu" }, @@ -1593,7 +1683,7 @@ dev = [ [package.metadata] requires-dist = [ { name = "click-default-group", specifier = ">=1.2.2" }, - { name = "lvmopstools", specifier = ">=0.2.0" }, + { name = "lvmopstools", extras = ["ephemeris"], specifier = ">=0.5.2" }, { name = "pymodbus", specifier = ">=3.6.0,<3.7" }, { name = "pyserial-asyncio", specifier = ">=0.6" }, { name = "sdss-clu", specifier = ">=2.1.0" }, @@ -1652,6 +1742,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl", hash = "sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686", size = 9755 }, ] +[[package]] +name = "six" +version = "1.17.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/94/e7/b2c673351809dca68a0e064b6af791aa332cf192da575fd474ed7d6f16a2/six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81", size = 34031 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", size = 11050 }, +] + [[package]] name = "sniffio" version = "1.3.1"