Add last_triggered_by Attribute to states

Hi everyone, I’m relatively new to Home Assistant but have been a long-time programmer. One feature that I feel is missing and could greatly enhance debugging and automation logic is the ability to track who or what changed the state of an entity.

In many programming environments, it’s common to have both a last_triggered (timestamp) and a last_triggered_by (the ID of the user, service, or automation responsible for the change). While Home Assistant provides the last_triggered timestamp, there’s no equivalent field to show what caused the state change.

Proposed Solution:

I propose introducing a new field in the attributes of each entity, such as:

  • last_triggered_by: Contains the ID or name of the person, automation, or service responsible for the last state change.
  • last_triggered_by_type: Specifies the type of entity responsible, for example: person, automation, service, or device.
  • last_triggered: The timestamp of the last change.

This information could be recorded alongside the existing last_changed timestamp, providing more detailed state change context.

Use Cases:

  1. Debugging Unintended State Changes:
  • When an entity’s state changes unexpectedly, it would be much easier to identify whether the change was triggered by a person, an automation, or an external service.
  • Example: If your thermostat unexpectedly changes temperature, you could check if it was manually adjusted by a user or triggered by an automation.
  1. Improving Automation Logic:
  • More intelligent automations can be created by referencing who or what last interacted with an entity.
  • Example: If a person manually changes the temperature, the automation could be temporarily paused to avoid overriding the manual change.
  1. Enhanced Security and Auditing:
  • For security-critical entities (e.g., door locks, alarm systems), tracking who last changed the state would allow better monitoring and auditing of important actions.

Example Implementation:

Each entity could have two new fields added to its attributes:

{
  "last_triggered": "2024-10-24T15:35:00.000Z",
  "last_triggered_by": "person.kate",
  "last_triggered_by_type": "person"
}

This information could be made available through the same API and UI views that display current entity attributes.

Conclusion:

By adding last_triggered_by and last_triggered_type attributes, Home Assistant would provide a more complete picture of entity state changes, improving debugging, automation design, and security tracking. This feature could benefit both advanced users and newcomers trying to understand their smart home’s behavior.

Thanks for considering this feature, and I’d be happy to provide further feedback or testing if needed!

Purely an FYI, you can get this info from logbook.

Ok thanks, will look into that, but still think I would be very usefull to have it on the entity it state in the attributes; for the reason I pointed out and many more,

Well, in regards to your bullets, you can do all of that now because the information is available in the states objects inside automations. The info isn’t in the state machine, but it is available in state changed events through <object>.context.id, <object>.context.user_id and <object>.context.parent_id.

For automation logic, this is already handled by context or parent id. Look up the posts made by the same person you replied to

My logbook shows nothing:

I been testing automation and changing it my self, the values of my AC; and the logbook shows zero info. I will read your other posts, but even if this info is availeble elsewhere I still believe it makes more sense tot have it on the entity it self also, HA is writing to it anyway for the last_triggerd.

Is that the actual entity name? It doesn’t seem right. Typically things don’t have dashes in the names.

Also, your logbook is still loading, notice the spinning circle? That will go away once it finds what it’s looking for.

Yes I gave everything name my self:


But 10min later it still loading the last 2 houres.

I will look more into this, this should make it possible to a least save that info somewhere in a helper for the ones i want so I have easy access to them.

I honestly don’t understand why you’re so against my proposal, even if it’s allready availeble elsewhere.

When did I say I was against your proposal?

I’m simply explaining that you can look at this information right now, without any changes. And they are accessible inside automations as well.

1 Like

Also with regards to the context information:

which is halfway down this page:

An example of logic using that may be this use case. I have cheap (PIR) motion sensors that are not really very good at determining presence (someone stops moving and they think nobody is there, etc.). Therefore I came up with the paradigm that any motion detected will only (re)start a timer, and nothing else. Then on that dedicated timer, when the timer is started, it turns lights on, and when it expires, the lights go off. So for let’s say a 15 minute duration timer, as long as someone moves more often than once every 15 minutes, the lights will stay on - and not turn off while people are in the room - and then will stay on no longer than 15 minutes after the last person has left the room.

