Use Signal Messenger for Notifications

Hi,

I decided to set up the Signal Messenger to receive notifications from my HA instance, so that I get “push notification” on my phone. Why I did this?

  • Works with iOS, Android and Linux/Mac/Windows (with the Signal Desktop Client)
  • Works with basic authentication on my nginx proxy (html5 notifications do not)
  • It is secure (Pushbullet actually sounds pretty fishy when it comes to security)
  • It’s free

So if you are also interested in setting this up, here is how I did it.

Setup Signal Messenger for HA Notifications

  1. Install the Signal App on your phone and register your number

  2. Download the Signal-Cli https://github.com/AsamK/signal-cli from github. There is also a link to precompiled binaires, so you don’t have to take care of this yourself.

  3. Register your cellphone number, also described here https://github.com/AsamK/signal-cli (I used a different one than the one on my phone). To do this, you need to receive a text message this number. This has to be done only once! (Details in the Signal-Cli description)

  4. Try to send yourself a message with ./signal-cli -u [number of sender] send -m "Testmessage" [receivernumber] Note that you have to include your country code. So the numbers start with +xxx (+49 for Germany). I didn’t try yet, what happens if sender and receiver share the same number.

  5. If this works, we connect the signal-cli with homeassistant. I adjusted a notification script which you see below.
    Place this in homeassistant/components/notify/signalmessenger.py and adjust your customize.yaml.

  6. You’re done! You can now use automations to send yourself a Signal message

Currently, only one receiver can be set. You can “hack” this by instantiating the notifier for each receiver.

Have fun trying it, feedback is appreciated!

Config Files

# configuration.yaml
notify:
 - name: [choose your notification name
   platform: signalmessenger
   sender_nr: "+0987654321"
   recp_nr: "+1234567890"
   signal_cli_path: /home/user/signal-cli



"""
Signal Messenger for notify component.
Place this in `homeassistant/components/notify/signalmessenger.py` 
"""
import pathlib
import subprocess
import logging
import voluptuous as vol
from homeassistant.components.notify import (
    ATTR_DATA, ATTR_TITLE, ATTR_TITLE_DEFAULT, PLATFORM_SCHEMA,
    BaseNotificationService)
from homeassistant.const import CONF_API_KEY
import homeassistant.helpers.config_validation as cv

REQUIREMENTS = []

_LOGGER = logging.getLogger("signalmessenger")

CONF_SENDER_NR = 'sender_nr'
CONF_RECP_NR = 'recp_nr'
CONF_SIGNAL_CLI_PATH = 'signal_cli_path'

PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
    vol.Optional(CONF_SENDER_NR): cv.string,
    vol.Optional(CONF_RECP_NR): cv.string,
    vol.Optional(CONF_SIGNAL_CLI_PATH): cv.string,
})


def get_service(hass, config, discovery_info=None):
    """Get the Join notification service."""
    sender_nr = config.get(CONF_SENDER_NR)
    recp_nr = config.get(CONF_RECP_NR)
    signal_cli_path = config.get(CONF_SIGNAL_CLI_PATH)

    if sender_nr is None or recp_nr is None or signal_cli_path is None:
        _LOGGER.error("No device was provided. Please specify sender_nr"
                      ", recp_nr, or signal_cli_path")
        return False

    return SignalNotificationService(sender_nr, recp_nr, signal_cli_path)


