Chan_dongle en asterisk 13 y superiores

Hace algunos años escribi un post donde explique de una manera muy detallada como hacer funcionar chan_dongle en dupla con asterisk para poder tener un telular, que como vimos más tarde se podría hacer crecer para generar un Gateway GSM medianamente decente.

Gateway GSM con asterisk
Fuente : http://wiki.e1550.mobi

La información en su momento funcionaba puesto que por aquellos años (2014 aproximadamente) el lanzamiento de Asterisk 13 era relativamente reciente y esa versión en particular de asterisk no era que se empleara con regularidad (por ser muy fresca), ahora, algunos años después tras intentar efectuar una instalación me percate que dicho proyecto ya no era del todo funcional por una infinidad de errores de compilación que generaba.

Por lo cual, recientemente encontré un fork bastante funcional del proyecto original en Github que esta justamente pensado para versiones recientes de asterisk y los kernels modernos, por lo cual, proceso a compartir el nuevo procedimiento de instalación para dejar funcionando chan_dongle y asterisk de una manera óptima.

Yo particularmente lo probé en asterisk 16 por lo cual, para versiones anteriores no debería generar mayor problema, incluso para la versión 17 de asterisk (personalmente yo no la ocupo puesto que no es LTS), una vez que se tiene el contexto entremos en materia.

Manual para poder instalar chan_dongle en versiones recientes de Asterisk

Emplee una distribución basada en Debian (Raspbian) aunque esta manual aplica para sistemas hijos de este sistema como: Ubuntu, Linux Mint, Kali Linux, etc.

Antes de comenzar propiamente con la configuración de chan_dongle debemos instalar algunas dependencias necesarias para poder evitarnos futuros dolores de cabeza, sin más, procederemos a instalarlas:

apt install build-essential automake autoconf asterisk asterisk-dev

Una vez instaladas las dependencias estaremos listos para proceder a instalar chan_dongle.
Para ello nos dirigiremos al repositorio fork del proyecto original en Github y clonaremos el proyecto:

git clone https://github.com/wdoekes/asterisk-chan-dongle

O en el espejo que genere en mi sitio: Mirror Chan_dongle

Des pues nos dirigiremos dentro de la carpeta que nos generó git:

cd asterisk-chan-dongle

En este punto ya estaremos listos para poder compilar el software, pero antes de ello debemos de tener presente que versión de asterisk tenemos instalada con el siguiente comando:

asterisk -V
Asterisk 16.2.1~dfsg-1+deb10u1

Como apreciamos la versión que tenemos instalada es la 16.2.1
Ahora que tenemos la versión de asterisk instalada en nuestro sistema procedemos a efectuar la compilación de chan_dongle, ingresando el siguiente comando:

./bootstrap

Después de ello emplearemos la versión de asterisk que en su momento obtuvimos:

./configure --with-astversion=16.2.1

Y efectuara el proceso como se aprecia en la siguiente salida:

root@raspberrypi:~/asterisk-chan-dongle# ./configure --with-astversion=16.2.1
checking build system type... armv6l-unknown-linux-gnueabihf
checking host system type... armv6l-unknown-linux-gnueabihf
checking target system type... armv6l-unknown-linux-gnueabihf
checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
checking for a thread-safe mkdir -p... /bin/mkdir -p
checking for gawk... no
checking for mawk... mawk
checking whether make sets $(MAKE)... yes
checking whether make supports nested variables... yes
checking for gcc... gcc
checking whether the C compiler works... yes
checking for C compiler default output file name... a.out
checking for suffix of executables... 
checking whether we are cross compiling... no
checking for suffix of object files... o
checking whether we are using the GNU C compiler... yes
checking whether gcc accepts -g... yes
checking for gcc option to accept ISO C89... none needed
checking whether gcc understands -c and -o together... yes
checking whether make supports the include directive... yes (GNU style)
checking dependency style of gcc... none
checking how to run the C preprocessor... gcc -E
checking for strip... strip
checking for rm... rm
checking for library containing iconv... none required
checking for grep that handles long lines and -e... /bin/grep
checking for egrep... /bin/grep -E
checking for ANSI C header files... yes
checking for sys/types.h... yes
checking for sys/stat.h... yes
checking for stdlib.h... yes
checking for string.h... yes
checking for memory.h... yes
checking for strings.h... yes
checking for inttypes.h... yes
checking for stdint.h... yes
checking for unistd.h... yes
checking fcntl.h usability... yes
checking fcntl.h presence... yes
checking for fcntl.h... yes
checking for stdlib.h... (cached) yes
checking for string.h... (cached) yes
checking sys/time.h usability... yes
checking sys/time.h presence... yes
checking for sys/time.h... yes

Después del paso anterior procederemos a:

make

Y nos mostrara una salida similar a la siguiente:

root@raspberrypi:~/asterisk-chan-dongle# make
gcc -g -O2 -O6 -Wno-old-style-declaration -I. -DAST_MODULE_SELF_SYM=__internal_chan_dongle_self -D_GNU_SOURCE -I/usr/include -I/usr/include -DHAVE_CONFIG_H  -fvisibility=hidden -fPIC -Wall -Wextra -MD -MT app.o -MF .app.o.d -MP  -o app.o -c app.c
gcc -g -O2 -O6 -Wno-old-style-declaration -I. -DAST_MODULE_SELF_SYM=__internal_chan_dongle_self -D_GNU_SOURCE -I/usr/include -I/usr/include -DHAVE_CONFIG_H  -fvisibility=hidden -fPIC -Wall -Wextra -MD -MT at_command.o -MF .at_command.o.d -MP  -o at_command.o -c at_comman
d.c
gcc -g -O2 -O6 -Wno-old-style-declaration -I. -DAST_MODULE_SELF_SYM=__internal_chan_dongle_self -D_GNU_SOURCE -I/usr/include -I/usr/include -DHAVE_CONFIG_H  -fvisibility=hidden -fPIC -Wall -Wextra -MD -MT at_parse.o -MF .at_parse.o.d -MP  -o at_parse.o -c at_parse.c
gcc -g -O2 -O6 -Wno-old-style-declaration -I. -DAST_MODULE_SELF_SYM=__internal_chan_dongle_self -D_GNU_SOURCE -I/usr/include -I/usr/include -DHAVE_CONFIG_H  -fvisibility=hidden -fPIC -Wall -Wextra -MD -MT at_queue.o -MF .at_queue.o.d -MP  -o at_queue.o -c at_queue.c
gcc -g -O2 -O6 -Wno-old-style-declaration -I. -DAST_MODULE_SELF_SYM=__internal_chan_dongle_self -D_GNU_SOURCE -I/usr/include -I/usr/include -DHAVE_CONFIG_H  -fvisibility=hidden -fPIC -Wall -Wextra -MD -MT at_read.o -MF .at_read.o.d -MP  -o at_read.o -c at_read.c
gcc -g -O2 -O6 -Wno-old-style-declaration -I. -DAST_MODULE_SELF_SYM=__internal_chan_dongle_self -D_GNU_SOURCE -I/usr/include -I/usr/include -DHAVE_CONFIG_H  -fvisibility=hidden -fPIC -Wall -Wextra -MD -MT at_response.o -MF .at_response.o.d -MP  -o at_response.o -c at_res
ponse.c
gcc -g -O2 -O6 -Wno-old-style-declaration -I. -DAST_MODULE_SELF_SYM=__internal_chan_dongle_self -D_GNU_SOURCE -I/usr/include -I/usr/include -DHAVE_CONFIG_H  -fvisibility=hidden -fPIC -Wall -Wextra -MD -MT chan_dongle.o -MF .chan_dongle.o.d -MP  -o chan_dongle.o -c chan_d
ongle.c
gcc -g -O2 -O6 -Wno-old-style-declaration -I. -DAST_MODULE_SELF_SYM=__internal_chan_dongle_self -D_GNU_SOURCE -I/usr/include -I/usr/include -DHAVE_CONFIG_H  -fvisibility=hidden -fPIC -Wall -Wextra -MD -MT channel.o -MF .channel.o.d -MP  -o channel.o -c channel.c
gcc -g -O2 -O6 -Wno-old-style-declaration -I. -DAST_MODULE_SELF_SYM=__internal_chan_dongle_self -D_GNU_SOURCE -I/usr/include -I/usr/include -DHAVE_CONFIG_H  -fvisibility=hidden -fPIC -Wall -Wextra -MD -MT char_conv.o -MF .char_conv.o.d -MP  -o char_conv.o -c char_conv.c
gcc -g -O2 -O6 -Wno-old-style-declaration -I. -DAST_MODULE_SELF_SYM=__internal_chan_dongle_self -D_GNU_SOURCE -I/usr/include -I/usr/include -DHAVE_CONFIG_H  -fvisibility=hidden -fPIC -Wall -Wextra -MD -MT cli.o -MF .cli.o.d -MP  -o cli.o -c cli.c
gcc -g -O2 -O6 -Wno-old-style-declaration -I. -DAST_MODULE_SELF_SYM=__internal_chan_dongle_self -D_GNU_SOURCE -I/usr/include -I/usr/include -DHAVE_CONFIG_H  -fvisibility=hidden -fPIC -Wall -Wextra -MD -MT helpers.o -MF .helpers.o.d -MP  -o helpers.o -c helpers.c
helpers.c: In function ‘send_reset’:
helpers.c:158:111: warning: cast between incompatible function types from ‘int (*)(struct cpvt *)’ to ‘int (*)(struct cpvt *, const char *, const char *, unsigned int,  int,  void **)’ [-Wcast-function-type]

