Home Assistant SIP Gateway

Hello Arne, I use ha-sip to be called by ha when an alarm is triggered (water, fire or burglary).

This works great! Thanks for that!!

Now it has happened, that my cell phone had no reception and therefore I missed an alarm. I found the web hook call_established in your documentation. Could I use this to create an action that calls a second number if the first number wasn’t reached? If that works, how should I do it?

Best wishes Marcus

(I only recently switched from iobroker to ha and am therefore not very familiar with ha)

hoping someone can help me here to figure this out. I also have an open issue on the repo with the same question, but maybe there is an extra pair of eyes here which might just give the right insight.

My goal

To enable my kids to call parents and grandparents using the old analog rotary dial phone connected to a Grandstream HT801.

My devices currently used for testing

device id
HA SIP add-on **620
Granstream (with analog phone) **621
My mobile phone +316123456789

note: the mobile number is of course not my real number, but I didn’t seem very wise to share it publicly on GitHub :wink:

What I currently have

Based on my initial setup, and the comments already provided in the GitHub issue, I have now created a menu in which I call a script.
In the script I initiate the call to my mobile phone, and then after connection is established, I try to bridge audio with the HA SIP add on (which initiated the call) and the Granstream (and therefor the analog phone).

Automation with the menu

automation:
  - id: aef85bb7-d7c6-4727-84b7-c15f222d7f71
    alias: Menu for Grandstream
    trigger:
      - platform: webhook
        local_only: true
        webhook_id: sip_call_webhook_id
    condition: []
    action:
      - choose:
          - conditions: "{{ trigger.json.parsed_caller == '**621' }}"
            sequence:
              - service: hassio.addon_stdin
                data:
                  addon: c7744bff_ha-sip
                  input:
                    command: answer
                    number: "**621"
                    menu:
                      message:
                        Hallo, draai 1 om papa te bellen
                        om te stoppen.
                      timeout: 30
                      choices:
                        "1":
                          id: papa
                          message: Papa wordt gebeld
                          action:
                            domain: script
                            service: turn_on
                            entity_id: script.call_dad
                          post_action: noop
    mode: single

script which is called from the menu

script:
  call_dad:
    alias: Call dad
    mode: restart
    sequence:
      - service: hassio.addon_stdin
        data:
          addon: c7744bff_ha-sip
          input:
            command: dial
            number: sip:[email protected]
            ring_timeout: 60
            sip_account: 1
            webhook_to_call:
              call_established: sip_connect_call_bridge_621
              call_disconnected: sip_call_disconnected
      - wait_for_trigger:
          - platform: webhook
            local_only: true
            webhook_id: sip_connect_call_bridge_621
        timeout:
          minutes: 5
      - service: hassio.addon_stdin
        data:
          addon: c7744bff_ha-sip
          input:
            command: bridge_audio
            number: "**620"
            bridge_to: sip:**[email protected]

What happens during testing

what works

  • the menu works, and the it mentions that dad is being called
  • the call is initiated, my phone will ring and I can pick up the message
  • the script runs all it’s actions

what doesn’t work

  • audio isn’t bridged to the grandstream. So both parties can’t hear each other.

Log report (level 2)

looks like it’s truncated to 100 lines

| 22:28:12.572833 [1] Connected media 1
| 22:28:12.578578 [1] Call connecting...
| 22:28:12.593258 [1] Call connected
| 22:28:13.604314 [1] Call is established.
| 22:28:13.604507 [ ] Calling webhook sip_call_webhook_id with data {'event': 'call_established', 'caller': '"HA SIP" <sip:**[email protected]>', 'parsed_caller': '**621', 'sip_account': 1}
| 22:28:13.615879 [ ] Webhook response 200 b''
| 22:28:13.616201 [1] Playing message: Hallo, draai 1 om papa te bellen, 2 om mama te bellen en 3 om te stoppen.
| 22:28:13.639059 [ ] Getting audio from "http://192.168.2.3:8123/api/tts_proxy/0d6c71cb34afc69c8d79b3ab6420a184c9caf762_nl-nl_dd0e95eb04_cloud.mp3"
| 22:28:13.937746 [1] No action supplied
Could not deserialize JSON: "command":"answer","number":"**621","menu":{"message":"Hallo, draai 1 om papa te bellen, 2 om mama te bellen en 3 om te stoppen.","timeout":30,"choices":{"1":{"id":"papa","message":"Papa wordt gebeld","action":{"domain":"script","service":"turn_on","entity_id":"script.call_dad"},"post_action":"noop"}}}}
| 22:28:17.619169 [1] Playback interrupted.
| 22:28:17.619429 [1] Scheduled post action: noop
| 22:28:17.624295 [1] onDtmfDigit: digit 1
| 22:28:17.624406 [ ] Calling webhook sip_call_webhook_id with data {'event': 'dtmf_digit', 'caller': '"HA SIP" <sip:**[email protected]>', 'parsed_caller': '**621', 'digit': '1', 'sip_account': 1}
| 22:28:17.632121 [ ] Webhook response 200 b''
| 22:28:17.632292 [1] Current input: 1
| 22:28:17.632333 [ ] Calling webhook sip_call_webhook_id with data {'event': 'entered_menu', 'caller': '"HA SIP" <sip:**[email protected]>', 'parsed_caller': '**621', 'menu_id': 'papa', 'sip_account': 1}
| 22:28:17.644434 [ ] Webhook response 200 b''
| 22:28:17.644736 [1] Playing message: Papa wordt gebeld
| 22:28:17.656002 [ ] Getting audio from "http://192.168.2.3:8123/api/tts_proxy/9a1857f9f2a6f548df225dc970b507f01b95382f_nl-nl_dd0e95eb04_cloud.mp3"
| 22:28:17.760298 [ ] Calling home assistant service on domain script service turn_on with entity script.call_dad
| 22:28:17.778029 [ ] Service response 200 b'[{"entity_id":"script.call_dad","state":"on","attributes":{"last_triggered":"2024-01-13T21:28:17.770475+00:00","mode":"restart","current":1,"friendly_name":"Call dad"},"last_changed":"2024-01-13T21:28:17.770602+00:00","last_updated":"2024-01-13T21:28:17.770602+00:00","context":{"id":"01HM2BKF36HZEDHCJ5E17JDWRD","parent_id":null,"user_id":"5cca702da9834cdeacf34de267570551"}}]'
Could not deserialize JSON: "command":"answer","number":"**621","menu":{"message":"Hallo, draai 1 om papa te bellen, 2 om mama te bellen en 3 om te stoppen.","timeout":30,"choices":{"1":{"id":"papa","message":"Papa wordt gebeld","action":{"domain":"script","service":"turn_on","entity_id":"script.call_dad"},"post_action":"noop"}}}}
| 22:28:17.924123 [ ] Got "dial" command for sip:[email protected]
| &id001
| id: null
| message: null
| audio_file: null
| language: en
| action: null
| choices_are_pin: false
| choices: {}
| default_choice:
|   id: null
|   message: Unknown option
|   audio_file: null
|   language: en
|   action: null
|   choices_are_pin: false
|   choices: null
|   default_choice: null
|   timeout_choice: null
|   post_action:
|     action: return
|     level: 1
|   timeout: 300.0
|   parent_menu: *id001
| timeout_choice:
|   id: null
|   message: null
|   audio_file: null
|   language: en
|   action: null
|   choices_are_pin: false
|   choices: null
|   default_choice: null
|   timeout_choice: null
|   post_action:
|     action: hangup
|   timeout: 300.0
|   parent_menu: *id001
| post_action:
|   action: noop
| timeout: 300.0
| parent_menu: null
| 
| 22:28:17.926182 [1] Registering call with id sip:[email protected]
| 22:28:17.926220 [ ] Add to state: sip:[email protected]
| 22:28:17.929656 [1] Calling
| 22:28:17.979517 [1] Early
| 22:28:17.979773 [1] onCallMediaState call info state 3
| 22:28:17.979811 [1] Connected media 1
| 22:28:20.037095 [1] Playback done.
| 22:28:20.040290 [1] Scheduled post action: noop
| 22:28:25.884630 [1] Call connecting...
| 22:28:25.886520 [1] onCallMediaState call info state 4
| 22:28:25.886581 [1] Connected media 1
| 22:28:25.886704 [1] Call connected
| 22:28:25.898348 [1] onCallMediaState call info state 5
| 22:28:25.898452 [1] Connected media 1
| 22:28:26.903964 [1] Call is established.
| 22:28:26.904038 [ ] Calling webhook sip_connect_call_bridge_621 with data {'event': 'call_established', 'caller': 'sip:[email protected]', 'parsed_caller': '+31123456789', 'sip_account': 1}
| 22:28:26.910687 [ ] Webhook response 200 b''
| 22:28:26.910822 [ ] Calling webhook sip_call_webhook_id with data {'event': 'call_established', 'caller': 'sip:[email protected]', 'parsed_caller': '+31123456789', 'sip_account': 1}
| 22:28:26.922122 [ ] Webhook response 200 b''
| 22:28:26.922231 [1] No action supplied
| 22:28:26.922292 [1] Scheduled post action: noop
| 22:28:26.924052 [ ] Warning: call not in progress: **620
| 22:28:39.456700 [1] Call disconnected
| 22:28:39.456788 [ ] Calling webhook sip_call_disconnected with data {'event': 'call_disconnected', 'caller': 'sip:[email protected]', 'parsed_caller': '+31123456789', 'sip_account': 1}
| 22:28:39.464117 [ ] Webhook response 200 b''
| 22:28:39.464264 [ ] Calling webhook sip_call_webhook_id with data {'event': 'call_disconnected', 'caller': 'sip:[email protected]', 'parsed_caller': '+31123456789', 'sip_account': 1}
| 22:28:39.471151 [ ] Webhook response 200 b''
| 22:28:39.471295 [ ] Remove from state: sip:[email protected]
| 22:28:42.821003 [1] Call disconnected
| 22:28:42.821063 [ ] Calling webhook sip_call_webhook_id with data {'event': 'call_disconnected', 'caller': '"HA SIP" <sip:**[email protected]>', 'parsed_caller': '**621', 'sip_account': 1}
| 22:28:42.827213 [ ] Webhook response 200 b''
| 22:28:42.827404 [ ] Remove from state: **621
| 22:28:42.928156 [ ] Got "answer" command for **621
| 22:28:42.928208 [ ] Warning: call not in progress: **621

