Log messages and user to file?

HI,

using a simple script and input_text:

58
my family and other logged in users can enter a text, and play it over the intercom pushing the execute button. What I would like to do is create an automation that writes the message and user to a line in a text file.

I know we can use the notify.file service, but am not sure how to log the user that pushed the button for the script.

Is this even possible? Thanks for having a look!

trying this, but neither of the automations trigger:

  - alias: 'Forward intercom messages to filed_intercom_messages'
    id: 'Forward intercom messages to filed_intercom_messages'
    trigger:
      platform: state
      entity_id: script.intercom_text_message
      to: 'on'
    condition: []
    action:
      service: notify.filed_intercom_messages
      data_template:
        message: >
          Script state: {{ as_timestamp(now()) | timestamp_custom('%d %b: %X') }}: {{ states('input_text.message')}} 
             played on {{states('input_select.intercom')}} in {{states('input_select.intercom_language')}}

  - alias: 'Call Service Event (Script) text message'
    id: 'Call Service Event (Script) test message'
    trigger:
      platform: event
      event_type: call_service
      event_data:
        domain: script
    condition:
      condition: template
      value_template: >
         {{ trigger.event.data.entity_id == script.intercom_text_message}}
    action:
      service: notify.filed_intercom_messages
      data_template:
        message: >
          Event call: {{ as_timestamp(now()) | timestamp_custom('%d %b: %X') }}: {{ states('input_text.message')}} 
             played on {{states('input_select.intercom')}} in {{states('input_select.intercom_language')}}

if I trigger manually the action is performed and files are written.
Somehow I cant get the script execution toi trigger the automations? Could use some help / tips…

please have a look? @petro and @pnbruckner might I ask you directly?

I know the script is run alright:

10

even with this in quotes, nothing happens…

      value_template: >
         {{ trigger.event.data.entity_id == 'script.intercom_text_message'}}

taking the condition out completely makes the file being written. I need a condition though, because now it will write to the file upon each script execution :wink:

tried this too, and thought it worked, but now nothing is written anymore…:

  - alias: 'Call Service Event (Script) text message'
    id: 'Call Service Event (Script) test message'
    trigger:
      platform: event
      event_type: call_service
      event_data:
        domain: script
    condition:
      condition: template
      value_template: >
        {{ trigger.event.data.entity_id in ['script.intercom_text_message']}}
    action:
      service: notify.filed_intercom_messages
      data_template:
        message: >
          Event call: {{ as_timestamp(now()) | timestamp_custom('%d %b: %X') }}: {{ states('input_text.message')}} 
             played on {{states('input_select.intercom')}} in {{states('input_select.intercom_language')}}

replacing the trigger notation in the template editor with the actual state:


shows the quoted condition syntax should be ok?

The state trigger automation doesn’t work at all

You’d have to play around with the context object from a trigger. I haven’t investigated the rules for it yet, but it does get populated and there is a field for user. It’s only available on state objects. So I don’t know if it’s accessible from an event trigger.

trigger.to_state.context.user_id

You’d then have to check it against the user_id’s for each user.

o great, will investigate! once I get the base automations to behave as I want… btw where is this documented, so I can investigate…?

could you see why this:

  - alias: 'Call Service Event (Script) text message'
    id: 'Call Service Event (Script) test message'
    trigger:
      platform: event
      event_type: call_service
      event_data:
        domain: script
    condition:
      condition: template
      value_template: >
        {{ trigger.event.data.entity_id == 'script.intercom_text_message'}}
    action:
      service: notify.filed_intercom_messages
      data_template:
        message: >
          Event call: {{ as_timestamp(now()) | timestamp_custom('%d %b: %X') }}: {{ states('input_text.message')}} 
             played on {{states('input_select.intercom')}} in {{states('input_select.intercom_language')}}

doesn’t trigger?

would this be a reason to use the state trigger automation and focus on getting that to work? Since I get this in the logs:

Error rendering data template: UndefinedError: 'dict object' has no attribute 'to_state'

I fear it won’t work with the event trigger as you already suspected.

taking the to: ‘on’ out of the state trigger automation looks promising:

  - alias: 'Forward intercom messages to filed_intercom_messages'
    id: 'Forward intercom messages to filed_intercom_messages'
    trigger:
      platform: state
      entity_id: script.intercom_text_message
    condition: []
    action:
      service: notify.filed_intercom_messages
      data_template:
        message: >
          Script state: {{ as_timestamp(now()) | timestamp_custom('%d %b: %X') }}: {{ states('input_text.message')}} 
             played on {{states('input_select.intercom')}} in {{states('input_select.intercom_language')}} by 
             {{trigger.to_state.context.user_id}}

results in:

Script state: 06 Nov: 14:36:20: testing for trigger.to_state.context.user_id 
   played on Office in Nl by 
   3a8d4c2-redacted-2f67356b63

! Cool. now I need to find a mapper for the id’s :wink:

Could you explain why the state trigger on the script won’t work using a state: ‘on’, but does work without a state defined? Suppose it now triggers on an attribute or maybe the last_changed?

Scripts only turn ‘on’ when you have a delay inside them. So that would be the cause of that.

Don’t know actually. It might actually trigger based on the context! Who cares, it triggers though.

haha, you’re right.

