Страница 1 из 2
Вызов через БД
Добавлено: 09 апр 2020, 09:38
DmitryB
Добрый день, пока идут не запланированные каникулы решил заняться самообразование.
Иногда по работе приходится сталкиваться с Астериском. Решил освоить вызовы через Базу Данных (БД).
Для себя наметил задачу, поступает вызов на номер 101,далее в БД где происходит сравнение номеров в таблице, если нет соответствия вызов идет на номер 101, если соответствия есть вызов идет на номер из таблицы.
Как мне кажется я запутался с планом нумерации (dial plan) не правильно составил выражение и имеются проблемы
Код: Выделить всё
exten=> _101,1,Set(CALLERID(num)=${ODBC_forward_call(${CALLERID(num)})})
с БД а точнее с драйверами ODBC так же не все в порядке.
Таблица имеет вид:
Код: Выделить всё
mysql> SELECT * FROM forward_call;
+---------------------+------+-----+
| Date | clid | dst |
+---------------------+------+-----+
| 2020-04-08 15:50:00 | 105 | 102 |
+---------------------+------+-----+
вывод логов:
Код: Выделить всё
[2020-04-09 09:37:57] WARNING[7232][C-0000004b]: func_odbc.c:476 execute: SQL Execute returned an error -1: 42S02: [MySQL][ODBC 5.3(w) Driver][mysqld-5.7.29-0ubuntu0.18.04.1]Table 'asterisktest.asterisktest' doesn't exist (106)
[2020-04-09 09:37:57] WARNING[7232][C-0000004b]: func_odbc.c:485 execute: SQL Exec Direct failed (-1)![SELECT dst FROM asterisktest where clid='102']
[2020-04-09 09:37:57] ERROR[7232][C-0000004b]: func_odbc.c:836 acf_odbc_read: Unable to execute query [SELECT dst FROM asterisktest where clid='102']
-- Executing [101@Local:1] Set("SIP/102-00000069", "CALLERID(num)=") in new stack
-- Auto fallthrough, channel 'SIP/102-00000069' status is 'UNKNOWN'
Заранее спасибо.
Re: Вызов через БД
Добавлено: 09 апр 2020, 11:43
ded
Рекомендации Создателей: вместо прямых odbc или mysql запросов вида [SELECT dst FROM asterisktest where clid='102']
из диалплана лучше написать небольшой скрипт на РНР например, протестировать его отдельно из командной строки, включив опции дебага, и, если всё ОК - вставить в диалплан через AGI, передаём в него параметр CID в качестве аргумента, получаем параметр Outbond CID в ответ:
В директории /var/lib/asterisk/agi-bin полно примеров!
Table 'asterisktest.asterisktest' doesn't exist
Ну и коллегу zzuz буду цитировать постоянно:
Переводы с английского, дорого. ©
Re: Вызов через БД
Добавлено: 09 апр 2020, 12:07
DmitryB
Спасибо, срипты это следующий этап. Для меня сейчас стоит задача по работе с БД.
Re: Вызов через БД
Добавлено: 09 апр 2020, 13:21
Vlad1983
показываете таблицу forward_call, а спрашиваете asterisktest
Re: Вызов через БД
Добавлено: 09 апр 2020, 13:38
DmitryB
Спасибо большое. Поправил. но вызов до 102 не проходит через БД. Напрямую вызов проходит. лог при этом чист.
Re: Вызов через БД
Добавлено: 09 апр 2020, 14:38
ded
DmitryB писал(а):Спасибо, срипты это следующий этап. Для меня сейчас стоит задача по работе с БД.
Дмитрий, с базами данных как раз и надо работать через скрипты. Это удобней и правильней.
/var/lib/asterisk/agi-bin/sql.php -
Код: Выделить всё
<?php
/* $Id: sql.php 11662 2011-03-04 00:28:02Z p_lindheimer $ */
// SQL Abstraction Layer for AGI Applications
// Original Release by Rob Thomas (xrobau@gmail.com)
// Copyright Rob Thomas (2009)
// Commands:
//
// $AGI = new AGI();
// $db = new AGIDB($AGI);
//
// $result = $db->escape($sql)
// Escapes any characters that could confuse the database and lead to SQL injection problems.
// You should use this on ANY browser-supplied or user-supplied input.
//
// $result = $db->sql($sql, $type)
// Returns the result of the SQL command $sql. This will die noisily if you
// try to do something that isn't portable between databases (eg ALTER TABLE
// or use CREATE with 'auto_increment') - use the alternate commands below,
// or design your database to be portable.
// $type specifies the return type -
// ASSOC for an Associative array
// NUM for a numeric array.
// BOTH for both in the same result
//
// Note this returns the ENTIRE result. So for example taken from routepermissions:
//
// $res = $db->sql("SELECT allowed,faildest FROM routepermissions WHERE exten='$cidnum' and routename='$routename'", "BOTH");
//
// if allowed and faildest return 'NO' and 'ext-vm,300', the result would look like this:
// $result = {
// [0] => {
// [0] = 'NO', // Only these with 'NUM' type
// [1] = 'ext-vm,300',
// 'allowed' => 'NO', // Only these with 'ASSOC' type
// 'faildest => 'ext-vm,300',
// }
// }
//
// if ($res[0]['allowed'] == 'NO') {
// $agi->goto($res[0]['faildest']);
// }
//
//
// $result = $db->rename_table($from, $to)
// Renames a table. Result is not null if an error occured, and the errorstr
// is in $result.
//
// $result = $db->add_col($tablename, $colname, $type)
// Add a column called $col_name of type $type to table $tablename. Result is not
// null if an error occured, and the errorstr is in $result.
//
// $result = $db->drop_col($tablename, $colname)
// Drops a column from table $tablename. Actually drops the column if using MySQL,
// recreates the table if using SQLite.
//
// $result = $db->alter_col($tablename, $colname, $type)
// Changes the type of a column. Changes it directly in MySQL, recreates the table
// if using SQLite
//
if (!class_exists('AGI')) {
}
class AGIDB {
// Database Variables from [globals]. Self explanatory.
private $dbhost;
private $dbuser;
private $dbpass;
private $dbfile;
private $dbname;
// sqlite3 needs some global variables to handle returns. They aren't needed
// to be defined here, but be aware that they are used by this module.
/* global $sql3holderAssoc; */
/* global $sql3holderNum; */
/* global $sql3holderRowNbr; */
private $agi; // A copy of the AGI class already running
private $db; // 'mysql', 'sqlite' or 'sqlite3'. Set in sql_database_connect, so we
// Public things that you might need to access
public $errstr; // Holder for error string
public $numrows; // Number of rows returned in the query
// Just in case someone REALLY wants to work around all the sanity checks here, these
// two variables are public, so you can use them if you REALLY must.
public $dbtype;
public $dbhandle;
function AGIDB($AGI=null) {
}
function sql_database_connect() {
// Determine DB type
// dl() is gone in php5, but since this will crash it anyhow, will just leave it as is
}
и так далее. Скрипт (выше) приведён не полностью.
Re: Вызов через БД
Добавлено: 09 апр 2020, 15:09
DmitryB
папка с скриптами у меня пустая, так что надо идти в гугл).
Объясните чем плох вариант работы с ODBC?
Вызовы пошли подмена происходит)) Еще раз спасибо.
Re: Вызов через БД
Добавлено: 09 апр 2020, 17:24
DmitryB
Vlad1983 писал(а):показываете таблицу forward_call, а спрашиваете asterisktest
Спасибо все отрабатывает корректно.
Дайте совет каким образом можно направить вызов на номер если номер вызывающего абонента отсутствует в таблице.
Re: Вызов через БД
Добавлено: 12 апр 2020, 21:45
DmitryB
Вызов через БД проходит все хорошо, но нуждаюсь в помощи.
При вызове с номера который присутствует в БД вызов идет на номер абонента 102. У абонента 102 происходит вызов, но отображение как будто абонент 102 набирает номер.
Код: Выделить всё
> 0x7fbf8c03b430 -- Strict RTP learning after remote address set to: 10.0.0.9:4074
-- Executing [104@Local:1] Set("SIP/105-000000a9", "BNUM=104") in new stack
-- Executing [104@Local:2] Set("SIP/105-000000a9", "CALLERID(num)=102") in new stack
-- Executing [104@Local:3] Dial("SIP/105-000000a9", "SIP/102,60") in new stack
== Using SIP RTP CoS mark 5
exten => 104,1,Set(BNUM=${CALLERID(DNID)}); забираем данные о Б номере и кладем их в переменную BNUM
same => n,Set(CALLERID(num)=${IF($["${ODBC_forward_call(${CALLERID(num)})}" = "" ]?${BNUM}:${ODBC_forward_call(${CALLERID(num)})})})
;Номер А входящего вызова сравниваем с БД и если номер совпадает, отправляем его на номер из БД, если номер не совпадает то отправляем его на номер переменной BNUM
Код: Выделить всё
same => n,Dial(SIP/${CALLERID(num)},60); Делаем вызов на номер заимвствованный из БД
Re: Вызов через БД
Добавлено: 12 апр 2020, 22:41
zzuz
Set("SIP/105-000000a9", "CALLERID(num)=102")
научитесь уже читать логи.