Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Prevent dome from opening during daytime
Browse files Browse the repository at this point in the history
albireox committed Dec 25, 2024
1 parent 687e06e commit 3a74a7e
Showing 8 changed files with 226 additions and 5 deletions.
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -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]
1 change: 1 addition & 0 deletions python/lvmecp/__main__.py
Original file line number Diff line number Diff line change
@@ -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"]:
52 changes: 51 additions & 1 deletion python/lvmecp/dome.py
Original file line number Diff line number Diff line change
@@ -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

Check warning on line 194 in python/lvmecp/dome.py

Codecov / codecov/patch

python/lvmecp/dome.py#L194

Added line #L194 was not covered by tests

if not is_daytime:
return True

Check warning on line 197 in python/lvmecp/dome.py

Codecov / codecov/patch

python/lvmecp/dome.py#L197

Added line #L197 was not covered by tests

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
4 changes: 4 additions & 0 deletions python/lvmecp/etc/lvmecp.yml
Original file line number Diff line number Diff line change
@@ -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
2 changes: 2 additions & 0 deletions python/lvmecp/plc.py
Original file line number Diff line number Diff line change
@@ -69,6 +69,8 @@ def __init__(
self.config = config
self.modbus = Modbus(config=config["modbus"])

self._actor = actor

self.dome = DomeController(
"dome",
self,
65 changes: 65 additions & 0 deletions tests/test_command_dome.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# @Author: José Sánchez-Gallego ([email protected])
# @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

from typing import TYPE_CHECKING

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_allowed", 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_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_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
2 changes: 1 addition & 1 deletion tests/test_command_engineering_mode.py
Original file line number Diff line number Diff line change
@@ -3,7 +3,7 @@
#
# @Author: José Sánchez-Gallego ([email protected])
# @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
103 changes: 101 additions & 2 deletions uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 3a74a7e

Please sign in to comment.