this indicates though it triggers on last_triggered:

Script state triggered on <state script.intercom_text_message=off; last_triggered=2019-11-06T14:42:53.679379+01:00, friendly_name=Intercom text message, custom_ui_state_card=state-card-custom-ui, action_name=Announce, icon=mdi:text-to-speech @ 2019-11-06T14:42:56.710785+01:00>: 06 Nov: 14:42:56: testing for trigger.to_state 
   played on Office in En by 
   3a8d4c-redacted-356b63

tested by:

    action:
      service: notify.filed_intercom_messages
      data_template:
        message: >
          Script state triggered on {{trigger.to_state}}: {{ as_timestamp(now()) | timestamp_custom('%d %b: %X') }}: {{ states('input_text.message')}} 
             played on {{states('input_select.intercom')}} in {{states('input_select.intercom_language')}} by 
             {{trigger.to_state.context.user_id}}

continuing on the context.user_id: I suppose we couldn’t use context.user_name, or maybe context.user? That would be much easier and not force me to use a mapper for the id’s.

The only options avialable from context are: user_id, parent_id, and id. Go into your users and create a map from your user name to your user_id. The user id is displayed in the ui for each user.

EDIT:

You may be able to access this information from a python_script. I don’t know off the top of my head. There has to be an object somewhere in the software that contains user information.

1 Like

ok thanks Petro, will do. where can I read up on this? Can’t find it in the docs just yet.

this works fine for now, will add more user_id’s too come and create a true mapper for that:

    action:
      service: notify.filed_intercom_messages
      data_template:
        message: >
          {% set message = states('input_text.message') %}
          {% set device = states('input_select.intercom') %}
          {% set language = states('input_select.intercom_language') %}
          {% set id = trigger.to_state.context.user_id %}
          {% set time = as_timestamp(now()) | timestamp_custom('%d %b: %X') %}
          {% set user = 'Marius' if id == '3a8d-redacted-6b63' else id %}
          {{time}}: {{user}} played "{{message}}" on {{device}} in {{language}}

so, this is cool, got a working messaging log in my Ha setup now for all family members :wink:

  - alias: 'Forward intercom messages to filed intercom messages'
    id: 'Forward intercom messages to filed intercom messages'
    trigger:
      platform: state
      entity_id: script.intercom_text_message
    condition: []
    action:
      service: notify.filed_intercom_messages
      data_template:
        message: >
          {% set message = states('input_text.message') %}
          {% set device = states('input_select.intercom') %}
          {% set language = states('input_select.intercom_language') %}
          {% set id = trigger.to_state.context.user_id %}
          {% set time = as_timestamp(now()) | timestamp_custom('%d %b: %X') %}
          {% set user = {'3a8d-redacted-b63':'Marius',
                         'ed40-redacted-68af0':'Wife',
                         '579-redacted-9d9':'Daughter1',
                         '425-redacted-a1fa66':'Daughter2',
                         '3297-redacted-c0fe7a':'Daughter3',
                         '734fc2-redacted-74a6a':'Daughter4'} %}
          {% set user = user[id] if id in user else id %}
          {{time}}: {{user}} played "{{message}}" on {{device}} in {{language}}

If only I could find a way how to move the mapper to the secrets file… don’t like all the user_id out in the open…

Why’d you name your daughters the same???

huh? Must be missing the pun… I’ve numbered them :wink: Only for this post, lol. Irl I do know their names :wink:
I’d like those to be moved to the secrets

No pun, just a stupid joke. My wife would be pissed if we named them all daughter1…etc

good news…

          {% set message = states('input_text.message') %}
          {% set device = states('input_select.intercom') %}
          {% set language = states('input_select.intercom_language') %}
          {% set id = trigger.to_state.context.user_id %}
          {% set time = as_timestamp(now()) | timestamp_custom('%d %b: %X') %}
          {% set user = states.person | selectattr('attributes.user_id', 'eq', id) | list | first %}
          {{time}}: {{user.id}} played "{{message}}" on {{device}} in {{language}}

that looks promising, but, after setting up all my persons (hadn’t used that before), the template doesn’t show me a name for the user, in the {{user.id}} part. No matter which attribute I use, it isn’t displayed. If only {{user}} is used, it shows all attributes of that particular person.

if I enter

 {{states.person.marijn.attributes.friendly_name}}

in the template editor, it reveals the name I am looking for.
How could I change your template to use that?

Oops…

{{user.attributes.friendly_name}}

duh, of course… sorry for that.

Ill use this then:

{% set message = states('input_text.message') %}
   {% set device = states('input_select.intercom') %}
   {% set language = states('input_select.intercom_language') %}
   {% set id = trigger.to_state.context.user_id %}
   {% set time = as_timestamp(now()) | timestamp_custom('%d %b: %X') %}
   {% set user = states.person | selectattr('attributes.user_id', 'eq', id) | list | first %}
   {% set user = user.attributes.friendly_name %}
   {{time}}: {{user}} played "{{message}}" on {{device}} in {{language}}

could you explain what:

{% set user = states.person | selectattr('attributes.user_id', 'eq', id) | list | first %}

does, especially the last 2 filters?

using:

 {% set user = states.person | selectattr('attributes.user_id', 'eq', id) | first %}

seems to give me the same correct result, though I am not sure why…