Blog

安装基于 Quectel EC20 模块的短信及语音转发服务

发布时间: ,大约 700 字 ,阅读时间:4 分钟,

前言

最近在“上网冲浪”的时候,发现有一款 4G 物联网模块不仅可以收发短信,还可以接打电话,甚至还支持 VoLTE。 考虑到自己境内外的手机卡加起来还是比较多的,因此决定尝试一下这个方案来减少带手机的数量。

EC20 是国内一家公司生产的给物联网设备使用的 LTE 模块,因此文档比较齐全,也方便进行二次开发。但是 EC20 是一个系列,下面有多个不同的型号,有的不支持语音,有的不支持电信 CDMA,因此建议购买 EC20CEFAG-512-SGNS 全能版本或者自行确认好参数选型。

实际上在看到这个方案之前,还有基于华为 3G USB 上网卡、多卡宝的方案, 但是 3G 以前的技术已经开始逐步退网,而多卡宝我个人认为将这类数据交给别人托管不是很安全, 并且这家公司最近还开始对多卡宝收取月费了(预想之中)。 在接触到这个方案之前,大多数情况下我只能用 4G 随身 Wi-Fi 或者旧的安卓手机来做短信转发。 这类方案只能转发短信,但不能转发语音,而在某些情况下语音也有一定程度上的需求,因此这些方案都不是很完美。

准备硬件

在看到这篇文章的时候文章里面提到一个 EC20CEFAG-512-SGNS 模块在闲⻥购买大约只需要 50-60 一片, 但我去搜索的时候已经变成 60-80 一片了。 此外,还需要购买 4G 天线、IPEX 转 SMA 转接线和 Mini PCI-e 4G 模块转 USB 转接卡, 成本一下就提到了 100 多一路。

因为手上有个发霉皮 3 Raspberry Pi 3 正在发霉,因此正好可以废物利用。 直接刷了一个 Raspbx 便可以省去安装 FreePBX 和 Asterisk 的麻烦。 不过自带的 FreePBX 版本有点旧(应该不影响使用),刷完以后可以直接去 FreePBX Web Management Interface 里的 Admin -> Module Admin 里面更新一下。更新之前 FreePBX 的管理界面是蓝色主题,更新完了就变成绿色的了。

此外,如果设备比较多的话 Raspberry Pi 的弱鸡供电是不够的,USB 口也不够,因此还需要购买带供电的 USB Hub。 电源需求可以根据树莓派 3B 20W + 一个模块 2.5W 来算,也就是树莓派 3B 需要 5V2A,模块需要 5V1A。 在这里我花了 23 买了一个 5V10A 的电源,然后还需要花 6.5 买一条电源线来接 220V 的电, 还有 8 块钱买了一条 USB 母头单头数据线(用来给树莓派供电)和两条 5.5x2.5 的圆口 DC 公头电源线(用来接 Hub)。 因为电源是工业电源模组,上面这些线得自己接,注意不要把 AC 的电接到 DC 上去了。

配置模块

配置模块的步骤基本上都参考了 这篇博客文章。 大致上就是重置模块、开启 VoLTE 和开启 UAC 音频。 在这里我比较懒,开了 UAC 音频但是没有配置,因此通话质量没那么高,但又不是不能用.jpg。

配置需要进入模块的 AT 指令串口,模块会在系统中释放入如下表所示的四个 ttyUSB 接口:

接口 描述
/dev/ttyUSB0
/dev/ttyUSB1 PCM语音,GPS信号
/dev/ttyUSB2 控制命令
/dev/ttyUSB3

如果你是在 Windows 环境下配置的,首先你需要安装驱动。 官方渠道下载驱动需要注册账号,据说还需要人工审核,但是这种东西稍微搜一下就可以发现有人放出来了

重置模块

接下来需要用串口连接工具进入 AT 接口(即 /dev/ttyUSB2,Windows 一般是 COM6)配置, 在开始配置之前可以先使用命令 at+qprtpara=3 重置一下模块,以避免模块里面有上一个用家的错误配置。 重置完以后用 AT+CFUN=1,1 重启。

