pyControl4.alarm API documentation
Description: Controls Control4 security panel and contact sensor (door, window, motion) devices.

# Module `pyControl4.alarm`

Controls Control4 security panel and contact sensor (door, window, motion) devices.

## Classes

`class C4ContactSensor (director: C4Director, item_id: int)`
  Expand source code

      class C4ContactSensor:
          def __init__(self, director: C4Director, item_id: int) -> None:
              """Creates a Control4 Contact Sensor object.

              Parameters:
                  `director` - A `pyControl4.director.C4Director` object that corresponds
                      to the Control4 Director that the contact sensor is connected to.

                  `item_id` - The Control4 item ID of the contact sensor.
              """
              self.director = director
              self.item_id = item_id

          async def get_contact_state(self) -> bool | None:
              """Returns `True` if contact is triggered (door/window is closed, motion is
              detected), otherwise returns `False`.
              """
              contact_state = await self.director.get_item_variable_value(
                  self.item_id, "ContactState"
              )
              if contact_state is None:
                  return None
              return bool(contact_state)

  Creates a Control4 Contact Sensor object.

  ## Parameters

  `director` - A `C4Director` object that corresponds to the Control4 Director that the contact sensor is connected to.

  `item_id` - The Control4 item ID of the contact sensor.

  ### Methods

  `async def get_contact_state(self) ‑> bool | None`
    Expand source code

        async def get_contact_state(self) -> bool | None:
            """Returns `True` if contact is triggered (door/window is closed, motion is
            detected), otherwise returns `False`.
            """
            contact_state = await self.director.get_item_variable_value(
                self.item_id, "ContactState"
            )
            if contact_state is None:
                return None
            return bool(contact_state)

    Returns `True` if contact is triggered (door/window is closed, motion is detected), otherwise returns `False`.

`class C4SecurityPanel (director: C4Director, item_id: int)`
  Expand source code

      class C4SecurityPanel(C4Entity):
          async def get_arm_state(self) -> str | None:
              """
              NOTE: Prefer using `get_partition_state()`
              and `get_armed_type()` over this method.
              Returns the arm state of the security panel as "DISARMED", "ARMED_HOME",
              or "ARMED_AWAY".
              """
              disarmed = await self.director.get_item_variable_value(
                  self.item_id, "DISARMED_STATE"
              )
              armed_home = await self.director.get_item_variable_value(
                  self.item_id, "HOME_STATE"
              )
              armed_away = await self.director.get_item_variable_value(
                  self.item_id, "AWAY_STATE"
              )
              try:
                  if disarmed is not None and int(disarmed) == 1:
                      return "DISARMED"
                  elif armed_home is not None and int(armed_home) == 1:
                      return "ARMED_HOME"
                  elif armed_away is not None and int(armed_away) == 1:
                      return "ARMED_AWAY"
              except (ValueError, TypeError):
                  pass
              return None

          async def get_alarm_state(self) -> bool | None:
              """Returns `True` if alarm is triggered, otherwise returns `False`."""
              alarm_state = await self.director.get_item_variable_value(
                  self.item_id, "ALARM_STATE"
              )
              if alarm_state is None:
                  return None
              return bool(alarm_state)

          async def get_display_text(self) -> str | None:
              """Returns the display text of the security panel."""
              display_text = await self.director.get_item_variable_value(
                  self.item_id, "DISPLAY_TEXT"
              )
              return display_text

          async def get_trouble_text(self) -> str | None:
              """Returns the trouble display text of the security panel."""
              trouble_text = await self.director.get_item_variable_value(
                  self.item_id, "TROUBLE_TEXT"
              )
              return trouble_text

          async def get_partition_state(self) -> str | None:
              """Returns the partition state of the security panel.

              Possible values include "DISARMED_NOT_READY", "DISARMED_READY", "ARMED_HOME",
              "ARMED_AWAY", "EXIT_DELAY", "ENTRY_DELAY"
              """
              partition_state = await self.director.get_item_variable_value(
                  self.item_id, "PARTITION_STATE"
              )
              return partition_state

          async def get_delay_time_total(self) -> int | None:
              """Returns the total exit delay time. Returns 0 if an exit delay is not
              currently running.
              """
              delay_time_total = await self.director.get_item_variable_value(
                  self.item_id, "DELAY_TIME_TOTAL"
              )
              return int(delay_time_total) if delay_time_total is not None else None

          async def get_delay_time_remaining(self) -> int | None:
              """Returns the remaining exit delay time. Returns 0 if an exit delay is
              not currently running.
              """
              delay_time_remaining = await self.director.get_item_variable_value(
                  self.item_id, "DELAY_TIME_REMAINING"
              )
              return int(delay_time_remaining) if delay_time_remaining is not None else None

          async def get_open_zone_count(self) -> int | None:
              """Returns the number of open/unsecured zones."""
              open_zone_count = await self.director.get_item_variable_value(
                  self.item_id, "OPEN_ZONE_COUNT"
              )
              return int(open_zone_count) if open_zone_count is not None else None

          async def get_alarm_type(self) -> str | None:
              """Returns details about the current alarm type."""
              alarm_type = await self.director.get_item_variable_value(
                  self.item_id, "ALARM_TYPE"
              )
              return alarm_type

          async def get_armed_type(self) -> str | None:
              """Returns details about the current arm type."""
              armed_type = await self.director.get_item_variable_value(
                  self.item_id, "ARMED_TYPE"
              )
              return armed_type

          async def get_last_emergency(self) -> str | None:
              """Returns details about the last emergency trigger."""
              last_emergency = await self.director.get_item_variable_value(
                  self.item_id, "LAST_EMERGENCY"
              )
              return last_emergency

          async def get_last_arm_failure(self) -> str | None:
              """Returns details about the last arm failure."""
              last_arm_failed = await self.director.get_item_variable_value(
                  self.item_id, "LAST_ARM_FAILED"
              )
              return last_arm_failed

          async def set_arm(self, usercode: str, mode: str) -> None:
              """Arms the security panel with the specified mode.

              Parameters:
                  `usercode` - PIN/code for arming the system.

                  `mode` - Arm mode to use. This depends on what is supported by the
                      security panel itself.
              """
              usercode = str(usercode)
              await self.director.send_post_request(
                  f"/api/v1/items/{self.item_id}/commands",
                  "PARTITION_ARM",
                  {"ArmType": mode, "UserCode": usercode},
              )

          async def set_disarm(self, usercode: str) -> None:
              """Disarms the security panel.

              Parameters:
                  `usercode` - PIN/code for disarming the system.
              """
              usercode = str(usercode)
              await self.director.send_post_request(
                  f"/api/v1/items/{self.item_id}/commands",
                  "PARTITION_DISARM",
                  {"UserCode": usercode},
              )

          async def get_emergency_types(self) -> list[str]:
              """Returns the available emergency types as a list.

              Possible types are "Fire", "Medical", "Panic", and "Police".
              """
              types_list: list[str] = []

              data = await self.director.get_item_info(self.item_id)
              if not data or not isinstance(data, list) or len(data) == 0:
                  return types_list

              capabilities = data[0].get("capabilities", {})
              if capabilities.get("has_fire"):
                  types_list.append("Fire")
              if capabilities.get("has_medical"):
                  types_list.append("Medical")
              if capabilities.get("has_panic"):
                  types_list.append("Panic")
              if capabilities.get("has_police"):
                  types_list.append("Police")

              return types_list

          async def get_arm_types(self) -> list[str]:
              """Returns the available arm types as a list."""
              data = await self.director.get_item_info(self.item_id)
              if not data or not isinstance(data, list) or len(data) == 0:
                  return []

              capabilities = data[0].get("capabilities", {})
              arm_types_str = capabilities.get("arm_types", "")
              if not arm_types_str:
                  return []
              return [t.strip() for t in arm_types_str.split(",") if t.strip()]

          async def trigger_emergency(self, emergency_type: str) -> None:
              """Triggers an emergency of the specified type.

              Parameters:
                  `emergency_type` - Type of emergency:
                  "Fire", "Medical", "Panic", or "Police"
              """
              await self.director.send_post_request(
                  f"/api/v1/items/{self.item_id}/commands",
                  "EXECUTE_EMERGENCY",
                  {"EmergencyType": emergency_type},
              )

          async def send_key_press(self, key: str) -> None:
              """Sends a single keypress to the security panel's virtual keypad (if
              supported).

              Parameters:
                  `key` - Keypress to send. Only one key at a time.
              """
              key = str(key)
              await self.director.send_post_request(
                  f"/api/v1/items/{self.item_id}/commands",
                  "KEY_PRESS",
                  {"KeyName": key},
              )

  Creates a Control4 object.

  ## Parameters

  `director` - A `C4Director` object that corresponds to the Control4 Director that the device is connected to.

  `item_id` - The Control4 item ID.

  ### Ancestors

  - C4Entity

  ### Methods

  `async def get_alarm_state(self) ‑> bool | None`
    Expand source code

        async def get_alarm_state(self) -> bool | None:
            """Returns `True` if alarm is triggered, otherwise returns `False`."""
            alarm_state = await self.director.get_item_variable_value(
                self.item_id, "ALARM_STATE"
            )
            if alarm_state is None:
                return None
            return bool(alarm_state)

    Returns `True` if alarm is triggered, otherwise returns `False`.

  `async def get_alarm_type(self) ‑> str | None`
    Expand source code

        async def get_alarm_type(self) -> str | None:
            """Returns details about the current alarm type."""
            alarm_type = await self.director.get_item_variable_value(
                self.item_id, "ALARM_TYPE"
            )
            return alarm_type

    Returns details about the current alarm type.

  `async def get_arm_state(self) ‑> str | None`
    Expand source code

        async def get_arm_state(self) -> str | None:
            """
            NOTE: Prefer using `get_partition_state()`
            and `get_armed_type()` over this method.
            Returns the arm state of the security panel as "DISARMED", "ARMED_HOME",
            or "ARMED_AWAY".
            """
            disarmed = await self.director.get_item_variable_value(
                self.item_id, "DISARMED_STATE"
            )
            armed_home = await self.director.get_item_variable_value(
                self.item_id, "HOME_STATE"
            )
            armed_away = await self.director.get_item_variable_value(
                self.item_id, "AWAY_STATE"
            )
            try:
                if disarmed is not None and int(disarmed) == 1:
                    return "DISARMED"
                elif armed_home is not None and int(armed_home) == 1:
                    return "ARMED_HOME"
                elif armed_away is not None and int(armed_away) == 1:
                    return "ARMED_AWAY"
            except (ValueError, TypeError):
                pass
            return None

    NOTE: Prefer using `get_partition_state()` and `get_armed_type()` over this method. Returns the arm state of the security panel as "DISARMED", "ARMED_HOME", or "ARMED_AWAY".

  `async def get_arm_types(self) ‑> list[str]`
    Expand source code

        async def get_arm_types(self) -> list[str]:
            """Returns the available arm types as a list."""
            data = await self.director.get_item_info(self.item_id)
            if not data or not isinstance(data, list) or len(data) == 0:
                return []

            capabilities = data[0].get("capabilities", {})
            arm_types_str = capabilities.get("arm_types", "")
            if not arm_types_str:
                return []
            return [t.strip() for t in arm_types_str.split(",") if t.strip()]

    Returns the available arm types as a list.

  `async def get_armed_type(self) ‑> str | None`
    Expand source code

        async def get_armed_type(self) -> str | None:
            """Returns details about the current arm type."""
            armed_type = await self.director.get_item_variable_value(
                self.item_id, "ARMED_TYPE"
            )
            return armed_type

    Returns details about the current arm type.

  `async def get_delay_time_remaining(self) ‑> int | None`
    Expand source code

        async def get_delay_time_remaining(self) -> int | None:
            """Returns the remaining exit delay time. Returns 0 if an exit delay is
            not currently running.
            """
            delay_time_remaining = await self.director.get_item_variable_value(
                self.item_id, "DELAY_TIME_REMAINING"
            )
            return int(delay_time_remaining) if delay_time_remaining is not None else None

    Returns the remaining exit delay time. Returns 0 if an exit delay is not currently running.

  `async def get_delay_time_total(self) ‑> int | None`
    Expand source code

        async def get_delay_time_total(self) -> int | None:
            """Returns the total exit delay time. Returns 0 if an exit delay is not
            currently running.
            """
            delay_time_total = await self.director.get_item_variable_value(
                self.item_id, "DELAY_TIME_TOTAL"
            )
            return int(delay_time_total) if delay_time_total is not None else None

    Returns the total exit delay time. Returns 0 if an exit delay is not currently running.

  `async def get_display_text(self) ‑> str | None`
    Expand source code

        async def get_display_text(self) -> str | None:
            """Returns the display text of the security panel."""
            display_text = await self.director.get_item_variable_value(
                self.item_id, "DISPLAY_TEXT"
            )
            return display_text

    Returns the display text of the security panel.

  `async def get_emergency_types(self) ‑> list[str]`
    Expand source code

        async def get_emergency_types(self) -> list[str]:
            """Returns the available emergency types as a list.

            Possible types are "Fire", "Medical", "Panic", and "Police".
            """
            types_list: list[str] = []

            data = await self.director.get_item_info(self.item_id)
            if not data or not isinstance(data, list) or len(data) == 0:
                return types_list

            capabilities = data[0].get("capabilities", {})
            if capabilities.get("has_fire"):
                types_list.append("Fire")
            if capabilities.get("has_medical"):
                types_list.append("Medical")
            if capabilities.get("has_panic"):
                types_list.append("Panic")
            if capabilities.get("has_police"):
                types_list.append("Police")

            return types_list

    Returns the available emergency types as a list.

    Possible types are "Fire", "Medical", "Panic", and "Police".

  `async def get_last_arm_failure(self) ‑> str | None`
    Expand source code

        async def get_last_arm_failure(self) -> str | None:
            """Returns details about the last arm failure."""
            last_arm_failed = await self.director.get_item_variable_value(
                self.item_id, "LAST_ARM_FAILED"
            )
            return last_arm_failed

    Returns details about the last arm failure.

  `async def get_last_emergency(self) ‑> str | None`
    Expand source code

        async def get_last_emergency(self) -> str | None:
            """Returns details about the last emergency trigger."""
            last_emergency = await self.director.get_item_variable_value(
                self.item_id, "LAST_EMERGENCY"
            )
            return last_emergency

    Returns details about the last emergency trigger.

  `async def get_open_zone_count(self) ‑> int | None`
    Expand source code

        async def get_open_zone_count(self) -> int | None:
            """Returns the number of open/unsecured zones."""
            open_zone_count = await self.director.get_item_variable_value(
                self.item_id, "OPEN_ZONE_COUNT"
            )
            return int(open_zone_count) if open_zone_count is not None else None

    Returns the number of open/unsecured zones.

  `async def get_partition_state(self) ‑> str | None`
    Expand source code

        async def get_partition_state(self) -> str | None:
            """Returns the partition state of the security panel.

            Possible values include "DISARMED_NOT_READY", "DISARMED_READY", "ARMED_HOME",
            "ARMED_AWAY", "EXIT_DELAY", "ENTRY_DELAY"
            """
            partition_state = await self.director.get_item_variable_value(
                self.item_id, "PARTITION_STATE"
            )
            return partition_state

    Returns the partition state of the security panel.

    Possible values include "DISARMED_NOT_READY", "DISARMED_READY", "ARMED_HOME", "ARMED_AWAY", "EXIT_DELAY", "ENTRY_DELAY"

  `async def get_trouble_text(self) ‑> str | None`
    Expand source code

        async def get_trouble_text(self) -> str | None:
            """Returns the trouble display text of the security panel."""
            trouble_text = await self.director.get_item_variable_value(
                self.item_id, "TROUBLE_TEXT"
            )
            return trouble_text

    Returns the trouble display text of the security panel.

  `async def send_key_press(self, key: str) ‑> None`
    Expand source code

        async def send_key_press(self, key: str) -> None:
            """Sends a single keypress to the security panel's virtual keypad (if
            supported).

            Parameters:
                `key` - Keypress to send. Only one key at a time.
            """
            key = str(key)
            await self.director.send_post_request(
                f"/api/v1/items/{self.item_id}/commands",
                "KEY_PRESS",
                {"KeyName": key},
            )

    Sends a single keypress to the security panel's virtual keypad (if supported).

    ## Parameters

    `key` - Keypress to send. Only one key at a time.

  `async def set_arm(self, usercode: str, mode: str) ‑> None`
    Expand source code

        async def set_arm(self, usercode: str, mode: str) -> None:
            """Arms the security panel with the specified mode.

            Parameters:
                `usercode` - PIN/code for arming the system.

                `mode` - Arm mode to use. This depends on what is supported by the
                    security panel itself.
            """
            usercode = str(usercode)
            await self.director.send_post_request(
                f"/api/v1/items/{self.item_id}/commands",
                "PARTITION_ARM",
                {"ArmType": mode, "UserCode": usercode},
            )

    Arms the security panel with the specified mode.

    ## Parameters

    `usercode` - PIN/code for arming the system.

    `mode` - Arm mode to use. This depends on what is supported by the security panel itself.

  `async def set_disarm(self, usercode: str) ‑> None`
    Expand source code

        async def set_disarm(self, usercode: str) -> None:
            """Disarms the security panel.

            Parameters:
                `usercode` - PIN/code for disarming the system.
            """
            usercode = str(usercode)
            await self.director.send_post_request(
                f"/api/v1/items/{self.item_id}/commands",
                "PARTITION_DISARM",
                {"UserCode": usercode},
            )

    Disarms the security panel.

    ## Parameters

    `usercode` - PIN/code for disarming the system.

  `async def trigger_emergency(self, emergency_type: str) ‑> None`
    Expand source code

        async def trigger_emergency(self, emergency_type: str) -> None:
            """Triggers an emergency of the specified type.

            Parameters:
                `emergency_type` - Type of emergency:
                "Fire", "Medical", "Panic", or "Police"
            """
            await self.director.send_post_request(
                f"/api/v1/items/{self.item_id}/commands",
                "EXECUTE_EMERGENCY",
                {"EmergencyType": emergency_type},
            )

    Triggers an emergency of the specified type.

    ## Parameters

    `emergency_type` - Type of emergency: "Fire", "Medical", "Panic", or "Police"