ELK M1 Interface

Thanks Glenn!

The change to the async_added_to_hass method also worked for me. As a precaution, I wiped out the whole custom_components directory and made a fresh copy. Zones are reporting their current status immediately after a restart.

I’ll play with some new automation rules tomorrow on how to report on which zone triggered the alarm using the new triggered_alarm attribute.

New version up! elkm1-lib version bumped to 0.7.8. hass code updated to include state not updating bug. Added services for DM, SW, and SP messages. See services.yaml for docs.

Enjoy.

1 Like

Am I crazy or did we lose a few of the alarm_control_panel.elkm1_area_001 attributes

  • Last User At
  • Last User Name
  • Last Keypad Number
  • Last Keypad Name

They redid the attribute names but my guess is you should find the same values under:

changed_by_user:
changed_by_time:
changed_by_keypad:
changed_by_keypad_name:

I just wanted to say that DM work great! Wife and I are really happy to have the outside temp and reminders back on the keypad :slight_smile:

I see those attributes from the latest pull of the refactor branch. I think I’m missing one, changed_by_user_name. I use that one to send a notification with the name of the person who disarmed the alarm.

Let me first say, I’m moving my way up the stack. Started with elkm1-lib, then hass integration. I have spent almost no time on automations. That said…

What is possible in automations such that changed_by_* are not attributes at all on the alarm_control_panel?

Right now they are an aberration compared with the rest of the hass code. Those are the only attributes that are shown that are not “native” to the hass component.

So my challenge to everyone is this. Can you come up with a way to get the automation you are looking for, without “standing on your head”, using only native attributes?

Is it possible that when a system is armed/disarmed that triggers the automation which then goes and grabs “last_user” from the keypad, which then grabs the “name” from users?

Throw down out there :slight_smile:

IMO the more attributes available the better. Attributes give me more information to work with, to trigger automations or to filter events.

I can’t speak of hass automation since I do all my automations in Node Red. When I have it trigger on a state change of a device, all the attributes of said device get sent as a json payload through my flows. If some attributes are not a part of this entity I have to add additionnal queries back to hass to obtain the values and include them in my automation. It sounds simple but it adds complexity to the process.

I don’t use the changed_by* attributes yet in my automations but I think that in a situation where you have multiple keypads it would make sense to have the changed_by* attributes on the alarm_panel entity so you directly know on which keypad the action took place without going through each keypad entities to figure out which one did the change and extract the values from there.

Perhaps it might be better. Perhaps it is breaking the model of the device. Perhaps something else :slight_smile:

First, all the attributes from the ElkM1 are represented and available. No question (unless I’ve missed one).

What we are talking about is storing attributes from one component, say a keypad, on another component, say an alarm_control_panel.

What if… the trigger for the automation is on a keypad? From that you get the area, the user, and of course the time (of the trigger). From there you can pull the arm status for the area. And, if you want something other than arm status you could pull that.

So, back to my throwdown :slight_smile: challenge… can we create the automation without creating cross component attributes?

It looks like changed_by on the alarm_control_panel entity worked just fine. @gwww I agree we can likely pull together the automations we want by using some automation logic. I’ll let you know if I run into any cases that won’t work or are prohibitively complicated. Thank you again for all of your work on this component.

- id: notify_alarm_disarmed
  alias: "Notify Jim who disarmed"
  hide_entity: True
  trigger:
    - platform: state
      entity_id: alarm_control_panel.elkm1_area_001
      from: 'pending'
      to: 'disarmed'
    - platform: state
      entity_id: alarm_control_panel.elkm1_area_001
      from: 'triggered'
      to: 'disarmed'
  action:
    service: notify.haas_notifier_jshank_pixel
    data_template:
      title: "Alarm Disarmed"
      message: '{{ states.alarm_control_panel.elkm1_area_001.attributes["changed_by"].split(" ")[0] }} disarmed the alarm'

