#Can you share your code?

1 messages · Page 1 of 1 (latest)

winter zinc
#

Coordinator: (it just polls every 30 seconds starting at a specified time until it gets some data from the api or it reaches the specified end time)

class SmartTagCoordinator(DataUpdateCoordinator[Optional[ActivityItem]]):
    def __init__(self, hass: HomeAssistant, api_client: SmartTagApiClient, am_timing: PollTimingData):
        super().__init__(hass, _LOGGER, name = f"SMART Tag Coordinator")

        self.api_client = api_client
        self.am_timing = am_timing
        self.hass = hass
        self.unsub_start_am = async_track_time_change(self.hass, self.on_am_start_embark, self.am_timing.embark_start.hour, self.am_timing.embark_start.minute, self.am_timing.embark_start.second)
        self.unsub_interval_poll = None

    async def _async_update_data(self) -> ActivityItem | None:
        try:
            async with async_timeout.timeout(10):
                return await self.api_client.get_last_activity()
        except AuthError as err:
            raise ConfigEntryAuthFailed from err

    @callback
    async def on_am_start_embark(self, t: datetime):
        # Weekends
        time = datetime.now()
        if time.weekday() == 5 or time.weekday() == 6:
            return

        self.unsub_interval_poll = async_track_time_interval(self.hass, self.on_interval, timedelta(seconds = 30))
        await self.on_interval(t)

    def unsub_interval(self):
        if self.unsub_interval_poll is not None:
            self.unsub_interval_poll()
            self.unsub_interval_poll = None

    async def on_interval(self, _t):
        await self.async_refresh()
        t = datetime.now()

        if self.last_update_success:
            if self.data is not None:
                    # Stop polling
                    self.unsub_interval()
        else:
            # Error occured
            self.unsub_interval()
        
        if t.time() > self.am_timing.embark_end:
            self.unsub_interval()
#

Entity: (just applies a value fn from the description to the coordinator data)

class SmartTagSensor(CoordinatorEntity[SmartTagCoordinator], Entity):
    _attr_has_entity_name = True
    entity_description: SmartTagEntityDescription

    def __init__(self, coordinator: SmartTagCoordinator, description: SmartTagEntityDescription, device_info: DeviceInfo, entry_id: str):
        super().__init__(coordinator)
        self._attr_unique_id = f"{entry_id}-{description.key}"
        self._attr_device_info = device_info
        self.entity_id = f"sensor.smart_tag_{description.key}"
        self.entity_description = description
        self._state = description.value_fn(coordinator.data)

    @property 
    def state(self) -> StateType:
        return self._state
    
    @callback
    def _handle_coordinator_update(self) -> None:
        new_state = self.entity_description.value_fn(self.coordinator.data)
        if new_state is not None:
            self._state = new_state
        self.async_write_ha_state()
worldly drum
#

it sounds like all the callbacks for automations are getting processed before the next state change is made

#

this could just be a timing issue

winter zinc
#

yeah that's what I thought too

#

I added a 1 second delay to the automation and it worked

#

is that the best solution in this case? should I change the order that the entities are created in?

#

this is the code in async_setup_entry if that's relevant:

sensors = [SmartTagSensor(
            coordinator,
            description,
            device_info,
            entry.entry_id
        ) for description in AVAILABLE_ENTITIES]

    async_add_entities(sensors, False)
#

"entity A" (in my original question) is the first element in AVAILABLE_ENTITIES so it would make sense that automations based on it would get processed first

#

also I have another question - in my on_interval fn above I have to manually get the time because the param passed in by hass seems to be inconsistent

#

when it's triggered by async_track_time_change it's in local time but when it's from async_track_time_interval it's utc

lime dagger
worldly drum
#

homeassistant.util.dt has functions to help with that

winter zinc