Thank you to all involved and @mbitard with the docker work. It was a bit of a challenge to register my phone my number with signal, but I can see here that I was not the only one.
If interested on one approach for receiving messages. Here is the approach that I have taken, but first lets have a look at the payload to understand the code used:
[
{
"envelope":{
"source":"+<number>",
"sourceNumber":"+<number>",
"sourceUuid":"<Uuid number>",
"sourceName":"Philippe Eveleigh",
"sourceDevice":2,
"timestamp":1635705623098,
"dataMessage":{
"timestamp":1635705623098,
"message":"Hello World1",
"expiresInSeconds":0,
"viewOnce":false,
"mentions":[],
"attachments":[],
"contacts":[]
}
}
},{
"envelope":{
"source":"+<number>",
"sourceNumber":"+<number>",
"sourceUuid":"<Uuid number>",
"sourceName":"Philippe Eveleigh",
"sourceDevice":2,
"timestamp":1635705632553,
"dataMessage":{
"timestamp":1635705632553,
"message":"Hello World2",
"expiresInSeconds":0,
"viewOnce":false,
"mentions":[],
"attachments":[],
"contacts":[]
}
}
}
]
What should be understood from the payload is it can contain multiple messages (envelope). Here is a payload with no messages:
Here is the code that I use to retrieve the payload:
- resource: 'http://services20:8085/v1/receive/+<number>'
scan_interval: 60
headers:
User-Agent: "Home Assistant"
Content-Type: "application/json"
sensor:
- name: signal_notification_inside_lights
json_attributes_path: "$"
value_template: >-
{% set ns = namespace(signal_notification_inside_lights_state = 'unavailable') %}
{% if value_json is defined %}
{% set ns.signal_notification_inside_lights_state = 'none' %}
{% if (value_json | length) > 0 %}
{# Change the payload order #}
{% set value_json = value_json | sort(attribute='envelope.timestamp', reverse = True) %}
{# jinja does not allow to break out of a loop making things a little challenging. I use the variable state instead #}
{% for i in value_json %}
{# Source Number #}
{% if i['envelope']['sourceNumber'] in ['+<source number1>','+<source number2>','+<source number3>','+<source number4>'] %}
{# Message intercepted #}
{% if ns.signal_notification_inside_lights_state == 'none' and
'turn on inside light' in (i['envelope']['dataMessage']['message'] | lower) %}
{% set ns.signal_notification_inside_lights_state = 'on' %}
{% elif ns.signal_notification_inside_lights_state == 'none' and
'turn off inside light' in (i['envelope']['dataMessage']['message'] | lower) %}
{% set ns.signal_notification_inside_lights_state = 'off' %}
{% endif %}
{% endif %}
{% endfor %}
{% endif %}
{% endif %}
{{ ns.signal_notification_inside_lights_state }}
- name: signal_notification_inside_lights_source_number
json_attributes_path: "$"
value_template: >-
{% set ns = namespace(signal_notification_source_number = 'unavailable') %}
{% if value_json is defined %}
{% set ns.signal_notification_source_number = 'none' %}
{% if (value_json | length) > 0 %}
{# Change the payload order #}
{% set value_json = value_json | sort(attribute='envelope.timestamp', reverse = True) %}
{# jinja does not allow to break out of a loop making things a little challenging. I use the variable state instead #}
{% for i in value_json %}
{# Source Number #}
{% if i['envelope']['sourceNumber'] in ['+<source number1>,'+<source number2>','+<source number3>','+<source number4>'] %}
{% if ns.signal_notification_source_number == 'none' and
('turn on inside light' in (i['envelope']['dataMessage']['message'] | lower) or
'turn off inside light' in (i['envelope']['dataMessage']['message'] | lower)) %}
{% set ns.signal_notification_source_number = (i['envelope']['sourceNumber']) %}
{% endif %}
{% endif %}
{% endfor %}
{% endif %}
{% endif %}
{{ ns.signal_notification_source_number }}
The above ‘sensor.signal_notification_inside_lights’ state will change to ‘on’ or ‘off’. If it finds ‘turn on inside light’ or ‘turn off inside light’ message.
The payload is traversed by descending time to intercept the last message that matches the above search criteria: ‘turn on inside light’ or ‘turn off inside light’.
In regards to the speed performance for receiving messages. I have noticed that it can be be as fast as three seconds but I have also wittiness taking fifteen seconds. For my needs I have set the scan_interval to 60 seconds.
Since the notification runs every 60 seconds and no feedback to the success of the request. I have added another ‘sensor.signal_notification_inside_lights_source_number’ that I use to reply back to the requester, confirming if it was successful executing the request. For you to decide if you need this sensor or not.
The payload is deleted from the signal servers once retrieved. If you need to add a second request such as ‘turn on/off outside light’ the sensor will need to be added above with the appropriate changes.