Система автоконфигурации для VoIP устройств на коленке

Когда у тебя в хозяйстве больше двух компьютеров очень часто приходит желание иметь возможность конфигурировать их из одного места. В среде Windows эта задача решается с помощью Active Directory, в Linux – с помощью cfengine, puppet и других систем конфигурации. У меня же было много VoIP устройств в которых постоянно приходилось что-то менять: то номер, то план дозвона, то надпись на экране и т.д.
Для этой цели также существуют системы автоконфигурации, но, по разным причинам, они мне не подходили. Да и хотелось изобрести свой велосипед что-то написать своими руками.

Дальше можно почитать что же из этого получилось…


Итак что мы имеем:
  • на входе, Asterisk PBX (или другую IP АТС) и кучу VoIP устройств.
  • на выходе я хочу получить возможность конфигурировать все свои VoIP устройства централизованно.


Мне повезло что мы придерживались одной линии и почти все устройства у нас были от одного производителя, а те несколько экземпляров которые были другими давно готовились в утиль. Все устройства были от Linksys: PAP2T, SPA3102, SPA901, SPA921, SPA941, SPA942. Позднее добавились и более новые Cisco SPA502 (после того как Cisco купила Linksys)
Все эти устройства имеют возможность автоматической конфигурации. Главное знать как правильно сформировать и подсунуть конфигурационный файл.

Для каждого из наших устройств есть утилита от производителя, которая генерирует конфигурационный файл, также его можно просто вытащить из устройства (вот по такому линку device_ip/admin/spacfg.xml — но это работает не на всех устройствах ) или найти где-то на бескрайних просторах интернета.
Конфигурационный файл – это просто xml файл с описаниями опций. В устройство конфигурационный файл можно залить tftp или http по протоколах. Во всех наших устройствах основные настройки описывались почти одинаково, что позволило просто выделить основную часть настроек которая была общей для всех устройств и дополнительные опции, которые отличались для каждого устройства. В итоге сформировалась такая схема работы системы автоконфигурации:

image

Один скрипт (generator.sh) собирает конфигурационный файл из информации об устройстве описанной в файле devices.list и кусков конфигурации из каталога templates {modelName, common/start, common/network, common/end}.
Другой скрипт (pusher.sh) – копирует уже сформированные файлы конфигурации устройств в каталог доступный через http:
http://server_ip/configs
а затем обращается к устройству по специальному линку в котором содержится информация откуда взять конфигурацию и затем её применить:
curl --digest -u USERNAME:PASSWORD  http://device_IP/admin/resync? http://server_ip/configs/CONFIGFILE.xml


Вот основные способы использования:

Добавление устройства:
1. Добавляем в DNS запись об устройстве
2. Подключаем устройство к сети – прописываем на нем его IP адресс (мы не используем DHCP для VoIP устройств ) и пароль администратора
3. Добавляем в файл devices.list строку которая описывает конфигурацию устройства, строка должна быть вот такого формата:
DEVICE_MODEL|NETWORK_NAME|LINE1_DESCR|LINE1_NUMBER|LINE1_PASS|LINE2_DESCR|LINE2_NUMBER|LINE2_PASS|STATION_NAME|USER_PASSWORD
Ненужные поля просто делаем пустыми, но позиционность параметров сохраняем.
4. Запускаем generator.sh
5. Запускаем pusher.sh single NETWORK_NAME_IN_DNS и смотрим лог в терминале

Изменение номера на устройстве:
1. Изменяем в файле devices.list строку которая описывает конфигурацию устройства.
2. Запускаем generator.sh
3. Запускаем pusher.sh single NETWORK_NAME_IN_DNS

Изменение dial плана на всех VoIP устройствах:
1. Правим generator.sh – в нём есть переменная которая отвечает за dial план.
2. Запускаем generator.sh
3. Запускаем pusher.sh all и смотрим лог в терминале или на вашем syslog сервере (он же у Вас есть, правда? ). Например, вот так: tail -f /var/log/messages | egrep -i "(pap2t|spa-)"

Данная система автоконфигурации абсолютно не требовательна к ресурсам и может быть установлена на любой linux дистрибутив.
Для её работы нужен bash, такие утилиты как sed, cut и вебсервер для отдачи файлов на устройства.

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