So far so good, but… a hole in that logic… for a wall switch that controls lights! (Of course I have logic that cancels the timer when that switch is turned off, which then turns off the lights - BUT…) Let’s say someone turns off the switch on their way out of the room. The lights go off, and then when they are walking out of the room the motion is sensed and the lights go back on!

My solution (which works very well for us) is that if motion is sensed, is to (re)start the timer for those lights ONLY IF the swtich was NOT turned off MANUALLY within the last 5 minutes.

As far as I can tell, that context information is lost almost imposible to find when the automation is completed. It may be somewhere but I do not know how to find it. Below is how I have saved the information for my use case, a template sensor that will remember… In any event I have the below code for say the bathroom wall switch that I can refer to in the moton related automation from which I can determine if the light was turned off manually and when it was last turned off (to figure out that 5 minutes):

template:
#
# Bathroom Lights (for accessing these and with the last_changed value):
# {{ states('sensor.bathroom_lights_off_context') }}
# {{ states.sensor['bathroom_lights_off_context'].last_changed }}
#
# 1. Track the 'off' context changing (has to be triggered even if turning on,
# so any change at all will cause logic to be triggered if subsequent objects
# already set as "physical" will still be updated)
#
  - trigger:
      - platform: state
        entity_id: light.bathroom_shelly_1_relay
    sensor:
      - name: "Bathroom Lights Off Context"
        state: >
          {% set c_id = trigger.to_state.context.id %}
          {% set c_parent = trigger.to_state.context.parent_id %}
          {% set c_user = trigger.to_state.context.user_id %}
          {% if states('light.bathroom_shelly_1_relay') == 'on' %}
            n/a
          {% elif c_id != none and c_parent == none and c_user == none %}
            physical
          {% elif c_id != none and c_parent == none and c_user != none %}
            dashboard_ui
          {% elif c_id != none and c_parent != none and c_user == none %}
            automation
          {% else %}
            unknown
          {% endif %}
        unique_id: bathroom_lights_off_context

The above can be made more generic to also include how the switch was turned ON etc., however my use case does not require it (hence the “n/a” value when the switch is on)…

These kinds of template sensors in the configuration.yaml file lose their value when HA is restarted of course (but that does not affect my use case either) - if you need to keep information about custom information or “variables” (for lack of a better term) between HA restarts - I have those too - then put the value into an input helper that is marked as enabled but hidden…

I hope the above helps in some way in your efforts, but I would like to know also, if possible and I have wanted this for a long time as well…

How can I derive the historical data regarding how a switch (or any other device) was changed and by whom at any time in the recent past - in code (meaning, how to reference that information in yaml synbtax or a script that does not have to query a database)…? (Or maybe at the very least someone could show us how to access that from the history DB from within code - ?)

I voted YES… if that could be added to HA there would armies of us praising whoever added that :slight_smile:

1 Like

You can get that information from the events table in the database, its not easy, but it’s doable. The events table is what generates logbook entries, so the info is there alone.

I thought it was there @petro can you show us an example?

1 Like

I think I’m on to something i maybe can use and help you also.

I opened the home-assistant_v2.db with “DB Browser for SQLite Version 3.13.1”
I looked for last data of my climate:

SELECT * FROM event_data where shared_data like '%climate.e8fb1cf%' order by data_id DESC LIMIT 1; 

Then I thook his data_id = 3118

SELECT *,  hex(context_id_bin) AS context_id_hex, 
    hex(context_user_id_bin) AS context_user_id_hex  FROM events 
WHERE data_id = 3118 ORDER BY event_id LIMIT 1;

If context_user_id_hex is empty its from an automation, if its not empty, it corresponds to the user_id you find in: .storage\person.

Its bedtime now, for me, I look into more this weekend, but still find this over complicated.

PS: I have no idea where the context Id refers to?
Some starting points:

And I think once I figured the data out completely you should be able to use this to retrieve the data in an automation:

1 Like

You don’t need to do a lookup to get this information in an automation. You use the context object provided by the trigger in a template.

E.g. trigger.to_state.context.user_id in condition section or this.context.user_id in the action section of an automation.

In a script, it’s just this.context.user_id.

