|
13 | 13 | _LOGGER = logging.getLogger(LOGGER_PATH + ".state") |
14 | 14 |
|
15 | 15 |
|
| 16 | +class StateVar(str): |
| 17 | + """Class for representing the value and attributes of a state variable.""" |
| 18 | + |
| 19 | + def __new__(cls, state): |
| 20 | + """Create a new instance given a state variable.""" |
| 21 | + new_var = super().__new__(cls, state.state) |
| 22 | + new_var.__dict__ = state.attributes.copy() |
| 23 | + new_var.last_updated = state.last_updated |
| 24 | + new_var.last_changed = state.last_changed |
| 25 | + return new_var |
| 26 | + |
| 27 | + |
16 | 28 | class State: |
17 | 29 | """Class for state functions.""" |
18 | 30 |
|
@@ -217,21 +229,15 @@ async def get(cls, var_name): |
217 | 229 | parts = var_name.split(".") |
218 | 230 | if len(parts) != 2 and len(parts) != 3: |
219 | 231 | raise NameError(f"invalid name '{var_name}' (should be 'domain.entity' or 'domain.entity.attr')") |
220 | | - value = cls.hass.states.get(f"{parts[0]}.{parts[1]}") |
221 | | - if not value: |
| 232 | + state = cls.hass.states.get(f"{parts[0]}.{parts[1]}") |
| 233 | + if not state: |
222 | 234 | raise NameError(f"name '{parts[0]}.{parts[1]}' is not defined") |
223 | 235 | # |
224 | 236 | # simplest case is just the state value |
225 | 237 | # |
| 238 | + state = StateVar(state) |
226 | 239 | if len(parts) == 2: |
227 | | - return value.state |
228 | | - # |
229 | | - # handle virtual attributes |
230 | | - # |
231 | | - if parts[2] == "last_changed": |
232 | | - return value.last_changed |
233 | | - if parts[2] == "last_updated": |
234 | | - return value.last_updated |
| 240 | + return state |
235 | 241 | # |
236 | 242 | # see if this is a service that has an entity_id parameter |
237 | 243 | # |
@@ -264,9 +270,12 @@ async def service_call(*args, **kwargs): |
264 | 270 | # |
265 | 271 | # finally see if it is an attribute |
266 | 272 | # |
267 | | - if parts[2] not in value.attributes: |
268 | | - raise AttributeError(f"state '{parts[0]}.{parts[1]}' has no attribute '{parts[2]}'") |
269 | | - return value.attributes.get(parts[2]) |
| 273 | + try: |
| 274 | + return getattr(state, parts[2]) |
| 275 | + except AttributeError: |
| 276 | + raise AttributeError( # pylint: disable=raise-missing-from |
| 277 | + f"state '{parts[0]}.{parts[1]}' has no attribute '{parts[2]}'" |
| 278 | + ) |
270 | 279 |
|
271 | 280 | @classmethod |
272 | 281 | async def getattr(cls, var_name): |
|
0 commit comments