Список форумов Asterisk Forum Asterisk Forum
The Asterisk Open Source PBX - Russian Community
 
 FAQFAQ   ПоискПоиск   ПользователиПользователи   ПравилаПравила   ГруппыГруппы   ИзбранноеИзбранное    LinksСсылки   РегистрацияРегистрация 
 RSSRSS   ПрофильПрофиль   Войти и проверить личные сообщения   ВходВход 

Rated dialplan

 
Список форумов Asterisk Forum -> Библиотека    вывод темы на печать
Предыдущая тема :: Следующая тема  
Автор Сообщение
Alextransit



Зарегистрирован:
27.10.2008
Сообщения: 187
Откуда: Perm

Статус: Оффлайн 

СообщениеДобавлено: Вт Авг 30, 2011 11:32    Заголовок сообщения: Rated dialplan

Годков несколько назад прикрутил у себя робота, который делает выбор транка в зависимости от его стоимости.
делюсь своей рабочей идеей.
для ее реализации нужно уметь работать с mysql.

Как это выглядит?
(дам куски кода. Живу в Перми. Соответственно код идет исходя из региона. Стоит у меня Elastix, раньше стоял Trixbox.)

Допустим, у меня есть несколько транков. У каждого провайдера своя цена на разные направления. И когда я набираю номер, то автоматом формируется список транков, через которе можно совершить звонок, начиная с самого дешевого.
Робот определяет принадлежность номера к региону. Далее в прайсе выбирает последнюю цену от каждого провайдера на данном направлении и делает звонок. (данные прайса можно дополнять. можно хранить историю цен)

Уверен что многие подобное используют у себя, и уверен что многие хотели бы сделать подобное.

Попробую все подробно расписать.
Я не программер и не админ, и просто повесил всю работу на SQL. Для работы нужно сделать несколько таблиц и процедур. И написать несколько строк в extension.conf
Для начала я преобразовываю номер в международный формат.

Код:
; to russia (blank)
exten => _ZXXXXXXXXX,1,GoTo(+7${EXTEN},1)
; to russia (7XXX)
exten => _7XXXXXXXXXX,1,GoTo(+${EXTEN},1)
; to russia (with prefiks 0 or 8)
exten => _[08]ZXXXXXXXXX,1,GoTo(+7${EXTEN:1},1)
; to perm
exten => _2XXXXXX,1,NoOp(====== to perm ========)
exten => _2XXXXXX,n,GoTo(+7342${EXTEN},1)
; to world (with 00)
exten => _00ZXXXXXXXXX.,2,GoTo(+${EXTEN:2},1)
exten => _00ZXXXXXXXXX.,1,NoOp(======begin========)
; to world (with 810)
;exten => _810ZXXXXXXXXX.,1,GoTo(+${EXTEN:3},1)


Далее подключаемся к базе и вызываем функцию с набранным номером
(логин и пароль без кавычек. Таблицы я добавил в базе asteriskcdrdb)

Код:
exten => _+ZXXXXXXXXX.,n,MYSQL(Connect connid localhost «тут логин» «а тут пароль» asteriskcdrdb)
exten => _+ZXXXXXXXXX.,n,MYSQL(Query resultid ${connid} CALL GetRates("${EXTEN:1}"))
exten => _+ZXXXXXXXXX.,n,MYSQL(Fetch 1 ${resultid} pr1 prd1 cnd1 ratee1 rule1)
exten => _+ZXXXXXXXXX.,n,MYSQL(Fetch 2 ${resultid} pr2 prd2 cnd2 ratee2 rule2)
exten => _+ZXXXXXXXXX.,n,MYSQL(Fetch 3 ${resultid} pr3 prd3 cnd3 ratee3 rule3)
exten => _+ZXXXXXXXXX.,n,MYSQL(Fetch 4 ${resultid} pr4 prd4 cnd4 ratee4 rule4)
exten => _+ZXXXXXXXXX.,n,MYSQL(Fetch 5 ${resultid} pr5 prd5 cnd5 ratee5 rule5)
exten => _+ZXXXXXXXXX.,n,MYSQL(Clear ${resultid})
exten => _+ZXXXXXXXXX.,n,MYSQL(Disconnect ${connid})

Получаем список из возможных транков, начиная с самого дешевого, и отключаемся от базы.