等待模块重启完成以后,再进入 AT 接口,这时候可以先看一下 SIM 卡是否注册成功:

AT+COPS?
+COPS: 0,0,"CHN-UNICOM",7

OK
AT+QNWINFO
+QNWINFO: "FDD LTE","46001","LTE BAND 3",1850

OK

配置 VoLTE

电信用户注意:电信卡激活了 VoLTE 以后就没发收发短信了,可能是因为配置文件不正确,就为了这个问题我花了两天时间在里面。 如果你用的是电信卡,并且还需要收发短信,请不要配置 VoLTE,直接跳到安装 asterisk-chan-quectel

然后可以配置 VoLTE 了,首先需要使用 AT+QCFG="ims",1 来开启 VoLTE, 然后可以使用 AT+QMBNCFG="List" 查看一下 VoLTE 的配置文件,一般会返回下面的输出:

+QMBNCFG: "List",0,1,1,"ROW_Generic_3GPP",0x05010824,201806201
+QMBNCFG: "List",1,0,0,"OpenMkt-Commercial-CU",0x05011510,202111301
+QMBNCFG: "List",2,0,0,"OpenMkt-Commercial-CT",0x0501131C,202202281
+QMBNCFG: "List",3,0,0,"Volte_OpenMkt-Commercial-CMCC",0x05012011,202111301

这里需要注意的是,自动选择的特定运营商的 VoLTE 配置文件通常不能使用,移动的可能可以用,但是联通和电信都不行。 这些配置文件可能是针对物联网卡配置的,因此需要按照下面输入命令的顺序切换成 ROW_Generic_3GPP 配置文件才能正常使用。

  1. 关闭自动选择mbn文件:AT+QMBNCFG="AutoSel",0
  2. 反激活当前的mbn:at+qmbncfg="deactivate"
  3. 强制选择3gpp:AT+QMBNCFG="select","ROW_Generic_3GPP"
  4. 重启:AT+CFUN=1,1

重启完了以后,可以使用 AT+QCFG="ims" 查询 VoLTE 激活状态。 如果是 +QCFG: "ims",1,1,就代表 VoLTE 已经启用并激活, 如果是 +QCFG: "ims",1,0 就代表 VoLTE 启用了但没有激活, 如果是 +QCFG: "ims",0,0 则代表 VoLTE 没有启用。

配置软件

安装 asterisk-chan-quectel,及配置 Asterisk

首先需要安装一些必要的软件和支持库:apt install asterisk asterisk-dev adb git autoconf automake libsqlite3-dev build-essential libasound2-dev alsa-utils

然后将代码库下载下来:git clone https://github.com/IchthysMaranatha/asterisk-chan-quectel

电信用户注意:因为 CDMA 没有短信中心号码这种说法,而 asterisk-chan-quectel 对没有短信中心的 PDU 处理存在问题,因此无法正常接受短信,需要手动修改这个函数来解决。在 int sca_digits = (pdu[i++] - 1) * 2; 这一行下面添加如下三行代码:

if (pdu[i-1] == 0) {
    return i;
}

接下来,需要在树莓派上编译安装 Quectel 4G 模块的支持,编译安装的命令跟着 Github 的 README 走就行了,大致上就这几条:

$ ./bootstrap
$ ./configure --with-astversion=16
$ make
$ make install

然后需要复制 quectel.conf/etc/asterisk 里面,并在最后添加类似下面的配置来配置 4G 模块的连接:

[quectel0]
audio=/dev/ttyUSB1                       ; tty port for Audio, set as ttyUSB4 for Simcom if no other dev present
data=/dev/ttyUSB2                        ; tty port for AT commands;no default value
;quec_uac=1                              ; Uncomment line if using UAC mode
;alsadev=hw:CARD=Android,DEV=0           ; Uncomment if using UAC, set device name or index as reqd