class SignalNotificationService(BaseNotificationService):
    """Implement the notification service for Join."""

    def __init__(self, sender_nr, recp_nr, signal_cli_path):
        """Initialize the service."""
        self.sender_nr = sender_nr
        self.recp_nr = recp_nr
        self.signal_cli_path = path.join(signal_cli_path, "signal-cli")

    def send_message(self, message="", **kwargs):
        """Send a message to a user."""

        # Raise an Exception if something goes wrong

        p = subprocess.Popen([self.signal_cli_path, "-u", self.sender_nr, "send", "-m", message, self.recp_nr], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        # Wait for completion
        p.wait()
        output, err = p.communicate()

        ret = p.returncode
        if ret != 0:
            raise Exception("Signal Error {}".format(ret))

Troubleshooting

During this setup i encountered some issues that I had to solve that I want to share with you.

  • Make sure you can receive a textmessage on the number that you use in the registration process.
  • If you try signal-cli on your local machine and you want to use it on your pi/server/nas afterwards, copy also /home/user/.config/signal to the new location.
  • Signal-cli takes ages to send a message? Then your entropy is probably too low required for the crypto stuff. Check with cat /proc/sys/kernel/random/entropy_avail It should be > 1000. If not you can install haveged.
    !! But I did not check in detail what havegd does with your random number generator, so do this on your own risk !!
  • It is worth to take a look at the issued of the signal-cli repo https://github.com/AsamK/signal-cli

Edit: Fixed the points that @nhok mentioned. Thanks!

21 Likes

Hi mpex,

thank you very much for the signal hass integration reciped. After trying it, it finely worked out. But the python file contained some small errors, so I just mentioned them,

  • the logger should contain a name, I think signalmessenger would be a good choice
  • I don’t now why, but the building of the signal_cli_path for subprocess produced an error on my debian install with python 3.5 (something with posixPath), I changed it to os.path.join.
  • the formatting in the signalmessenger.py code is not right, there are missing spaces, and the quotes are not correct

Additionally I added some some log outputs, as there where some problems with the sender_nr and recp_nr settings in the configuration. The yaml file format interprets number with a plus sign at the beginning as an integer. This leads to a disappearing plus sign in the signal-cli call. With the additional log output, this is seen easily in the log file.

To avoid this, the configuration should use string notation of the phone numbers like this:

# configuration.yaml
notify:
 - name: [choose your notification name
   platform: signalmessenger
   sender_nr: "+0987654321"
   recp_nr: "+1234567890"
   signal_cli_path: /home/user/signal-cli

Here the signalmessenger.py file with the small changes I applied

"""
Signal Messenger for notify component.
Place this in homeassistant/components/notify/signalmessenger.py
"""
import pathlib
import subprocess
import logging
import voluptuous as vol

from os import path
from homeassistant.components.notify import (
     ATTR_DATA, ATTR_TITLE, ATTR_TITLE_DEFAULT, PLATFORM_SCHEMA,
     BaseNotificationService)
from homeassistant.const import CONF_API_KEY
import homeassistant.helpers.config_validation as cv

REQUIREMENTS = []

_LOGGER = logging.getLogger("signalmessenger")

CONF_SENDER_NR = 'sender_nr'
CONF_RECP_NR = 'recp_nr'
CONF_SIGNAL_CLI_PATH = 'signal_cli_path'

PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
vol.Optional(CONF_SENDER_NR): cv.string,
vol.Optional(CONF_RECP_NR): cv.string,
vol.Optional(CONF_SIGNAL_CLI_PATH): cv.string,
})

def get_service(hass, config, discovery_info=None):
    """Get the Join notification service."""
    sender_nr = config.get(CONF_SENDER_NR)
    recp_nr = config.get(CONF_RECP_NR)
    signal_cli_path = config.get(CONF_SIGNAL_CLI_PATH)

    if sender_nr is None or recp_nr is None or signal_cli_path is None:
        _LOGGER.error("No device was provided. Please specify sender_nr"
                      ", recp_nr, or signal_cli_path")
        return False

    return SignalNotificationService(sender_nr, recp_nr, signal_cli_path)

class SignalNotificationService(BaseNotificationService):
    """Implement the notification service for Join."""

    def __init__(self, sender_nr, recp_nr, signal_cli_path):
        """Initialize the service."""
        self.sender_nr = sender_nr
        self.recp_nr = recp_nr
        self.signal_cli_path = path.join(signal_cli_path, "signal-cli")

    def send_message(self, message="", **kwargs):
        """Send a message to a user."""

        # Raise an Exception if something goes wrong
        p = subprocess.Popen([self.signal_cli_path, "-u", self.sender_nr, "send", "-m", message, self.recp_nr], stdout=subprocess.PIPE, stderr=subprocess.PIPE)

        # Wait for completion
        p.wait()
        output, err = p.communicate()

        ret = p.returncode

        if ret != 0:
            _LOGGER.error("output {} - err {}".format(output, err))
            raise Exception("Signal Error {}".format(ret))
2 Likes

Thank you for the feedback, really appreciating it!
I adjusted the original post and merged your corrections.