Я не стал делать обработчик больше 5 правил. Но при надобности можно нарастить.
Потом я сохраняю в CDR индекс стоимости и индекс правила
и делаю набор при помощи макроса (повторюсь. В астере и юнихе я разбираюсь плохо и использую «коробочное решение» типа Elastix)
Код:
exten => _+ZXXXXXXXXX.,n,Set(rt=${ratee1})
exten => _+ZXXXXXXXXX.,n,Set(rul=${rule1})
exten => _+ZXXXXXXXXX.,n,Set(CDR(rateid)=${ratee1})
exten => _+ZXXXXXXXXX.,n,Set(CDR(ruleid)=${rule1})
exten => _+ZXXXXXXXXX.,n,Macro(dialout-trunk,${pr1},${prd1}${EXTEN:${MATH(${cnd1}+1)},,)

ну и повторяю это 5 раз.
Каждый раз, перед макросом набора, заношу новые значения ratee и rule в CDR.
Теперь что означают значения от запроса:
Pr – это номер транка ( я использую макросы elastix. но можно взять имя. для этого нужно немного изменить процедуру)
Prd – это predial направления (можно сделать свой в зависимости от надобности)
Cnd – колько знаков отбросить на данном правиле
Ratee – индекс прайса (ссылка на сточку по какой цене прошел звонок)
Rule – индекс правила ( это нужно для отслеживания специфичных правил провайдера)

Для чего нужны rule? Да просто провайдеры дают разные условия по работе. Например буржуйский бетамакс дает бесплатные минуты (типа 200 минут бесплатно на определенные направления за последние 7 дней). Наши провайдеры могут дать условия типа абонентка включает какое то количество минут в месяц. И так далее.
Вот что бы это отловить я и записываю. А потом запросом можно быстренько все вычислить.
У себя я подобное так и не сделал. Из за лени, и мне это стало не нужно (посмотрел статистику и вижу что я и так вписываюсь). Но при необходимости можно написать функцию или процедуру и все будет работать.

Так. Теперь что я сделал в базе.
1. Добавил новые поля rateid и ruleid в таблицу CDR ( для сохранения ссылки на цену звонка и специфики правила)
2. Добавил таблицу DEF ( для определения принадлежности номера)
3. Добавил таблицу provider (список зарегистрированных провайдеров)
4. Добавил таблицу rates (цены каждого направления каждого провайдера)
5. Добавил процедуру GetRates ( которая определяет по DEF принадлежность и формирует список провайдеров с их правилами)

Таблица DEF.
Код:
CREATE TABLE `DEF` (
  `Id` INTEGER(11) NOT NULL AUTO_INCREMENT,
  `Country` INTEGER(11) DEFAULT NULL,
  `Num` VARCHAR(20) COLLATE latin1_swedish_ci NOT NULL DEFAULT '',
  `Type` INTEGER(11) NOT NULL,
  `Region` VARCHAR(20) COLLATE latin1_swedish_ci DEFAULT NULL,
  `Owner` INTEGER(11) DEFAULT NULL,
  `Description` VARCHAR(20) COLLATE latin1_swedish_ci DEFAULT NULL,
  `Date` DATE DEFAULT NULL,
  PRIMARY KEY (`Id`),
  UNIQUE KEY `Num` (`Num`, `Region`)
)ENGINE=MyISAM
AUTO_INCREMENT=362 CHARACTER SET 'latin1' COLLATE 'latin1_swedish_ci'
COMMENT='http://www.mtt.ru/mtt/def';


пример данных ( выдрал у себя кусочек с идентификацией пермских номеров)

Код:

INSERT INTO `DEF` (`Id`, `Country`, `Num`, `Type`, `Region`, `Owner`, `Description`, `Date`) VALUES
  (1, 7, '7', 1, NULL, NULL, 'Russia landlane', NULL),
  (2, 34, '34', 1, NULL, NULL, 'Spain', NULL),
  (3, 7, '79', 2, NULL, NULL, 'Russia mobile', NULL),
  (4, 34, '346', 2, NULL, NULL, 'Spain', NULL),
  (5, 380, '380', 3, NULL, NULL, 'Ukraine', NULL),
  (7, 7, '7495', 1, '77-495', NULL, 'Moscow', NULL),
  (8, 7, '7499', 1, '77-499', NULL, 'Moscow', NULL),
  (9, 7, '7800', 1, '8-800', NULL, 'Free', NULL),
  (10, 7, '7812', 1, '78', NULL, 'Piter', NULL),
  (204, 7, '790247', 2, '59', 4, NULL, '1999-08-30'),
  (205, 7, '790263', 2, '59', 4, NULL, '2003-12-09'),
  (206, 7, '790264', 2, '59', 4, NULL, '2003-12-09'),
  (207, 7, '790279', 2, '59', 4, NULL, '2003-02-19');

где:
Num - номер (начальные цифры номера)
Type - тип номера (1 - landline 2- mobile)
Region - это обозначение региона которое указывается в прайсе
Owner - можно сделать таблицу с операторами (если нужно)
Date - когда купили эти номера ( не нужно)
из всего этого нужно только номер и регион


таблица provider

Код:
CREATE TABLE `provider` (
  `ID` INTEGER(11) NOT NULL AUTO_INCREMENT,
  `NumAstr` INTEGER(11) NOT NULL,
  `PoviderName` VARCHAR(20) COLLATE latin1_swedish_ci NOT NULL DEFAULT '',
  `Description` TEXT COLLATE latin1_swedish_ci NOT NULL,
  `PreDial` VARCHAR(20) COLLATE latin1_swedish_ci DEFAULT '',
  `Priority` INTEGER(3) NOT NULL DEFAULT '0',
  `Enabled` TINYINT(1) DEFAULT NULL,
  PRIMARY KEY (`ID`),
  KEY `NumAstr` (`NumAstr`),
  KEY `Priority` (`Priority`),
  KEY `Enabled` (`Enabled`),
  FULLTEXT KEY `PoviderName` (`PoviderName`),
  FULLTEXT KEY `PreDial` (`PreDial`),
  FULLTEXT KEY `P1` (`PoviderName`, `PreDial`)
)ENGINE=MyISAM
AUTO_INCREMENT=17 CHARACTER SET 'latin1' COLLATE 'latin1_swedish_ci';


пример данных
Код:
INSERT INTO `provider` (`ID`, `NumAstr`, `PoviderName`, `Description`, `PreDial`, `Priority`, `Enabled`) VALUES
  (2, 11, 'SIP/SIPTra', 'Bronze', '00001', 0, 0),
  (3, 11, 'SIP/SIPTra', 'Silver', '00', 0, 0),
  (4, 11, 'SIP/SIPTra', 'Gold', '00000', 0, 0),
  (5, 9, 'SIP/21xxxx', '', '', 4, 0),
  (6, 10, 'IAX2/alfxxxx', '', '', 0, 1),
  (8, 2, 'SIP/1237xxxxx', '', '', 50, 1),
  (10, 14, 'SIP/nonxx', 'me', '00', 60, 1),
  (16, 3, 'SIP/9223xxxxx', 'megafon', '+', 50, 1),
  (12, 1, 'SIP/9223xxxxx', 'megafon', '+', 40, 1),
  (14, 6, 'SIP/27xxxx8', 'utel', '', 10, 1),
  (15, 15, 'SIP/965xxxxxx', 'huawei bee GSM', '+', 0, 1);

где:
NumAstr - номер транка в extension.conf
PoviderName - имя, которое можно использовать для набора
PreDial - это что нужно набрать перед номером. (можно не указывать, и указать predial в таблице с ценой)
Priority - это приоритет. если будет одна цена у разных провайдеров, то сортировка идет по приоритету)
Enabled - транк можно включить и выключить прямо из базы