Agreed as I was saying in my post with the template sensor code showing same. Unfortunately the only trime it is easy to get at the data from wihtin any code is when the trigger happens and it is only related to the item that was triggered (@HSken might be trying to look at historical trigger data for multiple objects, and not only at trigger time?)

Every state object has context. The id in context is how HA identifies that entity. If you traverse the table and get the context_user_id_bin, that is referencing another entities context_id_bin. Make an sql sensor where the state is the context_user_id_bin in hex. Then in the sql sensors value_template, use {{ states.person | selectattr('context.id', 'eq', value) | map(attribute='name') | list | first }}.

1 Like

I can’t do that in the automation I have currently, I start my heating, room by room if I got excess power production of my solor panels, so first living room, second my office, third the bedroom, turn on every 5 min I check agian if I can switch on, next I increase them temps every 5min 1 degree above the current, till I hit target themp. So I dont have the context of all three those climate, the trigger is time.

I supplied code above to capture the context for later reference…

I don’t quite understand the use case because all three climate controls or thermometers (whatever they are in each room) can not only be used as triggers but can also give you the state if you just request it. For the use case you are explaining if you need to know how the controls in any one room have most recently been changed and when, you can also use a sensor template like the code I supplied to keep the most recent trigger context information for whether each of those were turned on or off manually, by an automation, or by a dashboard UI and when. So there must be something I do not understand about your use case…? If you need the context in 5 minute increments, couldn’t you just have a timed automation that checks each of those template context sensors every 5 minutes and you can within your code to see if each of those context template sensors had changed within the last 5 minutes from the last check…?

1 Like

I think you just gave me an idea, I could just have a helper that keeps track of who was the person/script that changed the climate, that would solve it. Tomorrow I give that an try!

Ok did some more research and think idd you need to track it when the state changes and only the values you care about, in my case:
climate.e8fb1cffxxx when state chages form one of these: hvac_modes: off, cool, heat, fan_only, dry, auto to new value
or the attributes: temperature got a new value

You can idd check at anytime what changed the state, like this:

{% set changed_by_id = states.climate.e8fb1cffxxx.context.user_id  %}
{% set changed_by = (states.person | selectattr('attributes.user_id','==', changed_by_id))| list | first or "system" %}
Changed by: {{ "System" if changed_by == "system" else state_attr(changed_by.entity_id, "friendly_name") }} 

If I use this in the developer-tools/template; it outputs my name for a short time when I change the tempratue, but just seconds later, it changes back to System, even tough it stayed the same temprature and state.

{% set changed_by_id = trigger.to_state.context.user_id  %}
{% set changed_by = (states.person | selectattr('attributes.user_id','==', changed_by_id))| list | first or "system" %}
Changed by: {{ "System" if changed_by == "system" else state_attr(changed_by.entity_id, "friendly_name") }}   

Source: Get the user that changed an entity | Ludeeus

but the problem is that it changes none stop because the state contains all this data, one of them is current_temperature: 25.2 and that changes non stop…

hvac_modes: off, cool, heat, fan_only, dry, auto
min_temp: 16
max_temp: 32
target_temp_step: 0.5
fan_modes: Quiet, low, medium, high, auto
preset_modes: none, Minimum Heat
swing_modes: Vertical Swing, Highest, High, Low, Lowest
current_temperature: 25.2
temperature: 26
fan_mode: auto
preset_mode: none
swing_mode: Lowest
model: ASYG18KMTE
wifi_led: 0
indoor_tmp: 7525
outdoor_tmp: 7200
hmn_det: 0
onoff: 1
op_mode: 4
fan_spd: 0
set_tmp: 260
af_dir_vrt: 4
af_swg_vrt: 0
af_dir_hrz: 5
af_swg_hrz: 0
ou_low_noise: 0
fan_ctrl: 1
hmn_det_auto_save: 65535
min_heat: 0
powerful: 0
economy: 1
err_code: 0
demand: 0
fltr_sign_reset: 65535
icon: mdi:air-conditioner
friendly_name: bureau-airco
supported_features: 441

So for my case it should be possible to simply keep track of the lastchanged_by with an automation that is triggerd by the state, check if temprature or hvac_mode was changed, if so update the lastchanged_by

Or maybe its just possible to make new state that only contains those who values?