На данный момент моя система автоконфигурации уже успешно работает несколько лет.
Надеюсь моя статья сможет кому-то упростить жизнь. По подобному принципу можно построить конфигурацию для устройств от очень многих производителей.

Удачи.

Листинги скриптов и файлов конфигурации:
devices.list
#############################################################################################################################################
# LINE FORMAT: DEVICE_MODEL|NETWORK_NAME|LINE1_DESCR|LINE1_NUMBER|LINE1_PASS|LINE2_DESCR|LINE2_NUMBER|LINE2_PASS|STATION_NAME|USER_PASSWORD #
#############################################################################################################################################

#################
# voip gateways #
#################

#PAP2T
PAP2T|voip1.f3r1|Reception1|3000|3000pass|Reception2|3001|3001pass
PAP2T|voip2.f3r1|Finance|3030|3030pass|||


#SPA3102
SPA3102|voip0.f3r1|Meeting room|3131|3131pass

###############
# voip phones #
###############

#SPA901
SPA901|vph0.f3lr2|Zavhoz|3040|3040pass|||

#SPA921
SPA921|vph0.f3r3|Boss|3050|3050pass||||Shef|1234

#SPA941
SPA941|vph0.f3r4|Admin|3060|3060pass||||Admin|3060

#SPA942
SPA941|vph0.f4r1|Manager1|3080|3080pass||||Manager1

# Cisco SPA502G
SPA502G|vph1.f4r1|Manager2|3090|3090pass||||Manager2


generator.sh
#!/bin/bash

########################################## config section ##############################################

adminPass='qwerty123'
userPass='qwerty123'

dialPlan='(*8S0|*xx|1[0-9][0-9]S0|[95][0-9]xxS0|2xxxxxxS0|0[3-7]xxxxxxxxS0|0[89]x[1-9]xxxxxxS0|0[89]00xxxxxxxS0|02xxxxxxxS0|xxxxxxxxxxxx.)'
sipProxy='sip.yourdomain.com'

# here is configs for PSTN line on SPA3102 devices
dialPlanSPA3102='(xx.)'
sipProxySPA3102=$sipProxy

########################################### do not edit below this ######################################

curPath=`dirname ${0}`

devicesList=${curPath}/devices.list