таблица rates

Код:
CREATE TABLE `rates` (
  `Id` INTEGER(11) NOT NULL AUTO_INCREMENT,
  `Description` VARCHAR(20) COLLATE latin1_swedish_ci DEFAULT NULL,
  `Trunk` INTEGER(11) NOT NULL,
  `Country` INTEGER(11) NOT NULL,
  `Type` INTEGER(11) DEFAULT NULL,
  `Region` VARCHAR(20) COLLATE latin1_swedish_ci DEFAULT NULL,
  `Owner` INTEGER(11) DEFAULT NULL,
  `Rate` DECIMAL(11,2) DEFAULT NULL,
  `RateRule` DECIMAL(11,2) DEFAULT NULL,
  `ValidDate` DATE DEFAULT NULL,
  `PreDial` VARCHAR(5) COLLATE latin1_swedish_ci DEFAULT '',
  `CDel` INTEGER(4) DEFAULT '0',
  `Rule` INTEGER(11) DEFAULT NULL,
  PRIMARY KEY (`Id`),
  UNIQUE KEY `Id` (`Id`),
  UNIQUE KEY `Trunk` (`Trunk`, `Country`, `Type`, `Region`, `Owner`, `ValidDate`),
  KEY `Trunk1` (`Trunk`),
  KEY `Country` (`Country`),
  KEY `ValidDate` (`ValidDate`)
)ENGINE=MyISAM
AUTO_INCREMENT=35 CHARACTER SET 'latin1' COLLATE 'latin1_swedish_ci';


