El archivo features.conf en Asterisk PBX v.20

El archivo features.conf es uno de los componentes fundamentales en la configuración de Asterisk PBX, ya que define las funcionalidades de llamada que los usuarios pueden activar mediante secuencias DTMF durante una conversación activa. Estas características incluyen transferencias, grabación y otras funciones avanzadas que enriquecen la experiencia telefónica.

El archivo features.conf controla las funcionalidades en llamada (in-call features) que permiten a los usuarios manipular llamadas activas sin necesidad de colgar. Las principales funcionalidades que gestiona son:

Transferencias de llamadas: Permite transferir una llamada a otra extensión, ya sea de forma ciega (blind transfer) o atendida (attended transfer).

Grabación de llamadas: Activa o desactiva la grabación de conversaciones durante la llamada mediante códigos DTMF.

Desconexión de llamadas: Permite a cualquiera de las partes finalizar la llamada mediante una secuencia específica.

Características personalizadas: Define funcionalidades adicionales mediante aplicaciones dialplan que se activan con códigos DTMF.

Pickup de llamadas: Permite contestar llamadas que están sonando en otras extensiones.

Configuración del archivo features.conf

El archivo features.conf se estructura en varias secciones principales. A continuación se detalla cada una con ejemplos prácticos:

Sección [general]

Esta sección contiene parámetros globales que afectan al comportamiento general de las características:

[general]
transferdigittimeout = 3
atxfernoanswertimeout = 15
atxferdropcall = no
atxferloopdelay = 10
atxfercallbackretries = 2
courtesytone = beep
xfersound = beep
xferfailsound = beeperr
pickupexten = *8
pickupsound = beep
pickupfailsound = beeperr
featuredigittimeout = 2000
transferdialattempts = 3
transferretrysound = beep
transferinvalidsound = beeperr

transferdigittimeout: Tiempo en segundos para ingresar dígitos durante una transferencia (por defecto 3 segundos). Si el usuario no completa la marcación de la extensión destino en este tiempo, la operación se cancela.

atxfernoanswertimeout: Tiempo de espera en segundos cuando no se contesta una transferencia atendida (por defecto 15 segundos). Si el destino no contesta, la llamada puede regresar al origen.

atxferdropcall: Define si se cuelga la llamada original cuando falla una transferencia atendida. Valores: yes/no (por defecto: no).

atxferloopdelay: Retraso en segundos antes de reintentar una transferencia fallida.

atxfercallbackretries: Número de intentos para devolver la llamada al origen cuando falla una transferencia atendida.

courtesytone: Tono que se reproduce a ambas partes antes de reconectar después de una transferencia atendida. Puede ser "beep", un archivo de sonido personalizado, o estar vacío.

xfersound: Tono que se reproduce al iniciar una transferencia exitosa.

xferfailsound: Tono que se reproduce cuando una transferencia falla.

pickupexten: Código para contestar llamadas de otras extensiones (call pickup). El valor por defecto es *8.

pickupsound: Tono que se reproduce al realizar un pickup exitoso.

pickupfailsound: Tono que se reproduce cuando el pickup falla.

featuredigittimeout: Tiempo en milisegundos para esperar entre dígitos al activar una característica (por defecto 2000ms). Este parámetro es crítico para la detección correcta de códigos DTMF.

transferdialattempts: Número de intentos permitidos para marcar el destino durante una transferencia.

transferretrysound: Tono reproducido cuando se puede reintentar la transferencia.

transferinvalidsound: Tono reproducido cuando se marca una extensión inválida durante la transferencia.

Sección [featuremap]

Define los códigos DTMF para activar cada funcionalidad. Esta es la sección más importante del archivo:

[featuremap]
blindxfer => *1
atxfer => *2
disconnect => *0
automon => *3
automixmon => *4

blindxfer: Código para transferencia ciega (blind transfer). El usuario marca el código, introduce la extensión destino y la llamada se transfiere inmediatamente sin hablar con el destino. El formato es: durante la llamada, presionar *1, marcar extensión destino, la transferencia se completa automáticamente.