cat ${devicesList} | sed '/ *#/d; /^ *$/d' | while read line;
    do
	model=`echo ${line} | cut -f1 -d'|' | tr '[:lower:]' '[:upper:]'`
	networkName=`echo ${line} | cut -f2 -d'|' `
	ipStr=`host -t any ${networkName}`
        if [ `echo ${ipStr}| grep 'not found:' | wc -l` -gt 0   ] 
    	    then 
	        echo "Error: ${networkName} not found in DNS. Please, fix this. "
	        exit 1
	    else
		ip=`echo ${ipStr} | cut -f4 -d' ' `
	fi
	echo -n "Device ip - ${ip}. "
	line1Descr=`echo ${line} | cut -f3 -d'|' `
        line1Phone=`echo ${line} | cut -f4 -d'|' `
        line1Pass=`echo ${line} | cut -f5 -d'|' `
	line2Descr=`echo ${line} | cut -f6 -d'|' `
	line2Phone=`echo ${line} | cut -f7 -d'|' `
        line2Pass=`echo ${line} | cut -f8 -d'|' `
	stationName=`echo ${line} | cut -f9 -d'|' `
	userPassFromConfig=`echo ${line} | cut -f10 -d'|' `
	if [ "${userPassFromConfig}" != "" ]
	    then
		userPass=${userPassFromConfig}
		echo -n "Set not default user pass. "
	fi
	
	case "${model}" in
	PAP2T)
	    echo "Creating profile for ${model} - ${networkName}..." 
	    outputFile=${curPath}/configs/${model}-${ip}.xml
	    cat ${curPath}/templates/common/start > ${outputFile}
	    cat ${curPath}/templates/common/network >> ${outputFile}
	    cat ${curPath}/templates/pap2t >> ${outputFile}

	    # here config individual settings
	    echo '  <Static_IP ua="rw">'${ip}'</Static_IP>'  >> ${outputFile}
	    echo '  <HostName ua="rw">'${networkName}'</HostName>' >> ${outputFile}

	    echo '  <Admin_Passwd ua="na">'${adminPass}'</Admin_Passwd>' >> ${outputFile}
	    echo '  <User_Password ua="rw">'${userPass}'</User_Password>' >> ${outputFile}
	    
	    echo '  <Display_Name_1_ ua="na">'${line1Descr}'</Display_Name_1_>' >> ${outputFile}
	    echo '  <User_ID_1_ ua="na">'${line1Phone}'</User_ID_1_>' >> ${outputFile}
	    echo '  <Password_1_ ua="na">'${line1Pass}'</Password_1_>' >> ${outputFile}

	    echo '  <Display_Name_2_ ua="na">'${line2Descr}'</Display_Name_2_>' >> ${outputFile}
	    echo '  <User_ID_2_ ua="na">'${line2Phone}'</User_ID_2_>' >> ${outputFile}
	    echo '  <Password_2_ ua="na">'${line2Pass}'</Password_2_>' >> ${outputFile}
            
	    echo '  <Dial_Plan_1_ ua="na">'${dialPlan}'</Dial_Plan_1_>' >> ${outputFile}
	    echo '  <Proxy_1_ ua="na">'${sipProxy}'</Proxy_1_>' >> ${outputFile}

	    echo '  <Dial_Plan_2_ ua="na">'${dialPlan}'</Dial_Plan_2_>' >> ${outputFile}
	    echo '  <Proxy_2_ ua="na">'${sipProxy}'</Proxy_2_>' >> ${outputFile}

	    cat ${curPath}/templates/common/end >> ${outputFile}
	    ;;

	SPA3102)
	    echo "Creating profile for ${model} - ${networkName}..." 
	    outputFile=${curPath}/configs/${model}-${ip}.xml
	    cat ${curPath}/templates/common/start > ${outputFile}
	    cat ${curPath}/templates/common/network >> ${outputFile}
	    cat ${curPath}/templates/spa3102 >> ${outputFile}

	    # here config individual settings
	    echo '  <Static_IP ua="rw">'${ip}'</Static_IP>'  >> ${outputFile}
	    echo '  <HostName ua="rw">'${networkName}'</HostName>' >> ${outputFile}

	    echo '  <Admin_Passwd ua="na">'${adminPass}'</Admin_Passwd>' >> ${outputFile}
	    echo '  <User_Password ua="rw">'${userPass}'</User_Password>' >> ${outputFile}
	    
	    echo '  <Display_Name_1_ ua="na">'${line1Descr}'</Display_Name_1_>' >> ${outputFile}
	    echo '  <User_ID_1_ ua="na">'${line1Phone}'</User_ID_1_>' >> ${outputFile}
	    echo '  <Password_1_ ua="na">'${line1Pass}'</Password_1_>' >> ${outputFile}

	    echo '  <Display_Name_2_ ua="na">'${line2Descr}'</Display_Name_2_>' >> ${outputFile}
	    echo '  <User_ID_2_ ua="na">'${line2Phone}'</User_ID_2_>' >> ${outputFile}
	    echo '  <Password_2_ ua="na">'${line2Pass}'</Password_2_>' >> ${outputFile}
            
	    echo '  <Dial_Plan_1_ ua="na">'${dialPlan}'</Dial_Plan_1_>' >> ${outputFile}
	    echo '  <Proxy_1_ ua="na">'${sipProxy}'</Proxy_1_>' >> ${outputFile}
	    
    	    echo '  <Dial_Plan_1_2_ ua="na">'${dialPlanSPA3102}'</Dial_Plan_1_2_>' >> ${outputFile}
	    echo '  <Proxy_2_ ua="na">'${sipProxySPA3102}'</Proxy_2_>' >> ${outputFile}

	    cat ${curPath}/templates/common/end >> ${outputFile}
	    ;;

	SPA901)
	    echo "Creating profile for ${model} - ${networkName}..." 
	    outputFile=${curPath}/configs/${model}-${ip}.xml
	    cat ${curPath}/templates/common/start > ${outputFile}
	    cat ${curPath}/templates/common/network >> ${outputFile}
	    cat ${curPath}/templates/spa901 >> ${outputFile}

	    # here config individual settings
	    echo '  <Static_IP ua="rw">'${ip}'</Static_IP>'  >> ${outputFile}
	    echo '  <HostName ua="rw">'${networkName}'</HostName>' >> ${outputFile}

	    echo '  <Admin_Passwd ua="na">'${adminPass}'</Admin_Passwd>' >> ${outputFile}
	    echo '  <User_Password ua="rw">'${userPass}'</User_Password>' >> ${outputFile}
	    
	    echo '  <Display_Name_1_ ua="na">'${line1Descr}'</Display_Name_1_>' >> ${outputFile}
	    echo '  <User_ID_1_ ua="na">'${line1Phone}'</User_ID_1_>' >> ${outputFile}
	    echo '  <Password_1_ ua="na">'${line1Pass}'</Password_1_>' >> ${outputFile}

	    echo '  <Dial_Plan_1_ ua="na">'${dialPlan}'</Dial_Plan_1_>' >> ${outputFile}
	    echo '  <Proxy_1_ ua="na">'${sipProxy}'</Proxy_1_>' >> ${outputFile}

	    cat ${curPath}/templates/common/end >> ${outputFile}
	    ;;

	SPA921)
	    echo "Creating profile for ${model} - ${networkName}..." 
	    outputFile=${curPath}/configs/${model}-${ip}.xml
	    cat ${curPath}/templates/common/start > ${outputFile}
	    cat ${curPath}/templates/common/network >> ${outputFile}
	    #cat ${curPath}/templates/spa921 >> ${outputFile}
    	    
	    # here config individual settings
	    echo '  <Static_IP ua="rw">'${ip}'</Static_IP>'  >> ${outputFile}
	    echo '  <HostName ua="rw">'${networkName}'</HostName>' >> ${outputFile}
	    
	    echo '  <Admin_Passwd ua="na">'${adminPass}'</Admin_Passwd>' >> ${outputFile}
	    echo '  <User_Password ua="rw">'${userPass}'</User_Password>' >> ${outputFile}

	    echo '  <Station_Name ua="na">'${stationName}'</Station_Name>' >> ${outputFile}
	    
	    echo '  <Display_Name_1_ ua="na">'${line1Descr}'</Display_Name_1_>' >> ${outputFile}
	    echo '  <User_ID_1_ ua="na">'${line1Phone}'</User_ID_1_>' >> ${outputFile}
	    echo '  <Password_1_ ua="na">'${line1Pass}'</Password_1_>' >> ${outputFile}

	    echo '  <Dial_Plan_1_ ua="na">'${dialPlan}'</Dial_Plan_1_>' >> ${outputFile}
	    echo '  <Proxy_1_ ua="na">'${sipProxy}'</Proxy_1_>' >> ${outputFile}

	    cat ${curPath}/templates/common/end >> ${outputFile}
	    ;;

	SPA941)
	    echo "Creating profile for ${model} - ${networkName}..." 
	    outputFile=${curPath}/configs/${model}-${ip}.xml
	    cat ${curPath}/templates/common/start > ${outputFile}
	    cat ${curPath}/templates/common/network >> ${outputFile}
	    #cat ${curPath}/templates/spa941 >> ${outputFile}

	    # here config individual settings
	    echo '  <Static_IP ua="rw">'${ip}'</Static_IP>'  >> ${outputFile}
	    echo '  <HostName ua="rw">'${networkName}'</HostName>' >> ${outputFile}

	    echo '  <Admin_Passwd ua="na">'${adminPass}'</Admin_Passwd>' >> ${outputFile}
	    echo '  <User_Password ua="rw">'${userPass}'</User_Password>' >> ${outputFile}

	    echo '  <Station_Name ua="na">'${stationName}'</Station_Name>' >> ${outputFile}
	    
	    echo '  <Display_Name_1_ ua="na">'${line1Descr}'</Display_Name_1_>' >> ${outputFile}
	    echo '  <User_ID_1_ ua="na">'${line1Phone}'</User_ID_1_>' >> ${outputFile}
	    echo '  <Password_1_ ua="na">'${line1Pass}'</Password_1_>' >> ${outputFile}

	    echo '  <Display_Name_2_ ua="na">'${line2Descr}'</Display_Name_2_>' >> ${outputFile}
	    echo '  <User_ID_2_ ua="na">'${line2Phone}'</User_ID_2_>' >> ${outputFile}
	    echo '  <Password_2_ ua="na">'${line2Pass}'</Password_2_>' >> ${outputFile}
            
	    echo '  <Dial_Plan_1_ ua="na">'${dialPlan}'</Dial_Plan_1_>' >> ${outputFile}
	    echo '  <Proxy_1_ ua="na">'${sipProxy}'</Proxy_1_>' >> ${outputFile}

	    echo '  <Dial_Plan_2_ ua="na">'${dialPlan}'</Dial_Plan_2_>' >> ${outputFile}
	    echo '  <Proxy_2_ ua="na">'${sipProxy}'</Proxy_2_>' >> ${outputFile}

	    cat ${curPath}/templates/common/end >> ${outputFile}
	    ;;
	
	SPA502G)
	    echo "Creating profile for ${model} - ${networkName}..." 
	    outputFile=${curPath}/configs/${model}-${ip}.xml
	    cat ${curPath}/templates/common/start > ${outputFile}
	    cat ${curPath}/templates/common/network >> ${outputFile}
	    cat ${curPath}/templates/spa502g >> ${outputFile}

	    # here config individual settings
	    echo '  <Static_IP ua="rw">'${ip}'</Static_IP>'  >> ${outputFile}
	    echo '  <HostName ua="rw">'${networkName}'</HostName>' >> ${outputFile}

	    echo '  <Admin_Passwd ua="na">'${adminPass}'</Admin_Passwd>' >> ${outputFile}
	    echo '  <User_Password ua="rw">'${userPass}'</User_Password>' >> ${outputFile}
	    
	        
	    echo '  <Station_Name ua="na">'${stationName}'</Station_Name>' >> ${outputFile}
	    #<Station_Display_Name ua="na"></Station_Display_Name>
	    
	    echo '  <Display_Name_1_ ua="na">'${line1Descr}'</Display_Name_1_>' >> ${outputFile}
	    echo '  <User_ID_1_ ua="na">'${line1Phone}'</User_ID_1_>' >> ${outputFile}
	    echo '  <Password_1_ ua="na">'${line1Pass}'</Password_1_>' >> ${outputFile}

	    echo '  <Dial_Plan_1_ ua="na">'${dialPlan}'</Dial_Plan_1_>' >> ${outputFile}
	    echo '  <Proxy_1_ ua="na">'${sipProxy}'</Proxy_1_>' >> ${outputFile}

	    cat ${curPath}/templates/common/end >> ${outputFile}
	    ;;


	esac    
	
    done 


