SIP решения на основе библиотеки PJSIP
Pax (обсуждение | вклад) (Новая страница: «Иногда имеется необходимость реализовать какой нибудь дополнительный функционал для к…») |
Pax (обсуждение | вклад) |
||
Строка 10: | Строка 10: | ||
Пример сделан из примера к самой библиотеке. | Пример сделан из примера к самой библиотеке. | ||
− | < | + | <code> |
#coding=utf8 | #coding=utf8 | ||
# $Id: call.py 2171 2008-07-24 09:01:33Z bennylp $ | # $Id: call.py 2171 2008-07-24 09:01:33Z bennylp $ | ||
Строка 264: | Строка 264: | ||
lib = None | lib = None | ||
− | </ | + | </code> |
[[Категория:SIP]] | [[Категория:SIP]] | ||
[[Категория:М-200. Разработка]] | [[Категория:М-200. Разработка]] |
Версия 11:28, 24 декабря 2014
Иногда имеется необходимость реализовать какой нибудь дополнительный функционал для клиентов АТС М-200.С появлением IP телефонии стало возможно доставлять голосовую информацию как от пользователя, так и к пользователю.
Так как М-200 поддерживает протокол SIP есть интересная библиотека реализации SIP стека и Media интерфейса http://www.pjsip.org/. По мимо реализации библиотеки на классическом С, есть обертка для языка Python. PJSIP может работать по Linux, MAC, Linux платформами. Библиотека распространяется под лицензией GPLv2.
На сколько это просто, покажет следующий пример. Данный пример регистрируется на станции 192.168.5.48, под номером 7000 с паролем 7000. При входящем на себя вызове проигрывает мелодию из файла /ATS/SOUND/music0.wav, в предответном состоянии в разговорном играется мелодия из файла /ATS/SOUND/music1.wav. При исходящем вызове при ответе играет мелодию из файла /ATS/SOUND/music4.wav
Клавиша a - ответ, с - звонок на номер 100, h - положить трубку.
Пример сделан из примера к самой библиотеке.
- coding=utf8
- $Id: call.py 2171 2008-07-24 09:01:33Z bennylp $
-
- SIP call sample.
-
- Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
import sys
import pjsua as pj
import threading
LOG_LEVEL=0
current_call = None
- Logging callback
def log_cb(level, str, len):
print str,
- Callback to receive events from account
class MyAccountCallback(pj.AccountCallback):
def __init__(self, account=None):
pj.AccountCallback.__init__(self, account)
# уведомление о входящем вызове
def on_incoming_call(self, call):
global current_call
if current_call:
call.answer(486, "Busy")
return
print "Incoming call from ", call.info().remote_uri
print "Press 'a' to answer"
current_call = call
call_cb = callCallbackIn(current_call)
current_call.set_callback(call_cb)
# отвечаем call progressом
current_call.answer(183)
def wait(self):
self.sem = threading.Semaphore(0)
self.sem.acquire()
def on_reg_state(self):
if self.sem:
if self.account.info().reg_status >= 200:
self.sem.release()
- Сообщение от входящего вызова
class callCallbackIn(pj.CallCallback):
def __init__(self, call=None):
pj.CallCallback.__init__(self, call)
# уведомление об изменении состояния
def on_state(self):
global current_call
print "Call with", self.call.info().remote_uri,
print "is", self.call.info().state_text,
print "last code =", self.call.info().last_code,
print "(" + self.call.info().last_reason + ")"
# в предответном проключаем одну мелодию
if self.call.info().state == pj.CallState.EARLY:
call_slot = self.call.info().conf_slot
# создаем плеер wav файла
self.wav_player_id = pj.Lib.instance().create_player('/ATS/SOUND/music0.wav', loop=False)
self.wav_slot = pj.Lib.instance().player_get_slot(self.wav_player_id)
# проключаем канал плеера на разговор
pj.Lib.instance().conf_connect(self.wav_slot, call_slot)
# в разговорном подаем другую
if self.call.info().state == pj.CallState.CONFIRMED:
call_slot = self.call.info().conf_slot
# отключаем от музыки
pj.Lib.instance().conf_disconnect(self.wav_slot, call_slot)
# удаляем плеер
pj.Lib.instance().player_destroy(self.wav_player_id)
# создаем новый
self.wav_player_id = pj.Lib.instance().create_player('/ATS/SOUND/music1.wav', loop=False)
self.wav_slot = pj.Lib.instance().player_get_slot(self.wav_player_id)
# проключаем канал плеера на разговор
pj.Lib.instance().conf_connect(self.wav_slot, call_slot)
if self.call.info().state == pj.CallState.DISCONNECTED:
current_call = None
print 'Current call is', current_call
# уведомление об изменении состояния системы коммутации
def on_media_state(self):
if self.call.info().media_state == pj.MediaState.ACTIVE:
print "Media is now active"
else:
print "Media is inactive"
- Сообщение от исходящего вызова
class callCallbackOut(pj.CallCallback):
def __init__(self, call=None):
pj.CallCallback.__init__(self, call)
# уведомление об изменении состояния
def on_state(self):
global current_call
print "Call with", self.call.info().remote_uri,
print "is", self.call.info().state_text,
print "last code =", self.call.info().last_code,
print "(" + self.call.info().last_reason + ")"
# в разговорном подаем другую
if self.call.info().state == pj.CallState.CONFIRMED:
call_slot = self.call.info().conf_slot
# создаем новый
self.wav_player_id = pj.Lib.instance().create_player('/ATS/SOUND/music4.wav', loop=False)
self.wav_slot = pj.Lib.instance().player_get_slot(self.wav_player_id)
# проключаем канал плеера на разговор
pj.Lib.instance().conf_connect(self.wav_slot, call_slot)
if self.call.info().state == pj.CallState.DISCONNECTED:
current_call = None
print 'Current call is', current_call
# уведомление об изменении состояния системы коммутации
def on_media_state(self):
if self.call.info().media_state == pj.MediaState.ACTIVE:
print "Media is now active"
else:
print "Media is inactive"
- Function to make call
def make_call(uri):
try:
print "Making call to", uri
return acc.make_call(uri, cb=callCallbackOut())
except pj.Error, e:
print "Exception: " + str(e)
return None
- Create library instance
lib = pj.Lib()
try:
my_media_cfg = pj.MediaConfig()
my_media_cfg.clock_rate = 8000
my_media_cfg.snd_clock_rate = 44100
my_media_cfg.no_vad = True
my_media_cfg.quality = 10
my_media_cfg.ptime = 0
my_media_cfg.max_media_ports = 4
# Init library with default config and some customized
# logging config.
lib.init(log_cfg = pj.LogConfig(level=LOG_LEVEL, callback=log_cb), media_cfg = my_media_cfg)
# Create UDP transport which listens to any available port
transport = lib.create_transport(pj.TransportType.UDP, pj.TransportConfig(5060))
print "\nListening on", transport.info().host,
print "port", transport.info().port, "\n"
# Start the library
lib.start()
# Create local account
acc = lib.create_account(pj.AccountConfig("192.168.5.48", "7000", "7000"))
acc_cb = MyAccountCallback(acc)
acc.set_callback(acc_cb)
acc_cb.wait()
print "\n"
print "Registration complete, status=", acc.info().reg_status, \
"(" + acc.info().reg_reason + ")"
my_sip_uri = "sip:" + transport.info().host + \
":" + str(transport.info().port)
# Menu loop
while True:
print "My SIP URI is", my_sip_uri
print "Menu: m=make call, h=hangup call, a=answer call, c=call 407, q=quit"
input = sys.stdin.readline().rstrip("\r\n")
if input == "m":
if current_call:
print "Already have another call"
continue
print "Enter destination URI to call: ",
input = sys.stdin.readline().rstrip("\r\n")
if input == "":
continue
lck = lib.auto_lock()
current_call = make_call(input)
del lck
elif input == "h":
if not current_call:
print "There is no call"
continue
current_call.hangup()
elif input == "a":
if not current_call:
print "There is no call"
continue
current_call.answer(200)
elif input == "c":
lck = lib.auto_lock()
current_call = make_call("sip:100@192.168.5.48")
del lck
elif input == "q":
break
# Shutdown the library
transport = None
acc.delete()
acc = None
lib.destroy()
lib = None
except pj.Error, e:
print "Exception: " + str(e)
lib.destroy()
lib = None