Awesome! Signal is definetly the way to go. Telegram lacks end-to-end encryption when using a bot and therefore is a no go for me. So just wanted to give you a thumb up for your efforts.

I have two questions regarding your custom component.

  1. Do you plan on integrating a possibility to send files, e.g. for including camera pictures in the notification.

  2. I’m running HA in a docker and therefore need to find a way to run the singnal-cli in a separte docker. Just because I would need to reinstall the signal-cli everytime I update my HA docker.
    Do you know if it is possible to e.g. alter the signal_cli_path to address a singla_cli running in a docker on the same device?

I will look into it, but as I am not a developer my possibilities to contríbute are somehow limited.

Thanks!

1 Like

Hi Kraken,

thanks for the thumbs up! :grinning:

to 1) Currently I cannot send any images to signal. It worked in an earlier version, but not with the current one (just hangs, no error output). Currently not on my priority list. But feel free to investigate :slight_smile:

to 2) Calling signal-cli is just a subprocess call. You can alter it the way you want (and it is quite easy). E.g. call your docker with custom parameters (number, message). That should work

Hi all, could it be possible for one of you guys to create an hass.io addon with Signal cli ? I don’t know for now how to integrate it (maybe custum deps ?)…

Is there a reason why we don’t have Signal notifications in the 1st place ?

Well it always comes down to whether somebody invests their spare time to build it… I already pestered @frenck via Twitter :smile: I am still learning Docker, so I might have a stab at it myself one day, but no promises.

From what I understand we can not include signal-cli as an official component because of its incompatible license. A Hassio addon should be doable though (via MQTT?)

Thanks :frowning_face:
:wink:

1 Like

@mpex Thanks for your guide on how to install and use the signal-cli in HA.
I’m not a programmer and not very comfortable in Debian-linux, so I hope you could help me a little on how to get things going.

I use HA on Hassbian and got signal-cli installed and working, I can send messages from the command-line. So far so good.

Now I like to integrate singal in HA. I made the "signalmessenger.py" -file.
But in my "/home/homeassitant" -dir there is no dir named "components". So I placed the "signalmessenger.py" file in my "/home/homeassistant/.homeassitant/custom_components/notify" folder. Is this OK? I don’t get any errors when checking the config in HA, so I guess it should be fine. Only I have no way to check if the component actually works.

There is also no “/home/user/signal-cli” to be found. When I run
sudo find / -name signal-cli
I get these locations:

/home/pi/.local/share/signal-cli
/usr/local/bin/signal-cli
/opt/signal-cli-0.6.2/bin/signal-cli

Wich one is the right signal-cli to point to in config.yaml?

And my last question: How does the "action" -part of an automation whith Signal-notifications look like?
For example my automation to receive a message when the frontdoor is opened (433Mhz sensor via a sonoff RF-Bridge), should this work or do I have to use a different syntax?

trigger:
  platform: mqtt
  topic: tele/BRIDGE/RESULT
condition:
  condition: template
  value_template: '{{ trigger.payload_json[''RfReceived''][''Data''] == ''F894B9'' }}'
action:
- service: notify.signalmessenger
  data:
    message: Attention Front door opened!

Hope you can help me out.

2 Likes

First of all, thanks for the post. Adding the python script to homeassistant/custom_components/notify/ worked great.

I’d like to suggest the following modification to the python script. I was looking into the documentation for signal-cli and the better way to call it for sending is not:

self.signal_cli_path, "-u", self.sender_nr, "send", "-m", message, self.recp_nr

but rather:

self.signal_cli_path, "-u", self.sender_nr, "send", self.recp_nr, "-m", message

where we put the recipient’s number before the message. Doing it this way also lets the following happen:

self.signal_cli_path, "-u", self.sender_nr, "send", self.recp_nr, "-m", message, "-a", "/path/to/image.jpg"

which will send the image.jpg as an attachment.