pusher.sh
#!/bin/bash

user=admin
pass=qwerty123
sourceLink="http://192.168.50.10/configs"

configsPath="`dirname ${0}`/configs"

cp ${configsPath}/*.xml /var/www/html/configs


case $1 in
    all)
        ls -1 ${configsPath} | while read line;
	do
	    deviceIP=`echo ${line} | cut -f2 -d- | cut -f1-4 -d.`
	    echo "${deviceIP} _______________________________________________________________________"
	    curl --digest -u ${user}:${pass} http://${deviceIP}/admin/resync?${sourceLink}/${line}
        done
    ;;
    single)
        networkName=$2
	ipStr=`host -t any ${networkName}`
        if [ `echo ${ipStr}| grep 'not found:' | wc -l` -gt 0   ] 
    	    then 
	        echo "Error: ${networkName} not found in DNS. Please, fix this. "
	        exit 1
	    else
		ip=`echo ${ipStr} | cut -f4 -d' ' `
	fi

        ls -1 ${configsPath} | grep ${ip} | while read line;
	do
	    deviceIP=`echo ${line} | cut -f2 -d- | cut -f1-4 -d.`
	    echo "${deviceIP} _______________________________________________________________________"
	    curl --digest -u ${user}:${pass} http://${deviceIP}/admin/resync?${sourceLink}/${line}
        done
    ;;
    *)
	echo "Use this script with parameters. Here is examples:"
	echo "*${0} all* - for provisioning on all devices"
	echo "*${0} single NETWORK_NAME_IN_DNS* - for provisioning on single device"
    ;;
esac


templates/pap2t
  <Ring_Waveform ua="na">Trapezoid</Ring_Waveform>


templates/spa3102
  <Ring_Waveform ua="na">Trapezoid</Ring_Waveform>
  <FAX_Line_Toggle_Code ua="na"></FAX_Line_Toggle_Code>


templates/spa502g
<Paging_Code ua="na"></Paging_Code>
<Call_Park_Code ua="na"></Call_Park_Code>
<Call_UnPark_Code ua="na"></Call_UnPark_Code>
<Call_Pickup_Code ua="na"></Call_Pickup_Code>
<Group_Call_Pickup_Code ua="na"></Group_Call_Pickup_Code>
<Enable_CDP ua="na">No</Enable_CDP>


templates/spa901
<Paging_Code ua="na"></Paging_Code>
<Call_Park_Code ua="na"></Call_Park_Code>
<Call_UnPark_Code ua="na"></Call_UnPark_Code>
<Call_Pickup_Code ua="na"></Call_Pickup_Code>


templates/common/start
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<flat-profile>


templates/common/network
  <Restricted_Access_Domains ua="na"></Restricted_Access_Domains>
  <Enable_Web_Server ua="na">Yes</Enable_Web_Server>
  <Web_Server_Port ua="na">80</Web_Server_Port>
  <Enable_Web_Admin_Access ua="na">Yes</Enable_Web_Admin_Access>
  <DHCP ua="rw">No</DHCP>
  <NetMask ua="rw">255.255.255.0</NetMask>
  <Gateway ua="rw">192.168.50.254</Gateway>
  <Domain ua="rw">yourdomain.com</Domain>
  <Primary_DNS ua="rw">192.168.71.3</Primary_DNS>
  <Secondary_DNS ua="rw">192.168.71.6</Secondary_DNS>
  <Primary_NTP_Server ua="na">ntp.yourdomain.com</Primary_NTP_Server>
  <Secondary_NTP_Server ua="na">ntp2.yourdomain.com</Secondary_NTP_Server>
  <Syslog_Server ua="na">syslog.yourdomain.com</Syslog_Server>
  <DNS_Server_Order ua="na">Manual</DNS_Server_Order>
  <DNS_Query_Mode ua="na">Parallel</DNS_Query_Mode>
  <Debug_Server ua="na"></Debug_Server>
  <Debug_Level ua="na">0</Debug_Level>
  <Provision_Enable ua="na">Yes</Provision_Enable>
  <Resync_On_Reset ua="na">No</Resync_On_Reset>
  <Resync_Periodic ua="na">3600</Resync_Periodic>
  <Profile_Rule ua="na">/init.cfg</Profile_Rule>
  <Profile_Rule_B ua="na"></Profile_Rule_B>
  <Profile_Rule_C ua="na"></Profile_Rule_C>
  <Profile_Rule_D ua="na"></Profile_Rule_D>
  <Upgrade_Enable ua="na">Yes</Upgrade_Enable>
  <Upgrade_Error_Retry_Delay ua="na">3600</Upgrade_Error_Retry_Delay>
  <Log_Upgrade_Request_Msg ua="na">$PN $MAC -- Requesting upgrade $SCHEME://$SERVIP:$PORT$PATH</Log_Upgrade_Request_Msg>
  <Log_Upgrade_Success_Msg ua="na">$PN $MAC -- Successful upgrade $SCHEME://$SERVIP:$PORT$PATH -- $ERR</Log_Upgrade_Success_Msg>
  <Log_Upgrade_Failure_Msg ua="na">$PN $MAC -- Upgrade failed: $ERR</Log_Upgrade_Failure_Msg>
  <Call_Return_Code ua="na"></Call_Return_Code>
  <Blind_Transfer_Code ua="na"></Blind_Transfer_Code>
  <Call_Back_Act_Code ua="na"></Call_Back_Act_Code>
  <Call_Back_Deact_Code ua="na"></Call_Back_Deact_Code>
  <Cfwd_All_Act_Code ua="na"></Cfwd_All_Act_Code>
  <Cfwd_All_Deact_Code ua="na"></Cfwd_All_Deact_Code>
  <Cfwd_Busy_Act_Code ua="na"></Cfwd_Busy_Act_Code>
  <Cfwd_Busy_Deact_Code ua="na"></Cfwd_Busy_Deact_Code>
  <Cfwd_No_Ans_Act_Code ua="na"></Cfwd_No_Ans_Act_Code>
  <Cfwd_No_Ans_Deact_Code ua="na"></Cfwd_No_Ans_Deact_Code>
  <Cfwd_Last_Act_Code ua="na"></Cfwd_Last_Act_Code>
  <Cfwd_Last_Deact_Code ua="na"></Cfwd_Last_Deact_Code>
  <Block_Last_Act_Code ua="na"></Block_Last_Act_Code>
  <Block_Last_Deact_Code ua="na"></Block_Last_Deact_Code>
  <Accept_Last_Act_Code ua="na"></Accept_Last_Act_Code>
  <Accept_Last_Deact_Code ua="na"></Accept_Last_Deact_Code>
  <CW_Act_Code ua="na"></CW_Act_Code>
  <CW_Deact_Code ua="na"></CW_Deact_Code>
  <CW_Per_Call_Act_Code ua="na"></CW_Per_Call_Act_Code>
  <CW_Per_Call_Deact_Code ua="na"></CW_Per_Call_Deact_Code>
  <Block_CID_Act_Code ua="na"></Block_CID_Act_Code>
  <Block_CID_Deact_Code ua="na"></Block_CID_Deact_Code>
  <Block_CID_Per_Call_Act_Code ua="na"></Block_CID_Per_Call_Act_Code>
  <Block_CID_Per_Call_Deact_Code ua="na"></Block_CID_Per_Call_Deact_Code>
  <Block_ANC_Act_Code ua="na"></Block_ANC_Act_Code>
  <Block_ANC_Deact_Code ua="na"></Block_ANC_Deact_Code>
  <DND_Act_Code ua="na"></DND_Act_Code>
  <DND_Deact_Code ua="na"></DND_Deact_Code>
  <CID_Act_Code ua="na"></CID_Act_Code>
  <CID_Deact_Code ua="na"></CID_Deact_Code>
  <CWCID_Act_Code ua="na"></CWCID_Act_Code>
  <CWCID_Deact_Code ua="na"></CWCID_Deact_Code>
  <Dist_Ring_Act_Code ua="na"></Dist_Ring_Act_Code>
  <Dist_Ring_Deact_Code ua="na"></Dist_Ring_Deact_Code>
  <Speed_Dial_Act_Code ua="na"></Speed_Dial_Act_Code>
  <Secure_All_Call_Act_Code ua="na"></Secure_All_Call_Act_Code>
  <Secure_No_Call_Act_Code ua="na"></Secure_No_Call_Act_Code>
  <Secure_One_Call_Act_Code ua="na"></Secure_One_Call_Act_Code>
  <Secure_One_Call_Deact_Code ua="na"></Secure_One_Call_Deact_Code>
  <Conference_Act_Code ua="na"></Conference_Act_Code>
  <Attn-Xfer_Act_Code ua="na"></Attn-Xfer_Act_Code>
  <Modem_Line_Toggle_Code ua="na"></Modem_Line_Toggle_Code>
  <Media_Loopback_Code ua="na"></Media_Loopback_Code>
  <Time_Zone ua="na">GMT+02:00</Time_Zone>
  <Daylight_Saving_Time_Rule ua="na">start=3/-1/7/3;end=10/-1/7/4;save=1</Daylight_Saving_Time_Rule>


templates/common/end
</flat-profile>
Поделиться публикацией

Комментарии 3

    0
    Напишите пожалуйста как выдрать конфиг в формате XML из SPAXXX и PAP2.

    Подход у Вас несколько нестандартный, ведь есть же на всех девайсах Provisioning, где можно указать откуда брать конфиги — по-моему это более быстрый вариант.
      0
      Выдрать конфиг можно с помощью вот по такому линку
      http://device_ip/admin/spacfg.xml
      — но это работает не на всех устройствах.

      А подход такой потому что если просто указать provision линк на устройстве, то устройство будет брать его с определенной периодичностью (тоже можно указать), а способ указанный в статье позволяет применить конфиг практически сразу по команде с сервера
        0
        Ни на одном из 3-х устройств, не сработал такой метод выдирания…

      Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

      Самое читаемое