[sip/asterisk] Une classe pour écrire des applications AGI
This commit is contained in:
parent
8b724825bc
commit
8ce6d5d4e8
1 changed files with 114 additions and 2 deletions
116
sip/asterisk.py
116
sip/asterisk.py
|
@ -10,7 +10,9 @@ import shutil
|
|||
import syslog
|
||||
import socket
|
||||
import base64
|
||||
import syslog
|
||||
import psycopg2
|
||||
import threading
|
||||
import psycopg2.extras
|
||||
from datetime import datetime
|
||||
|
||||
|
@ -202,7 +204,7 @@ class History(object):
|
|||
|
||||
class Manager(object):
|
||||
|
||||
def __init__(self, username, password, timeout=10, server='asterisk.adm.crans.org', port=5038, debug=False, event=False, auto_connect=True):
|
||||
def __init__(self, username, password, timeout=10, server='asterisk.adm.crans.org', port=5038, debug=False, event=False, auto_connect=True, agi=None):
|
||||
self.timeout = timeout
|
||||
self.server = server
|
||||
self.port = port
|
||||
|
@ -214,6 +216,7 @@ class Manager(object):
|
|||
self._event=[]
|
||||
self._event_callback = {}
|
||||
self._toread = ""
|
||||
self._agi = agi
|
||||
self.fullybooted = False
|
||||
|
||||
self.username = username
|
||||
|
@ -223,6 +226,11 @@ class Manager(object):
|
|||
if auto_connect:
|
||||
self.connect()
|
||||
|
||||
def agi(self, *args, **kwargs):
|
||||
if not self._agi:
|
||||
self._agi = AGI(*args, manager=self, **kwargs)
|
||||
return self._agi
|
||||
|
||||
def _FullyBooted(self, manager, params):
|
||||
manager.fullybooted = True
|
||||
|
||||
|
@ -246,7 +254,7 @@ class Manager(object):
|
|||
def _parse_msg(self, msg):
|
||||
msg = msg.strip().split('\r\n')
|
||||
type, value = msg[0].split(': ', 1)
|
||||
params = dict([line.split(': ', 1) for line in msg[1:]])
|
||||
params = dict([line.split(': ', 1) if len(line.split(': ', 1))==2 else (line.split(': ', 1)[0], '') for line in msg[1:]])
|
||||
handler = getattr(self, "_do_"+type, None)
|
||||
handler(value, params)
|
||||
|
||||
|
@ -339,6 +347,10 @@ class Manager(object):
|
|||
raise EnvironmentError("%r should be a list or a bool" % param)
|
||||
return self.action('events', eventmask=eventmask)
|
||||
|
||||
def hangup(self, channel):
|
||||
"""Hangup a channel"""
|
||||
return self.action('hangup', channel=channel)
|
||||
|
||||
def reload(self, module):
|
||||
"""Synopsis: Send a reload event
|
||||
Privilege: system,config,all"""
|
||||
|
@ -351,3 +363,103 @@ class Manager(object):
|
|||
if body_type == "str":
|
||||
body = base64.b64encode(body).strip()
|
||||
return self._action('messageSend', {'to':dst, 'from':src, 'base64body':body})
|
||||
|
||||
|
||||
|
||||
class AGI(object):
|
||||
"""voir http://www.voip-info.org/wiki/view/Asterisk+AGI"""
|
||||
def __init__(self, read=sys.stdin, write=sys.stdout, manager=None, **params):
|
||||
self.debug = True
|
||||
self.read=read
|
||||
self.write=write
|
||||
self.params=params
|
||||
self._manager=manager
|
||||
self._lock=False
|
||||
self._locklock = threading.Lock()
|
||||
|
||||
self._read_params()
|
||||
|
||||
def manager(self, *args, **kwargs):
|
||||
if not self._manager:
|
||||
self._manager=Manager(*args, agi=self, **kwargs)
|
||||
return self._manager
|
||||
|
||||
def __getitem__(self, key):
|
||||
try:
|
||||
return self.params[key]
|
||||
except KeyError:
|
||||
(result, data) = self.command("GET VARIABLE", key)
|
||||
if int(result) != 1:
|
||||
raise KeyError(key)
|
||||
return data[1:-2]
|
||||
|
||||
def __setitem__(self, key, value):
|
||||
if key in self.params.keys():
|
||||
raise ValueError("ReadOnly value")
|
||||
else:
|
||||
(result, data) = self.command("SET VARIABLE", key, value)
|
||||
return result
|
||||
|
||||
def _read_params(self):
|
||||
line=self.read.readline()
|
||||
while line.strip():
|
||||
syslog.syslog(line)
|
||||
if line.startswith('agi_'):
|
||||
(key, data) = line[4:].split(':',1)
|
||||
self.params[key.strip()]=data.strip()
|
||||
line = self.read.readline()
|
||||
|
||||
def command(self, name, *params):
|
||||
with self._locklock:
|
||||
if self._lock:
|
||||
raise AsteriskError("Cannot lauch AGI command %s, an other command is processing" % name, name, params)
|
||||
else:
|
||||
self._lock = True
|
||||
cmd=' '.join([name] + ["%s" % p for p in params])
|
||||
if self.debug:
|
||||
syslog.syslog("%s\n" % cmd)
|
||||
self.write.write("%s\n" % cmd)
|
||||
self.write.flush()
|
||||
line=self.read.readline()
|
||||
if self.debug:
|
||||
syslog.syslog(line)
|
||||
lines=[line]
|
||||
code=int(line[0:3])
|
||||
type=line[3]
|
||||
if type == '-':
|
||||
while not "%s End of " % code not in line:
|
||||
line=self.read.readline()
|
||||
if self.debug:
|
||||
syslog.syslog("%s\n" % cmd)
|
||||
lines.append(line)
|
||||
|
||||
self._lock=False
|
||||
if code != 200:
|
||||
raise AsteriskError((code, '\n'.join(lines)), name, params)
|
||||
|
||||
try:
|
||||
(result, data) = lines[0][4:].split(' ', 1)
|
||||
except ValueError:
|
||||
result = lines[0][4:]
|
||||
data=""
|
||||
result=result.split('=',1)[1].strip()
|
||||
return (int(result), data)
|
||||
|
||||
def hangup(self):
|
||||
self.command("hangup")
|
||||
def set_callerid(self, callerid):
|
||||
self.command("set_callerid", callerid)
|
||||
def noop(self, str):
|
||||
self.command("noop", str)
|
||||
def launch_app(self, app, *params):
|
||||
self.command("exec", app, *params)
|
||||
def dial(self, to):
|
||||
self.launch_app("dial", to)
|
||||
def goto(self, arg):
|
||||
self.launch_app("goto", arg)
|
||||
|
||||
|
||||
### TODO
|
||||
class FastAGI(object):
|
||||
def __init__(self, bind, port, *args,**kwargs):
|
||||
pass
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue