Asterisk in Home Assistant – Part 1

The birth of the Home Assistant asterisk plugin

I have been poking around with “Home Assistant” for some time. It seems like a very strong platform to host my home automations. I have also been using Asterisk/Freepbx for a long time and suddently got the idea of having my Philips Hue lightbulbs flash when my phone rings. This is my thought process of getting to that goal.

I have never programmed Python, so the learning curve was a little steep. Lucily I have some experience from C#, C++, Perl and PHP, that made it quite easy to get the basic hang of the language. Python seems to be the best way to interact with Home Assistant.

In this three-part story I will show a finished, homemade plugin for Home Assistant, that will get the status of my phones (if they are online, busy, talking or ringing). This can be used for any kind of automation, like turning down the volume on the sonos when the phone rings.

Talking to asterisk via API.

The first part i needed to figure out was how to talk to my Asterisk/Freepbx installation. It seems to be standard that Freepbx internally talks to Asterisk via AMI (Asterisk manager interface). The AMI is default listening on port 5038. I had a look in /etc/asterisk/manager.conf on my Asterisk server:

[general]
enabled = yes
port = 5038
bindaddr = 0.0.0.0
displayconnects=no ;only effects 1.6+

[admin]
secret = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
permit=127.0.0.1/255.255.255.0 192.168.0.0/255.255.0.0
#deny=0.0.0.0/0.0.0.0
read = system,call,log,verbose,command,agent,user,config,command,dtmf,reporting,cdr,dialplan,originate,message
write = system,call,log,verbose,command,agent,user,config,command,dtmf,reporting,cdr,dialplan,originate,message
writetimeout = 5000

I noticed the deny rule and commented it out, because I wanted to contact my Asterisk from my Home Assistant server. I will be controlling access more granuarly with firewall rules.

Testing access to Asterisk

From my home assistant server I did a telnet to my Asterisk server on port 5038 and I sent this:

Action: Login
Username: admin
Secret: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

and got this response:

Response: Success
Message: Authentication accepted

Event: FullyBooted
Privilege: system,all
Status: Fully Booted

That shows me that I can communicate without problems.

Using python to talk to Asterisk

Instead of reinventing the wheel, I started searching for a python library for interacting via the AMI interface.  I found PYST2, which unfortunately was quite under-documented. That kind of forced me to start reading and understanding python code. I looked here:

Pyst2: https://pypi.python.org/pypi/pyst2

Pyst2 code: https://github.com/rdegges/pyst2/blob/master/asterisk/manager.py

First i needed to install the library:

pip3 install pyst2

Then I made the smallest possible program that would allow me to get events from asterisk and to send commands to it:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
import time
import asterisk.manager

def handle_event(event, manager):
    print ("Event name:i {}".format(event.name))
    if event.name=="ExtensionStatus":
        print ("  Extension: {}". format(event.get_header('Exten')))
        print ("  Status: {}". format(event.get_header('StatusText')))

manager = asterisk.manager.Manager()
manager.connect('192.168.xxx.xxx')
manager.login('admin', 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx')
manager.register_event('*', handle_event)

extension = 1000
result=manager.extension_state(extension, "default")
print ( "Current status of extension {} is {}".format ( extension, result.get_header("StatusText") ) )

print ( "Enless loop waiting for events..." )
time.sleep(10000)

In line 4 I define an eventhandler that will handle whenever events are received from AMI. The handler is registred in line 13 after connecting to Asterisk.

In line 15-17 I query Asterisk for the status of an extension. This is a manual poll of the status.

In the end of the program i go into en endless loop (almost), and wait for incoming messages from AMI. I made a few phone calls and could follow the status going from Idle to Ringing to InUse.

What do I have now?

Now I have the parts of code and configuration I need to integrate Asterisk into my Home Assistant. In part 2 I will make the actual plugin code with some comments.

Part 2

Leave a Reply

Your email address will not be published. Required fields are marked *