diff --git a/doc/news/DM-46980.feature.rst b/doc/news/DM-46980.feature.rst
new file mode 100644
index 000000000..91cb954c6
--- /dev/null
+++ b/doc/news/DM-46980.feature.rst
@@ -0,0 +1 @@
+Add home dome SAL Script for ``maintel``.
diff --git a/python/lsst/ts/standardscripts/data/scripts/maintel/mtdome/home_dome.py b/python/lsst/ts/standardscripts/data/scripts/maintel/mtdome/home_dome.py
new file mode 100755
index 000000000..66e362fd5
--- /dev/null
+++ b/python/lsst/ts/standardscripts/data/scripts/maintel/mtdome/home_dome.py
@@ -0,0 +1,27 @@
+#!/usr/bin/env python
+# This file is part of ts_standardscripts
+#
+# Developed for the LSST Telescope and Site Systems.
+# This product includes software developed by the LSST Project
+# (https://www.lsst.org).
+# See the COPYRIGHT file at the top-level directory of this distribution
+# for details of code ownership.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+import asyncio
+
+from lsst.ts.standardscripts.maintel.mtdome import HomeDome
+
+asyncio.run(HomeDome.amain())
diff --git a/python/lsst/ts/standardscripts/maintel/mtdome/__init__.py b/python/lsst/ts/standardscripts/maintel/mtdome/__init__.py
index bfc5d7265..0b67cd067 100644
--- a/python/lsst/ts/standardscripts/maintel/mtdome/__init__.py
+++ b/python/lsst/ts/standardscripts/maintel/mtdome/__init__.py
@@ -22,6 +22,7 @@
from .crawl_az import *
from .disable_dome_following import *
from .enable_dome_following import *
+from .home_dome import *
from .park_dome import *
from .slew_dome import *
from .unpark_dome import *
diff --git a/python/lsst/ts/standardscripts/maintel/mtdome/home_dome.py b/python/lsst/ts/standardscripts/maintel/mtdome/home_dome.py
new file mode 100644
index 000000000..af661a597
--- /dev/null
+++ b/python/lsst/ts/standardscripts/maintel/mtdome/home_dome.py
@@ -0,0 +1,111 @@
+# This file is part of ts_standardscripts
+#
+# Developed for the LSST Telescope and Site Systems.
+# This product includes software developed by the LSST Project
+# (https://www.lsst.org).
+# See the COPYRIGHT file at the top-level directory of this distribution
+# for details of code ownership.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .``
+
+__all__ = ["HomeDome"]
+
+import yaml
+from lsst.ts import salobj
+from lsst.ts.observatory.control.maintel.mtcs import MTCS, MTCSUsages
+
+
+class HomeDome(salobj.BaseScript):
+ """Home azimuth of the MTDome.
+
+ Parameters
+ ----------
+ index : `int`
+ Index of Script SAL component.
+
+ Notes
+ -----
+ **Checkpoints**
+
+ Homing dome: Before commanding azimuth dome to be homed.
+ """
+
+ def __init__(self, index, add_remotes: bool = True):
+ super().__init__(index=index, descr="Home MT dome.")
+
+ self.mtcs = None
+ self.physical_az = None
+ self.home_dome_duration = 60.0
+
+ @classmethod
+ def get_schema(cls):
+ schema_yaml = """
+ $schema: http://json-schema.org/draft-07/schema#
+ $id: https://github.com/lsst-ts/ts_standardscripts/maintel/mtdome/home_dome.yaml
+ title: HomeDome v1
+ description: Configuration for HomeDome.
+ type: object
+ properties:
+ physical_az:
+ description: Physical azimuth position for the dome as read by markings.
+ type: number
+ ignore:
+ description: >-
+ CSCs from the group to ignore in status check. Name must
+ match those in self.group.components, e.g.; hexapod_1.
+ type: array
+ items:
+ type: string
+ additionalProperties: false
+ required: [physical_az]
+ """
+ return yaml.safe_load(schema_yaml)
+
+ async def configure(self, config):
+ """Configure script.
+
+ Parameters
+ ----------
+ config : `types.SimpleNamespace`
+ Script configuration, as defined by `schema`.
+ """
+ self.config = config
+ self.physical_az = config.physical_az
+
+ if self.mtcs is None:
+ self.mtcs = MTCS(
+ domain=self.domain,
+ intended_usage=MTCSUsages.Slew | MTCSUsages.StateTransition,
+ log=self.log,
+ )
+ await self.mtcs.start_task
+
+ if hasattr(self.config, "ignore"):
+ for comp in self.config.ignore:
+ if comp not in self.mtcs.components_attr:
+ self.log.warning(
+ f"Component {comp} not in CSC Group. "
+ f"Must be one of {self.mtcs.components_attr}. Ignoring."
+ )
+ else:
+ self.log.debug(f"Ignoring component {comp}.")
+ setattr(self.mtcs.check, comp, False)
+
+ def set_metadata(self, metadata):
+ metadata.duration = self.home_dome_duration
+
+ async def run(self):
+ await self.mtcs.assert_all_enabled()
+ await self.checkpoint("Homing dome")
+ await self.mtcs.home_dome(physical_az=self.physical_az)
diff --git a/tests/test_maintel_mtdome_home_dome.py b/tests/test_maintel_mtdome_home_dome.py
new file mode 100644
index 000000000..bfbc23a60
--- /dev/null
+++ b/tests/test_maintel_mtdome_home_dome.py
@@ -0,0 +1,97 @@
+# This file is part of ts_standardscripts
+#
+# Developed for the LSST Telescope and Site Systems.
+# This product includes software developed by the LSST Project
+# (https://www.lsst.org).
+# See the COPYRIGHT file at the top-level directory of this distribution
+# for details of code ownership.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+import contextlib
+import unittest
+
+import pytest
+from lsst.ts import salobj, standardscripts
+from lsst.ts.idl.enums.Script import ScriptState
+from lsst.ts.standardscripts.maintel.mtdome import HomeDome
+
+
+class TestHomeDome(
+ standardscripts.BaseScriptTestCase, unittest.IsolatedAsyncioTestCase
+):
+ async def basic_make_script(self, index):
+ self.script = HomeDome(index=index)
+
+ return (self.script,)
+
+ @contextlib.asynccontextmanager
+ async def make_dry_script(self):
+ async with self.make_script(self):
+ self.script.mtcs = unittest.mock.AsyncMock()
+ self.script.mtcs.assert_all_enabled = unittest.mock.AsyncMock()
+ self.script.mtcs.home_dome = unittest.mock.AsyncMock()
+ yield
+
+ async def test_run(self):
+ async with self.make_dry_script():
+ await self.configure_script(physical_az=300.0)
+
+ await self.run_script()
+ self.script.mtcs.assert_all_enabled.assert_awaited_once()
+ self.script.mtcs.home_dome.assert_awaited_once()
+ self.script.mtcs.home_dome.assert_called_with(physical_az=300.0)
+
+ async def test_executable(self):
+ scripts_dir = standardscripts.get_scripts_dir()
+ script_path = scripts_dir / "maintel" / "mtdome" / "home_dome.py"
+ await self.check_executable(script_path)
+
+ async def test_config(self):
+ async with self.make_script():
+ await self.configure_script(physical_az=300.0)
+ assert self.script.physical_az == 300.0
+
+ async def test_invalid_configurations(self):
+ # Set of invalid configurations to test, all should fail to configure
+ configs_bad = [
+ dict(physical_az="not_valid"),
+ dict(physical_az=[1, 3]),
+ dict(physical_az=None),
+ ]
+
+ async with self.make_script():
+ for config in configs_bad:
+ with pytest.raises(salobj.ExpectedError):
+ await self.configure_script(**config)
+ assert self.script.state == ScriptState.CONFIGURE_FAILED
+
+ async def test_configure_ignore(self):
+ async with self.make_script():
+ components = ["mtptg"]
+ await self.configure_script(physical_az=300.0, ignore=components)
+
+ assert self.script.mtcs.check.mtptg is False
+
+ async def test_configure_ignore_not_csc_component(self):
+ async with self.make_script():
+ components = ["not_csc_comp", "mtptg"]
+ await self.configure_script(physical_az=300.0, ignore=components)
+
+ assert hasattr(self.script.mtcs, "not_csc_comp") is False
+ assert self.script.mtcs.check.mtptg is False
+
+
+if __name__ == "__main__":
+ unittest.main()