Una vez finalizado el proceso deberemos continuar con:

make install

Cuya salida será:

root@raspberrypi:~/asterisk-chan-dongle# make install
strip chan_dongle.so
/usr/bin/install -c -m 644 chan_dongle.so /usr/lib/asterisk/modules

A estas alturas del partido ya tendremos nuestro módulo de asterisk listo para hacer funcionar nuestro amado chan_dongle.


Pero antes de ello debemos tener presente que para que chan_dongle funcione requiere de un archivo de configuración, donde realizando una búsqueda del mismo nos percatamos que estará en:

/root/asterisk-chan-dongle/etc/dongle.conf

Como nos lo indico la búsqueda realizada:

root@raspberrypi:~/asterisk-chan-dongle# find / -name "*dongle.conf*"
/root/asterisk-chan-dongle/etc/dongle.conf

Ahora procederemos a copiar dicho archivo de configuración al directorio de asterisk por medio del siguiente comando:

cp /root/asterisk-chan-dongle/etc/dongle.conf /etc/asterisk/

En teoría ya tendríamos chan_dongle casi listo para funcionar pero antes de ello deberíamos conectar nuestro Modem usb Huawei (yo particularmente encuentro muy útil el Huawei E153) y validar que puerto se le asigno por medio del siguiente comando:

root@raspberrypi:/home/pi# dmesg | grep ttyUSB
[   20.588870] usb 1-1.3.1.2: GSM modem (1-port) converter now attached to ttyUSB0
[   20.619440] usb 1-1.3.1.2: GSM modem (1-port) converter now attached to ttyUSB1
[   20.632078] usb 1-1.3.1.2: GSM modem (1-port) converter now attached to ttyUSB2
[   20.668550] usb 1-1.3.2.1: GSM modem (1-port) converter now attached to ttyUSB3
[   20.697946] usb 1-1.3.2.1: GSM modem (1-port) converter now attached to ttyUSB4
[   20.707379] usb 1-1.3.2.1: GSM modem (1-port) converter now attached to ttyUSB5

Cabe mencionar que la asignación de los puertos es secuencial, por ejemplo, yo tengo 2 modems conectados donde cada modem recibe 3 puertos, es decir: al modem 1 le corresponde ttyUSB0, ttyUSB1,ttyUSB2 y al modem 2 le corresponde ttyUSB3, ttyUSB4 y ttyUSB5 respectivamente. Una vez que tengamos certeza de los puertos procedemos a validar dicha configuración en el archivo de configuración que anteriormente copiamos al directorio de asterisk:

cat /etc/asterisk/dongle.conf

Mostrando la siguiente salida:

; dongle required settings
[dongle0]
;audio=/dev/ttyUSB1		; tty port for audio connection; 	no default value
;data=/dev/ttyUSB2		; tty port for AT commands; 		no default value

Donde hasta al final nos percatamos que la sección de audio y data hacen referencia de manera correcta a los puertos del modem.
Ahora sí, una vez validados los requerimientos procederemos a cargar el modulo dentro de asterisk, ingresaremos en asterisk con:

asterisk -rv

Después ingresaremos el siguiente comando:

module load chan_dongle.so

Y al fin, tendremos nuestro chan dongle cargado como se aprecia en la salida del comando anterior:

raspberrypi*CLI> module load chand_dongle.so


raspberrypi*CLI> 
[Jan 15 20:58:32] NOTICE[2195]: chan_dongle.c:1588 reload_config: [dongle0] Loaded device
  == Registered channel type 'Dongle' (Huawei 3G Dongle Channel Driver)
  == Registered application 'DongleStatus'
  == Registered application 'DongleSendSMS'
  == Registered application 'DongleSendUSSD'
  == Manager registered action DongleShowDevices
  == Manager registered action DongleSendUSSD
  == Manager registered action DongleSendSMS
  == Manager registered action DongleSendPDU
  == Manager registered action DongleSetCCWA
  == Manager registered action DongleReset
  == Manager registered action DongleRestart

Por lo cual ya solo nos restara validar el estado de los modems con el siguiente comando:

raspberrypi*CLI> dongle show devices
ID           Group State      RSSI Mode Submode Provider Name  Model      Firmware          IMEI             IMSI             Number        
dongle0	     0     Free       25   0    0       weex           E153       11.609.18.00.00   XXXXXXXXXXXXXXX  XXXXXXXXXXXXXXX  Unknown       
dongle1      0     Free       27   0    0       weex           E153       11.609.18.00.00   XXXXXXXXXXXXXXX  XXXXXXXXXXXXXXX  Unknown

Ya tendremos listo y funcional chan_dongle para efectuar llamadas, el próximo paso solo será configurar el dial plan. 🙂

Para cualquier duda o comentario puedes escribirlo en la sección de comentarios y con gusto responderé. O en su caso en la sección de contacto si tu duda es muy específica.