So I simply set up the list and check to see if a kwarg is passed.
(I was also getting an error that the pathing was wrong (using 0.91.4), so I’ve updated the placement path to: homeassistant/custom_components/signalmessenger/notify.py
So the full python script becomes:

"""
Signal Messenger for notify component.
Place this in `homeassistant/components/signalmessenger/notify.py` 
"""
from os import path
import subprocess
import logging
import voluptuous as vol
from homeassistant.components.notify import (
    ATTR_DATA, ATTR_TITLE, ATTR_TITLE_DEFAULT, PLATFORM_SCHEMA,
    BaseNotificationService)
from homeassistant.const import CONF_API_KEY
import homeassistant.helpers.config_validation as cv

REQUIREMENTS = []

_LOGGER = logging.getLogger("signalmessenger")

CONF_SENDER_NR = 'sender_nr'
CONF_RECP_NR = 'recp_nr'
CONF_SIGNAL_CLI_PATH = 'signal_cli_path'

PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
    vol.Optional(CONF_SENDER_NR): cv.string,
    vol.Optional(CONF_RECP_NR): cv.string,
    vol.Optional(CONF_SIGNAL_CLI_PATH): cv.string,
})


def get_service(hass, config, discovery_info=None):
    """Get the Join notification service."""
    sender_nr = config.get(CONF_SENDER_NR)
    recp_nr = config.get(CONF_RECP_NR)
    signal_cli_path = config.get(CONF_SIGNAL_CLI_PATH)

    if sender_nr is None or recp_nr is None or signal_cli_path is None:
        _LOGGER.error("No device was provided. Please specify sender_nr"
                      ", recp_nr, or signal_cli_path")
        return False

    return SignalNotificationService(sender_nr, recp_nr, signal_cli_path)


class SignalNotificationService(BaseNotificationService):
    """Implement the notification service for Join."""

    def __init__(self, sender_nr, recp_nr, signal_cli_path):
        """Initialize the service."""
        self.sender_nr = sender_nr
        self.recp_nr = recp_nr
        self.signal_cli_path = path.join(signal_cli_path, "signal-cli")

    def send_message(self, message="", **kwargs):
        """Send a message to a user."""

        # Establish default command line arguments
        mainargs = [self.signal_cli_path, "-u", self.sender_nr, "send", self.recp_nr, "-m", message]

        # Add any "data":{"attachments":<value>} values as attachments to send. 
        # Supports list to send multiple attachments at once.
        if kwargs is not None:
            data = kwargs.get('data',None)
            if data and data.get('attachments',False):
                attachments = kwargs['data']['attachments']
                mainargs.append('-a')
                if isinstance(attachments,str):
                    mainargs.append(attachments)
                else:
                    mainargs.extend(attachments)

        # Raise an Exception if something goes wrong
        p = subprocess.Popen(mainargs, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        # Wait for completion
        p.wait()
        output, err = p.communicate()

        ret = p.returncode
        if ret != 0:
            raise Exception("Signal Error {}".format(ret))

This will then allow (at least through the debug interface) to call the notify script via a call to notify.[notification_name_from_configuration.yaml]:

{"message":"Hello world notify script single attachment", "data":{"attachments":"~/path/to/picture1.jpg"}}

or

{"message":"Hello world notify script multiple attachments", "data":{"attachments":["~/path/to/picture1.jpg","~/path/to/picture2.jpg"]}}

Also, note that if you can’t/won’t setup a different signal number, it is possible to simply link signal-cli to an existing account and send a “Note to Self” that will be sent to all linked devices using same number as sender and receiver.

1 Like

Thanks for the update, I get my command-line signal-cli working via SSH on a Hassbian installation.
I cannot seem to get it working in HA, when I call the notify.signal service, I get Errno 13:
errno13
Any idea what is going wrong?

this is the config-part:

notify:
  - name: signal
    platform: signalmessenger
    sender_nr: "+secretnumber"
    recp_nr: "+secretnumber"
    signal_cli_path: /home/homeassistant/.homeassistant/signal-cli

and in the mentioned directory are the folders ‘bin’ and ‘lib’ with all the precompiled files from github.

If you look in the python script,
signal_cli_path option should be the full path to the folder containing the signal-cli script/binary. If you have a bin folder under /home/homeassistant/.homeassistant/signal-cli such that the full path you could execute on a command line is /home/homeassistant/.homeassistant/signal-cli/bin/signal-cli, then your signal_cli_path config should be /home/homeassistant/.homeassistant/signal-cli/bin, so your config should read:

notify:
  - name: signal
    platform: signalmessenger
    sender_nr: "+secretnumber"
    recp_nr: "+secretnumber"
    signal_cli_path: /home/homeassistant/.homeassistant/signal-cli/bin

It would also be good to verify you can run signal-cli on a regular command line (as the homeassistant user) via:

$> /home/homeassistant/.homeassistant/signal-cli/bin/signal-cli -u "+sendernumber" send "+receiver number" -m "Hello world from command line"

If that doesn’t work, then you need to figure out how to get that working first, before HA will ever have a chance.

1 Like

edit: added support for groups

Thank you for this script. I made three changes.

  • log stderr on error
  • support group as recipient
  • support --config, because I run HA in Docker and mount signal-cli, JRE and the data folder as volumes
notify:
  - name: [name]
    platform: signalmessenger
    sender_nr: [sender]
    recp_nr: [recipient]
    signal_cli_path: /signal-cli/signal-cli-latest/bin
    signal_conf_path: /signal-cli/data
  - name: [group notification name]
    platform: signalmessenger
    sender_nr: [sender]
    group: [group_id]
    signal_cli_path: /signal-cli/signal-cli-latest/bin
    signal_conf_path: /signal-cli/data
"""
Signal Messenger for notify component.
Place this in `homeassistant/components/signalmessenger/notify.py` 
"""
from os import path
import subprocess
import logging
import voluptuous as vol
from homeassistant.components.notify import (
    ATTR_DATA, ATTR_TITLE, ATTR_TITLE_DEFAULT, PLATFORM_SCHEMA,
    BaseNotificationService)
from homeassistant.const import CONF_API_KEY
import homeassistant.helpers.config_validation as cv

REQUIREMENTS = []

_LOGGER = logging.getLogger("signalmessenger")

CONF_SENDER_NR = 'sender_nr'
CONF_RECP_NR = 'recp_nr'
CONF_GROUP = 'group'
CONF_SIGNAL_CLI_PATH = 'signal_cli_path'
CONF_SIGNAL_CONF_PATH = 'signal_conf_path'

PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
    vol.Optional(CONF_SENDER_NR): cv.string,
    vol.Optional(CONF_RECP_NR): cv.string,
    vol.Optional(CONF_GROUP): cv.string,
    vol.Optional(CONF_SIGNAL_CLI_PATH): cv.string,
    vol.Optional(CONF_SIGNAL_CONF_PATH): cv.string,
})