然后在 /etc/asterisk/extensions_custom.conf 里面添加下面的内容, 下面配置了短信写入 /var/log/asterisk/sms.txt,USSD 写入 /var/log/asterisk/ussd.txt,以及通话走向。 请根据自己的实际需求自行配置,这份配置是东拼西凑出来的,我自己都不是很懂。

[incoming-mobile]
exten => sms,1,Verbose(Incoming SMS from ${CALLERID(num)} ${BASE64_DECODE(${SMS_BASE64})})
;store
exten => sms,n,System(echo '${STRFTIME(${EPOCH},,%Y-%m-%d %H:%M:%S)} - ${QUECTELNAME} - ${CALLERID(num)}: ${BASE64_DECODE(${SMS_BASE64})}' >> /var/log/asterisk/sms.txt)
;for tg bot use
;exten => sms,n,System(echo '${STRFTIME(${EPOCH},,%Y-%m-%d %H:%M:%S)} - ${QUECTELNAME} - ${CALLERID(num)}\n${BASE64_DECODE(${SMS_BASE64})}' >> /var/log/asterisk/unread_sms/${STRFTIME(${EPOCH},,%Y%m%d%H%M%S)}-${CALLERID(num)}.txt)
exten => sms,n,Hangup()

exten => ussd,1,Verbose(Incoming USSD: ${BASE64_DECODE(${USSD_BASE64})})
exten => ussd,n,System(echo '${STRFTIME(${EPOCH},,%Y-%m-%d %H:%M:%S)} - ${QUECTELNAME}: ${BASE64_DECODE(${USSD_BASE64})}' >> /var/log/asterisk/ussd.txt)
exten => ussd,n,Hangup()

exten => _.,1,Set(CALLERID(name)=${CALLERID(num)})
exten => _.,n,Goto(from-trunk,${EXTEN},1)

然后重启一下 FreePBX:sudo systemd restart freepbx

配置 FreePBX

首先,需要进入 Applications -> Extensions ,点击 Add Extension -> Add New SIP [chan_pjsip] Extension 按钮(位置在下图),添加一个 SIP 用户,这个用户用来接打电话。

FreePBX-Add-Extendsion-Button.png

然后进入用户添加界面,输入类似如下图的信息来添加 SIP 用户:

FreePBX-Add-SIP-User.png

其中,User Extension 的数字是内部的分机号,也是 SIP 的登录用户名,你可以理解成企业电话系统里面的短号。Secret 是 SIP 密码,请务必记住这两个字段的信息,待会要用到。

然后来到 Connectivity -> Trunks,把模块添加进去,你有几个模块就需要添加几个 Trunks。配置如下图所示:

FreePBX-Add-Trunk.png

这个 Tab 要改的只有 Trunk Name,Maximum Channels 最好改成 1,然后还要修改 Dial String:

FreePBX-Add-Trunk-Custom-Dial.png

这里只有一个框,想都不用想就知道要改哪里。 里面写入类似 Quectel/quectel0/$OUTNUM$ 的内容,中间的 quectel0 对应了你在配置文件里面配置的设备名字。

将设备添加完以后,需要进入 Connectivity -> Outbound Routes 添加 Outbound Routes。Route Name 是必要的,但可以设定成自己喜欢的值,毕竟它只是个名字。Route CID 代表的是内部的分机号,图片上写的是 200,但应该设置成上面设置的 114514。Trunk Sequence for Mached Routes 代表了使用哪个模块进行通话,这里选择一个喜欢的模块就行了,如果选择了两个或以上,那么后面的只有在前面的占线了才会使用。

FreePBX-Add-Outbound-Routes.png

接下来切到 Dial Patterns,设置一个 X. 作为 Pattern 就可以了,这代表匹配所有呼出的号码。

FreePBX-Add-Outbound-Routes-Dial-Patterns.png

最后,需要进入 Connectivity -> Inbound Routes,配置呼入电话转发给谁,这里 Description 写一个自己喜欢的,然后在最下面 Set Destination 选择 Extensions,然后会出现一个新的下拉框,在新的下拉框选择 114514 这个分机,这样就会把所有呼入转发给这个分机号。