пример данных
Код:

INSERT INTO `rates` (`Id`, `Description`, `Trunk`, `Country`, `Type`, `Region`, `Owner`, `Rate`, `RateRule`, `ValidDate`, `PreDial`, `CDel`, `Rule`) VALUES
  (11, 'megafon', 3, 7, 1, NULL, NULL, 1.5, NULL, '2011-01-01', '', 0, NULL),
  (12, 'umtel', 6, 7, 1, '59-3422', NULL, 0, NULL, '2011-01-01', '', 4, 1),
  (13, 'umtel', 6, 7, 2, '59', NULL, 1.5, NULL, '2011-01-01', '8', 1, NULL),
  (14, 'bee gsm unlim', 15, 7, 1, '59', NULL, 0.17, NULL, '2011-01-01', '', 0, 2),
  (16, 'alf msk', 10, 7, 1, '77-499', NULL, 0, NULL, '2011-01-01', '8', 1, NULL),
  (21, 'UMTel', 6, 7, 1, '8-800', NULL, 0, NULL, '2011-01-01', '8', 1, NULL);


процедура Getrates
Код:
CREATE DEFINER = 'root'@'localhost' PROCEDURE `GetRates`(IN DialNum VARCHAR(20))
    DETERMINISTIC
    READS SQL DATA
    SQL SECURITY DEFINER
    COMMENT ''
begin
SELECT
`provider`.`NumAstr`,
CONCAT(`provider`.`PreDial`,(select `rates`.`PreDial` from `rates` where `rates`.`Id` = PrRate.RID)) as PRD,
(select `rates`.`CDel` from `rates` where `rates`.`Id` = PrRate.RID) as CDel,
`PrRate`.`RId`,
(select `rates`.`Rule` from `rates` where `rates`.`Id` = PrRate.RID) as RuleId
from `provider`,
(select
`provider`.`ID`,
(select
`rates`.`Id`
from `rates`,
(select
`DEF`.`Country`,
`DEF`.`Type`,
`DEF`.`Region`,
`DEF`.`Owner`
from `DEF`
where `DialNum` like CONCAT(`DEF`.`Num`,"%")
order by LENGTH(`DEF`.`Num`) DESC LIMIT 1) as NumDesc

where
`rates`.`Trunk` = `provider`.`NumAstr` and
`rates`.`Country` = `NumDesc`.`Country` and
`rates`.`ValidDate` <= now() and
(`rates`.`Type`= `NumDesc`.`Type` or `rates`.`Type` is NULL) and
(`rates`.`Region` = `NumDesc`.`Region` or `rates`.`Region` is NULL) AND
(`rates`.`Owner`= `NumDesc`.`Owner` or `rates`.`Owner` is NULL)
order by `rates`.`ValidDate` desc,
(IF(`rates`.`Type`,1,0) + IF(`rates`.`Region`,1,0) + IF(`rates`.`Owner`,1,0)) desc
LIMIT 1) as RID
from `provider`
where `provider`.`Enabled` = TRUE) as PrRate
where `provider`.`ID` = PrRate.id
and PrRate.RID is not null
order by (select `rates`.`Rate` from `rates` where `rates`.`Id` = PrRate.RID),`provider`.`Priority`;
end;


резюме.
мы определяем принадлежность номера к региону
берем последнюю цену всех провайдеров, которые могут сделать звонок по данному направлению.
и сортируем их по приоритету.
все это делает Sql, который и так установлен. Smile

у самого подключено несколько транков по меди
несколько по сипу. даже модем юсб прикрутил.
вот для всего этого зоопарка и была сделана данная приблуда.

вроде все.
С Уважением Алексей Милько

для чего это все написал?
да просто многому научился читая подобные примеры. жалко что флудеры мешаются (как новички, так и старперы) Smile
глядишь и эти примеры кому то помогут.
Вернуться к началу
Посмотреть профиль Отправить личное сообщение Телефон
beba



Зарегистрирован:
29.07.2006
Сообщения: 232
Откуда: Беларусь

Статус: Оффлайн 

СообщениеДобавлено: Чт Сен 01, 2011 09:13    Заголовок сообщения:

спасибо
Вернуться к началу
Посмотреть профиль Отправить личное сообщение Jabber ID
Список форумов Asterisk Forum -> Библиотека Ответить на тему
Страница 1 из 1

Добавить в Избранное

 
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
You cannot attach files in this forum
You cannot download files in this forum