def get_service(hass, config, discovery_info=None):
    """Get the Join notification service."""
    sender_nr = config.get(CONF_SENDER_NR)
    recp_nr = config.get(CONF_RECP_NR)
    group = config.get(CONF_GROUP)
    signal_cli_path = config.get(CONF_SIGNAL_CLI_PATH)
    signal_conf_path = config.get(CONF_SIGNAL_CONF_PATH)

    if sender_nr is None or signal_cli_path is None:
        _LOGGER.error("Please specify sender_nr and signal_cli_path")
        return False
    if not (recp_nr is None ^ group is None):
        _LOGGER.error("Either recp_nr or group is required")
        return False

    return SignalNotificationService(sender_nr, recp_nr, group,
                                     signal_cli_path, signal_conf_path)


class SignalNotificationService(BaseNotificationService):
    """Implement the notification service for Join."""

    def __init__(self, sender_nr, recp_nr, group, signal_cli_path, signal_conf_path):
        """Initialize the service."""
        self.sender_nr = sender_nr
        self.recp_nr = recp_nr
        self.group = group
        self.signal_cli_path = path.join(signal_cli_path, "signal-cli")
        self.signal_conf_path = signal_conf_path

    def send_message(self, message="", **kwargs):
        """Send a message to a user."""

        # Establish default command line arguments
        mainargs = [self.signal_cli_path]
        if self.signal_conf_path is not None:
            mainargs.extend(['--config', self.signal_conf_path])

        mainargs.extend(["-u", self.sender_nr, "send"])
        if self.group is not None:
            mainargs.extend(["-g", self.group])
        else:
            mainargs.extend(self.recp_nr)

        mainargs.extend(["-m", message])

        # Add any "data":{"attachments":<value>} values as attachments to send. 
        # Supports list to send multiple attachments at once.
        if kwargs is not None:
            data = kwargs.get('data',None)
            if data and data.get('attachments',False):
                attachments = kwargs['data']['attachments']
                mainargs.append('-a')
                if isinstance(attachments,str):
                    mainargs.append(attachments)
                else:
                    mainargs.extend(attachments)

        # Raise an Exception if something goes wrong
        p = subprocess.Popen(mainargs, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        # Wait for completion
        p.wait()
        output, err = p.communicate()
        ret = p.returncode

        if ret != 0:
            raise Exception("Signal Error %d: '%s'" % (ret, err))

1 Like

Thank you very, very much. After some tweaking I got a functioning signal-notification. It was indeed a faulty directory-referral, as you suggested, but also I registered my land-line-phone number as ‘pi’-user.
When I changed the user to ‘homeassistant’-user with:

sudo su -s /bin/bash homeassistant

and then registered my home-phone(landline) with the commands:

./signal-cli -u +LAND_LINE_NR register --voice

I got a robot-voice telling me my VERIFICATION_NR, so I verified with:

./signal-cli -u +LAND_LINE_NR verify VERIFICATION_NR

After that I was able to get a message across from the command line as ‘homeassistant’-user:

[email protected]: ~/.homeassistant/signal-cli-0.6.2/bin $ /home/homeassistant/.homeassistant/signal-cli-0.6.2/bin/signal-cli -u +LAND_LINE_NR send +MOBILE_NR -m "Hello world from command line"

IMG_32BEF9E861CA-1

Changing my config in HA to:

name: signal_jp
platform: signalmessenger
sender_nr: "+LAND_LINE_NR"
recp_nr: "+MOBILE_NR"
signal_cli_path: /home/homeassistant/.homeassistant/signal-cli-0.6.2/bin

And finally in the HA-service, I called:

and IT WORKS :slight_smile:

1 Like

Frist: Thanks for you awesome work!

Poorly I get the following error after setting up the notify.py:

2019-05-03 06:24:26 ERROR (MainThread) [homeassistant.components.notify] Error setting up platform signalmessenger
Traceback (most recent call last):
  File "/srv/homeassistant/lib/python3.5/site-packages/homeassistant/components/notify/__init__.py", line 76, in async_setup_platform
    platform.get_service, hass, p_config, discovery_info)
  File "/usr/lib/python3.5/asyncio/futures.py", line 380, in __iter__
    yield self  # This tells Task to wait for completion.
  File "/usr/lib/python3.5/asyncio/tasks.py", line 304, in _wakeup
    future.result()
  File "/usr/lib/python3.5/asyncio/futures.py", line 293, in result
    raise self._exception
  File "/usr/lib/python3.5/concurrent/futures/thread.py", line 55, in run
    result = self.fn(*self.args, **self.kwargs)
  File "/home/homeassistant/.homeassistant/custom_components/signalmessenger/notify.py", line 41, in get_service
    return SignalNotificationService(sender_nr, recp_nr, signal_cli_path)
  File "/home/homeassistant/.homeassistant/custom_components/signalmessenger/notify.py", line 51, in __init__
    self.signal_cli_path = path.join(signal_cli_path, "signal-cli")