I think what @Gwww is hoping for is that we can figure out a pattern where we can do something like :

“({{ states.alarm_control_panel.elkm1_keypad_{{states.alarm_control_panel.elkm1_area_001.attributes.changed_by_keypad}}.attributes.friendly_name) accessed by {{ states.alarm_control_panel.elkm1_keypad_{{states.alarm_control_panel.elkm1_area_001.attributes.changed_by_keypad}}.attributes.last_user_name }}”

Or in other words, look up the keypad using the changed_by_keypad and then get the user name / etc from there.

If we can make it work, then we avoid duplicating information, and keep information as much as possible only on the entities it is relevant to.

However I don’t know enough about the automation scripting/templating to know if you can perform such lookups in a template “code” (you could certainly do it with proper code in AppDaemon). Also, there might be a gotcha with the formatting (since currently we’re zero-padding the entity names so they are sorted nice and pretty in the entity list in order, but the changed_by_keypad likely lacks that, so even if it worked it might not work … ). Again in AppDaemon this would be trivial to work around, but in template “code” I’m not sure how to do it. It might all be doable but I don’t know that part of HASS well enough to say.

I can say that in our usage of the Elk at my office, we do have multiple keypads (technically M1KAM RFID readers), and thus do have a need as @mathd postulated for being able to get who accessed / etc an area. We post that to our internal chat system. So one way or the other, this will be getting solved in a functional fashion :wink:

Let me start with a proposal for device_state_attributes…

On the alarm_control_panel (area in Elk terms), all keypad attributes will be removed except one: the index of the keypad that last entered a code on its keypad. So, user index, user name, keypad name would not be attributes.

Why? Because automations can support everything with them. I tried to figure out how to get rid of the keypad index too, but have not figured out how (yet).

Here’s the automation:

- id: alarm_panel_status
  alias: "Alarm panel arm/disarm"
  initial_state: 'on'
  trigger:
    - platform: state
      entity_id: alarm_control_panel.elkm1_area_001
      to: 'armed_night'
      for:
        seconds: 1.5
    - platform: state
      entity_id: alarm_control_panel.elkm1_area_001
      to: 'disarmed'
  condition:
    condition: template
    value_template: "{{ trigger.to_state.attributes.changed_by_keypad > 0 }}"
  action:
    service: persistent_notification.create
    data_template:
      title: "Alarm arm/disarm"
      message: >-
        {%- set keypad_num = trigger.to_state.attributes.changed_by_keypad %}
        {%- set keypad = "sensor.elkm1_keypad_{:03d}".format(keypad_num) %}
        Alarm has been set to {{ trigger.to_state.attributes.state }}
        by "{{ state_attr(keypad, 'last_user_name') }}"
        ({{ state_attr(keypad, 'last_user') }})
        at {{ state_attr(keypad, 'last_user_time') }}.

Of course you can put in your own action.

I have also created an automation when for keypad code is entered.

- id: keypad_code_entered
  alias: "Keypad code entered"
  initial_state: 'on'
  trigger:
    - platform: state
      entity_id:
        - sensor.elkm1_keypad_001
        - sensor.elkm1_keypad_002
        - sensor.elkm1_keypad_003
  condition:
    condition: template
    value_template: "{{ trigger.from_state.attributes['last_user_time'] != trigger.to_state.attributes['last_user_time'] }}"
  action:
    service: persistent_notification.create
    data_template:
      title: "Keypad triggered"
      message: >-
        {%- set a = trigger.to_state.attributes %}
        {%- if trigger.to_state.attributes['last_user'] %}
          User "{{ a['last_user_name'] }}" entered valid code at
        {%- else %}
          Invalid code "{{ trigger.to_state.attributes['code'] }}" entered at
        {%- endif %}
        keypad {{ a['index'] }} ({{ a['friendly_name'] }})

Here’s the output of the two automations when entering a valid code on a keypad:

User "Glenn" entered valid code at keypad 1 (Lower Hall)

Alarm has been set to armed_night by "Glenn" (1) at 2018-09-10T03:22:17.537389+00:00.

Alarm has been set to disarmed by "Glenn" (1) at 2018-09-10T03:23:25.976835+00:00.

So, I propose that the keypad attributes will be removed from alarm_control_panel.

Thoughts?

Requires a lot more lines of code but honestly I don’t feel it matters as long as it works, since it’s something you would copy and paste and modify if necessary, not something you have to remember how to do from scratch. And we’d of course have such examples in the documentation.

That example shows some template coding possibilities I hadn’t yet taken the time to learn were possible … :sunglasses:

I’ll try to test this out with our use case ASAP and ensure it works, but as long as we can get the keypad number and then use it to reference the keypad entity as you show, I don’t foresee any problems - all things will be solvable.

@BioSehnsucht Curious how you did this before, can you share an example?

@gwww Here’s a snippet of our existing way of handling this (there’s more for other areas):

sensor:
  - platform: template
    sensors:
      elk_area_1_last_user_at:
        value_template: '{{ states.alarm_control_panel.elkm1_area_001.attributes["Last User At"] }}'
        friendly_name: 'ELK Area 1 last accessed at'
automation:
  - alias: 'Main Area Accessed'
    trigger:
      platform: state
      entity_id: sensor.elk_area_1_last_user_at
    action:
     - service: notify.stride
       data_template:
         message: "Main Area ({{ states.alarm_control_panel.elkm1_area_001.attributes.last_keypad_name }}) accessed by {{ states.alarm_control_panel.elk_area_001.attributes['Last User Name'] }}"

the template sensor nonsense is because I couldn’t get triggering on attributes to work (perhaps this works now) so I had to create the fake sensor from an attribute then trigger on it.

Well, you still have to create a “fake” sensor to track an attribute change in the current hass.

Overall it’s not much different in lines of “code” if you take into account the attribute sensor and the automation bit. The formatting I used broke it into multiple lines. I also see you are using a template too.

There’s a new issue popping up (look for another Elk thread on the forum) around unique_id vs entity_id. It seems that entities are supposed to create a unique_id not an entity_id. I googling around to try and figure out the “right” answer. Not much clarity on what is right. I’ve played around a wee bit today, switched to creating the unique_id and let hass create the entity_id. Seems to work except the entity_id names are all the default names from the library. But entity_ids can be edited.

So, warning that to get integrated into hass we may need to change to unique_id. Simple code change. Bigger impacts for automations, etc. Might also impact how the keypad is linked to the alarm_control_panel.

This may be a problem : Accessing entity registry values in an Automation

TL;DR : Apparently you cannot currently access the unique_id from Jinja

Yah. I figured that. Instead of the keypad index (on which the entity_id is currently computed) the actually entity_id could be stored.

That should work fine. If someone manages to rename their entity ID between the event occuring and the automation firing, they only have themselves to blame :smiley:

This of course assumes we can look up the entity_id from within HASS itself, but if it’s not doable with some built in functionality, worst case we can track that ourselves (similar to the old discovered devices code would be one way).

@BioSehnsucht Appears doable to have entity_id as the changed_by_keypad. Still need to test further.

Hey all, another breaking change. This is big(ish). First, still investigating, but looks like to be latest hass compatible the entity_id should be generated by hass. The Elk hass code should be generating a unique_id.

What does this mean? The Elk-hass code would generate a unique_id for each entity. The unique_id would look just like the entity_id does today. For example a unique_id would be something such as sensor.elkm1_zone_001. The hass-generated entity_id would be something like sensor.zone001.

With this change all your entity_ids will change. However, you are now able to edit your entity_ids to be what you want (within reason).

Thanks to @lddubeau for point the entity_id/unique_id usage. I had an inkling that what was in the Elk-hass code was not correct but did not have details until today.

Thoughts?