Setting up a Message Box in Home Assistant

Home Assistant Script

This has been replaced now with the new improved todo list options.

I wanted a way to store up messages, such as “You have a new voicemail”, which could be read out easily when we get in and be used to flash the lights if we needed to read them. I found a very useful post by “123 Taras” and worked it up to a fairly easy solution.

  1. Add the template trigger to the Template: section of your Configuration.yaml
  2. Create a new script using the code below. It is fully prompted and can be tested easily in Dev tools.
  3. To add a message use call service to call the script and select “create message” with optional id
  4. Messages with id’s can be removed using “delete message” with the id
  5. All messages can be removed using “Delete All Messages”
  6. The macro can be used to list all the messages in a Markdown box or Template Card.

The core is a template sensor controlled by a trigger, which needs to be added to a package or to the configuration.yaml.

Template Trigger:

# ------------------------------------------------------------ Messaging System

- trigger:
    - platform: event
      event_type:
        - message_create
        - message_delete
        - message_delete_all
  sensor:
    - name: Messages
      state: "{{ now().timestamp() | timestamp_custom() }}"
      attributes:
        messages: >
          {% set msgs = this.attributes.get('messages', []) %}
          {% if trigger.event.event_type == 'message_create' %}
            {% set new = [{
                "id": trigger.event.data.id | default('TS' ~ now().timestamp()),
                "title": trigger.event.data.title | default(''),
                "message": trigger.event.data.message | default(''),
                "time": now().isoformat() }] %}
            {{ (msgs + new) }}
          {% elif trigger.event.event_type == 'message_delete' %}
            {% if trigger.event.data.id is defined %}
              {% set msgs = msgs | rejectattr('id', 'eq', trigger.event.data.id) | list %}
            {% elif trigger.event.data.index is defined and trigger.event.data.index | is_number %}
              {% set t = trigger.event.data.index | int(0) - 1 %}
              {% if 0 <= t < msgs|count %}
                {% set msgs = msgs | rejectattr('id', 'eq', msgs[t].id) | list %}
              {% endif %}
            {% endif %}
            {{ msgs }}
          {% else %}
            {{ [] }}
          {% endif %}

This can add messages and remove them by ID or all messages. In order to make it easy to remember the calls, I created a single Messages Update Script complete with parameters to allow messages to be added, removed etc.

Message update script:

alias: Messages Update
sequence:
  - choose:
      - conditions:
          - condition: template
            value_template: "{{action == 'create_message'}}"
        sequence:
          - event: message_create
            event_data:
              id: "{{id | default('TS' ~ now().timestamp())}}"
              title: "{{title}}"
              message: "{{message}}"
      - conditions:
          - condition: template
            value_template: "{{action == 'delete_message'}}"
        sequence:
          - event: message_delete
            event_data:
              id: "{{id | default('TS' ~ now().timestamp())}}"
      - conditions:
          - condition: template
            value_template: "{{action == 'delete_all_messages'}}"
        sequence:
          - event: message_delete_all
            event_data: {}
mode: single
fields:
  action:
    name: Action
    description: Action to take,  title and message are only required for Create
    selector:
      select:
        options:
          - label: Create
            value: create_message
          - label: Delete Message By ID
            value: delete_message
          - label: Delete All Messages
            value: delete_all_messages
  id:
    name: Message ID
    description: Optional for Create, mandatory for delete by id
    selector:
      text: null
  title:
    name: Message Title
    description: title for message
    selector:
      text: null
  message:
    name: Message
    description: Message Text, mandatory for Create only
    selector:
      text: null

The script above can be called easily in the Script UI or from the Developers tools. Finally a quick Jinja macro to read the messages or tell you there are none, which can be called direct from an intent or via a script for Alexa.

Jinja Macro to read the messages:

{%- macro read_messages() -%}
{% from 'easy_time.jinja' import easy_time  %} 
{% set msgs = state_attr('sensor.messages', 'messages') %}
{% set count = msgs| count %}
{%- if count == 0 -%}
You have no messages.
{%- else -%}
{% for m in msgs %}
Message {{loop.index}} received {{easy_time(m.time) }} ago
{{ m.title }}, {{ m.message }}.
{%- endfor %}
{%- endif -%}
{%- endmacro -%}

Note: The above script uses Petro31’s easy_time macros available on HACS to read out how old the message is.