Для тех, кто в танке, конференц-колл – возможность разговора одновременно нескольких участников.
В документациях к астериск описывается приложение MeetMe (которое заведует конференциями) и способ организовать "статические залы" - т.е., мы заранее прописываем номер зала и пароль, а потом пользователи к нему присоединяются.
Недостаток этого, на мой взгляд, в следующем: допустим, я организовал конференцию в конференц-зале с номером 1 и разговариваю с поставщиком. Мой коллега решает тоже поговорить в режиме конференции и организует конференцию. Для начала ему нужно как-то узнать – свободен ли зал 1, и потом занять зал 2. Третий участник уже должен опрашивать двоих…
В общем, мне видится правильным другой путь:
- Я организую конференцию, звоня на служебный номер, например, *9*.
- Я набираю номер того, кого хочу присоединить (через 0).
- Человек присоединяется. Если он из внутренних пользователей, он так же может пригласить нового участника.
Начальная настройка.
Создаем файл /etc/asterisk/meetme.conf и вносим в него:
; Разрешаем использование realtime
schedule=yes
; таблица будет обновляться при входе/выходе участников
logmembercount=yes
Как и в предыдущих случаях, данные конференций будут храниться в MySQL. Создадим для них таблицу:
confno char(80) NOT NULL default '0',
starttime datetime NOT NULL default '0000-00-00 00:00:00',
endtime datetime NOT NULL default '2099-12-31 23:59:59' ,
pin char(20) default NULL,
opts char(100) default NULL,
adminpin char(20) default NULL,
adminopts char(100) default NULL,
members int(11) NOT NULL default '0',
maxusers int(11) NOT NULL default '0',
created_at datetime NOT NULL default '0000-00-00 00:00:00',
PRIMARY KEY (confno,starttime)
);
И внесем строчку в /etc/asterisk/extconfig.conf
Так же, восстановим из копии файл /etc/asterisk/indications.conf и в секции [general] установим country=ru.
Не забываем перезапустить asterisk.
Создание конференции
Для начала – займемся процедурой создания конференции. Задача звучит так: по набору *9* необходимо вставить строчку в таблицу и вернуть номер конференции, после чего задиалится на него.
Создадим хранимку в MySQL, которая создает новую конференцию и возвращает ее номер. Заодно, она подчищает конференции, созданные более одного дня назад.
CREATE DEFINER=`root`@`%` PROCEDURE `create_meetme_conference`()
BEGIN
DELETE FROM tbl_meetme WHERE members=0 AND DATE_ADD(created_at, INTERVAL 1 DAY)<NOW();
SELECT @NewConfNo:=IFNULL(CAST(MAX(confno) as UNSIGNED),0)+1
FROM tbl_meetme;
INSERT INTO tbl_meetme (confno,created_at) SELECT @NewConfNo,NOW();
SELECT @NewConfNo;
END
В файл func_odbc.conf добавляем вызов этой хранимки
; создание новой meetme конференции
dsn=asterisk
readsql=call asterisk.create_meetme_conference
В диалплан добавляем (пока – в тестовых целях) создание конференции
exten => *9*,1,NoOp(Start Conference)
exten => *9*,n,Goto(conference_main,s,1)
exten => *9*,n,Return
[conference_main]
; контекст работы с конференцией
exten => s,1,NoOp(conference_main)
; ставим запрет на динамические фишки
exten => s,n,Set(__DYNAMIC_FEATURES=)
; получаем номер конференции при помощи процедуры (если его еще нет)
exten => s,n,Set(__CONFNO=${IF($["${CONFNO}"=""]?${ODBC_CREATE_NEW_CONFERENCE()}:${CONFNO})})
; устанавливаем контекст, по которому будет производится выход (в нашем случае - доп. набор)
exten => s,n,Set(MEETME_EXIT_CONTEXT=conference_invite_user)
; проигрываем приветствие
exten => s,n,Playback(rittal/meetme_welcome)
; если это внутренний пользователь - рассказываем как приглашать
exten => s,n,GotoIf($["${SIPPEER(${CALLERID(num)},dynamic)}" = "yes"]?:create_conf)
exten => s,n,Playback(rittal/meetme_add_possible)
; и запускаем конференцию
exten => s,n(create_conf),MeetMe(${CONFNO},X1)
Приглашение в конференцию
Пользователь, уже находящийся в конференции, должен иметь возможность пригласить еще кого-то. Идея взята отсюда.
Сформулируем задачу так:
- Находясь в конференции, пользователь нажимает 0.
- Пользователь выпрыгивает из конференции в набор номера.
- После набора номера и разговора с набранным номером, если пользователь нажимает **, он подключает набранного человека к конференции, если *# - не подключает.
- Далее пользователь возвращается в конференцию обратно.
Для начала, создадим файл /etc/asterisk/features.conf и пропишем в него две комбинации - ** и *#.
[featuremap]
[applicationmap]
conference_invite_user => *0,caller,Macro,conference_invite_user
conference_invite_cancel => *#,caller,Macro,conference_invite_cancel
conference_invite_ok => **,caller,Macro,conference_invite_ok
Теперь диалплан приглашения и макросы реакции на комбинации
; контекст для приглашения пользователей в конференцию
exten => 0,1,NoOp(conference_invite_user. ConfNo: ${CONFNO})
; проверяем, что это внутренний номер - только им можно приглашать участников
exten => 0,n,GotoIf($["${SIPPEER(${CALLERID(num)},dynamic)}" = "yes"]?:return_to_conference)
exten => 0,n,Playback(rittal/meetme_add_instruction)
; читаем номер, набранный пользователем, попутно выдавая тон
exten => 0,n,Read(NEWDIAL,dial,,i)
; устанавливаем разрешения на работу функций по переводу звонка
exten => 0,n,Set(__DYNAMIC_FEATURES=conference_invite_ok#conference_invite_cancel)
; и набираем номер, устанавливая флаг "продолжить после хенгапа"
exten => 0,n,Gosub(internal_phones_outgoing_dial,${NEWDIAL},1)
; возвращаемся обратно в конференцию
exten => 0,n(return_to_conference),Goto(conference_main,s,1)
[macro-conference_invite_ok]
; если отвечено **,
exten => s,1,NoOp(macro-conference_invite_ok)
; то переводим пользователя в конференцию,
exten => s,n,ChannelRedirect(${BRIDGEPEER},conference_main,s,1)
; и сами возвращаемся туда.
[macro-conference_invite_cancel]
; если отвечено *#, то кладем трубку и возвращаемся в конференцию
exten => s,1,NoOp(macro-conference_invite_cancel)
exten => s,n,SoftHangup(${BRIDGEPEER})