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.