Use Signal Messenger for Notifications

Does it have better features then Telegram?

I will check that, thank you :)!

Thanks for the great idea.

I’ve been a big fan of Signal but am just getting started with Home Assistant on my Raspberry Pi.

I’m a little confused about the directory structure required for the notification python function.

In this thread I see that the python script is either in <config dir>/custom_components/notify/signalmessenger.py or <config dir>/components/signalmessenger/notify.py

I’ve tried both but my HA instance continues to complain that:

3   2019-06-16 19:49:57 ERROR (MainThread) [homeassistant.setup] Setup failed for signalmessenger: Integration not found.                                                       │

where my configuration.yaml has:

notify:
  - name: signal
    platform: signalmessenger
    sender_nr: "number"
    recp_nr: "number"                                                                                                                                   
    signal_cli_path: /usr/local/bin/signal-cli                                                                                                                          

I’ve been trying to follow the setup described here but it’s a little confusing about the relationship between the directories, domain name, and services.

Any help would be appreciated. Thanks

EDIT: I’m looking at the Matrix notification bot and it seems we need additional structure/setup code. For example a setup function is required?

I have the same problem as @skulumani, or similar. I get

"Failed to call service notify/signal_test. Service not found."

…when I try to call my defined notify service

I’m trying to install the script to the same two location as you tried. I actually get no mention of “signalmessenger” if I don’t also add

signalmessenger:

to the configuration.yaml file. If I do, I get this in the logs:

2019-06-18 19:29:47 ERROR (MainThread) [homeassistant.setup] Setup failed for signalmessenger: Integration not found.

I’m running HA version 0.94.3 installed from pip in a docker container, and signal-cli works perfectly when I test it from the command line. I also tried all versions of the script from this thread and neither of them worked. Did something change in HA regarding how it handles these modules? I also tried to manually add the file to /usr/local/lib/python3.7/dist-packages/homeassistant/components/notify/ to see if that helps, it didn’t change anything.

Okay cool. I think this integration requires more framework for Homeassistant to treat it as another component, which is why it fails to load.

I’m working on this as I learn more about home assistant. I’ll try to create a full package that can be added.

2 Likes

Okay, I figured out how to just make it work with minimal modifications. I used @sehaas (thanks!) version because it supports attachments, but I had to make two fixes in the code:

45c45
<     if not (recp_nr is None ^ group is None):
---
>     if not ((recp_nr is None) ^ (group is None)):
76c76
<             mainargs.extend(self.recp_nr)
---
>             mainargs.extend([self.recp_nr])

So, the solution for actually making the custom_component work is to add an __init__.py file in the folder and to avoid setup error messages, a setup function that returns True.

The test payload I tried was (of course the image existed on my computer – it won’t send anything if the file doesn’t exist):

{"message": "foo bar", "data": {"attachments": "/config/www/images/bath-active.png"}}

Here’s a complete version of what works for me at version 0.94.3 of Home Assistant:

Add this to configuration.yaml (of course adjust the signal_cli_path and signal_conf_path variables according to where you have them):

signalmessenger:

notify:
  - name: signal_test
    platform: signalmessenger
    sender_nr: '<mysender-number>'
    recp_nr: '<myrecipient-number>'
    signal_cli_path: /opt/signal-cli/bin
    signal_conf_path: /config/.signal-cli

__init__.py:

"""Signal Messenger integration using signal-cli.
Place this in `<confdir>/custom_components/signalmessenger/__init__.py`
"""

def setup(hass, config):
    return True

notify.py, including the two fixes above (it is actually important to call it notify.py, otherwise the notify integration won’t be picked up by HA):

"""
Signal Messenger for notify component.
Place this in `<confdir>/custom_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))

After this you should see the notify.<whatever_you_named_it> in the list of services on the Home Assistant web interface. If it’s not there, check the logs for mentions of signalmessenger.

2 Likes

That’s awesome! I’ll try it out tonight as well.

Thanks for the reply and debugging!

Hey @sehaas,

I just started using HA in docker but am not able to use signal-cli any more in this environment.

On my host system I can send signal messages via signal-cli and before I switched to docker, I was also able to send signal messages via HA.

What I did was to mount signal_cli_path, signal_conf_path and /usr/lib/jvm/default-java/bin but HA gives me the following error when I try to send a signal message via HA:

    output b "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
    Please set the JAVA_HOME variable in your environment to match the location of your Java installation." - err b''

I have not much experience with docker. Could you explain a bit more in detail how you mounted signal-cli, JRE and the data folder as volumes?

Hey @s0n1c-hedgehog,
I mount a single volume under /signal-cli, which looks something like this:

  • java-latest/ => an extracted AdoptOpenJDK version
  • signal-cli-latest/ => current signal-cli version
  • data/ => the signal-cli config and data storage

The JAVA_HOME is set in my docker-compose.yml:

environment:
      - JAVA_HOME=/signal-cli/java-latest

I think you have to mount more than only the bin folder.

@attila_ha you are right, I made the same modifications for current HA versions, but I didn’t update my post. An empty __init__.py with an manifest.json file worked for me.

Thank you, @sehaas,

I got it working now :slight_smile:

@sehaas As I am new to docker, could you help me to ‘mount’ the three parts mentioned and where I can find the yml-file to modify?

Would this work in Hassio? Or is that not possible because of the Resin-OS it is based on?

1 Like

Is this compatible with a hassio install on a generic Linux host?

Raspbian stretch

And Debian stretch?

Doesn’t fit on a raspberry ;-), but as far as I know it’s based on Debian

This would make a killer hassio addon :exploding_head:

2 Likes

I am working on it: https://github.com/agileek/hassio-addons

3 Likes

Great @mbitard!

Looking forward to test your alpha/beta/final :heart_eyes: and help debugging if needed :blush:

Just out of curiosity: Would their be any way (theoretically in the signal implementation) to also receive messages in home assistant?

1 Like

Yes of course it’s possible I have a working POC on my machine.

Right now I’m only working on sending message from home assistant to a user, but once it’s done I think it’ll be quite simple to do the other way around.

If someone want to try it, install the addon, (It assumes you already have a .signal folder in your config directory) and, from another addon (like the ssh addon), you can try it with curl http://4a36bbd1-signal:5000/message --request POST --data '{"number":"+yourphonenumber","content":"tralalayoupi"}' --header "Content-Type: application/json"

2 Likes

Actually I don’t have any .signal folder (yet). Do you plan a easier onboarding/configuriaton/setup with the hassio addon in the future?