NameError: name 'path' is not defined

Has anyone a suggestion :(?

It looks like you’re missing a

from os import path

import statement.

Here’s my notify.py.
The import statement is on top.

from os import path
import subprocess
import logging
import voluptuous as vol
from homeassistant.components.notify import (
ATTR_DATA, ATTR_TITLE, ATTR_TITLE_DEFAULT, PLATFORM_SCHEMA,
BaseNotificationService)
from homeassistant.const import CONF_API_KEY
import homeassistant.helpers.config_validation as cv

REQUIREMENTS = []

_LOGGER = logging.getLogger(“signalmessenger”)

CONF_SENDER_NR = ‘sender_nr’
CONF_RECP_NR = ‘recp_nr’
CONF_GROUP = ‘group’
CONF_SIGNAL_CLI_PATH = ‘signal_cli_path’

PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
vol.Optional(CONF_SENDER_NR): cv.string,
vol.Optional(CONF_RECP_NR): cv.string,
vol.Optional(CONF_GROUP): cv.string,
vol.Optional(CONF_SIGNAL_CLI_PATH): cv.string,
})

def get_service(hass, config, discovery_info=None):
“”“Get the Join notification service.”""
sender_nr = config.get(CONF_SENDER_NR)
recp_nr = config.get(CONF_RECP_NR)
group = config.get(CONF_GROUP)
signal_cli_path = config.get(CONF_SIGNAL_CLI_PATH)

