Home Assistant SIP Gateway

Currently this add-on can only react on things that can trigger an automation. With pjsip running inside the add-on you have a full sip stack and it would be possible to do that. Not on my agenda right now, but if you want to get your hands dirty I’m open to pull requests.

This is possible now (without the video part).

This add-on is great. However, I only hear fax-like noises when playing a message.
I’m not sure I’m doing this the right way. Here is what I tried.

sip:
  registrar_uri: sip:fritz.box
  port: 5060
  id_uri: sip:[email protected]
  realm: '*'
  user_name: homeassistant
  password: **********
tts:
  platform: google_translate
tts:
  platform: tts
tts:
  platform: cloud_say

tts:
  platform: tts.cloud_say

I cannot find a sample-configuration in your readme.

This is how I call the service in devtools:

service: hassio.addon_stdin
data: 
  addon: c7744bff_ha-sip
  input:
    command: dial
    number: sip:+************@fritz.box
    menu:
      message: "There's a burglar in da house."

This is the error:

Logger: aiohttp.server
Source: components/tts/__init__.py:331
First occurred: 09:29:28 (3 occurrences)
Last logged: 09:41:29

Error handling request
Traceback (most recent call last):
  File "/usr/local/lib/python3.9/site-packages/aiohttp/web_protocol.py", line 422, in _handle_request
    resp = await self._request_handler(request)
  File "/usr/local/lib/python3.9/site-packages/aiohttp/web_app.py", line 499, in _handle
    resp = await handler(request)
  File "/usr/local/lib/python3.9/site-packages/aiohttp/web_middlewares.py", line 119, in impl
    return await handler(request)
  File "/usr/src/homeassistant/homeassistant/components/http/security_filter.py", line 60, in security_filter_middleware
    return await handler(request)
  File "/usr/src/homeassistant/homeassistant/components/http/forwarded.py", line 98, in forwarded_middleware
    return await handler(request)
  File "/usr/src/homeassistant/homeassistant/components/http/request_context.py", line 24, in request_context_middleware
    return await handler(request)
  File "/usr/src/homeassistant/homeassistant/components/http/ban.py", line 78, in ban_middleware
    return await handler(request)
  File "/usr/src/homeassistant/homeassistant/components/http/auth.py", line 138, in auth_middleware
    return await handler(request)
  File "/usr/src/homeassistant/homeassistant/components/http/view.py", line 135, in handle
    result = await result
  File "/usr/src/homeassistant/homeassistant/components/tts/__init__.py", line 612, in post
    path = await self.tts.async_get_url_path(
  File "/usr/src/homeassistant/homeassistant/components/tts/__init__.py", line 331, in async_get_url_path
    provider = self.providers[engine]
KeyError: 'tts'

The call is successfully made. But when I pick up I only hear noises that remind me of old times (modem-internet) :smiley:
It seems the tts service is not configured correctly.

Any ideas?

Probably you did not configure the tts service in your configuration.yaml.

Please check if you have a tts section like

tts:
  - platform: google_translate

in there. More information on that is available at Text-to-Speech (TTS) - Home Assistant

For the configuration of the add-on your first (and default) config option is correct.

Let me know if that helped!

Hi Seanomat,

I had exact the same issue and got it fixed with this configuration:

tts:
  - platform: google_translate
    language: "de"
    cache: true
    cache_dir: /tmp/tts
    time_memory: 120
    base_url: http://192.168.xxx.xxx:8123
    service_name: google_say

Maybe it works for you too.

1 Like

Yes this worked. Thank you both.
I change to cloud_say a long time ago, and didn’t have google_translate configured anymore.

@seanomat Then this actually could be a bug in the add-on.

Google tts is producing mp3 files which need to be converted to wave files in order to play them through pjsip. Do you know if cloud_say also is creating mp3 files? If it does, maybe the conversion to wave is going wrong.

Could you send me one of the cached mp3 files so I could check if the conversion is creating the modem sound?

To be honest, I’m not quite sure how cloud_say works. It’s not an integration that is configured anywhere. It’s just there.
But you have to pass several parameters when you call the service, like language, voice, media-player and cache (true/false). So I guess it could cache the .mp3s but I have no idea where.

I suppose this is not suited for your add-on.

This sounds like a great add-on. Has anyone been able to integrate this with freepbx? I seem be hitting a registration timeout error and I’m not sure my configuration is correct.

Hi!

I haven’t been able to install it on my RPI3 with Home Assistant OS 6.6 and core-2021.12.7
It seems the device hangs and restarts after a while (2 hours, maybe). According to the Supervisor logs the ha-sip started building when instructed. For some reason the current supervisor logs don’t show information from that time.

All I can find in the home-assistant.log file is this:

[supervisor.misc.tasks] Watchdog found a problem with Home Assistant Docker!

and from the home-assistant.log.1 file:

Failed to to call /addons/c7744bff_ha-sip/start - Image c7744bff/aarch64-addon-ha-sip:1.3 does not exist for addon
-sip

Could it be that the RPi3 does not have enough memory to build what it is instructed to do on the Dockerfile?

I have tried several times to do this, but I haven’t been able to catch something else as the logs are overwritten. But I seem to recall from the other night something about the make command issuing an error, but I’m not sure about it.

Any help is appreciated.

Thank you

EDIT:
For some reason, now there is new info on the Supervisor log that seems related to the add-on.

mkdir -p /usr/local/include/
for d in pjlib pjlib-util pjnath pjmedia pjsip; do \
	cp -RLf $d/include/* /usr/local/include/; \
done
mkdir -p /usr/local/lib/pkgconfig
sed -e "s!@PREFIX@!/usr/local!" libpjproject.pc.in | \
	sed -e "s!@INCLUDEDIR@!/usr/local/include!" | \
	sed -e "s!@LIBDIR@!/usr/local/lib!" | \
	sed -e "s/@PJ_VERSION@/2.11-dev/" | \
	sed -e "s!@PJ_INSTALL_LDFLAGS@!-L/usr/local/lib -lpjsua2 -lstdc++ -lpjsua -lpjsip-ua -lpjsip-simple -lpjsip -lpjmedia-codec -lpjmedia -lpjmedia-videodev -lpjmedia-audiodev -lpjmedia -lpjnath -lpjlib-util -lpj!" | \
	sed -e "s!@PJ_INSTALL_LDFLAGS_PRIVATE@!-lsrtp -lresample -lgsmcodec -lspeex -lilbccodec -lg7221codec -lyuv  -L/lib -lm -lrt -lpthread  !" | \
	sed -e "s!@PJ_INSTALL_CFLAGS@!-I/usr/local/include -DPJ_AUTOCONF=1  -DPJ_IS_BIG_ENDIAN=0 -DPJ_IS_LITTLE_ENDIAN=1!" > /usr/local/lib/pkgconfig/libpjproject.pc
+ cd pjsip-apps/src/swig

+ make python

make  --no-print-directory -C python
swig -I../../../../pjlib/include -I../../../../pjlib-util/include -I../../../../pjmedia/include -I../../../../pjsip/include -I../../../../pjnath/include -c++  -w312  -python -o pjsua2_wrap.cpp ../pjsua2.i
python3 setup.py build 
running build
running build_py
creating build
creating build/lib.linux-aarch64-3.9
copying pjsua2.py -> build/lib.linux-aarch64-3.9
running build_ext
building '_pjsua2' extension
creating build/temp.linux-aarch64-3.9
aarch64-linux-gnu-gcc -pthread -Wno-unused-result -Wsign-compare -DNDEBUG -g -fwrapv -O2 -Wall -g -ffile-prefix-map=/build/python3.9-PN012d/python3.9-3.9.2=. -fstack-protector-strong -Wformat -Werror=format-security -g -fwrapv -O2 -g -ffile-prefix-map=/build/python3.9-PN012d/python3.9-3.9.2=. -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -fPIC -I/usr/include/python3.9 -c pjsua2_wrap.cpp -o build/temp.linux-aarch64-3.9/pjsua2_wrap.o -g -O2 -DPJ_AUTOCONF=1 -I/include -O2 -DPJ_IS_BIG_ENDIAN=0 -DPJ_IS_LITTLE_ENDIAN=1 -fPIC -DPJMEDIA_USE_OLD_FFMPEG=1 -DPJMEDIA_USE_OLD_FFMPEG=1 -I/pjproject/pjlib/include -I/pjproject/pjlib-util/include -I/pjproject/pjnath/include -I/pjproject/pjmedia/include -I/pjproject/pjsip/include
aarch64-linux-gnu-gcc: fatal error: Killed signal terminated program cc1plus
compilation terminated.
error: command '/usr/bin/aarch64-linux-gnu-gcc' failed with exit code 1
make[1]: *** [Makefile:37: _pjsua2.so] Error 1
make: *** [Makefile:29: python] Error 2

Removing intermediate container e2e6b6420f31

22-01-04 12:20:55 ERROR (MainThread) [asyncio] Task exception was never retrieved
future: <Task finished name='Task-18240' coro=<AddonManager.install() done, defined at /usr/src/supervisor/supervisor/jobs/decorator.py:71> exception=AddonsError()>
Traceback (most recent call last):
  File "/usr/src/supervisor/supervisor/docker/addon.py", line 522, in _build
    image, log = self.sys_docker.images.build(
  File "/usr/local/lib/python3.9/site-packages/docker/models/images.py", line 285, in build
    raise BuildError(chunk['error'], result_stream)
docker.errors.BuildError: The command '/bin/bash -o pipefail -c set -xe     && git clone https://github.com/pjsip/pjproject.git     && cd pjproject     && git reset --hard 4dc183bf373535a9cb37ed6f2cc6b510bdb3901b     && ./configure --enable-shared --disable-libwebrtc     && make     && make dep     && make install     && cd pjsip-apps/src/swig     && make python     && make -C python install     && ldconfig' returned a non-zero code: 2
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
  File "/usr/src/supervisor/supervisor/addons/__init__.py", line 181, in install
    await addon.instance.install(store.version, store.image)
  File "/usr/src/supervisor/supervisor/utils/__init__.py", line 33, in wrap_api
    return await method(api, *args, **kwargs)
  File "/usr/local/lib/python3.9/concurrent/futures/thread.py", line 58, in run
    result = self.fn(*self.args, **self.kwargs)
  File "/usr/src/supervisor/supervisor/docker/addon.py", line 506, in _install
    self._build(version)
  File "/usr/src/supervisor/supervisor/docker/addon.py", line 542, in _build
    raise DockerError() from err
supervisor.exceptions.DockerError
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
  File "/usr/src/supervisor/supervisor/jobs/decorator.py", line 108, in wrapper
    raise err
  File "/usr/src/supervisor/supervisor/jobs/decorator.py", line 106, in wrapper
    return await self._method(*args, **kwargs)
  File "/usr/src/supervisor/supervisor/addons/__init__.py", line 184, in install
    raise AddonsError() from err
supervisor.exceptions.AddonsError

hello is this work with all sip numbers inside FreePBX ?

Hi. First of all thanks for sharing. But i have a problem. I cannot install it over the configuration → Home Assistant addons by Arne Gellhaus ->ha-sip. If i press install, it takes forever. Is there any logfile?

Hi Brainjay,

you can look into the supervisor log of your home assistant os installation. The installation itself can take quite some time, as pjsip is compiled on the device. I had some reports, that the installation does not work on devices with little memory. I personally use a raspi4 with 2GB of RAM. What device are you trying to install the add-on on?

1 Like

Hi Arnonym,

thanks for the fast response. I also have a respi with 2GB of RAM. Finally it took about 20 minutes to install your plugin. I’m eger to test it now with my 2n ip verso door bell. Hope it works with it and my fritzbox 7590

I made version 1.4 of the add-on available which

  1. comes with pre-compiled images to allow usage on devices on which the compilation was not possible before
  2. can react on incoming calls (call will not picked up, but will start an automation where you have the caller id available).
  3. has an icon now :slight_smile:

I tried your config in my ha-sip configuration, but still don’t hear any message.
There was no tts in /tmp, so I created it with sudo mkdir tts, but there is still no change.
Any suggestion, what I might have missed?

Where did you put the cache_dir configuration option? In your configuration.yaml or the config of the add-on?

You need to have

tts:
  - platform: google_translate

in your configuration.yaml. I did not specify a cache_dir, so ha will use the default. I would also suggest to remove the tts directory from /tmp again, as this might be created with the wrong permissions.

If you have the specified configuration already in place I would suggest to look into the logs of the add-on to see if there are some errors.

Hi Arne,
thanks for your quick response.

I have this in my configuration.yaml (without the other stuff)

The full blown tts config I have in the ha-sip config (obviously a valid entry is mandatory using the UI):

platform: google_translate
language: de
cache: true
cache_dir: /tmp/tts
time_memory: 120
base_url: http://192.168.68.70:8123
service_name: google_say

my call looks like this and the call comes through perfectly:

service: hassio.addon_stdin
data:
  addon: my_ha-sip
  input:
    command: dial
    number: sip:[email protected]
    menu:
      message: >-
        Der Wasseralarm wurde ausgelöst und die Kaffeemaschine vorsichtshalber
        ausgeschaltet!

I also tried this with:

message: Der Wasseralarm wurde ausgelöst und die Kaffeemaschine vorsichtshalber
        ausgeschaltet!

and

message: "Der Wasseralarm wurde ausgelöst und die Kaffeemaschine vorsichtshalber
        ausgeschaltet!"

But on the call it keeps quiet.

Anything in the logs?

There is something wrong with TTS I suppose:

urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='myhost', port=443): Max retries exceeded with url: /api/tts_proxy/xxxx_-_google_translate.mp3 (Caused by NewConnectionError('<urllib3.connection.HTTPSConnection object at 0xAAAAAA>: Failed to establish a new connection: [Errno 113] No route to host'))

EDIT I:
So, I assume google does not find it’s way back?
Because I switched to Nabu Casa, I assume this needs to be set?

 base_url: https://Nabu.Casa:URL

?

EDIT II:
I can confirm that this was the issue.
Thanks for your help! :smiley:

I’ve just released version 2.0 of my add-on which

  • allows the dialing and hanging up of phone numbers through a SIP end-point
  • triggering of services through dial tones (DTMF) after the call was established.
  • listens for incoming calls and can trigger actions through a web-hook (the call is not picked up)
  • accepting calls (optionally filtered by number)
  • handle PIN input before triggering actions
  • send DTMF digits to an established call (incoming or outgoing)

Hope there’s something in it for you! Take a look at the docs at GitHub - arnonym/ha-plugins: Home-Assistant SIP Gateway for details.