所有这些任务都可以通过 AMI 或 ARI 来解决,但是 ARI 提供的信息要少得多,事件不多,AMI 仍然有很多变量(例如,宏调用,宏内部设置变量,包括调用记录)没有被跟踪。 因此,为了正确和准确的跟踪,我们暂时选择 AMI(但不完全)。 另外(嗯,没有这个哪里来的,我们都是懒人)——原作中(哈布尔文章) 使用 PAMI。 *然后你需要尝试重写为 ARI,但不是它会工作的事实。
重塑集成
为了让我们的 FreePBX 能够以简单的方式向 AMI 报告通话的开始、结束时间、号码、录音文件的名称,最简单的方法是使用与原作者相同的技巧来计算通话时长- 输入您的变量并解析其存在的输出。 PAMI 建议通过过滤器功能简单地完成此操作。
下面是为呼叫开始时间设置您自己的变量的示例(s 是在开始 DID 搜索之前执行的拨号方案中的一个特殊数字)
[globals]
;; Проверьте пути и права на папки - юзер asterisk должен иметь права на запись
;; Сюда будет писаться разговоры
WAV=/var/www/html/callme/records/wav
MP3=/var/www/html/callme/records/mp3
;; По этим путям будет воспроизводится и скачиваться запись
URLRECORDS=https://www.host.ru/callmeplus/records/mp3
;; Адрес для калбека при исходящем вызове
URLPHP=https://www.host.ru/callmeplus
;; Да пишем разговоры
RECORDING=1
;; Это макрос для записи разговоров в нашу папку.
;; Можно использовать и системную запись, но пока пусть будет эта -
;; она работает
[recording]
exten => ~~s~~,1,Set(LOCAL(calling)=${ARG1})
exten => ~~s~~,2,Set(LOCAL(called)=${ARG2})
exten => ~~s~~,3,GotoIf($["${RECORDING}" = "1"]?4:14)
exten => ~~s~~,4,Set(fname=${UNIQUEID}-${STRFTIME(${EPOCH},,%Y-%m-%d-%H_%M)}-${calling}-${called})
exten => ~~s~~,5,Set(datedir=${STRFTIME(${EPOCH},,%Y/%m/%d)})
exten => ~~s~~,6,System(mkdir -p ${MP3}/${datedir})
exten => ~~s~~,7,System(mkdir -p ${WAV}/${datedir})
exten => ~~s~~,8,Set(monopt=nice -n 19 /usr/bin/lame -b 32 --silent "${WAV}/${datedir}/${fname}.wav" "${MP3}/${datedir}/${fname}.mp3" && rm -f "${WAV}/${fname}.wav" && chmod o+r "${MP3}/${datedir}/${fname}.mp3")
exten => ~~s~~,9,Set(FullFname=${URLRECORDS}/${datedir}/${fname}.mp3)
exten => ~~s~~,10,Set(CDR(filename)=${fname}.mp3)
exten => ~~s~~,11,Set(CDR(recordingfile)=${fname}.wav)
exten => ~~s~~,12,Set(CDR(realdst)=${called})
exten => ~~s~~,13,MixMonitor(${WAV}/${datedir}/${fname}.wav,b,${monopt})
exten => ~~s~~,14,NoOp(Finish if_recording_1)
exten => ~~s~~,15,Return()
;; Это основной контекст для начала разговора
[ext-did-custom]
;; Это хулиганство, делать это так и здесь, но работает - добавляем к номеру '8'
exten => s,1,Set(CALLERID(num)=8${CALLERID(num)})
;; Тут всякие переменные для скрипта
exten => s,n,Gosub(recording,~~s~~,1(${CALLERID(number)},${EXTEN}))
exten => s,n,ExecIF(${CallMeCallerIDName}?Set(CALLERID(name)=${CallMeCallerIDName}):NoOp())
exten => s,n,Set(CallStart=${STRFTIME(epoch,,%s)})
exten => s,n,Set(CallMeDISPOSITION=${CDR(disposition)})
;; Самое главное! Обработчик окончания разговора.
;; Обычные пути обработки конца через (exten=>h,1,чтототут) в FreePBX не работают - Macro(hangupcall,) все портит.
;; Поэтому вешаем Hangup_Handler на окончание звонка
exten => s,n,Set(CHANNEL(hangup_handler_push)=sub-call-from-cid-ended,s,1(${CALLERID(num)},${EXTEN}))
;; Обработчик окончания входящего вызова
[sub-call-from-cid-ended]
;; Сообщаем о значениях при конце звонка
exten => s,1,Set(CDR_PROP(disable)=true)
exten => s,n,Set(CallStop=${STRFTIME(epoch,,%s)})
exten => s,n,Set(CallMeDURATION=${MATH(${CallStop}-${CallStart},int)})
;; Статус вызова - Ответ, не ответ...
exten => s,n,Set(CallMeDISPOSITION=${CDR(disposition)})
exten => s,n,Return
;; Обработчик исходящих вызовов - все аналогичено
[outbound-allroutes-custom]
;; Запись
exten => _.,1,Gosub(recording,~~s~~,1(${CALLERID(number)},${EXTEN}))
;; Переменные
exten => _.,n,Set(__CallIntNum=${CALLERID(num)})
exten => _.,n,Set(CallExtNum=${EXTEN})
exten => _.,n,Set(CallStart=${STRFTIME(epoch,,%s)})
exten => _.,n,Set(CallmeCALLID=${SIPCALLID})
;; Вешаем Hangup_Handler на окончание звонка
exten => _.,n,Set(CHANNEL(hangup_handler_push)=sub-call-internal-ended,s,1(${CALLERID(num)},${EXTEN}))
;; Обработчик окончания исходящего вызова
[sub-call-internal-ended]
;; переменные
exten => s,1,Set(CDR_PROP(disable)=true)
exten => s,n,Set(CallStop=${STRFTIME(epoch,,%s)})
exten => s,n,Set(CallMeDURATION=${MATH(${CallStop}-${CallStart},int)})
exten => s,n,Set(CallMeDISPOSITION=${CDR(disposition)})
;; Вызов скрипта, который сообщит о звонке в CRM - это исходящий,
;; так что по факту окончания
exten => s,n,System(curl -s ${URLPHP}/CallMeOut.php --data action=sendcall2b24 --data ExtNum=${CallExtNum} --data call_id=${SIPCALLID} --data-urlencode FullFname='${FullFname}' --data CallIntNum=${CallIntNum} --data CallDuration=${CallMeDURATION} --data-urlencode CallDisposition='${CallMeDISPOSITION}')
exten => s,n,Return
要开始,您还需要通过登录名和密码在 AMI 中运行脚本 - 为此,FreePBX 也有一个 _custom 文件
manager_custom.conf 文件
;; это логин
[callmeplus]
;; это пароль
secret = trampampamturlala
deny = 0.0.0.0/0.0.0.0
;; я работаю с локальной машиной - но если надо, можно и другие прописать
permit = 127.0.0.1/255.255.255.255
read = system,call,log,verbose,agent,user,config,dtmf,reporting,cdr,dialplan
write = system,call,agent,log,verbose,user,config,command,reporting,originate
如果你想快速尝试解决方案——Docker 有一个选项——快速创建一个容器,给它外部端口,滑动设置文件并尝试(这是 LetsEncrypt 容器的选项,如果你已经有证书,你只需要将反向代理重定向到FreePBX web服务器(我们给它另一个端口是88),LetsEncrypt in docker based on 这篇文章