I found this project and I am very excited to implement it using the FreePBX system I already have running for quite some years right now. Especially in conjunction with an Akuvox R20a doorbell.

Unfortunately, I can’t get the configuration to work. I tried several options. I also verified that Home Assistant is in the same subnet, which is wasn’t at first. It now is.

At the moment this is my configuration:

port: 5061 # yes, this is correct
log_level: 5
name_server: ""

enabled: true
registrar_uri: sip:zzzzzz
id_uri: sip:"301"@zzzzzz
realm: "*"
user_name: "301"
password: xxxx
answer_mode: listen
settle_time: 1
incoming_call_file: ""

This is the log from HA-SIP:

s6-rc: info: service s6rc-oneshot-runner: starting
s6-rc: info: service s6rc-oneshot-runner successfully started
s6-rc: info: service fix-attrs: starting
s6-rc: info: service fix-attrs successfully started
s6-rc: info: service legacy-cont-init: starting
s6-rc: info: service legacy-cont-init successfully started
s6-rc: info: service legacy-services: starting
s6-rc: info: service legacy-services successfully started

The log file on FreePBX is not showing anything. It is not registering on the PBX.
I am running Home Assistant OS.

Since I am able to get every VoIP phone working with FreePBX, I thought this wouldn’t be any different. What is going wrong here?

Ofcourse after some more trying FreePBX said the extension was trying to register, but with the wrong password, AND, that it was trying on SIP instead of PJSIP. So after correcting the password and chaning the extension inside FreePBX to SIP, it now is registered on the PBX.

My assumption after reading here was that the extension should register as PJSIP. Did I misread this?

Together with some help on Github and Discord, I was able to create this menu using HA-SIP and an analogue phone connected to a Grandstream HT801

Background

I have 2 kids aged 3 and 5. I want them to be able to contact us, or their grandmothers themselves. So when I found out about HA-SIP and the possibilities, I decided to give it a go, and try to create a way to achieve this.

Used hardware

  • An old phone (in my case a Heemaf type 1955)
  • Grandstream HT801
  • Fritz!Box 7590
  • Home Assistant server

What I did

Connect everything

I already had the Grandstream and phone connected, and was using it to connect to Assist. However, this didn’t cover the use case described above.

As I also wanted my kids to be able to connect to external numbers, I purchased a number using a voip service (in my case using cheapconnect) and connected that to the Fritz!Box.

Make the calls

I created a menu using an automtion which is triggered when the phone is taken from the hook. The Grandstream automatically dials **620 which is the number assigned to Home Assistant in the Fritz!Box.
The automation checks if the right webhook is sent, and if the right phone is used, using the data sent with the webhook.

The menu options in the automation then call a script, which calls the number. I use only one script, since as of version 3.4 of HA-SIP, it allows to use service data. So the person to be called is sent as a variable.

For the person to be called is it checked if he (currently I only set this up for myself) is connected to the WiFI network, in that case the internal number is used, and the Fritz!Fon call will be used for the connection. Otherwise the external number is used.
As soon as the person picks up, HA-SIP bridges the number to the Granstream.

When either party hangs up, the other party is also disconnected. To achieve this the script listens to the webhooks in a repeat loop. If this is a disconnect webhook, it checks the number, and will disconnect the other one as well.

Added bonus

As an additional feature I added a menu option in which the kids can start a Spotify playlist on the Google Home speakers on the ground floor (where the phone is also located). For this a second script is added.

The automation & Scripts

The automation an scripts used can be found on my Github Repo

Some notes:

  • I had some issues using @fritz.box for HA-SIP, so therefor I use the ip address of the router (in my case I use @192.168.2.100)
  • The menu messages are in Dutch, but the rest is in English (aliases, variables, etc)
  • The automation and scripts have some user specific variables, eg internal numbers, extension for the SIP numbers, and the phonebooks). These are in the top level variables section. The script to make calls also has a variables section in the sequence, this should not be changed.
  • I have the external phone numbers stored in secrets.yaml but the format is like this: sip:[email protected]

Short video demonstration of connecting the phones, and disconnecting (YouTube link)

2 Likes

ha-sip is using pjsip internally. It does not matter which library is used by the server, as they all should speak sip. So both should work.

I’ve added a ring_timeout event, which you could use after a specified time to call a different number.

I can’t make it run!
It’s reverting setting to (my) initial one.
I have a yeastar s20 pbx and created an account/number for testing.
Any clue what to do?

I am trying to play an audio message when calling an extension. I can make a call using dial, but when I use the following, nothing happens.

service: hassio.addon_stdin
data:
    addon: c7744bff_ha-sip
    input:
        command: play_audio_file
        number: sip:**[email protected]
        audio_file: '/config/audio/welcome.mp3'

How should the yaml look like when I want to dial an extension and then play a specific mp3 file?

First of all, I have to say that I think the addon is just great, a big thank you goes to arnonym!

Everything is actually working… But:

How do I get an incoming call from my doorbell (Siedle) to be displayed in the Home Assistant and then accept it and send a DTMF tone to trigger the buzzer.

Outgoing goes via automation with the doorbell, call, delay 3 seconds and then send DTMF afterwards.

Does anyone have an automation script for incoming calls or another solution for me? I’ve already read through the documentation and the forum many times, maybe I’m just a bit blind!

To accept an incoming call based on the number: Generating dynamic Menus and messages on HA Entity State · Issue #86 · arnonym/ha-plugins · GitHub

You only need to change the action part.

1 Like

I have come a bit further on playing an audio file over sip.

I have an automation that makes a call. When the call is established, another automation is triggered by a webhook to play an audio file, but I can’t get any audio file to play.

This is the automation to make a call (which is working):

alias: Alarm triggered - geluid
sequence:
  - service: hassio.addon_stdin
    data:
      addon: c7744bff_ha-sip
      input:
        command: dial
        number: sip:[email protected]
        webhook_to_call_after_call_was_established: play_alarm_sound
mode: single
icon: mdi:home-sound-in-outline

This is the automation to play the audio file:

alias: Alarm - Play Alarm Sound
description: ""
trigger:
  - platform: webhook
    allowed_methods:
      - POST
    local_only: true
    webhook_id: play_alarm_sound
action:
  - service: hassio.addon_stdin
    data:
      addon: c7744bff_ha-sip
      input:
        command: play_audio_file
        number: sip:[email protected]
        audio_file: /media/alarm_sound.mp3
mode: single

This is the last message in the log:

--end msg--
17:04:55.256               stream.c  G722 codec used, remote samples per frame detected = 80
17:04:55.768     strm0x7f16527b5078 !VAD re-enabled
| 17:04:56.138078 [1] Call is established.
| 17:04:56.138548 [ ] Calling webhook play_alarm_sound with data {'event': 'call_established', 'caller': 'sip:[email protected]', 'parsed_caller': '201', 'sip_account': 1}
| 17:04:56.193151 [ ] Webhook response 200 b''
| 17:04:56.194664 [ ] Calling webhook sip_call_webhook_id with data {'event': 'call_established', 'caller': 'sip:[email protected]', 'parsed_caller': '201', 'sip_account': 1}
| 17:04:56.285826 [ ] Webhook response 200 b''
| 17:04:56.286777 [1] No action supplied
| 17:04:56.287423 [1] Scheduled post action: noop
| 17:04:56.297900 [1] Playing audio file: /media/alarm_sound.mp3
Error: could not find audio file: /media/alarm_sound.mp3

Appearantly the file cannot be found. In what folder is ha-sip looking for audio files?

I just found this on the Github page:
Note The audio files need to reside in your home-assistant config directory, as this is the only directory accessible inside the add-on.

Where is the config directory? For me on HA Core it is /homeassistant/. In there I created a folder alarm_sounds. The automation looks like this now and it works:

addon: c7744bff_ha-sip
input:
  command: play_audio_file
  number: sip:[email protected]
  audio_file: /config/alarm_sounds/alarm_sound_2.wav

This explains how the mapping happens…

You’re looking for the addon config folder for the HA sip gateway addon.

Thank you so much for sharing this add-on! I believe I’m very close to integrating my building intercom into HA, a big win for smart homes everywhere!

I’m running into a final hurdle: the door unlock. I live in a condo building and have an integrated Wifi doorbell/buzzer that connects to the VDPConnect SIP. I’ve successfully (with a lot of troubleshooting) deployed the HA-SIP add-on and connected it to my unit - I learned the difference between a “user ID” and “home ID” along the way. I can issue the “dial” and “hangup” commands and can see the unit light up when doing so (showing that I’m connected, as I would if I accessed it through the app), but am looking for a final command in-between: “open”, to trigger the front door opening/buzzing.

I experimented with the send_dtmf command issuing “#”, “*” and “1” but haven’t had luck. I can’t see the command that VDP Connect sends the hub to trigger an unlock, so I’m not sure if this is the right path forward. My building doesn’t have a number for the front door, just a FOB or key. Is there a standard dtmf command that should work here, or am I on the wrong trail?

Thanks in advance for any tips!

There isn’t a standard DTMF command to open doors. It fully depends on your intercom. It might also be something proprietary. The only thing you can try are the different methods to send DTMF commands:

service: hassio.addon_stdin
data:
    addon: c7744bff_ha-sip
    input:
        command: send_dtmf
        number: sip:**[email protected]
        digits: "123#"
        method: in_band # method can be "in_band" (default), "rfc2833" or "sip_info"

Hello @arnonym huge fan of this add-on. I was easily able to get it installed and running and calling my FPBX system.

However, there is an issue when trying to play a message. I have piper setup as my tts engine, but no matter how I configure the addon I get a 500 internal server error with the TTS. Here is the call stack:

| 16:28:43.852016 [ ] Calling webhook sip_call_webhook_id with data {'event': 'call_established', 'caller': 'sip:[email protected]', 'parsed_caller': '2002', 'sip_account': 1}
| 16:28:43.911708 [ ] Webhook response 200 b''
| 16:28:43.913191 [1] Playing message: test
| 16:28:43.963051 [ ] Error getting tts file 500 b'500: Internal Server Error'
16:28:43.964            pjsua_aud.c  Creating file player: /ha-sip/sound/answer.wav..
16:28:43.965           wav_player.c  .File player '/ha-sip/sound/answer.wav' created: samp.rate=44100, ch=1, bufsize=4KB, filesize=176KB
16:28:43.965            pjsua_aud.c  .Player created, id=0, slot=2
16:28:43.965            pjsua_aud.c  Conf connect: 2 --> 1
16:28:43.965           conference.c  .Port 2 (/ha-sip/sound/answer.wav) transmitting to port 1 (sip:[email protected])
| 16:28:43.966051 [1] No action supplied
| 16:28:45.976293 [1] Playback done.

