Реализовал таки схему предложенную мной выше.
Используемое оборудование: Grandstream GXP2140 с LCD доп. панелью GXP2200EXT.
Сразу скажу о недостатках:
1. У организатора/модератора должно быть два телефона: один с панелью, другой для участия любой. Проблема связана с автопровижингом - телефон не принимает новую конфигурацию, если занят.
2. Обновлении списка участников занимает секунд 15 - время на автопровижинг.
Итак выглядит все это так:
1. Участники регистрируются в конференции.
2. Организатор/модератор на панели телефона нажимает кнопку "обновить". На панель загружаются участники конференции. При этом лампы панели загораются зеленым цветом.
3. В конференции при входе/выходе участника проигрывается "beep" или что-то подобное. По этому сигналу или просто периодически организатор/модератор нажимает "обновить", с панели удаляются вышедшие участники, добавляются новые.
4. Участник при желании выступить нажимает на своем телефоне определенную цифру(я делал 3). При этом на панели начинает мигать красным соответствующая участнику лампа.
5. Организатор/модератор нажимает мигающую кнопку и у соответствующего участника включается микрофон, кнопка горит красным.
6. Организатор/модератор нажимает горящую красным кнопку и у соответствующего участника выключается микрофон. Кнопка загорается зеленым.
7. При завершении конференции организатор/модератор нажимают "обновить" и с панели удаляются все участники, т.к. их нет. Можно конечно и независимо от участников сделать кнопку "завершение", но я не делал, реализуется думаю.
Получаем, что кнопка участника имеет три состояния - зеленый(микрофон выключен), красный(микрофон включен), мигающий красный(просит включить микрофон).
Описание реализации:
9002 - exten вызова конференция
9003 - exten запроса голоса
change_status_conf - exten смены кастомного статуса
_XXXX9002 - exten включения/выключения микрофона
1. В sip_notify.conf прописываем событие для обновления конфигурации телефона без перезагрузки. В моем случае:
- Код: выделить все
[gs-check-cfg]
Event=>resync
2. Делаем конфигурационный файл для автопровижинга(у меня grandstream21xx_1.0.7.97_conf.xml) - оставляем поля, ответственные за BLF-панель, исключая начальные клавиши - на них будет висеть обновление участников и может что еще нужно постоянное. В моем случае это поля от P23000 до P23198. На одну кнопку выделено 4 записи по порядку, между записями одна пропускается, т.е. запись + 5 это уже следующая. Я оставил необновляемыми 2 кнопки, поэтому начинаю с P23010.
3. Настраиваем автопровижинг для телефона. Настройку не привожу - стандартно.
4. В confbridge.conf создаем профиль конференции и ее меню. Все стандартно за исключением:
- убрать возможность включать микрофон самостоятельно
- на кнопку повесить тот самый запрос слова участником - выполнение команды диалплана, в моем случае
- Код: выделить все
3=dialplan_exec(conferention,change_status_conf,1)
5. Для всех возможных участников конференции создать кастомные хинты вида:
- Код: выделить все
exten=>25369002,hint,Custom:25369002
Можно сделать и скрипт, который будет добавлять в отдельный файл конкретные хинты при регистрации участника, а файл заинклюдить в контексте конференции. Я не делал.
6. Собственно контекст конференции:
- Код: выделить все
[conferention]
exten => 9002,1,Answer()
same => n,Set(DEVICE_STATE(Custom:${CALLERID(num)}${EXTEN})=NOT_INUSE)
same => n,ConfBridge(${EXTEN},conf_bridge,conf_user,conf_menu)
same => n,Hangup()
exten => 9003,1,NoOp()
; запуск скрипта с параметрами: номер конференции и номер телефона с BLF-панелью
same => n,System(/usr/share/asterisk/agi-bin/check_status_queue.php "9002" "2595")
same => n,Hangup()
exten => change_status_conf,1,Set(DEVICE_STATE(Custom:${CALLERID(num)}9002)=RINGING)
same => n,Hangup()
exten => _XXXX9002,1,NoOp(Изменение статуса номера ${EXTEN:0:4} в конференции ${EXTEN:4} и включение/выключение микрофона)
same => n,GoSubIf($[${DEVICE_STATE(Custom:${EXTEN})}=BUSY]?off:on)
same => n(off),Set(DEVICE_STATE(Custom:${EXTEN})=NOT_INUSE)
same => n,System(asterisk -rx 'confbridge mute ${EXTEN:4} SIP/${EXTEN:0:4}')
same => n,Hangup()
same => n(on),Set(DEVICE_STATE(Custom:${EXTEN})=BUSY)
same => n,System(asterisk -rx 'confbridge unmute ${EXTEN:4} SIP/${EXTEN:0:4}')
same => n,Hangup()
7. Собственно сам скрипт check_status_queue.php. Писал на PHP, сразу говорю - не умею, делал, чтоб получилось, поэтому код скорей всего из вида "*овнокода"
- Код: выделить все
<?php
# Изменяемый файл конфигурации
$file_conf = "/usr/share/asterisk/phoneprov/grandstream21xx_1.0.7.97_conf.xml";
# Переданные скрипту параметры:
## Номер телефона, на котором обновляется панель
$phone_number = $argv[2];
## Номер конференции
$conf_number = $argv[1];
#$conf_number = "9002";
# Первый и последний параметр файла конфигурации, отвечающий за клавиши панели, которые будем менять
$member_first = 23010;
$member_end = 23195;
# шаг в значениях параметров соседних клавиш
$member_step = 5;
# Позиция начала номера участника конференции в выводе 'confbridge list'
$position = 88;
# Длина строки в выводе 'confbridge list'
$line_len = 94;
# Открытие файла конфигурации для изменения
if (file_exists($file_conf)) {
$xml = simplexml_load_file($file_conf);
}
else {
exit('Не удалось открыть файл '.$file_conf."\n");
}
# Получение данных об участниках конференции
$output = shell_exec("asterisk -rx 'confbridge list $conf_number' | grep conf_");
# Заполнение массива участников на основании полученных данных
$step = 1;
if (strlen($output) > 1) {
while ( $position <= strlen($output)){
$conf_member = $output[$position+1].$output[$position+2].$output[$position+3].$output[$position+4];
$position = $position+$line_len;
echo $conf_member."\n";
$conf_members[$step]["name"] = "Member".$conf_member;
$conf_members[$step]["number"] = $conf_member.$conf_number;
$step = $step + 1;
}
}
else {
echo("Ошибка получения списка участников конференции. Убедитесь, что конференция запущена.\n");
}
# Установка переменной текущего параметра в файле конфигурации
$memberX = $member_first;
# Статус устанавливаемой кнопки("1" - BLF, "-1" - отключена)
$member_status = 1;
# Запись клавиш для каждого участника очереди
# На каждую клавишу приходится 4 параметра:
# - состояние клавиши
# - привязанная учетная запись(не меняется, т.к. на телефоне используется одна)
# - подпись
# - значение
if (isset($conf_members)) {
foreach ($conf_members as $conf_member) {
echo $conf_member["name"]." ".$conf_member["number"]."\n";
$memberX1 = $memberX + 2;
$memberX2 = $memberX + 3;
$member1 = 'P'.$memberX;
$member2 = 'P'.$memberX1;
$member3 = 'P'.$memberX2;
$xml->config[0]->$member1 = $member_status;
$xml->config[0]->$member2 = $conf_member["name"];
$xml->config[0]->$member3 = $conf_member["number"];
$memberX = $memberX + $member_step;
}
}
# Обнуление неиспользуемых клавиш
$member_status = -1;
while ($memberX <= $member_end){
$memberX1 = $memberX + 2;
$memberX2 = $memberX + 3;
$member1 = 'P'.$memberX;
$member2 = 'P'.$memberX1;
$member3 = 'P'.$memberX2;
$xml->config[0]->$member1 = $member_status;
$xml->config[0]->$member2 = "";
$xml->config[0]->$member3 = "";
$memberX = $memberX + $member_step;
}
$xml->asXML($file_conf);
shell_exec("asterisk -rx 'sip notify gs-check-cfg $phone_number'");
?>
Кажется ничего не забыл.
Как-то так, вдруг кому пригодится.
Еще была мысли через MicroSIP - там есть загрузка XML-справочника абонетов с показом состояния. Может через него можно. Но мысль пришла позже, проверять уже не очень хочется.