text: """Support for HomematicIP Cloud binary sensor."""
  from typing import Any, Dict
  
  from homematicip.aio.device import (
      AsyncAccelerationSensor,
      AsyncContactInterface,
      AsyncDevice,
      AsyncFullFlushContactInterface,
      AsyncFullFlushContactInterface6,
      AsyncMotionDetectorIndoor,
      AsyncMotionDetectorOutdoor,
      AsyncMotionDetectorPushButton,
      AsyncPluggableMainsFailureSurveillance,
      AsyncPresenceDetectorIndoor,
      AsyncRotaryHandleSensor,
      AsyncShutterContact,
      AsyncShutterContactMagnetic,
      AsyncSmokeDetector,
      AsyncTiltVibrationSensor,
      AsyncWaterSensor,
      AsyncWeatherSensor,
      AsyncWeatherSensorPlus,
      AsyncWeatherSensorPro,
      AsyncWiredInput32,
  )
  from homematicip.aio.group import AsyncSecurityGroup, AsyncSecurityZoneGroup
  from homematicip.base.enums import SmokeDetectorAlarmType, WindowState
  
  from homeassistant.components.binary_sensor import (
      DEVICE_CLASS_BATTERY,
      DEVICE_CLASS_DOOR,
      DEVICE_CLASS_LIGHT,
      DEVICE_CLASS_MOISTURE,
      DEVICE_CLASS_MOTION,
      DEVICE_CLASS_MOVING,
      DEVICE_CLASS_OPENING,
      DEVICE_CLASS_POWER,
      DEVICE_CLASS_PRESENCE,
      DEVICE_CLASS_SAFETY,
      DEVICE_CLASS_SMOKE,
      BinarySensorEntity,
  )
  from homeassistant.config_entries import ConfigEntry
  from homeassistant.helpers.typing import HomeAssistantType
  
  from . import DOMAIN as HMIPC_DOMAIN, HomematicipGenericEntity
  from .hap import HomematicipHAP
  
  ATTR_ACCELERATION_SENSOR_MODE = "acceleration_sensor_mode"
  ATTR_ACCELERATION_SENSOR_NEUTRAL_POSITION = "acceleration_sensor_neutral_position"
  ATTR_ACCELERATION_SENSOR_SENSITIVITY = "acceleration_sensor_sensitivity"
  ATTR_ACCELERATION_SENSOR_TRIGGER_ANGLE = "acceleration_sensor_trigger_angle"
  ATTR_INTRUSION_ALARM = "intrusion_alarm"
  ATTR_MOISTURE_DETECTED = "moisture_detected"
  ATTR_MOTION_DETECTED = "motion_detected"
  ATTR_POWER_MAINS_FAILURE = "power_mains_failure"
  ATTR_PRESENCE_DETECTED = "presence_detected"
  ATTR_SMOKE_DETECTOR_ALARM = "smoke_detector_alarm"
  ATTR_TODAY_SUNSHINE_DURATION = "today_sunshine_duration_in_minutes"
  ATTR_WATER_LEVEL_DETECTED = "water_level_detected"
  ATTR_WINDOW_STATE = "window_state"
  
  GROUP_ATTRIBUTES = {
      "moistureDetected": ATTR_MOISTURE_DETECTED,
      "motionDetected": ATTR_MOTION_DETECTED,
      "powerMainsFailure": ATTR_POWER_MAINS_FAILURE,
      "presenceDetected": ATTR_PRESENCE_DETECTED,
      "waterlevelDetected": ATTR_WATER_LEVEL_DETECTED,
  }
  
  SAM_DEVICE_ATTRIBUTES = {
      "accelerationSensorNeutralPosition": ATTR_ACCELERATION_SENSOR_NEUTRAL_POSITION,
      "accelerationSensorMode": ATTR_ACCELERATION_SENSOR_MODE,
      "accelerationSensorSensitivity": ATTR_ACCELERATION_SENSOR_SENSITIVITY,
      "accelerationSensorTriggerAngle": ATTR_ACCELERATION_SENSOR_TRIGGER_ANGLE,
  }
  
  
  async def async_setup_entry(
      hass: HomeAssistantType, config_entry: ConfigEntry, async_add_entities
  ) -> None:
      """Set up the HomematicIP Cloud binary sensor from a config entry."""
      hap = hass.data[HMIPC_DOMAIN][config_entry.unique_id]
      entities = [HomematicipCloudConnectionSensor(hap)]
      for device in hap.home.devices:
          if isinstance(device, AsyncAccelerationSensor):
              entities.append(HomematicipAccelerationSensor(hap, device))
          if isinstance(device, AsyncTiltVibrationSensor):
              entities.append(HomematicipTiltVibrationSensor(hap, device))
          if isinstance(device, AsyncWiredInput32):
              for channel in range(1, 33):
                  entities.append(
                      HomematicipMultiContactInterface(hap, device, channel=channel)
                  )
          elif isinstance(device, AsyncFullFlushContactInterface6):
              for channel in range(1, 7):
                  entities.append(
                      HomematicipMultiContactInterface(hap, device, channel=channel)
                  )
          elif isinstance(
              device, (AsyncContactInterface, AsyncFullFlushContactInterface)
          ):
              entities.append(HomematicipContactInterface(hap, device))
          if isinstance(
              device,
              (AsyncShutterContact, AsyncShutterContactMagnetic),
          ):
              entities.append(HomematicipShutterContact(hap, device))
          if isinstance(device, AsyncRotaryHandleSensor):
              entities.append(HomematicipShutterContact(hap, device, True))
          if isinstance(
              device,
              (
                  AsyncMotionDetectorIndoor,
                  AsyncMotionDetectorOutdoor,
                  AsyncMotionDetectorPushButton,
              ),
          ):
              entities.append(HomematicipMotionDetector(hap, device))
          if isinstance(device, AsyncPluggableMainsFailureSurveillance):
              entities.append(
                  HomematicipPluggableMainsFailureSurveillanceSensor(hap, device)
              )
          if isinstance(device, AsyncPresenceDetectorIndoor):
              entities.append(HomematicipPresenceDetector(hap, device))
          if isinstance(device, AsyncSmokeDetector):
              entities.append(HomematicipSmokeDetector(hap, device))
          if isinstance(device, AsyncWaterSensor):
              entities.append(HomematicipWaterDetector(hap, device))
          if isinstance(device, (AsyncWeatherSensorPlus, AsyncWeatherSensorPro)):
              entities.append(HomematicipRainSensor(hap, device))
          if isinstance(
              device, (AsyncWeatherSensor, AsyncWeatherSensorPlus, AsyncWeatherSensorPro)
          ):
              entities.append(HomematicipStormSensor(hap, device))
              entities.append(HomematicipSunshineSensor(hap, device))
          if isinstance(device, AsyncDevice) and device.lowBat is not None:
              entities.append(HomematicipBatterySensor(hap, device))
  
      for group in hap.home.groups:
          if isinstance(group, AsyncSecurityGroup):
              entities.append(HomematicipSecuritySensorGroup(hap, device=group))
          elif isinstance(group, AsyncSecurityZoneGroup):
              entities.append(HomematicipSecurityZoneSensorGroup(hap, device=group))
  
      if entities:
          async_add_entities(entities)
  
  
  class HomematicipCloudConnectionSensor(HomematicipGenericEntity, BinarySensorEntity):
      """Representation of the HomematicIP cloud connection sensor."""
  
      def __init__(self, hap: HomematicipHAP) -> None:
          """Initialize the cloud connection sensor."""
          super().__init__(hap, hap.home)
  
      @property
      def name(self) -> str:
          """Return the name cloud connection entity."""
  
          name = "Cloud Connection"
          # Add a prefix to the name if the homematic ip home has a name.
          return name if not self._home.name else f"{self._home.name} {name}"
  
      @property
      def device_info(self) -> Dict[str, Any]:
          """Return device specific attributes."""
          # Adds a sensor to the existing HAP device
          return {
              "identifiers": {
                  # Serial numbers of Homematic IP device
                  (HMIPC_DOMAIN, self._home.id)
              }
          }
  
      @property
      def icon(self) -> str:
          """Return the icon of the access point entity."""
          return (
              "mdi:access-point-network"
              if self._home.connected
              else "mdi:access-point-network-off"
          )
  
      @property
      def is_on(self) -> bool:
          """Return true if hap is connected to cloud."""
          return self._home.connected
  
      @property
      def available(self) -> bool:
          """Sensor is always available."""
          return True
  
  
  class HomematicipBaseActionSensor(HomematicipGenericEntity, BinarySensorEntity):
      """Representation of the HomematicIP base action sensor."""
  
      @property
      def device_class(self) -> str:
          """Return the class of this sensor."""
          return DEVICE_CLASS_MOVING
  
      @property
      def is_on(self) -> bool:
          """Return true if acceleration is detected."""
          return self._device.accelerationSensorTriggered
  
      @property
      def device_state_attributes(self) -> Dict[str, Any]:
          """Return the state attributes of the acceleration sensor."""
          state_attr = super().device_state_attributes
  
          for attr, attr_key in SAM_DEVICE_ATTRIBUTES.items():
              attr_value = getattr(self._device, attr, None)
              if attr_value:
                  state_attr[attr_key] = attr_value
  
          return state_attr
  
  
  class HomematicipAccelerationSensor(HomematicipBaseActionSensor):
      """Representation of the HomematicIP acceleration sensor."""
  
  
  class HomematicipTiltVibrationSensor(HomematicipBaseActionSensor):
      """Representation of the HomematicIP tilt vibration sensor."""
  
  
  class HomematicipMultiContactInterface(HomematicipGenericEntity, BinarySensorEntity):
      """Representation of the HomematicIP multi room/area contact interface."""
  
      def __init__(
          self,
          hap: HomematicipHAP,
          device,
          channel=1,
          is_multi_channel=True,
      ) -> None:
          """Initialize the multi contact entity."""
          super().__init__(
              hap, device, channel=channel, is_multi_channel=is_multi_channel
          )
  
      @property
      def device_class(self) -> str:
          """Return the class of this sensor."""
          return DEVICE_CLASS_OPENING
  
      @property
      def is_on(self) -> bool:
          """Return true if the contact interface is on/open."""
          if self._device.functionalChannels[self._channel].windowState is None:
              return None
          return (
              self._device.functionalChannels[self._channel].windowState
              != WindowState.CLOSED
          )
  
  
  class HomematicipContactInterface(HomematicipMultiContactInterface, BinarySensorEntity):
      """Representation of the HomematicIP contact interface."""
  
      def __init__(self, hap: HomematicipHAP, device) -> None:
          """Initialize the multi contact entity."""
          super().__init__(hap, device, is_multi_channel=False)
  
  
  class HomematicipShutterContact(HomematicipMultiContactInterface, BinarySensorEntity):
      """Representation of the HomematicIP shutter contact."""
  
      def __init__(
          self, hap: HomematicipHAP, device, has_additional_state: bool = False
      ) -> None:
          """Initialize the shutter contact."""
          super().__init__(hap, device, is_multi_channel=False)
          self.has_additional_state = has_additional_state
  
      @property
      def device_class(self) -> str:
          """Return the class of this sensor."""
          return DEVICE_CLASS_DOOR
  
      @property
      def device_state_attributes(self) -> Dict[str, Any]:
          """Return the state attributes of the Shutter Contact."""
          state_attr = super().device_state_attributes
  
          if self.has_additional_state:
              window_state = getattr(self._device, "windowState", None)
              if window_state and window_state != WindowState.CLOSED:
                  state_attr[ATTR_WINDOW_STATE] = window_state
  
          return state_attr
  
  
  class HomematicipMotionDetector(HomematicipGenericEntity, BinarySensorEntity):
      """Representation of the HomematicIP motion detector."""
  
      @property
      def device_class(self) -> str:
          """Return the class of this sensor."""
          return DEVICE_CLASS_MOTION
  
      @property
      def is_on(self) -> bool:
          """Return true if motion is detected."""
          return self._device.motionDetected
  
  
  class HomematicipPresenceDetector(HomematicipGenericEntity, BinarySensorEntity):
      """Representation of the HomematicIP presence detector."""
  
      @property
      def device_class(self) -> str:
          """Return the class of this sensor."""
          return DEVICE_CLASS_PRESENCE
  
      @property
      def is_on(self) -> bool:
          """Return true if presence is detected."""
          return self._device.presenceDetected
  
  
  class HomematicipSmokeDetector(HomematicipGenericEntity, BinarySensorEntity):
      """Representation of the HomematicIP smoke detector."""
  
      @property
      def device_class(self) -> str:
          """Return the class of this sensor."""
          return DEVICE_CLASS_SMOKE
  
      @property
      def is_on(self) -> bool:
          """Return true if smoke is detected."""
          if self._device.smokeDetectorAlarmType:
              return (
                  self._device.smokeDetectorAlarmType
                  == SmokeDetectorAlarmType.PRIMARY_ALARM
              )
          return False
  
  
  class HomematicipWaterDetector(HomematicipGenericEntity, BinarySensorEntity):
      """Representation of the HomematicIP water detector."""
  
      @property
      def device_class(self) -> str:
          """Return the class of this sensor."""
          return DEVICE_CLASS_MOISTURE
  
      @property
      def is_on(self) -> bool:
          """Return true, if moisture or waterlevel is detected."""
          return self._device.moistureDetected or self._device.waterlevelDetected
  
  
  class HomematicipStormSensor(HomematicipGenericEntity, BinarySensorEntity):
      """Representation of the HomematicIP storm sensor."""
  
      def __init__(self, hap: HomematicipHAP, device) -> None:
          """Initialize storm sensor."""
          super().__init__(hap, device, "Storm")
  
      @property
      def icon(self) -> str:
          """Return the icon."""
          return "mdi:weather-windy" if self.is_on else "mdi:pinwheel-outline"
  
      @property
      def is_on(self) -> bool:
          """Return true, if storm is detected."""
          return self._device.storm
  
  
  class HomematicipRainSensor(HomematicipGenericEntity, BinarySensorEntity):
      """Representation of the HomematicIP rain sensor."""
  
      def __init__(self, hap: HomematicipHAP, device) -> None:
          """Initialize rain sensor."""
          super().__init__(hap, device, "Raining")
  
      @property
      def device_class(self) -> str:
          """Return the class of this sensor."""
          return DEVICE_CLASS_MOISTURE
  
      @property
      def is_on(self) -> bool:
          """Return true, if it is raining."""
          return self._device.raining
  
  
  class HomematicipSunshineSensor(HomematicipGenericEntity, BinarySensorEntity):
      """Representation of the HomematicIP sunshine sensor."""
  
      def __init__(self, hap: HomematicipHAP, device) -> None:
          """Initialize sunshine sensor."""
          super().__init__(hap, device, post="Sunshine")
  
      @property
      def device_class(self) -> str:
          """Return the class of this sensor."""
          return DEVICE_CLASS_LIGHT
  
      @property
      def is_on(self) -> bool:
          """Return true if sun is shining."""
          return self._device.sunshine
  
      @property
      def device_state_attributes(self) -> Dict[str, Any]:
          """Return the state attributes of the illuminance sensor."""
          state_attr = super().device_state_attributes
  
          today_sunshine_duration = getattr(self._device, "todaySunshineDuration", None)
          if today_sunshine_duration:
              state_attr[ATTR_TODAY_SUNSHINE_DURATION] = today_sunshine_duration
  
          return state_attr
  
  
  class HomematicipBatterySensor(HomematicipGenericEntity, BinarySensorEntity):
      """Representation of the HomematicIP low battery sensor."""
  
      def __init__(self, hap: HomematicipHAP, device) -> None:
          """Initialize battery sensor."""
          super().__init__(hap, device, post="Battery")
  
      @property
      def device_class(self) -> str:
          """Return the class of this sensor."""
          return DEVICE_CLASS_BATTERY
  
      @property
      def is_on(self) -> bool:
          """Return true if battery is low."""
          return self._device.lowBat
  
  
  class HomematicipPluggableMainsFailureSurveillanceSensor(
      HomematicipGenericEntity, BinarySensorEntity
  ):
      """Representation of the HomematicIP pluggable mains failure surveillance sensor."""
  
      def __init__(self, hap: HomematicipHAP, device) -> None:
          """Initialize pluggable mains failure surveillance sensor."""
          super().__init__(hap, device)
  
      @property
      def device_class(self) -> str:
          """Return the class of this sensor."""
          return DEVICE_CLASS_POWER
  
      @property
      def is_on(self) -> bool:
          """Return true if power mains fails."""
          return not self._device.powerMainsFailure
  
  
  class HomematicipSecurityZoneSensorGroup(HomematicipGenericEntity, BinarySensorEntity):
      """Representation of the HomematicIP security zone sensor group."""
  
      def __init__(self, hap: HomematicipHAP, device, post: str = "SecurityZone") -> None:
          """Initialize security zone group."""
          device.modelType = f"HmIP-{post}"
          super().__init__(hap, device, post=post)
  
      @property
      def device_class(self) -> str:
          """Return the class of this sensor."""
          return DEVICE_CLASS_SAFETY
  
      @property
      def available(self) -> bool:
          """Security-Group available."""
          # A security-group must be available, and should not be affected by
          # the individual availability of group members.
          return True
  
      @property
      def device_state_attributes(self) -> Dict[str, Any]:
          """Return the state attributes of the security zone group."""
          state_attr = super().device_state_attributes
  
          for attr, attr_key in GROUP_ATTRIBUTES.items():
              attr_value = getattr(self._device, attr, None)
              if attr_value:
                  state_attr[attr_key] = attr_value
  
          window_state = getattr(self._device, "windowState", None)
          if window_state and window_state != WindowState.CLOSED:
              state_attr[ATTR_WINDOW_STATE] = str(window_state)
  
          return state_attr
  
      @property
      def is_on(self) -> bool:
          """Return true if security issue detected."""
          if (
              self._device.motionDetected
              or self._device.presenceDetected
              or self._device.unreach
              or self._device.sabotage
          ):
              return True
  
          if (
              self._device.windowState is not None
              and self._device.windowState != WindowState.CLOSED
          ):
              return True
          return False
  
  
  class HomematicipSecuritySensorGroup(
      HomematicipSecurityZoneSensorGroup, BinarySensorEntity
  ):
      """Representation of the HomematicIP security group."""
  
      def __init__(self, hap: HomematicipHAP, device) -> None:
          """Initialize security group."""
          super().__init__(hap, device, post="Sensors")
  
      @property
      def device_state_attributes(self) -> Dict[str, Any]:
          """Return the state attributes of the security group."""
          state_attr = super().device_state_attributes
  
          smoke_detector_at = getattr(self._device, "smokeDetectorAlarmType", None)
          if smoke_detector_at:
              if smoke_detector_at == SmokeDetectorAlarmType.PRIMARY_ALARM:
                  state_attr[ATTR_SMOKE_DETECTOR_ALARM] = str(smoke_detector_at)
              if smoke_detector_at == SmokeDetectorAlarmType.INTRUSION_ALARM:
                  state_attr[ATTR_INTRUSION_ALARM] = str(smoke_detector_at)
          return state_attr
  
      @property
      def is_on(self) -> bool:
          """Return true if safety issue detected."""
          parent_is_on = super().is_on
          if parent_is_on:
              return True
  
          if (
              self._device.powerMainsFailure
              or self._device.moistureDetected
              or self._device.waterlevelDetected
              or self._device.lowBat
              or self._device.dutyCycle
          ):
              return True
  
          if (
              self._device.smokeDetectorAlarmType is not None
              and self._device.smokeDetectorAlarmType != SmokeDetectorAlarmType.IDLE_OFF
          ):
              return True
  
          return False
  