atxfer: Código para transferencia atendida (attended transfer). El usuario marca el código, habla con el destino antes de completar la transferencia y puede cancelarla si es necesario. El proceso es: presionar *2, marcar extensión, hablar con el destino, colgar para completar o presionar * para cancelar.

disconnect: Permite colgar la llamada desde cualquiera de los extremos. Útil cuando los endpoints no tienen un botón de colgar confiable o en conferencias.

automon: Activa la grabación de la llamada usando la aplicación Monitor. Graba los canales por separado (entrada y salida en archivos diferentes).

automixmon: Activa la grabación usando MixMonitor, que mezcla ambos canales en un solo archivo. Este es el método preferido en versiones modernas de Asterisk.

Códigos adicionales disponibles:

  • disconnect: Desconecta la llamada
  • parkcall: Estaciona la llamada (requiere configuración adicional de parking)
  • atxferthreeway: Crea conferencia de tres vías durante transferencia atendida

Sección [applicationmap]

Permite crear funcionalidades personalizadas que ejecutan aplicaciones del dialplan. Esta sección es extremadamente poderosa para extender las capacidades de Asterisk:

[applicationmap]
pauseagent => *5,self/caller,Pause()
unpauseagent => *6,self/caller,Unpause()
togglehold => *7,self,Macro(toggle-hold)
conference => *9,peer,ConfBridge(${EXTEN})

La sintaxis es: nombre => código,activador,aplicación(argumentos)

Parámetros de activador:

  • caller: Solo el que llama puede activar la característica
  • callee: Solo el que recibe puede activar la característica
  • both: Cualquiera de las dos partes puede activarla
  • self: La característica afecta al canal que la activa
  • peer: La característica afecta al canal de la otra parte
  • self/caller: Combinación que especifica que afecta a quien llama si es el caller

Ejemplos prácticos:

[applicationmap]
; Pausar/despausar agente en cola
pauseagent => *5,self,PauseQueueMember(,Local/${CALLERID(num)}@from-internal)
unpauseagent => *6,self,UnpauseQueueMember(,Local/${CALLERID(num)}@from-internal)

; Enviar llamada a buzón de voz
sendtovm => *8,self,VoiceMail(${EXTEN}@default,s)

; Agregar la llamada a una conferencia existente
addtoconf => *9,both,ConfBridge(sala1)

; Activar/desactivar spy en otro canal
startspy => #1,self,ChanSpy(PJSIP,q)

; Ejecutar una macro personalizada
customaction => **1,caller,Macro(custom-action,${EXTEN})

; Activar/desactivar grabación con MixMonitor
togglerecord => *3,both,System(/usr/local/bin/toggle-recording.sh ${CHANNEL})

Variables de canal importantes

Durante la ejecución de características personalizadas, Asterisk proporciona variables especiales:

  • ${DYNAMIC_FEATURES}: Lista de características dinámicas habilitadas para el canal
  • ${DYNAMIC_WHO_ACTIVATED}: Quién activó la característica (caller/callee)
  • ${CHANNEL}: Canal actual
  • ${BRIDGEPEER}: Canal del peer conectado

Sección [featuregroups]

Permite agrupar características en conjuntos reutilizables:

[featuregroups]
agentfeatures => pauseagent,unpauseagent,togglerecord
managerfeatures => #startspy,#addtoconf,#togglerecord
customerfeatures => #blindxfer

Para activar un grupo de características en un canal, se usa:

; En el dialplan
same => n,Set(DYNAMIC_FEATURES=agentfeatures)
same => n,Dial(PJSIP/${EXTEN})

Integración con pjsip.conf

La integración de features.conf con los endpoints definidos en pjsip.conf es crucial para que las funcionalidades DTMF operen correctamente. Hay varios parámetros que deben configurarse adecuadamente.

Parámetros críticos en pjsip.conf

Para que un endpoint pueda utilizar las características definidas en features.conf, debe configurarse con los siguientes parámetros:

[6001](basic-endpoint)
type = endpoint
context = internal
disallow = all
allow = ulaw
allow = alaw
aors = 6001
auth = 6001
direct_media = no
dtmf_mode = rfc4733
one_touch_recording = yes
allow_transfer = yes

dtmf_mode: Este es el parámetro más importante. Define cómo se transmiten los tonos DTMF:

  • rfc4733 (recomendado): Envía DTMF como eventos RTP fuera de banda. Es el método más confiable, consume menos ancho de banda y no se degrada por códecs de audio. Este es el valor que debes usar.

  • inband: DTMF se envía como tonos audibles dentro del flujo de audio. Puede degradarse con códecs comprimidos y es menos confiable. Solo usar si los dispositivos no soportan RFC4733.

  • info: DTMF se envía mediante mensajes SIP INFO. Menos común y puede tener problemas de compatibilidad.

  • auto: Asterisk intenta detectar automáticamente el método. No recomendado para producción.

  • auto_info: Combinación de auto e info.

direct_media: Debe estar configurado en "no" para que Asterisk permanezca en el path del media y pueda detectar los códigos DTMF de características. Si está en "yes", el audio (RTP) fluye directamente entre endpoints y Asterisk no puede interceptar las secuencias DTMF. Esta es la razón número uno por la que las características no funcionan.

one_touch_recording: Habilita la grabación mediante código DTMF definido en featuremap (normalmente *3 para automon o *4 para automixmon).

allow_transfer: Permite transferencias de llamada para este endpoint. Si está en "no", los códigos de transferencia no funcionarán.

Configuración de direct_media y media_address

En escenarios más complejos, puedes necesitar:

[6001](basic-endpoint)
type = endpoint
; ... otras opciones ...
direct_media = no
media_address = 192.168.1.10
rtp_symmetric = yes
force_rport = yes
rewrite_contact = yes

media_address: IP que Asterisk anuncia en SDP. Útil cuando Asterisk está detrás de NAT.

rtp_symmetric: Envía RTP a la dirección origen en lugar de la anunciada en SDP.

force_rport: Fuerza el uso del puerto remoto real.

rewrite_contact: Reescribe el contacto SIP basándose en la IP/puerto de origen.

Habilitar características específicas por canal

Puedes habilitar características dinámicamente en el dialplan:

