[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 syslog
|
||||||
import socket
|
import socket
|
||||||
import base64
|
import base64
|
||||||
|
import syslog
|
||||||
import psycopg2
|
import psycopg2
|
||||||
|
import threading
|
||||||
import psycopg2.extras
|
import psycopg2.extras
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
|
@ -202,7 +204,7 @@ class History(object):
|
||||||
|
|
||||||
class Manager(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.timeout = timeout
|
||||||
self.server = server
|
self.server = server
|
||||||
self.port = port
|
self.port = port
|
||||||
|
@ -214,6 +216,7 @@ class Manager(object):
|
||||||
self._event=[]
|
self._event=[]
|
||||||
self._event_callback = {}
|
self._event_callback = {}
|
||||||
self._toread = ""
|
self._toread = ""
|
||||||
|
self._agi = agi
|
||||||
self.fullybooted = False
|
self.fullybooted = False
|
||||||
|
|
||||||
self.username = username
|
self.username = username
|
||||||
|
@ -223,6 +226,11 @@ class Manager(object):
|
||||||
if auto_connect:
|
if auto_connect:
|
||||||
self.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):
|
def _FullyBooted(self, manager, params):
|
||||||
manager.fullybooted = True
|
manager.fullybooted = True
|
||||||
|
|
||||||
|
@ -246,7 +254,7 @@ class Manager(object):
|
||||||
def _parse_msg(self, msg):
|
def _parse_msg(self, msg):
|
||||||
msg = msg.strip().split('\r\n')
|
msg = msg.strip().split('\r\n')
|
||||||
type, value = msg[0].split(': ', 1)
|
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 = getattr(self, "_do_"+type, None)
|
||||||
handler(value, params)
|
handler(value, params)
|
||||||
|
|
||||||
|
@ -339,6 +347,10 @@ class Manager(object):
|
||||||
raise EnvironmentError("%r should be a list or a bool" % param)
|
raise EnvironmentError("%r should be a list or a bool" % param)
|
||||||
return self.action('events', eventmask=eventmask)
|
return self.action('events', eventmask=eventmask)
|
||||||
|
|
||||||
|
def hangup(self, channel):
|
||||||
|
"""Hangup a channel"""
|
||||||
|
return self.action('hangup', channel=channel)
|
||||||
|
|
||||||
def reload(self, module):
|
def reload(self, module):
|
||||||
"""Synopsis: Send a reload event
|
"""Synopsis: Send a reload event
|
||||||
Privilege: system,config,all"""
|
Privilege: system,config,all"""
|
||||||
|
@ -351,3 +363,103 @@ class Manager(object):
|
||||||
if body_type == "str":
|
if body_type == "str":
|
||||||
body = base64.b64encode(body).strip()
|
body = base64.b64encode(body).strip()
|
||||||
return self._action('messageSend', {'to':dst, 'from':src, 'base64body':body})
|
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