Установить asterisk
sudo apt update && sudo apt install asterisk
Создать папку с логами.
sudo mkdir -p /var/log/asterisk && sudo chown -R asterisk:asterisk /var/log/asterisk
Будем рассматривать условный случай с 2 калитками и 2 домами за ними по 2 подъезда в каждом. Просто, чтоб не перегружать примеры.
Все файлы, указнные далее, расположены по пути /etc/asterisk. Вся настройка производилась с дефолтными конфигами asterisk v13. Если что-то изменялось вами отдельно, учитывайте это.
[modules]
autoload=no
load => app_bridgewait.so
load => app_cdr.so
load => app_dial.so
load => app_exec.so
load => app_macro.so
load => app_read.so
load => app_senddtmf.so
load => app_softhangup.so
load => app_stack.so
load => app_system.so
load => app_verbose.so
load => bridge_builtin_features.so
load => bridge_native_rtp.so
load => bridge_simple.so
load => cdr_csv.so
load => chan_pjsip.so
load => chan_rtp.so
load => codec_alaw.so
load => codec_ulaw.so
load => format_wav.so
load => func_callerid.so
load => func_cdr.so
load => func_dialplan.so
load => func_global.so
load => func_logic.so
load => func_strings.so
load => pbx_config.so
load => res_clioriginate.so
load => res_pjproject.so
load => res_pjsip.so
load => res_pjsip_acl.so
load => res_pjsip_authenticator_digest.so
load => res_pjsip_caller_id.so
load => res_pjsip_config_wizard.so
load => res_pjsip_dtmf_info.so
load => res_pjsip_endpoint_identifier_user.so
load => res_pjsip_header_funcs.so
load => res_pjsip_history.so
load => res_pjsip_nat.so
load => res_pjsip_outbound_authenticator_digest.so
load => res_pjsip_outbound_registration.so
load => res_pjsip_registrar.so
load => res_pjsip_sdp_rtp.so
load => res_pjsip_session.so
load => res_rtp_asterisk.so
load => res_rtp_multicast.so
load => res_sorcery_astdb.so
load => res_sorcery_config.so
load => res_sorcery_memory.so
[global]
[transport-udp]
type=transport
protocol=udp
bind=0.0.0.0:5067
В этом случае панели (и калитки, и подъезда) одним sip-ом подключаются к астериску, а вторым - к Росдомофону. Соответственно, во время вызова отправляют звонок в оба адреса.
[domofon_template](!) ; шаблон для дальнейшего использования
type = wizard
transport = transport-udp ; Имя транспорта, описанного в файле pjsip.conf
accepts_auth = yes
accepts_registrations = yes
inbound_auth/password = 123456 ; Тот пароль, с которым панели ходят в астериск
endpoint/allow = ulaw,alaw
endpoint/allow_subscribe = no
aor/max_contacts = 1
; Далее список всех панелей
[ul_Rosinka_dom7_p1](domofon_template) ; Название, которое будет использоваться в Диалплане
inbound_auth/username = rosinkad7p1 ; Имя, с которым панель регистрируется
endpoint/context = from-panel
[ul_Rosinka_dom7_p2](domofon_template)
inbound_auth/username = rosinkad7p2
endpoint/context = from-panel
[ul_Rosinka_dom8_p1](domofon_template)
inbound_auth/username = rosinkad8p1
endpoint/context = from-panel
[ul_Rosinka_dom8_p2](domofon_template)
inbound_auth/username = rosinkad8p2
endpoint/context = from-panel
; Калитки
[kalitka_Rosinka7_8-1](domofon_template) ; Имя для диалплана
inbound_auth/username = rosinka-kal1 ; Имя, с которым калитка регистрируется
endpoint/context = from-kalitka
[kalitka_Rosinka7_8-2](domofon_template)
inbound_auth/username = rosinka-kal2
endpoint/context = from-kalitka
[general]
static=yes
writeprotect=yes
clearglobalvars=yes
[globals]
PANELFOUND="" ; служебная переменная, не трогать
DOM1PREFIX=0007 ; Префиксы для домов
DOM2PREFIX=0008 ; Если нужно больше домов, то нужно
DOM3PREFIX=0003 ; добавить для них префиксы сюда. Любые, лишь бы не пересекались.
DOM1P1trunk=ul_Rosinka_dom7_p1 ; Имя, как задано в файле с учётками.
DOM1P1min=1 ; Диапазон квартир. ОТ...
DOM1P1max=100 ; и ...ДО
DOM1P2trunk=ul_Rosinka_dom7_p2
DOM1P2min=101
DOM1P2max=200
DOM2P1trunk=ul_Rosinka_dom8_p1 ; Аналогично для второго дома
DOM2P1min=1 ; начало диапазона для подъезда
DOM2P1max=20 ; и конец
DOM2P2trunk=ul_Rosinka_dom8_p2
DOM2P2min=21
DOM2P2max=40
;
; Дальнейший текст править не нужно, он будет работать сам
; в зависимости от заданных переменных выше.
;
[callfinished-found]
exten => s,1,Verbose(Завершение вызова)
same => n,Hangup()
; Вызов на Физическую трубку
[sub-dialFlat]
;ARG1 - Dom
;ARG2 - Entrance
;ARG3 - Flat
exten => s,1,Log(NOTICE, Звоним в квартиру ${ARG3} на панели ${${ARG1}${ARG2}trunk} (${ARG1}, ${ARG2}) )
same => n,Set(GLOBAL(PANELFOUND)=${ARG1}${ARG2})
same => n,Dial(PJSIP/${ARG3}@${${ARG1}${ARG2}trunk},60)
; Проверка всех диапазонов по подъездам в доме
; и поиск, куда попадает набранная квартира
[sub-selectEntrance]
;ARG1 - Dom
;ARG2 - Entrance (empty)
;ARG3 - Flat
exten => s,1,Log(NOTICE, Ищем подходящий подъезд для квартиры ${ARG3} в доме ${ARG1})
same => n,GoSubIf($[ $[EXISTS(${${ARG1}P1min})] & $[${ARG3} >= ${${ARG1}P1min}] & $[${ARG3} <= ${${ARG1}P1max}] ]?sub-dialFlat,s,1(${ARG1},P1,${ARG3}))
same => n,GoSubIf($[ $[EXISTS(${${ARG1}P2min})] & $[${ARG3} >= ${${ARG1}P2min}] & $[${ARG3} <= ${${ARG1}P2max}] ]?sub-dialFlat,s,1(${ARG1},P2,${ARG3}))
same => n,GoSubIf($[ $[EXISTS(${${ARG1}P3min})] & $[${ARG3} >= ${${ARG1}P3min}] & $[${ARG3} <= ${${ARG1}P3max}] ]?sub-dialFlat,s,1(${ARG1},P3,${ARG3}))
same => n,GoSubIf($[ $[EXISTS(${${ARG1}P4min})] & $[${ARG3} >= ${${ARG1}P4min}] & $[${ARG3} <= ${${ARG1}P4max}] ]?sub-dialFlat,s,1(${ARG1},P4,${ARG3}))
same => n,GoSubIf($[ $[EXISTS(${${ARG1}P5min})] & $[${ARG3} >= ${${ARG1}P5min}] & $[${ARG3} <= ${${ARG1}P5max}] ]?sub-dialFlat,s,1(${ARG1},P5,${ARG3}))
same => n,GoSubIf($[ $[EXISTS(${${ARG1}P6min})] & $[${ARG3} >= ${${ARG1}P6min}] & $[${ARG3} <= ${${ARG1}P6max}] ]?sub-dialFlat,s,1(${ARG1},P6,${ARG3}))
same => n,GoSubIf($[ $[EXISTS(${${ARG1}P7min})] & $[${ARG3} >= ${${ARG1}P7min}] & $[${ARG3} <= ${${ARG1}P7max}] ]?sub-dialFlat,s,1(${ARG1},P7,${ARG3}))
same => n,GoSubIf($[ $[EXISTS(${${ARG1}P8min})] & $[${ARG3} >= ${${ARG1}P8min}] & $[${ARG3} <= ${${ARG1}P8max}] ]?sub-dialFlat,s,1(${ARG1},P8,${ARG3}))
same => n,GoSubIf($[ $[EXISTS(${${ARG1}P9min})] & $[${ARG3} >= ${${ARG1}P9min}] & $[${ARG3} <= ${${ARG1}P9max}] ]?sub-dialFlat,s,1(${ARG1},P9,${ARG3}))
same => n,GotoIf($[ "x${GLOBAL(PANELFOUND)}" = "x" ]?pnotfound)
same => n,Log(WARNING, Если панель найдена то как мы тут оказались? Дом ${ARG1} и квартира ${ARG3})
same => n(pnotfound),Log(WARNING, Не нашли совпадение диапазона по подъездам в доме ${ARG1} и квартиры ${ARG3})
same => n,Return()
; Входная точка для вызовов с калитки. Задаём нужные переменные
; и выбираем дом в зависимости от префикса.
[from-kalitka]
exten => _X.,1,Set(number=${EXTEN})
same => n,Set(GLOBAL(FLATSTART)=${LEN(DOM1PREFIX)})
same => n,Set(GLOBAL(PANELFOUND)=)
same => n,Log(NOTICE, На калитке набран номер = ${number})
same => n,Set(house=${number:0:${FLATSTART}})
same => n,Set(flat=${number:${FLATSTART}})
same => n,Log(NOTICE, Дом ${house} квартира ${flat})
same => n,GosubIf($[ $[EXISTS(${DOM1PREFIX})] & $["${house}" = "${DOM1PREFIX}"] ]?sub-selectEntrance,s,1(DOM1,,${flat}))
same => n,GosubIf($[ $[EXISTS(${DOM2PREFIX})] & $["${house}" = "${DOM2PREFIX}"] ]?sub-selectEntrance,s,1(DOM2,,${flat}))
same => n,GosubIf($[ $[EXISTS(${DOM3PREFIX})] & $["${house}" = "${DOM3PREFIX}"] ]?sub-selectEntrance,s,1(DOM3,,${flat}))
same => n,GosubIf($[ $[EXISTS(${DOM4PREFIX})] & $["${house}" = "${DOM4PREFIX}"] ]?sub-selectEntrance,s,1(DOM4,,${flat}))
same => n,GosubIf($[ $[EXISTS(${DOM5PREFIX})] & $["${house}" = "${DOM5PREFIX}"] ]?sub-selectEntrance,s,1(DOM5,,${flat}))
same => n,GosubIf($[ $[EXISTS(${DOM6PREFIX})] & $["${house}" = "${DOM6PREFIX}"] ]?sub-selectEntrance,s,1(DOM6,,${flat}))
same => n,GosubIf($[ $[EXISTS(${DOM7PREFIX})] & $["${house}" = "${DOM7PREFIX}"] ]?sub-selectEntrance,s,1(DOM7,,${flat}))
same => n,GosubIf($[ $[EXISTS(${DOM8PREFIX})] & $["${house}" = "${DOM8PREFIX}"] ]?sub-selectEntrance,s,1(DOM8,,${flat}))
same => n,GosubIf($[ $[EXISTS(${DOM9PREFIX})] & $["${house}" = "${DOM9PREFIX}"] ]?sub-selectEntrance,s,1(DOM9,,${flat}))
same => n,Log(NOTICE, Конец вызова. Никуда не позвонили.)
same => n,Hangup()
; Входная точка для вызова с подъезда.
; в ней мы ничего делать не будем, т.к. панель сама умеет звонить в Росдомофон
; Но вызов всё равно прилетит, т.к. панель шлёт его всем, кто у неё прописан.
[from-panel]
exten => _X,1,Noop(Вызов с домовой панели ${CDR(src)} в квартиру ${EXTEN} (1))
exten => _X.,1,Noop(Вызов с домовой панели ${CDR(src)} в квартиру ${EXTEN} (2))
Здесь имеем случай с любыми панелями у которых настроен один сип. Можно его использовать и с Beward, но смысла нет. Учитывая, что на панели сип только один, и это будет астериск, то именну астериску нужно будет обрабатывать все поступающие звонки и отправлять их в Росдомофон.
Данный конфиг рассчитан на то, что панели авторизуются в астериске с тем же именем, которое заведено в системе Росдомофон (пароль может и отличаться). Иначе вызов не пройдёт и будет отбой.
[rosdom_trunk_template](!) ; шаблон для дальнейшего использования
type = wizard
transport = transport-udp
sends_auth = yes
;sends_registrations = yes ; Транкам регистрация не нужна
remote_hosts = sip.rosdomofon.com:5062 ; Для Транка только порт 5062
endpoint/allow = !all,ulaw,alaw
endpoint/allow_subscribe = no
endpoint/context = from-rosdom
endpoint/direct_media = false ; Если не отключить, то астер шлёт повторный инвайт, который ломает сипадаптер
;endpoint/direct_media_method = update ; с этим параметром вместо повторного инвайта летит update, который звонок не обрывает, но ошибку показывает
;registration/retry_interval = 60 ; параметры для регистрации - не нужны, если отключена
;registration/forbidden_retry_interval = 600
;registration/expiration = 3600
[domofon_template](!) ; шаблон для дальнейшего использования
type = wizard
transport = transport-udp ; Имя транспорта, описанного в файле pjsip.conf
accepts_auth = yes
accepts_registrations = yes
inbound_auth/password = 123456 ; Тот пароль, с которым панели ходят в астериск
endpoint/allow = ulaw,alaw
endpoint/allow_subscribe = no
aor/max_contacts = 1
; Выход в РД
[rosdom_siptrunk_Rosinka78](rosdom_trunk_template)
;endpoint/from_user = siptrunk_Rosinka78 ; данный параметр нужен при включенной регистрации, чтоб астер не использовал имя в квадратных скобках
outbound_auth/username = siptrunk_Rosinka78
outbound_auth/password = qDf#jFh&dS%AKJc87@
; Далее список всех панелей
[ul_Rosinka_dom7_p1](domofon_template) ; Название, которое будет использоваться в Диалплане
inbound_auth/username = rosinkad7p1 ; Имя, с которым панель регистрируется
endpoint/context = from-panel
[ul_Rosinka_dom7_p2](domofon_template)
inbound_auth/username = rosinkad7p2
endpoint/context = from-panel
[ul_Rosinka_dom8_p1](domofon_template)
inbound_auth/username = rosinkad8p1
endpoint/context = from-panel
[ul_Rosinka_dom8_p2](domofon_template)
inbound_auth/username = rosinkad8p2
endpoint/context = from-panel
; Калитки
[kalitka_Rosinka7_8-1](domofon_template) ; Имя для диалплана
inbound_auth/username = rosinka-kal1 ; Имя, с которым калитка регистрируется
endpoint/context = from-kalitka
[kalitka_Rosinka7_8-2](domofon_template)
inbound_auth/username = rosinka-kal2
endpoint/context = from-kalitka
[general]
static=yes
writeprotect=yes
clearglobalvars=yes
[globals]
PANELFOUND="" ; служебная переменная, не трогать
RDTRUNK=rosdom_siptrunk_Rosinka78 ; Trunk interface
DOM1PREFIX=0007 ; Префиксы для домов
DOM2PREFIX=0008 ; Если нужно больше домов, то нужно
DOM3PREFIX=0003 ; добавить для них префиксы сюда. Любые, лишь бы не пересекались.
DOM1P1trunk=ul_Rosinka_dom7_p1 ; Имя, как задано в файле с учётками.
DOM1P1min=1 ; Диапазон квартир. ОТ...
DOM1P1max=100 ; и ...ДО
DOM1P2trunk=ul_Rosinka_dom7_p2
DOM1P2min=101
DOM1P2max=200
DOM2P1trunk=ul_Rosinka_dom8_p1 ; Аналогично для второго дома
DOM2P1min=1 ; начало диапазона для подъезда
DOM2P1max=20 ; и конец
DOM2P2trunk=ul_Rosinka_dom8_p2
DOM2P2min=21
DOM2P2max=40
;
; Дальнейший текст править не нужно, он будет работать сам
; в зависимости от заданных переменных выше.
;
[callfinished-found]
exten => s,1,Verbose(Завершение вызова)
same => n,Hangup()
; Вызов на Физическую трубку
[sub-dialFlat]
;ARG1 - Dom
;ARG2 - Entrance
;ARG3 - Flat
exten => s,1,Log(NOTICE, Звоним в квартиру ${ARG3} на панели ${${ARG1}${ARG2}trunk} (${ARG1}, ${ARG2}) и в МП)
same => n,Set(GLOBAL(PANELFOUND)=${ARG1}${ARG2})
same => n,Dial(PJSIP/${ARG3}@${${ARG1}${ARG2}trunk}&PJSIP/${${ARG1}PREFIX}${ARG3}@${RDTRUNK},60)
same => n,Log(NOTICE, Вызов совершён. Ответил: ${DIALEDPEERNAME}. Статус: ${DIALSTATUS} )
same => n,Goto(callfinished-found,s,1)
; Проверка всех диапазонов по подъездам в доме
; и поиск, куда попадает набранная квартира
[sub-selectEntrance]
;ARG1 - Dom
;ARG2 - Entrance (empty)
;ARG3 - Flat
exten => s,1,Log(NOTICE, Ищем подходящий подъезд для квартиры ${ARG3} в доме ${ARG1})
same => n,GoSubIf($[ $[EXISTS(${${ARG1}P1min})] & $[${ARG3} >= ${${ARG1}P1min}] & $[${ARG3} <= ${${ARG1}P1max}] ]?sub-dialFlat,s,1(${ARG1},P1,${ARG3}))
same => n,GoSubIf($[ $[EXISTS(${${ARG1}P2min})] & $[${ARG3} >= ${${ARG1}P2min}] & $[${ARG3} <= ${${ARG1}P2max}] ]?sub-dialFlat,s,1(${ARG1},P2,${ARG3}))
same => n,GoSubIf($[ $[EXISTS(${${ARG1}P3min})] & $[${ARG3} >= ${${ARG1}P3min}] & $[${ARG3} <= ${${ARG1}P3max}] ]?sub-dialFlat,s,1(${ARG1},P3,${ARG3}))
same => n,GoSubIf($[ $[EXISTS(${${ARG1}P4min})] & $[${ARG3} >= ${${ARG1}P4min}] & $[${ARG3} <= ${${ARG1}P4max}] ]?sub-dialFlat,s,1(${ARG1},P4,${ARG3}))
same => n,GoSubIf($[ $[EXISTS(${${ARG1}P5min})] & $[${ARG3} >= ${${ARG1}P5min}] & $[${ARG3} <= ${${ARG1}P5max}] ]?sub-dialFlat,s,1(${ARG1},P5,${ARG3}))
same => n,GoSubIf($[ $[EXISTS(${${ARG1}P6min})] & $[${ARG3} >= ${${ARG1}P6min}] & $[${ARG3} <= ${${ARG1}P6max}] ]?sub-dialFlat,s,1(${ARG1},P6,${ARG3}))
same => n,GoSubIf($[ $[EXISTS(${${ARG1}P7min})] & $[${ARG3} >= ${${ARG1}P7min}] & $[${ARG3} <= ${${ARG1}P7max}] ]?sub-dialFlat,s,1(${ARG1},P7,${ARG3}))
same => n,GoSubIf($[ $[EXISTS(${${ARG1}P8min})] & $[${ARG3} >= ${${ARG1}P8min}] & $[${ARG3} <= ${${ARG1}P8max}] ]?sub-dialFlat,s,1(${ARG1},P8,${ARG3}))
same => n,GoSubIf($[ $[EXISTS(${${ARG1}P9min})] & $[${ARG3} >= ${${ARG1}P9min}] & $[${ARG3} <= ${${ARG1}P9max}] ]?sub-dialFlat,s,1(${ARG1},P9,${ARG3}))
same => n,GotoIf($[ "x${GLOBAL(PANELFOUND)}" = "x" ]?pnotfound)
same => n,Log(WARNING, Если панель найдена то как мы тут оказались? Дом ${ARG1} и квартира ${ARG3})
same => n(pnotfound),Log(WARNING, Не нашли совпадение диапазона по подъездам в доме ${ARG1} и квартиры ${ARG3})
same => n,Return()
; Входная точка для вызовов с калитки. Задаём нужные переменные
; и выбираем дом в зависимости от префикса.
[from-kalitka]
exten => _X.,1,Set(number=${EXTEN})
same => n,Set(GLOBAL(FLATSTART)=${LEN(DOM1PREFIX)})
same => n,Set(GLOBAL(PANELFOUND)=)
same => n,Log(NOTICE, На калитке набран номер = ${number})
same => n,Set(house=${number:0:${FLATSTART}})
same => n,Set(flat=${number:${FLATSTART}})
same => n,Log(NOTICE, Дом ${house} квартира ${flat})
same => n,GosubIf($[ $[EXISTS(${DOM1PREFIX})] & $["${house}" = "${DOM1PREFIX}"] ]?sub-selectEntrance,s,1(DOM1,,${flat}))
same => n,GosubIf($[ $[EXISTS(${DOM2PREFIX})] & $["${house}" = "${DOM2PREFIX}"] ]?sub-selectEntrance,s,1(DOM2,,${flat}))
same => n,GosubIf($[ $[EXISTS(${DOM3PREFIX})] & $["${house}" = "${DOM3PREFIX}"] ]?sub-selectEntrance,s,1(DOM3,,${flat}))
same => n,GosubIf($[ $[EXISTS(${DOM4PREFIX})] & $["${house}" = "${DOM4PREFIX}"] ]?sub-selectEntrance,s,1(DOM4,,${flat}))
same => n,GosubIf($[ $[EXISTS(${DOM5PREFIX})] & $["${house}" = "${DOM5PREFIX}"] ]?sub-selectEntrance,s,1(DOM5,,${flat}))
same => n,GosubIf($[ $[EXISTS(${DOM6PREFIX})] & $["${house}" = "${DOM6PREFIX}"] ]?sub-selectEntrance,s,1(DOM6,,${flat}))
same => n,GosubIf($[ $[EXISTS(${DOM7PREFIX})] & $["${house}" = "${DOM7PREFIX}"] ]?sub-selectEntrance,s,1(DOM7,,${flat}))
same => n,GosubIf($[ $[EXISTS(${DOM8PREFIX})] & $["${house}" = "${DOM8PREFIX}"] ]?sub-selectEntrance,s,1(DOM8,,${flat}))
same => n,GosubIf($[ $[EXISTS(${DOM9PREFIX})] & $["${house}" = "${DOM9PREFIX}"] ]?sub-selectEntrance,s,1(DOM9,,${flat}))
same => n,Dial(PJSIP/${number}@${RDTRUNK},60)
same => n,Log(NOTICE, Конец вызова. Звонок от калитки отправили только в МП.)
same => n,Hangup()
; Входная точка для вызова с подъезда.
; Просто отправляем звонок в транк, подменив вызывающего на имя панели
[from-panel]
exten => s,1,Log(NOTICE, Вызов с панели ${CDR(src)} в квартиру ${EXTEN}. Звоним в МП от имени панели через имеющийся транк.)
exten => _X,1,Noop(Вызов с домовой панели ${CDR(src)} в квартиру ${EXTEN} (1))
same => n,Set(CALLERID(name)=${CDR(src)})
same => n,Set(CALLERID(num)=${CDR(src)})
same => n,Set(PJSIP_HEADER(update,From)=${CDR(src)})
same => n,Dial(PJSIP/${EXTEN}@${RDTRUNK})
same => n,Log(NOTICE, Вызов совершён. Ответил: ${DIALEDPEERNAME}. Статус: ${DIALSTATUS} )
same => n,Hangup()
exten => _X.,1,Noop(Вызов с домовой панели ${CDR(src)} в квартиру ${EXTEN} (2))
same => n,Set(CALLERID(name)=${CDR(src)})
same => n,Set(CALLERID(num)=${CDR(src)})
same => n,Set(PJSIP_HEADER(update,From)=${CDR(src)})
same => n,Dial(PJSIP/${EXTEN}@${RDTRUNK})
same => n,Log(NOTICE, Вызов совершён. Ответил: ${DIALEDPEERNAME}. Статус: ${DIALSTATUS} )
same => n,Hangup()
Будем рассматривать условный случай с 2 калитками и 2 домами за ними по 3 подъезда в каждом. Просто, чтоб не перегружать примеры.
Установить asterisk
sudo apt update && sudo apt install asterisk
На рда он почему-то сам не создаёт папку с логами. Это не критично, но можно ему помочь:
sudo mkdir -p /var/log/asterisk && sudo chown -R asterisk:asterisk /var/log/asterisk
Создадим рабочую директорию, в которой будем запускать скрипт. и складывать файлы.
mkdir -p ~/asterisk-workdir/templates
cd ~/asterisk-workdir/templates
Скачать и распаковать в эту директорию файлы из архива (или поштучно скопировать, как получится)
templates.zip
В архиве базовые шаблоны для генерации конфигов и диалплан, работа которого будет зависеть от переменных. (пока действует ограничение на 9 калиток, 9 домов по 9 подъездов в каждом, но можно увеличить добавлением строчек в диалплане и увеличением циферки в скрипте)
Данный скрипт нужно создать в директории на уровень выше templates.
пусть он будет назван genconfigs.sh
#!/bin/bash
set -e
INTERMEDIATE_wizard="result/pjsip_wizard.conf.template"
INTERMEDIATE_vars="result/rosdomofon.vars.template"
mkdir -p result
# Подгрузим заданные переменные
#source envVariables.txt
set -a
source <(sed -E 's/\s+=\s+/=/g' envVariables.txt)
#export $(sed -nE 's/^\s*([a-zA-Z0-9_-]+)\s+*=.*$/\1/p' envVariables.txt | xargs)
PanelPassword_rd=${PanelPassword_rd:-"qDf#jFh&dS%AKJc87@"}
PanelPassword=${PanelPassword:-'123456'}
# Копируем то, что не нужно изменять
cp -v templates/modules.conf result/
cp -v templates/extensions.conf result/
cp -v templates/pjsip.conf result/
cp -v templates/pjsip_notify.conf result/
cp -v templates/pjsip_wizard.conf "${INTERMEDIATE_wizard}"
cp -v templates/rosdomofon.vars "${INTERMEDIATE_vars}"
# Разберёмся с транком, если нужно
TRUNK_MODE_COMMENT=""
if [ "${SIPTrunk_Mode_Enabled}" -eq 1 ] ; then # если включен режим сиптранка
TRUNK_MODE_COMMENT=";"
if [ -z "${RD_SiptrunkName}" ] ; then # если имя транка не задано явно
if [ "${DualSipKalitka}" -ne 1 ] ; then # и калитки не ходят напрямую
RD_SiptrunkName="${KalitkaName_1_rd}" # то присвоим транку имя первой калитки
RD_SiptrunkPassword="${KalitkaPassword_1_rd:-${PanelPassword_rd}}"
elif [ "${DualSipPanel}" -ne 1 ] ; then # если калитки ходят напрямую, но подъезды нет
RD_SiptrunkName="${PanelName_Dom1_P1_rd}" # то транком будет первая пенель
RD_SiptrunkPassword="${PanelPassword_Dom1_P1_rd:-${PanelPassword_rd}}"
else
echo "Ошибка. Не удаётся определить имя транка для режима siptrunk" #
exit 1
fi
fi
echo -e "\n\n; Сиптранк для РД" >> "${INTERMEDIATE_wizard}"
echo -e "\n[rosdom_\${RD_SiptrunkName}](rosdom_trunk_template)" >> "${INTERMEDIATE_wizard}"
echo "endpoint/from_user = \${RD_SiptrunkName}" >> "${INTERMEDIATE_wizard}"
echo "outbound_auth/username = \${RD_SiptrunkName}" >> "${INTERMEDIATE_wizard}"
if [ ! -z "${RD_SiptrunkPassword}" ] ; then echo "outbound_auth/password = \${RD_SiptrunkPassword}" >> "${INTERMEDIATE_wizard}" ; fi
else
RD_SiptrunkName="" # Do we need this line?
fi
echo -e "\n\n; Список калиток. Локальные учётки и внешние (если нужно)" >> "${INTERMEDIATE_wizard}"
echo -e "\n\n; Список калиток." >> "${INTERMEDIATE_vars}"
for (( kal_i=1 ; kal_i<=9 ; kal_i++ )) ; do
kalname="KalitkaName_${kal_i}"
kalname_rd="KalitkaName_${kal_i}_rd"
kalpass="KalitkaPassword_${kal_i}"
kalpass_rd="KalitkaPassword_${kal_i}_rd"
if [ ! -z "${!kalname}" ] ; then
export KalitkaName_${kal_i}_rd=${!kalname_rd:-${!kalname}}
# Переменные для калиток в промежуточный шаблон
echo "KALITKA${kal_i}=\${KalitkaName_${kal_i}}" >> "${INTERMEDIATE_vars}"
echo "KALITKA${kal_i}_EXT=\${KalitkaName_${kal_i}_rd}" >> "${INTERMEDIATE_vars}"
# Сущности pjsip для калиток в промежуточный шаблон
echo -e "\n\n[\${KalitkaName_${kal_i}}](domofon_template)" >> "${INTERMEDIATE_wizard}"
echo "inbound_auth/username = \${KalitkaName_${kal_i}}" >> "${INTERMEDIATE_wizard}"
if [ ! -z "${!kalpass}" ] ; then echo -e "inbound_auth/password = \${KalitkaPassword_${kal_i}}" >> "${INTERMEDIATE_wizard}" ; fi
echo "endpoint/context = from-kalitka-${kal_i}" >> "${INTERMEDIATE_wizard}"
# Если у нас не сиптранк, то создадим внешние каналы (если калитки сами звонить не умеют в РД.)
if [ "${SIPTrunk_Mode_Enabled}" -ne 1 ] && [ "${DualSipKalitka}" -ne 1 ]; then
echo -e "\n[rosdom_\${KalitkaName_${kal_i}_rd}](rosdom_trunk_template)" >> "${INTERMEDIATE_wizard}"
# echo "endpoint/from_user = \${KalitkaName_${kal_i}_rd}" >> "${INTERMEDIATE_wizard}" # В режиме транка не нужно, иначе перебивает подмен CallerID
echo "outbound_auth/username = \${KalitkaName_${kal_i}_rd}" >> "${INTERMEDIATE_wizard}"
if [ ! -z "${!kalpass_rd}" ] ; then echo -e "outbound_auth/password = \${KalitkaPassword_${kal_i}_rd}" >> "${INTERMEDIATE_wizard}" ; fi
fi
fi
done
echo -e "\n\n\n; Список подъездов. Локальные учётки и внешние (если нужно)" >> "${INTERMEDIATE_wizard}"
echo -e "\n\n; Список подъездов." >> "${INTERMEDIATE_vars}"
for (( dom_i=1 ; dom_i<=9 ; dom_i++ )) ; do
dompref="Dom${dom_i}_Prefix"
if [ -z "${!dompref}" ] ; then continue ; fi
echo -e "\nDOM${dom_i}PREFIX=\${Dom${dom_i}_Prefix}\n" >> "${INTERMEDIATE_vars}"
for (( pod_i=1 ; pod_i<=9 ; pod_i++ )) ; do
podname="PanelName_Dom${dom_i}_P${pod_i}"
podname_rd="PanelName_Dom${dom_i}_P${pod_i}_rd"
podpass="PanelPassword_Dom${dom_i}_P${pod_i}"
podpass_rd="PanelPassword_Dom${dom_i}_P${pod_i}_rd"
if [ ! -z "${!podname}" ] ; then
export PanelName_Dom${dom_i}_P${pod_i}_rd=${!podname_rd:-${!podname}}
# Переменные для подъездов в промежуточный шаблон
echo -e "DOM${dom_i}P${pod_i}trunk=\${PanelName_Dom${dom_i}_P${pod_i}}" >> "${INTERMEDIATE_vars}"
echo -e "DOM${dom_i}P${pod_i}trunkExt=\${PanelName_Dom${dom_i}_P${pod_i}_rd}" >> "${INTERMEDIATE_vars}"
echo -e "DOM${dom_i}P${pod_i}min=\${Flat_Dom${dom_i}_P${pod_i}_min}" >> "${INTERMEDIATE_vars}"
echo -e "DOM${dom_i}P${pod_i}max=\${Flat_Dom${dom_i}_P${pod_i}_max}" >> "${INTERMEDIATE_vars}"
# Сущности pjsip для домовых панелей в промежуточный шаблон
echo -e "\n\n[\${PanelName_Dom${dom_i}_P${pod_i}}](domofon_template)" >> "${INTERMEDIATE_wizard}"
echo -e "inbound_auth/username = \${PanelName_Dom${dom_i}_P${pod_i}}" >> "${INTERMEDIATE_wizard}"
if [ ! -z "${!podpass}" ] ; then echo -e "inbound_auth/password = \${PanelPassword_Dom${dom_i}_P${pod_i}}" >> "${INTERMEDIATE_wizard}" ; fi
echo -e "endpoint/context = from-panel-d${dom_i}p${pod_i}" >> "${INTERMEDIATE_wizard}"
# Если у нас не сиптранк, то создадим внешние каналы для панелей (если панели сами звонить не умеют в РД.)
if [ "${SIPTrunk_Mode_Enabled}" -ne 1 ] && [ "${DualSipPanel}" -ne 1 ]; then
echo -e "\n[rosdom_\${PanelName_Dom${dom_i}_P${pod_i}_rd}](rosdom_trunk_template)" >> "${INTERMEDIATE_wizard}"
echo -e "endpoint/from_user = \${PanelName_Dom${dom_i}_P${pod_i}_rd}" >> "${INTERMEDIATE_wizard}"
echo -e "outbound_auth/username = \${PanelName_Dom${dom_i}_P${pod_i}_rd}" >> "${INTERMEDIATE_wizard}"
if [ ! -z "${!podpass_rd}" ] ; then echo -e "outbound_auth/password = \${PanelPassword_Dom${dom_i}_P${pod_i}_rd}" >> "${INTERMEDIATE_wizard}" ; fi
fi
fi
done
done
set +a
# Подставим переменные
envsubst < "${INTERMEDIATE_vars}" > "${INTERMEDIATE_vars%.template}"
envsubst < "${INTERMEDIATE_wizard}" > "${INTERMEDIATE_wizard%.template}"
# Подчистим временные файлы
rm -fv "${INTERMEDIATE_wizard}"
rm -fv "${INTERMEDIATE_vars}"
echo "Закончили"
Создадим файл envVariables.txt с содержимым, удовлетворяющим условиям:
# 1 - Если выход в РД настроен в виде siptrunk,
SIPTrunk_Mode_Enabled = 1
RD_SiptrunkName = "siptrunk_kalitki-doma" # имя сиптранка. Если не указано, то будет использовано от первой калитки.
RD_SiptrunkPassword = "qDf#jFh&dS%AKJc87@"
# Умеют ли калитки напрямую звонить в Росдомофон? 1 = да. 0 = нет. Рекомендуется включать для панелей Beward.
DualSipKalitka = 1
# Умеют ли подъездные панели напрямую звонить в Росдомофон? 1 = да. 0 = нет. Рекомендуется включать для панелей Beward.
DualSipPanel = 1
# Адрес сип сервера с портом (для Транка только порт 5062)
Sip_Server = "sip.rosdomofon.com:5062"
# Общий пароль, с которым панели ходят регистрироваться в астериск (будет использован, если не заданы индивидуальные)
PanelPassword = "123456"
# общий пароль для регистрации астериска в Росдомофоне (будет использован, если не заданы индивидуальные)
PanelPassword_rd = "qDf#jFh&dS%AKJc87@"
# Ограничение - не более 9 домов по 9 подъездов в каждом
# И не более 9 калиток
#
# Параметры для Калиток
#
# Названия калитки №1 локальное и в системе Росдомофон.
KalitkaName_1 = "kalitka1"
KalitkaName_1_rd = "siptrunk_kalitka1"
# Пароль для конкретной панели,
# первый - для регистрации панели в астериске, второй - для регистрации астериска в Росдомофоне
# (второй пароль только для случая, если астериск отвечает за все звонки)
# Можно не задавать, тогда будет использован общий
KalitkaPassword_1 = "123456"
KalitkaPassword_1_rd = "qDf#jFh&dS%AKJc87@"
#
#
# Параметры для Первого дома
#
# Префикс. Такой же, как указан на калиточном домофоне (если есть такая опция).
Dom1_Prefix = "0001"
# Названия панели (дом 1, подъезд 1) локальное и в системе Росдомофон.
PanelName_Dom1_P1 = "dom1-p1"
PanelName_Dom1_P1_rd = "siptrunk_dom1-p1"
# Пароль для конкретной панели,
# первый - для регистрации панели в астериске, второй - для регистрации астериска в Росдомофоне
# (второй пароль только для случая, если астериск отвечает за все звонки и не в режиме сиптранка)
# Можно не задавать, тогда будет использован общий
PanelPassword_Dom1_P1 = "123456"
PanelPassword_Dom1_P1_rd = "qDf#jFh&dS%AKJc87@"
# Подъезд 1
Flat_Dom1_P1_min=1
Flat_Dom1_P1_max=10
# Подъезд 2
Flat_Dom1_P2_min=11
Flat_Dom1_P2_max=20
PanelName_Dom1_P2 = "dom1-p2"
PanelName_Dom1_P2_rd = "siptrunk_dom1-p2"
#
Условный пример, без Бевардов.
# 1 - Если выход в РД настроен в виде siptrunk,
SIPTrunk_Mode_Enabled = 1
RD_SiptrunkName = "siptrunk_Rosinka78" # имя сиптранка.
# Умеют ли калитки напрямую звонить в Росдомофон? 1 = да. 0 = нет. Рекомендуется включать для панелей Beward.
DualSipKalitka = 0
# Умеют ли подъездные панели напрямую звонить в Росдомофон? 1 = да. 0 = нет. Рекомендуется включать для панелей Beward.
DualSipPanel = 0
# Адрес сип сервера с портом (для Транка только порт 5062)
Sip_Server = "sip.rosdomofon.com:5062"
# Общий пароль, с которым панели ходят регистрироваться в астериск (будет использован, если не заданы индивидуальные)
PanelPassword = "123456"
# общий пароль для регистрации астериска в Росдомофоне (будет использован, если не заданы индивидуальные)
PanelPassword_rd = "qDf#jFh&dS%AKJc87@"
# Параметры для Калиток
#
# Названия калитки №1 локальное и в системе Росдомофон.
KalitkaName_1 = "rosinka-kal1"
KalitkaName_1_rd = "siptrunk_rosinka-kal1"
# Вторая калитка
KalitkaName_2 = "rosinka-kal2"
KalitkaName_2_rd = "siptrunk_rosinka-kal2"
# Третья калитка
KalitkaName_2 = "rosinka-kal-master"
KalitkaName_2_rd = "siptrunk_rosinka-kal3"
# Параметры для Первого дома
#
Dom1_Prefix = "0007"
# Подъезд 1
PanelName_Dom1_P1 = "rosinkad7p1"
PanelName_Dom1_P1_rd = "siptrunk_rosinkad7p1"
Flat_Dom1_P1_min=1
Flat_Dom1_P1_max=100
# Подъезд 2
PanelName_Dom1_P2 = "rosinkad7p2"
PanelName_Dom1_P2_rd = "siptrunk_rosinkad7p2"
Flat_Dom1_P2_min=101
Flat_Dom1_P2_max=200
# Подъезд 3
PanelName_Dom1_P3 = "rosinkad7p3"
PanelName_Dom1_P3_rd = "siptrunk_rosinkad7p3"
Flat_Dom1_P3_min=200
Flat_Dom1_P3_max=299
#
# Параметры для Второго дома
#
Dom2_Prefix = "0008"
# Подъезд 1
PanelName_Dom2_P1 = "rosinkad8p1"
PanelName_Dom2_P1_rd = "siptrunk_rosinkad8p1"
Flat_Dom2_P1_min=1
Flat_Dom2_P1_max=100
# Подъезд 2
PanelName_Dom2_P2 = "rosinkad8p2"
PanelName_Dom2_P2_rd = "siptrunk_rosinkad8p2"
Flat_Dom2_P2_min=101
Flat_Dom2_P2_max=200
# Подъезд 3
PanelName_Dom3_P3 = "rosinkad8p3"
PanelName_Dom3_P3_rd = "siptrunk_rosinkad8p3"
Flat_Dom3_P3_min=200
Flat_Dom3_P3_max=299
#
Должна получится следующая структура файлов:
~/asterisk-workdir
├── envVariables.txt
├── genconfig.sh
└── templates
├── extentions.conf
├── modules.conf
├── pjsip.conf
├── pjsip_notify.conf
├── pjsip_wizard.conf
└── rosdomofon.vars
Запускаем скрипт и должны получить такой вывод.
$ bash genconfigs.sh
'templates/modules.conf' -> 'result/modules.conf'
'templates/extensions.conf' -> 'result/extensions.conf'
'templates/pjsip.conf' -> 'result/pjsip.conf'
'templates/pjsip_notify.conf' -> 'result/pjsip_notify.conf'
'templates/pjsip_wizard.conf' -> 'result/pjsip_wizard.conf.template'
'templates/rosdomofon.vars' -> 'result/rosdomofon.vars.template'
removed 'result/pjsip_wizard.conf.template'
removed 'result/rosdomofon.vars.template'
Закончили
В случае чистой установки asteriskm копируем полученный результат из папки result в конфиги астериска и перезапускаем сервис
sudo cp result/* /etc/asterisk/
sudo service asterisk restart
Оптимальным решением будет прописывать локальный астериск по ip адресу на SIP1, а Росдомофон на SIP2.