return SignalNotificationService(sender_nr, recp_nr, group,
signal_cli_path)

class SignalNotificationService(BaseNotificationService):
“”“Implement the notification service for Join.”""

def init(self, sender_nr, recp_nr, group, signal_cli_path):
“”“Initialize the service.”""
self.sender_nr = “+49123456”
self.recp_nr = “+49123456”
self.group = group
self.signal_cli_path = “/opt/signal-cli-0.6.2/bin/signal-cli”

def send_message(self, message="", **kwargs):
“”“Send a message to a user.”""

   # Establish default command line arguments
   mainargs = [self.signal_cli_path]


   mainargs.extend(["-u", self.sender_nr, "send"])
   if self.group is not None:
       mainargs.extend(["-g", self.group])
   else:
       mainargs.extend(self.recp_nr)

   mainargs.extend(["-m", message])

   # Supports list to send multiple attachments at once.
   # Add any "data":{"attachments":<value>} values as attachments to send. 
   if kwargs is not None:
       data = kwargs.get('data',None)
       if data and data.get('attachments',False):
           attachments = kwargs['data']['attachments']
           mainargs.append('-a')
           if isinstance(attachments,str):
               mainargs.append(attachments)
           else:
               mainargs.extend(attachments)

   # Raise an Exception if something goes wrong
   p = subprocess.Popen(mainargs, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
   # Wait for completion
   p.wait()
   output, err = p.communicate()
   ret = p.returncode

   if ret != 0:
       raise Exception("Signal Error %d: '%s'" % (ret, err))

KaQn4p,

a) something is messed up with your formatting of the code, so it makes it hard to read.
b) There’s nothing in your notify.py that you’ve pasted that even includes the phrase

path.join

It might have gotten eaten by the formatting issues?

One way of troubleshooting could be to put the
from os import path statement right above the

self.signal_cli_path = path.join(signal_cli_path,"signal-cli")

or just change that line to

self.signal_cli_path = '/'.join(signal_cli_path,"signal-cli") 

if on linux/unix (and will probably work on windows, honestly) or more correctly for windows:

self.signal_cli_path = '\\'.join(signal_cli_path,"signal-cli")

Note that path change should be for wherever HA is running on (probably linux), not where your client is.

Ah i’m sorry. I did not double check if the code is formatted correctly.
I’ve updatet the code so it does not use the join-command anymore (directly inserted the path to the signal-cli).

But now I’ve got a different sort of problem:
When using the service “notify.signalmessenger” with the data {“message”:“Hello World”} it always says “Error calling service notify/signalmessenger. Signal Error 1: ‘b’User is not registered.\n’’”

Here is the snippet from my configuration.yaml.

notify:

  • name: SignalMessenger
    platform: signalmessenger
    sender_nr: “+4912345”
    recp_nr: “+4912345”
    signal_cli_path: /opt/signal-cli-0.6.2/bin

I’ve updated the notify.py snippet in my last post to the actual version.

Any ideas where this error comes from?

The listDevices command and my desktop client both say that the number is validated.
Using the signal-cli from command line works without problems.

Are you using the signal-cli as the same user that home assistant is run under?

A good troubleshooting method I found is to temporarily insert a

_LOGGER.error("Running signal-cli as: [%s]" % ' '.join(mainargs))

right above

p = subprocess.Popen(mainargs, stdout=subprocess.PIPE, stderr=subprocess.PIPE)

and then try to run the same command as the homeassistant user. My suspicion is that you have a similar problem as @jpduhen, so I would try his post above. Particularly, the following:

sudo su -s /bin/bash homeassistant
/home/homeassistant/.homeassistant/signal-cli-0.6.2/bin/signal-cli -u +4912345 send +4912345 -m "Hello world from command line"

Note that signal-cli registration is linux user-dependent, as it stores all information under each user’s home directory. You can probably simply copy the signal-cli directory from your working user to the homeassistant user as a test if the above doesn’t work (but I’ve never tried it so I can’t verify that’ll work).