понедельник, 14 ноября 2016 г.

Asterisk cdr viewer + postgresql

config.inc.php
...
$db_type = 'pgsql';
...

Для базы в которой находится таблица cdr:

CREATE OR REPLACE FUNCTION public.unix_timestamp (
  date timestamptz
)
RETURNS double precision AS
$body$
SELECT  date_part('epoch', date)
$body$
LANGUAGE 'sql';

среда, 19 октября 2016 г.

Очередной nway call в asterisk через confbridge

Написано для  Asterisk 13.11.0.

confbridge.conf
...
[nway_menu]
type=menu
1=dialplan_exec(nway-invite,0,1)

features.conf
...
[applicationmap]
nway =>*0,self,AGI(nway.pl),default

extensions.conf
...
[from-internal]
exten = _1XX,1,Set(CHANNEL(language)=ru)
 same = n,Set(__DYNAMIC_FEATURES=nway)
...
[nway-invite]
exten = 0,1,NoOp()
 same = n,Read(DEST,,3)
 same = n,GoSub(subDialString,start,1,(${DEST}))
 same = n,Originate(${GOSUB_RETVAL},exten,dynamic-nway,${CONFNO},1)
exten = i,1,SoftHangup(${BRIDGEPEER})
exten = t,1,SoftHangup(${BRIDGEPEER})

[dynamic-nway]
exten = _X.,1,Answer()
 same = n,Set(__CONFNO=${EXTEN})
 same = n,ConfBridge(${EXTEN},,,nway_menu)

/var/lib/asterisk/agi-bin/nway.pl
#!/usr/bin/perl
use strict;
use warnings;

use Asterisk::AGI;
use Asterisk::AMI;

my $agi = Asterisk::AGI->new();
my $channel = $agi->get_variable('CHANNEL');
my $bridgepeer = $agi->get_variable('BRIDGEPEER');
my ($confno) = split /\./,$agi->get_variable('UNIQUEID');

my $ami = Asterisk::AMI->new(
    PeerAddr => '127.0.0.1',
    PeerPort => '5038',
    Username => 'script',
    Secret => '123456');

my $action = $ami->action({
    Action => 'Redirect',
    Channel => $channel,
    Context => 'dynamic-nway',
    Exten => $confno,
    Priority => 1,
    ExtraChannel => $bridgepeer,
    ExtraContext => 'dynamic-nway',
    ExtraExten => $confno,
    ExtraPriority => 1
     });

$agi->hangup();
exit();

Примечания:
  1. Подпрограмма subDialString создает строку подключения для разных каналов по заданному номеру. Например для unistim USTM/100@100, для sip SIP/101 и т.д. Если все аппараты используют один протокол, строка GoSub не нужна, следующую строку можно изменить на, например, same = n,Originate(SIP/${DEST},exten,dynamic-nway,${CONFNO},1).
  2. В строчке exten = _1XX шаблон должен быть конечно Ваш, как и длина номера в same = n,Read(DEST,,3)
  3. В качестве номер конференции используется часть UNIQUEID для того, чтобы начавший конференцию, мог выйти из нее и начать новую.

Порядок работы:
  1. Если в ходе разговора есть необходимость подключить третьего, нажать *0 (features.conf) при этом разговор преобразуется в конференцию (можеть делать и caller, и callee)
  2. Для подключения дополнительного собеседника нажать 1 (confbridge.conf) и номер (может делать любой участвующий в конференции)
К сожалению, другие способы (более простые?): channelredirect(), agi из macro и прочее у меня не работает. Только agi (ami) из features.conf.

пятница, 9 сентября 2016 г.

При попытке настроить asterisk realtime в связке с postgresql 9.2.13 (через odbc), после создания таблиц (либо через alembic, либо используя /usr/src/asterisk/contrib/realtime/postgresql/postgresql_config.sql) при попытке зарегестрировать sip пользователя (таблица sippeers) получал ошибки несоотвествия типов полей lastms, regseconds... Со стороны сервера это выглядит так: ОШИБКА:  колонка "lastms" имеет тип integer, а выражение - character (символ 136). Т.е регистрация аппарата проходит, но поля ipaddr, port, regseconds, fullcontact и т.д. не заполняются.
Для pjsip пользователей подобные ошибки в таблице ps_contacts. Аппарат так же регистрируется, но данные в ps_contacts не добавляются.
Удаление полей порождающих ошибки и их создание с типом char помогают для таблицы sippeers, но после изменений в ps_contacts asterisk стал перезагружатся с периодом около минуты.
Помогло явное создание неявного преобразования типов в БД :).
Для sippeers достаточно:
create cast (character as integer) with inout as implicit;
Для ps_contacts необходимо добавить:
create cast (character as double precision) with inout as implicit;
create cast (character as bigint) with inout as implicit;
create cast (character as yesno_values) with inout as implicit;