[internal]
exten => _6XXX,1,NoOp(Llamando a extensión ${EXTEN})
same => n,Set(DYNAMIC_FEATURES=blindxfer#atxfer#automon)
same => n,Set(__DYNAMIC_FEATURES=${DYNAMIC_FEATURES})
same => n,Dial(PJSIP/${EXTEN},30)
same => n,Hangup()

La variable DYNAMIC_FEATURES contiene una lista separada por # de las características que estarán disponibles durante la llamada. El doble guión bajo (__) hace que la variable se herede a los canales bridged.

features.conf completo

[general]
; Configuración de temporización
transferdigittimeout = 3
atxfernoanswertimeout = 15
atxferdropcall = no
atxferloopdelay = 10
atxfercallbackretries = 2
featuredigittimeout = 2000
transferdialattempts = 3

; Tonos y sonidos
courtesytone = beep
xfersound = beep
xferfailsound = beeperr
transferretrysound = beep
transferinvalidsound = beeperr

; Pickup de llamadas
pickupexten = *8
pickupsound = beep
pickupfailsound = beeperr

[featuremap]
; Códigos DTMF para características estándar
blindxfer => *1              ; Transferencia ciega
atxfer => *2                 ; Transferencia atendida
disconnect => *0             ; Desconectar llamada
automon => *3                ; Grabar con Monitor (dos archivos)
automixmon => *4             ; Grabar con MixMonitor (un archivo)

[applicationmap]
; Características personalizadas
pauseagent => *5,self,Macro(pause-agent)
unpauseagent => *6,self,Macro(unpause-agent)
togglehold => *7,self,Macro(toggle-hold)
addconf => *9,both,ConfBridge(sala_${CALLERID(num)})
sendtovm => **1,self,VoiceMail(${EXTEN}@default,s)
emergency => ***911,caller,Dial(PJSIP/emergency-line)

[featuregroups]
; Grupos de características
agentfeatures => pauseagent,unpauseagent,automixmon
supervisorfeatures => pauseagent,unpauseagent,automixmon,addconf
basicfeatures => blindxfer,atxfer,automixmon

pjsip.conf correspondiente

; ============================================
; TRANSPORTE
; ============================================
[transport-udp]
type = transport
protocol = udp
bind = 0.0.0.0:5060
external_media_address = TU.IP.PUBLICA.AQUI
external_signaling_address = TU.IP.PUBLICA.AQUI
local_net = 192.168.1.0/24

; ============================================
; PLANTILLA BASE PARA ENDPOINTS
; ============================================
[basic-endpoint](!)
type = endpoint
context = internal
disallow = all
allow = ulaw
allow = alaw
allow = g722

; CRUCIAL: Parámetros para que funcionen las características
direct_media = no                ; Asterisk debe ver el RTP
dtmf_mode = rfc4733             ; Método DTMF recomendado
allow_transfer = yes            ; Habilitar transferencias
one_touch_recording = yes       ; Habilitar grabación DTMF

; Parámetros NAT (ajustar según necesidad)
rtp_symmetric = yes
force_rport = yes
rewrite_contact = yes

; Otros parámetros útiles
trust_id_inbound = yes
send_pai = yes
callerid = "Extension ${EXTEN}" <${EXTEN}>

; ============================================
; ENDPOINTS ESPECÍFICOS
; ============================================

; Agente de call center con características extendidas
[6001](basic-endpoint)
auth = auth6001
aors = 6001
callerid = "Agente 1" <6001>

[auth6001]
type = auth
auth_type = userpass
username = 6001
password = agentePass123!

[6001]
type = aor
max_contacts = 1
remove_existing = yes

; Usuario básico con características limitadas
[6002](basic-endpoint)
auth = auth6002
aors = 6002
callerid = "Usuario 2" <6002>

[auth6002]
type = auth
auth_type = userpass
username = 6002
password = userPass456!

[6002]
type = aor
max_contacts = 1

; Supervisor con todas las características
[6003](basic-endpoint)
auth = auth6003
aors = 6003
callerid = "Supervisor" <6003>

[auth6003]
type = auth
auth_type = userpass
username = 6003
password = superPass789!

[6003]
type = aor
max_contacts = 2
remove_existing = yes

; ============================================
; TRUNK SIP (ejemplo)
; ============================================
[trunk-proveedor](!)
type = endpoint
context = from-trunk
disallow = all
allow = ulaw
allow = alaw
direct_media = no
dtmf_mode = rfc4733

[proveedor-sip](trunk-proveedor)
auth = auth-proveedor
aors = proveedor-sip
outbound_auth = auth-proveedor

[auth-proveedor]
type = auth
auth_type = userpass
username = tu_usuario_trunk
password = tu_password_trunk

[proveedor-sip]
type = aor
contact = sip:tu_proveedor.com:5060

[proveedor-sip]
type = identify
endpoint = proveedor-sip
match = IP.DEL.PROVEEDOR

extensions.conf (dialplan) integrado

[general]
static = yes
writeprotect = no

[globals]
RECORDING_DIR = /var/spool/asterisk/monitor

; ============================================
; CONTEXTO PARA EXTENSIONES INTERNAS
; ============================================
[internal]

; Extensiones de agentes con características completas
exten => _600[1-5],1,NoOp(=== Llamada a Agente ${EXTEN} ===)
same => n,Set(__DYNAMIC_FEATURES=agentfeatures)
same => n,Set(CHANNEL(language)=es)
same => n,Dial(PJSIP/${EXTEN},30,tTkK)
same => n,Goto(no-answer,1)

; Extensiones de supervisores con características extendidas
exten => _600[6-9],1,NoOp(=== Llamada a Supervisor ${EXTEN} ===)
same => n,Set(__DYNAMIC_FEATURES=supervisorfeatures)
same => n,Set(CHANNEL(language)=es)
same => n,Dial(PJSIP/${EXTEN},30,tTkK)
same => n,Goto(no-answer,1)

; Usuarios básicos
exten => _61XX,1,NoOp(=== Llamada a Usuario ${EXTEN} ===)
same => n,Set(__DYNAMIC_FEATURES=basicfeatures)
same => n,Set(CHANNEL(language)=es)
same => n,Dial(PJSIP/${EXTEN},20,tTkK)
same => n,Goto(no-answer,1)

; Manejo de no respuesta
exten => no-answer,1,NoOp(No hubo respuesta de ${EXTEN})
same => n,VoiceMail(${EXTEN}@default,su)
same => n,Hangup()

; Acceso a buzón de voz
exten => *97,1,NoOp(=== Acceso a Buzón de Voz ===)
same => n,VoiceMailMain(${CALLERID(num)}@default)
same => n,Hangup()

; Pickup de llamadas
exten => *8,1,NoOp(=== Call Pickup ===)
same => n,Pickup()
same => n,Hangup()

; Pickup de grupo
exten => **8,1,NoOp(=== Group Pickup ===)
same => n,PickupChan(PJSIP/${EXTEN})
same => n,Hangup()

; Sala de conferencia
exten => 9000,1,NoOp(=== Conferencia Principal ===)
same => n,Answer()
same => n,ConfBridge(sala1)
same => n,Hangup()

; Eco test
exten => 9999,1,NoOp(=== Echo Test ===)
same => n,Answer()
same => n,Echo()
same => n,Hangup()

; ============================================
; MACROS PARA CARACTERÍSTICAS PERSONALIZADAS
; ============================================
[macro-pause-agent]
exten => s,1,NoOp(=== Pausando Agente ===)
same => n,PauseQueueMember(,Local/${CALLERID(num)}@from-internal)
same => n,Playback(agent-paused)
same => n,MacroExit()

[macro-unpause-agent]
exten => s,1,NoOp(=== Despausando Agente ===)
same => n,UnpauseQueueMember(,Local/${CALLERID(num)}@from-internal)
same => n,Playback(agent-unpaused)
same => n,MacroExit()

[macro-toggle-hold]
exten => s,1,NoOp(=== Toggle Hold ===)
same => n,Set(HOLD_STATUS=${DB(hold/${CHANNEL})})
same => n,GotoIf($["${HOLD_STATUS}" = "1"]?unhold:hold)
same => n(hold),Set(DB(hold/${CHANNEL})=1)
same => n,MusicOnHold()
same => n,MacroExit()
same => n(unhold),Set(DB(hold/${CHANNEL})=0)
same => n,StopMusicOnHold()
same => n,MacroExit()

; ============================================
; CONTEXTO DESDE TRUNK
; ============================================
[from-trunk]
exten => _X.,1,NoOp(=== Llamada entrante desde trunk: ${CALLERID(num)} ===)
same => n,Set(CHANNEL(language)=es)
same => n,Goto(internal,${EXTEN},1)

exten => _6XXX,1,NoOp(=== DID a extensión ${EXTEN} ===)
same => n,Goto(internal,${EXTEN},1)

En el dialplan, la aplicación Dial() acepta flags que interactúan con features.conf:

Dial(PJSIP/extension,timeout,options)

Opciones importantes:

  • t: Permite a quien llama usar características de transferencia
  • T: Permite a quien recibe usar características de transferencia
  • k: Permite a quien llama usar características de parking
  • K: Permite a quien recibe usar características de parking
  • w: Permite a quien llama usar características de automon
  • W: Permite a quien recibe usar características de automon

Ejemplo combinado:

same => n,Dial(PJSIP/${EXTEN},30,tTkKwW)

Esto habilita todas las características para ambas partes.

Verificar configuración

Desde la CLI de Asterisk:

# Ver configuración actual de features
asterisk -rx "features show"

# Ver características mapeadas
asterisk -rx "core show config features.conf"

# Verificar endpoints PJSIP
asterisk -rx "pjsip show endpoints"

# Ver detalles de un endpoint específico
asterisk -rx "pjsip show endpoint 6001"

Activar logs detallados

# En la consola de Asterisk
asterisk -rvvvv

# O aumentar verbosidad
core set verbose 5
core set debug 5

# Logs específicos de DTMF
core set debug 3

Problemas comunes y soluciones

Las características DTMF no funcionan:

Solución 1: Verificar que direct_media = no en pjsip.conf

Solución 2: Confirmar que dtmf_mode = rfc4733 tanto en endpoint como que el dispositivo lo soporte

Solución 3: Revisar que los códigos en [featuremap] no conflictúan con códigos de extensiones

Transferencias no se completan:

Solución 1: Verificar allow_transfer = yes en el endpoint

Solución 2: Aumentar transferdigittimeout si el usuario tarda en marcar

Solución 3: Revisar que el contexto tenga acceso a la extensión destino

Grabación DTMF no inicia:

Solución 1: Confirmar one_touch_recording = yes en endpoint

Solución 2: Verificar permisos de escritura en directorio de grabaciones

Solución 3: Revisar que MixMonitor esté disponible: asterisk -rx "core show application MixMonitor"

DTMF se escucha como audio:

Problema: El modo es inband en lugar de rfc4733

Solución: Cambiar dtmf_mode = rfc4733 y reiniciar el endpoint

Timeout muy corto para marcar:

Solución: Aumentar featuredigittimeout en [general] a 3000 o más

Logs útiles

# Ver logs en tiempo real
tail -f /var/log/asterisk/full

# Filtrar solo DTMF
tail -f /var/log/asterisk/full | grep -i dtmf

# Filtrar transferencias
tail -f /var/log/asterisk/full | grep -i transfer

# Filtrar features
tail -f /var/log/asterisk/full | grep -i feature

Simplicidad en códigos: Usa códigos DTMF cortos y memorables. Evita secuencias largas o complejas.

Documentación: Mantén un documento con todos los códigos y compártelo con usuarios.

Testing progresivo: Prueba cada característica individualmente antes de habilitar todas.

Grupos de características: Usa [featuregroups] para asignar características según roles (agentes, supervisores, usuarios).

Monitoreo: Implementa logging adecuado para auditar uso de características.

Capacitación: Asegúrate que usuarios conozcan los códigos y cómo usarlos correctamente.

Respaldo: Siempre respalda configuraciones antes de cambios importantes.

Consistencia: Mantén los mismos códigos DTMF en todos los sistemas de la organización.

SEGURIDAD:

Prevención de abuso: Limita características sensibles (como transferencias externas) mediante contextos restrictivos.

Auditoría: Registra todas las transferencias y grabaciones para compliance.

Permisos: Asigna características según necesidad real, no des acceso universal.

Códigos seguros: Evita códigos DTMF obvios o predecibles para funciones críticas.

Validación: En applicationmap, valida siempre las entradas antes de ejecutar acciones.

Conclusión

El archivo features.conf proporciona funcionalidades esenciales que transforman Asterisk de una simple centralita en un sistema telefónico completo y profesional. Su correcta integración con pjsip.conf requiere atención especial a parámetros como direct_media y dtmf_mode para garantizar que todas las características funcionen según lo esperado.

La clave del éxito está en:

  • Mantener direct_media = no para que Asterisk pueda interceptar DTMF
  • Usar dtmf_mode = rfc4733 para máxima confiabilidad
  • Configurar los flags apropiados en la aplicación Dial()
  • Documentar y capacitar a usuarios en el uso de códigos DTMF
  • Monitorear y depurar sistemáticamente

Con la configuración adecuada, los usuarios pueden disfrutar de transferencias fluidas, grabación bajo demanda y características personalizadas, mejorando significativamente la productividad y experiencia telefónica en cualquier implementación de Asterisk PBX.

Vota el Articulo: 

Sin votos (todavía)
Evalúa la calidad del articulo
Suscribirse a Comentarios de "El archivo features.conf en Asterisk PBX v.20" Suscribirse a VozToVoice - Todos los comentarios