FreePBX-Add-Inbound-Routes.png

测试呼叫

到这里,点击右上角的 Apply Configuration,然后就可以测试短信收发以及电话功能了。去网上下载一个 Zoiper,用户名输入刚刚创建的 114514,密码填写刚刚记录的 SIP Secret,然后就可以测试一下接打电话是否正常,还可以给自己的手机号发短信,短信应当写入到 /var/log/asterisk/sms.txt。发送短信使用 asterisk -rx 'quectel sms quectel0 10086 "cxll"'

拓展:设定类似和多号的功能

由于想用一个 SIP 账号来同时接听或从多个不同的手机卡拨打电话(某些软件多账号要收费),因此需要使用类似和多号一样在前面加拨一段数字来表明需要使用的手机卡,并且需要了解到呼入的电话是从哪个手机卡打进来的。FreePBX 可以通过一些特殊设置来实现这个功能。

首先,需要确定手机号码。可以使用 asterisk -rx 'quectel show devices' 来查看所有设备,其中会包含手机号码,输出类似下面几行:

$ asterisk -rx 'quectel show devices'
ID           Group State      RSSI Mode Submode Provider Name  Model      Firmware          IMEI             IMSI             Number
quectel0     0     Free       25   0    0       Mi Mobile      EC20F      EC20CEFAGR06A17M4 8688888888888888  460000000000000  +8617123456789
quectel1     0     Free       22   0    0       CHINA MOBILE   EC20F      EC20CEFAGR06A17M4 8666666666666666  460000000000001  Unknown

如果 Number 列有正确的号码,则可以直接进入下一步,如果没有,则需要手动设置一个号码。一般情况下建议设置真实的号码以便于区分。一般情况下,可以使用下面两行命令设置:

asterisk -rx 'quectel cmd quectel0 AT+CPBS=\"ON\"'
asterisk -rx 'quectel cmd quectel0 AT+CPBW=1,\"+8613800138000\",145'

设置完成以后,不需要重启,再列出一下设备列表应该就能看到号码以及应用了。 随后,需要进入 Connectivity -> Inbound Routes,添加一个新的 Inbound 规则,并且填写如图所示的内容:

FreePBX-Inbound-CID-Distinguish.png

请注意 DID Number 和 CID name prefix,这两个 fields 与上面的配置有所不同。DID Number 需要填写 asterisk -rx 'quectel show devices' 的手机号码,CID name prefix 可以自己随便定义(甚至可以包含英文和符号),这里填写的内容会在呼入电话号码前面添加,只要能让自己区分开来就可以了。

然后进入 Connectivity -> Outbound Routes,创建新的呼出规则。Route Settings 还是和之前一样,但是 Dial Patterns 有所不同,如下图所示:

FreePBX-Outbound-Number-Distinguish.png

可以看到,Pattern 多了一个 prefix,这个 prefix 用于在拨打电话的时候区分需要使用的模块,例如图上写了 125831,即使用 125831 开头的号码全部使用 quectel1 拨打。

最后进入 Connectivity -> Trunks,编辑之前的 Trunks,进入 Dialed Number Manipulation Rules,添加一行规则,如下图所示:

FreePBX-Trunk-DialedNumber.png

这样做的目的是为了确保呼出的电话没有内部使用的区分电话卡的前缀。设置完成后,点击右上角的 “Apply Config” 应用设置,然后便可以测试了。

测试呼入及呼出

Incoming-Call-Test.png

从上图可以看见,呼入成功地添加了以 19991 + 收到电话的手机卡号码 为开头的前缀,最后跟着的是打进来的电话号码。

Outgoing-Call-Test.png

从上图可以看见,使用 12583110086 拨打电话可以被接通

写在最后

从 SSH 拿短信内容还是有点麻烦,所以后面还是得写个程序把短信转发到别的方便的平台上。

EC20-Modem-Pool.png

原来 EC20 已经被用来做猫池了


License

如未明确声明,所有文章皆以

知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。如果您需要商用,您可以通过电子邮件( [email protected] )联系。