Additionally here is my configuration:

sip_global:
  port: 5060
  log_level: 5
  name_server: ""
sip:
  enabled: true
  registrar_uri: sip:192.168.1.145
  id_uri: sip:[email protected]
  realm: "*"
  user_name: "2003"
  password: 550b8caef427e97449511a30de794d34
  answer_mode: listen
  settle_time: 1
  incoming_call_file: ""
sip_2:
  enabled: false
  registrar_uri: sip:fritz.box
  id_uri: sip:[email protected]
  realm: "*"
  user_name: anotheruser
  password: secret
  answer_mode: listen
  settle_time: 1
  incoming_call_file: ""
sip_3:
  enabled: false
  registrar_uri: sip:192.168.178.10
  id_uri: ""
  realm: "*"
  user_name: ""
  password: ""
  answer_mode: listen
  settle_time: 1
  incoming_call_file: ""
tts:
  platform: google_translate
  language: en
webhook:
  id: sip_call_webhook_id

Finally here is the automation I’m using:

service: hassio.addon_stdin
data:
  addon: c7744bff_ha-sip
  input:
    command: dial
    number: sip:[email protected]
    ring_timeout: 30
    sip_account: 1
    menu:
      message: test

Any help you can provide would be greatly appreciated. Thank you for all your hard work

Hello,
I’m facing the same prroblem!
Did you find a solution?

Hi Dirk, take a look at Error getting tts file 500 b'500: Internal Server Error' · Issue #98 · arnonym/ha-plugins · GitHub. Maybe you’re facing the same issue.

I’m also running Home Assistant Core and I would love to see this as a standalone docker container.

Hi all,
can someone help me to understand why I cannot place a call?

looks like it is trying but being rejected?
Thanks

23:19:18.013           pjsua_core.c  ..TX 446 bytes Request msg ACK/cseq=9324 (tdta0x7fc596c13888) to UDP 118.127.57.156:5060:
ACK sip:[email protected] SIP/2.0
Via: SIP/2.0/UDP 27.32.54.70:4507;rport;branch=z9hG4bKPjpk2dSIbWkLBGZF7wXiZjfkeNPJsaesQ8
Max-Forwards: 70
From: sip:[email protected];tag=JHOUsmlSj2dCsTf0L832j4MPXm0n0K6G
To: sip:[email protected];tag=e3a77d15d464ab182e7ba5a2128168a6-a93623b0
Call-ID: y3YNI-7LzlupY1FdHE8C1ozCzgq45f27
CSeq: 9324 ACK
Content-Length:  0


--end msg--
23:19:18.013          pjsua_media.c  .....Call 0: deinitializing media..
23:19:18.013          pjsua_media.c  ......
  [DISCONNECTED] To: sip:[email protected]
    Call time: 00h:00m:00s, 1st res in 126 ms, conn in 0ms
23:19:18.013          pjsua_media.c  ......Call 0: cleaning up provisional media, prov_med_cnt=1, med_cnt=0
23:19:18.013                icetp00  ......Stopping ICE, reason=media stop requested
23:19:18.013                icetp00  ......Destroying ICE session 0x7fc596ea65b8
23:19:18.013     srtp0x7fc596c955f0  ......Destroying SRTP transport
23:19:18.013                icetp00  ......Destroying ICE transport
23:19:18.013          ice_session.c  ......ICE session 0x7fc596ea65b8 destroyed
23:19:18.013                icetp00  ......ICE stream transport 0x7fc596c11348 destroyed
23:19:18.013                icetp00  ......ICE transport destroyed
23:19:18.013     srtp0x7fc596c955f0  ......SRTP transport destroyed
| 23:19:18.013914 [1] Call disconnected
| 23:19:18.013981 [ ] Calling webhook sip_call_webhook_id with data {'event': 'call_disconnected', 'caller': 'sip:[email protected]', 'parsed_caller': '6969', 'sip_account': 1}
| 23:19:18.020931 [ ] Webhook response 200 b''
| 23:19:18.021300 [ ] Remove from state: sip:[email protected]
23:19:19.022            pjsua_aud.c  Closing sound device after idle for 1 second(s)
23:19:19.022            pjsua_aud.c  .Closing null sound device..