Repository: home-assistant/core
File: homeassistant/components/ring/camera.py (Python)

Code before:
        self._attr_unique_id = f"{device.id}-{description.key}"
        if description.motion_detection and device.has_capability(
            MOTION_DETECTION_CAPABILITY
        ):
            self._attr_motion_detection_enabled = device.motion_detection
        if description.live_stream:
            self._attr_supported_features |= CameraEntityFeature.STREAM

    @callback
    def _handle_coordinator_update(self) -> None:
        """Call update method."""
        self._device = self._get_coordinator_data().get_video_device(
            self._device.device_api_id
        )

        # Live stream entities are primarily for WebRTC live viewing, which works
        # without a subscription. Recording history (for still images/MJPEG) requires
        # a Ring Protect subscription. Skip processing recording history when there's
        # no subscription since: 1) no recordings exist to display, 2) the ring_doorbell
        # library logs warnings when attempting to fetch recording URLs without one.
        if self.entity_description.live_stream and not self._device.has_subscription:
            self.async_write_ha_state()
            return

        history_data = self._device.last_history
        if history_data:
            self._last_event = history_data[0]
            # will call async_update to update the attributes and get the
            # video url from the api
            self.async_schedule_update_ha_state(True)
        else:
            self._last_event = None
            self._last_video_id = None
            self._video_url = None
            self._images = {}
            self._expires_at = dt_util.utcnow()
            self.async_write_ha_state()

    @property
    def extra_state_attributes(self) -> dict[str, Any]:
        """Return the state attributes."""
        return {
            "video_url": self._video_url,
            "last_video_id": self._last_video_id,
        }

    async def async_camera_image(
        self, width: int | None = None, height: int | None = None
    ) -> bytes | None:
        """Return a still image response from the camera."""
        key = (width, height)

Review comment (suggestion):
```suggestion
        if history_data and self._device.has_subscription
```

It is probably even simpler. Both cameras will not work if there is no subscription, and the subscription can be terminated when HA is running (assumed from your last comment). Therefore, we should not limit it to one check

btw this also cleans up old recordings URLs, which cannot accessed anymore if I understood it correctly from your comment

Code after:
            MOTION_DETECTION_CAPABILITY
        ):
            self._attr_motion_detection_enabled = device.motion_detection
        if description.live_stream:
            self._attr_supported_features |= CameraEntityFeature.STREAM

    @callback
    def _handle_coordinator_update(self) -> None:
        """Call update method."""
        self._device = self._get_coordinator_data().get_video_device(
            self._device.device_api_id
        )

        history_data = self._device.last_history
        if history_data and self._device.has_subscription:
            self._last_event = history_data[0]
            # will call async_update to update the attributes and get the
            # video url from the api
            self.async_schedule_update_ha_state(True)
        else:
            self._last_event = None
            self._last_video_id = None
            self._video_url = None
            self._images = {}
            self._expires_at = dt_util.utcnow()
            self.async_write_ha_state()

    @property
    def extra_state_attributes(self) -> dict[str, Any]:
        """Return the state attributes."""
        return {
            "video_url": self._video_url,
            "last_video_id": self._last_video_id,
        }

    async def async_camera_image(
        self, width: int | None = None, height: int | None = None
    ) -> bytes | None:
        """Return a still image response from the camera."""
        if self._video_url is None:
            if not self._device.has_subscription:
                raise HomeAssistantError(
                    translation_domain=DOMAIN,
                    translation_key="no_subscription",
                )
            return None

        key = (width, height)
        if not (image := self._images.get(key)):
            image = await ffmpeg.async_get_image(
                self.hass,