domingo, 6 de maio de 2018

ARA - Como armazenar corretamente os dados de uma chamada.


CDR (Call Data Redord) contém informaões sobre todas as chamadas que o Asterisk tratou, incluindo aquelas que falharam. Para a manutenção de sistemas de telefonia, uma das mais importantes fontes de informação sobre mau funcionamento, e para iniciar o diagnostico para responder sobre o mau funcionamento é sem via de duvidas o CDR!

No artigo de hoje vou estar respondendo a varias  perguntas que me é feita em comunidades pelo Telegram, bate papos casuais e principalmente em sala de aula. Vou estar discutindo aqui como é o procedimento no meu ver, correto para guardar o CDR do Asterisk no Bando de Dados MySQL! Uma vez com o CDR em um Bando de Dados, poderemos visualizá-los posteriormente por meio de uma interface Web. Como vamos estar falando sobre armazenamento de dados mais detalhado, eu suponho que você tenha conhecimento de ARA (Asterisk Realtime Architecture). Para que você possa aproveitar este artigo você já deve ter uma Appliance rodando com MySQL, Asterisk, Apache2, PHP e phpMyAdmin. Como todos sabem sou fá de carteirinha do Debian, e estou escrevendo este artigo sobre Debian 9 Stretch e Asterisk 13.1.

Para ficar claro o entendimento eu vou estar usando o nome do projeto do Asterisk, asteriskcdrdb, mas você fique a vontade para depois de entender como é a logica do CDR adaptar ao seu Bando de Dados.

1 - Crie um banco de dados com a estrutura:


001SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
002SET time_zone = "+00:00";
003
004/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
005/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
006/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
007/*!40101 SET NAMES utf8 */;
008
009--
010-- Banco de Dados: `asteriskcdrdb`
011--
012CREATE DATABASE IF NOT EXISTS `asteriskcdrdb` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
013USE `asteriskcdrdb`;
014
015-- --------------------------------------------------------
016
017--
018-- Estrutura da tabela `cdr`
019--
020
021DROP TABLE IF EXISTS `cdr`;
022CREATE TABLE IF NOT EXISTS `cdr` (
023`id` int(10) NOT NULL,
024  `calldate` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
025  `clid` varchar(80) NOT NULL DEFAULT '',
026  `src` varchar(80) NOT NULL DEFAULT '',
027  `realsrc` varchar(80) NOT NULL,
028  `dst` varchar(80) NOT NULL DEFAULT '',
029  `realdst` varchar(80) NOT NULL DEFAULT '',
030  `dcontext` varchar(80) NOT NULL DEFAULT '',
031  `channel` varchar(80) NOT NULL DEFAULT '',
032  `dstchannel` varchar(80) NOT NULL DEFAULT '',
033  `lastapp` varchar(80) NOT NULL DEFAULT '',
034  `lastdata` varchar(80) NOT NULL DEFAULT '',
035  `duration` int(11) NOT NULL DEFAULT '0',
036  `billsec` int(11) NOT NULL DEFAULT '0',
037  `disposition` varchar(45) NOT NULL DEFAULT '',
038  `amaflags` int(11) NOT NULL DEFAULT '0',
039  `remoteip` varchar(60) NOT NULL DEFAULT '',
040  `accountcode` varchar(20) NOT NULL DEFAULT '',
041  `hangupcause` varchar(50) NOT NULL,
042  `peerip` varchar(50) NOT NULL,
043  `recvip` varchar(50) NOT NULL,
044  `useragent` varchar(50) NOT NULL,
045  `uri` varchar(50) NOT NULL,
046  `fromuri` varchar(50) NOT NULL,
047  `peeraccount` varchar(20) NOT NULL DEFAULT '',
048  `uniqueid` varchar(32) NOT NULL DEFAULT '',
049  `userfield` varchar(255) NOT NULL DEFAULT '',
050  `did` varchar(50) NOT NULL DEFAULT '',
051  `linkedid` varchar(32) NOT NULL DEFAULT '',
052  `sequence` int(11) NOT NULL DEFAULT '0',
053  `filename` varchar(255) DEFAULT 'none',
054  `recordingfile` varchar(255) DEFAULT NULL
055) ENGINE=InnoDB AUTO_INCREMENT=21758 DEFAULT CHARSET=utf8;
056
057--
058-- Gatilhos `cdr`
059--
060DROP TRIGGER IF EXISTS `t_cdr`;
061DELIMITER //
062CREATE TRIGGER `t_cdr` BEFORE INSERT ON `cdr`
063 FOR EACH ROW BEGIN
064 IF ((NEW.dst = 's' OR NEW.dst = '~~s~~') AND NEW.realdst != '') THEN
065  SET NEW.dst = NEW.realdst;
066 END IF;
067END
068//
069DELIMITER ;
070
071-- --------------------------------------------------------
072
073--
074-- Estrutura da tabela `cel`
075--
076
077DROP TABLE IF EXISTS `cel`;
078CREATE TABLE IF NOT EXISTS `cel` (
079`id` int(11) NOT NULL,
080  `eventtype` varchar(30) NOT NULL,
081  `eventtime` datetime NOT NULL,
082  `cid_name` varchar(80) NOT NULL,
083  `cid_num` varchar(80) NOT NULL,
084  `cid_ani` varchar(80) NOT NULL,
085  `cid_rdnis` varchar(80) NOT NULL,
086  `cid_dnid` varchar(80) NOT NULL,
087  `exten` varchar(80) NOT NULL,
088  `context` varchar(80) NOT NULL,
089  `channame` varchar(80) NOT NULL,
090  `src` varchar(80) NOT NULL,
091  `dst` varchar(80) NOT NULL,
092  `channel` varchar(80) NOT NULL,
093  `dstchannel` varchar(80) NOT NULL,
094  `appname` varchar(80) NOT NULL,
095  `appdata` varchar(80) NOT NULL,
096  `amaflags` int(11) NOT NULL,
097  `accountcode` varchar(20) NOT NULL,
098  `uniqueid` varchar(32) NOT NULL,
099  `linkedid` varchar(32) NOT NULL,
100  `peer` varchar(80) NOT NULL,
101  `userdeftype` varchar(255) NOT NULL,
102  `eventextra` varchar(255) NOT NULL,
103  `userfield` varchar(255) NOT NULL
104) ENGINE=InnoDB AUTO_INCREMENT=207114 DEFAULT CHARSET=utf8;
105
106--
107-- Índices de tabelas salvas
108--
109
110--
111-- Índice da tabela `cdr`
112--
113ALTER TABLE `cdr`
114 ADD PRIMARY KEY (`id`), ADD KEY `calldate` (`calldate`), ADD KEY `src` (`src`), ADD KEY `dst` (`dst`), ADD KEY `accountcode` (`accountcode`), ADD KEY `uniqueid` (`uniqueid`), ADD KEY `dcontext` (`dcontext`), ADD KEY `clid` (`clid`), ADD KEY `did` (`did`), ADD KEY `id` (`id`);
115
116--
117-- Índice da tabela `cel`
118--
119ALTER TABLE `cel`
120 ADD PRIMARY KEY (`id`), ADD KEY `uniqueid_index` (`uniqueid`), ADD KEY `linkedid_index` (`linkedid`);
121
122--
123-- AUTO_INCREMENT para tabelas salvas
124--
125
126--
127-- AUTO_INCREMENT para tabela `cdr`
128--
129ALTER TABLE `cdr`
130MODIFY `id` int(10) NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=21758;
131--
132-- AUTO_INCREMENT para tabela `cel`
133--
134ALTER TABLE `cel`
135MODIFY `id` int(11) NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=207114;
136/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
137/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
138/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;

2 - Edite o arquivo /etc/asterisk/cdr_mysql.conf

01[global]
02usegmtime=no
03cdrzone=America/Sao_Paulo
04
05[columns]
06alias start => calldate
07alias realdst => realdst
08alias remoteip => remoteip
09alias start => calldate
10alias hangupcause => hangupcause
11alias peerip => peerip
12alias recvip => recvip
13alias fromuri => fromuri
14alias useragent => useragent
15alias filename => filename
16alias realsrc => realsrc

Na seção [global], não há dados de conexão, já que gravamos dados no MySQL através do driver ODBC.

3 - Edite o arquivo /etc/asterisk/cdr_adaptive_odbc.conf


01[cdr_adaptive_connection]
02connection=asteriskcdrdb
03table=cdr
04usegmtime=no
05alias start => calldate
06alias realdst => realdst
07alias remoteip => remoteip
08alias start => calldate
09alias hangupcause => hangupcause
10alias peerip => peerip
11alias recvip => recvip
12alias fromuri => fromuri
13alias useragent => useragent
14alias filename => filename
15alias realsrc => realsrc


4 - Edite o arquivo /etc/asterisk/cdr_odbc.conf

1[global]
2dsn=asteriskcdrdb
3loguniqueid=yes
4dispositionstring=yes
5table=cdr
6usegmtime=no
7hrtime=yes
8newcdrcolumns=yes


5 - Crie a MACRO para CDR Estendido (Extended CDR):

1;CDR Estendido
2[macro-cdr-extended]
3exten => s,1,NoOp("Extended CDR")
4 same => n,Set(CDR(hangupcause)=${HANGUPCAUSE})
5 same => n,Set(CDR(peerip)=${CHANNEL(peerip)})
6 same => n,Set(CDR(recvip)=${CHANNEL(recvip)})
7 same => n,Set(CDR(uri)=${CHANNEL(uri)})
8 same => n,Set(CDR(fromuri)=${CHANNEL(from)})
9 same => n,Set(CDR(useragent)=${CHANNEL(useragent)})
 same => n,MacroExit()

Agora para que funcione de maneira correta os contextos que você quer ter ARA Exentend CDR, voce invoca nossa macro.
1
same => n,Macro(cdr-extended,${CALLERID(num)},${EXTEN})

Caso você queira guardar tudo, use na ultima linha do seu Dialplan o padrão especial h.
1
exten => h,1,Macro(cdr-extended,${CALLERID(num)},${EXTEN})

Para que toda vez que uma chamada seja desligada HangUp( ) acione o padrão h, você tem que colocar no aplicativo Dial( ), as opções Hh