Home Assistant Unofficial Reference 2024.12.1
camera.py
Go to the documentation of this file.
1 """Camera that loads a picture from a local file."""
2 
3 from __future__ import annotations
4 
5 import logging
6 import mimetypes
7 
8 import voluptuous as vol
9 
11  PLATFORM_SCHEMA as CAMERA_PLATFORM_SCHEMA,
12  Camera,
13 )
14 from homeassistant.config_entries import SOURCE_IMPORT, ConfigEntry
15 from homeassistant.const import CONF_FILE_PATH, CONF_NAME
16 from homeassistant.core import DOMAIN as HOMEASSISTANT_DOMAIN, HomeAssistant
17 from homeassistant.exceptions import ServiceValidationError
18 from homeassistant.helpers import (
19  config_validation as cv,
20  entity_platform,
21  issue_registry as ir,
22 )
23 from homeassistant.helpers.entity_platform import AddEntitiesCallback
24 from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
25 from homeassistant.util import slugify
26 
27 from .const import DEFAULT_NAME, DOMAIN, SERVICE_UPDATE_FILE_PATH
28 from .util import check_file_path_access
29 
30 _LOGGER = logging.getLogger(__name__)
31 
32 PLATFORM_SCHEMA = CAMERA_PLATFORM_SCHEMA.extend(
33  {
34  vol.Required(CONF_FILE_PATH): cv.string,
35  vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
36  }
37 )
38 
39 
41  hass: HomeAssistant,
42  entry: ConfigEntry,
43  async_add_entities: AddEntitiesCallback,
44 ) -> None:
45  """Set up the Camera for local file from a config entry."""
46 
47  platform = entity_platform.async_get_current_platform()
48  platform.async_register_entity_service(
49  SERVICE_UPDATE_FILE_PATH,
50  {
51  vol.Required(CONF_FILE_PATH): cv.string,
52  },
53  "update_file_path",
54  )
55 
57  [
58  LocalFile(
59  entry.options[CONF_NAME],
60  entry.options[CONF_FILE_PATH],
61  entry.entry_id,
62  )
63  ]
64  )
65 
66 
68  hass: HomeAssistant,
69  config: ConfigType,
70  async_add_entities: AddEntitiesCallback,
71  discovery_info: DiscoveryInfoType | None = None,
72 ) -> None:
73  """Set up the Camera that works with local files."""
74  file_path: str = config[CONF_FILE_PATH]
75  file_path_slug = slugify(file_path)
76 
77  if not await hass.async_add_executor_job(check_file_path_access, file_path):
78  ir.async_create_issue(
79  hass,
80  DOMAIN,
81  f"no_access_path_{file_path_slug}",
82  breaks_in_ha_version="2025.5.0",
83  is_fixable=False,
84  learn_more_url="https://www.home-assistant.io/integrations/local_file/",
85  severity=ir.IssueSeverity.WARNING,
86  translation_key="no_access_path",
87  translation_placeholders={
88  "file_path": file_path_slug,
89  },
90  )
91  return
92 
93  ir.async_create_issue(
94  hass,
95  HOMEASSISTANT_DOMAIN,
96  f"deprecated_yaml_{DOMAIN}",
97  breaks_in_ha_version="2025.5.0",
98  is_fixable=False,
99  issue_domain=DOMAIN,
100  learn_more_url="https://www.home-assistant.io/integrations/local_file/",
101  severity=ir.IssueSeverity.WARNING,
102  translation_key="deprecated_yaml",
103  translation_placeholders={
104  "domain": DOMAIN,
105  "integration_title": "Local file",
106  },
107  )
108 
109  hass.async_create_task(
110  hass.config_entries.flow.async_init(
111  DOMAIN,
112  context={"source": SOURCE_IMPORT},
113  data=config,
114  )
115  )
116 
117 
119  """Representation of a local file camera."""
120 
121  def __init__(self, name: str, file_path: str, unique_id: str) -> None:
122  """Initialize Local File Camera component."""
123  super().__init__()
124  self._attr_name_attr_name = name
125  self._attr_unique_id_attr_unique_id = unique_id
126  self._file_path_file_path = file_path
127  # Set content type of local file
128  content, _ = mimetypes.guess_type(file_path)
129  if content is not None:
130  self.content_typecontent_type = content
131 
133  self, width: int | None = None, height: int | None = None
134  ) -> bytes | None:
135  """Return image response."""
136  try:
137  with open(self._file_path_file_path, "rb") as file:
138  return file.read()
139  except FileNotFoundError:
140  _LOGGER.warning(
141  "Could not read camera %s image from file: %s",
142  self.namename,
143  self._file_path_file_path,
144  )
145  return None
146 
147  async def update_file_path(self, file_path: str) -> None:
148  """Update the file_path."""
149  if not await self.hasshass.async_add_executor_job(
150  check_file_path_access, file_path
151  ):
152  raise ServiceValidationError(f"Path {file_path} is not accessible")
153  self._file_path_file_path = file_path
154  self.schedule_update_ha_stateschedule_update_ha_state()
155 
156  @property
157  def extra_state_attributes(self) -> dict[str, str]:
158  """Return the camera state attributes."""
159  return {"file_path": self._file_path_file_path}
bytes|None camera_image(self, int|None width=None, int|None height=None)
Definition: camera.py:134
None __init__(self, str name, str file_path, str unique_id)
Definition: camera.py:121
None schedule_update_ha_state(self, bool force_refresh=False)
Definition: entity.py:1244
str|UndefinedType|None name(self)
Definition: entity.py:738
None async_setup_entry(HomeAssistant hass, ConfigEntry entry, AddEntitiesCallback async_add_entities)
Definition: camera.py:44
None async_setup_platform(HomeAssistant hass, ConfigType config, AddEntitiesCallback async_add_entities, DiscoveryInfoType|None discovery_info=None)
Definition: camera.py:72
None open(self, **Any kwargs)
Definition: lock.py:86