using an AD app in the Frontend works great, with one exception: the entity created by the app doesn’t exist before the app is actually triggered to update. I used the CC ‘Variables’ before and could use something like this:
variable:
last_motion:
value: No motion detected
which allowed to be available, and this displayed, before an actual value was set.
With my AP app/module I need to wait for the first (in this case) motion, for the entity to be created. Until that time, the entity doesn’t exist and all red cards in the frontend are displayed…
please see my code below. How could this be adapted to create the ‘new_entity’ at startup (preferably recorded by recorder) so it shows immediately?:
apps.yaml:
LastMotionOutside:
class: MultiBinSensor
module: last_motion_outside
new_entity: sensor.last_motion_outside_ad
max_history: 10
binary_sensors:
binary_sensor.backdoor_buiten_sensor_motion: Backdoor
binary_sensor.driveway_buiten_sensor_motion: Driveway
binary_sensor.garden_backyard_buiten_sensor_motion: Garden backyard
etc etc etc
format_last_changed: '%H:%M:%S'
friendly_name: Last motion outside
and the module:
# -*- coding: utf-8 -*-
from collections import deque
from typing import Deque, Dict
import appdaemon.plugins.hass.hassapi as hass
_ATTR_NAME = "history_"
class MultiBinSensor(hass.Hass):
_entity: str
_date_format: str
_history: Deque[str]
_friendly_names: Dict[str, str]
_entity_attributes: Dict[str, str]
def initialize(self):
"""AppDaemon required method for app init."""
self._entity = self.args.get("new_entity")
icon = self.args.get("icon", "mdi:motion-sensor")
friendly_name = self.args.get("friendly_name", "Last motion outside")
self._entity_attributes = {"icon": icon, "friendly_name": friendly_name}
self._date_format = self.args.get("format_last_changed")
# Set up state history for attributes
self._history = deque([], maxlen=int(self.args.get("max_history")))
# Listen for binary sensor activations and store friendly names for them
bin_sensors: Dict[str, str] = self.args.get("binary_sensors")
self._friendly_names = {}
for sensor, pretty_name in bin_sensors.items():
self._friendly_names[sensor] = pretty_name
self.listen_state(self._bin_sensor_activation, sensor, new="on")
# recover old values, if any
old_attrs = self.get_state(self._entity, attribute="all")
if old_attrs:
state = old_attrs.get("state", "unknown")
for k, old_value in reversed(old_attrs.get("attributes", {}).items()):
if k.startswith(_ATTR_NAME) and ": " in old_value:
self._history.append(old_value)
# Re-Publish old state
self._set_new_sensor_state(state)
def _set_new_sensor_state(self, state):
"""Publish a new state for the sensor."""
history_attrs = {
f"{_ATTR_NAME}{i}": old_state
for i, old_state in enumerate(reversed(self._history))
if i > 0
}
attributes = {**self._entity_attributes, **history_attrs}
self.set_state(self._entity, state=state, attributes=attributes)
def _bin_sensor_activation(self, entity, attribute, old, new, kwargs):
"""Listen to bin sensors turning on, update history and publish a new state."""
location = self._friendly_names[entity]
pretty_date_now = self.datetime().strftime(self._date_format)
# Add to history
self._history.append(f"{location}: {pretty_date_now}")
# Publish new state
self._set_new_sensor_state(location)