发布于  更新于 

Grandstream HT813 双模语音网关 FreePBX 配置指北

voip freepbx 指北

概述

Grandstream HT813 是一款双模语音网关,支持 FXS 和 FXO 两种接口,可以连接传统的电话机和 PSTN 线路,也可以连接 VoIP 服务器。HT813 最重要的特点是便宜,咸鱼二手价格在 130 元左右,同价位其他语音网关往往只有 FXS 或者 FXO 一种接口。FreePBX 是一款开源的 IP 电话系统,支持 SIP 协议,可以用来搭建企业电话系统。尽管 FreePBX 并不好用(前端卡的离谱),但是免费,而且有大量的社区支持。本文介绍一种使用 HT813 和 FreePBX 搭建简易电话系统的方法,主要列出配置步骤,不涉及具体的技术原理。

我们准备搭建的系统包含以下元素:

  • 有一条中国电信的 PSTN 线路,用于接收来电和拨打外线
  • 有一部传统的电话机,用于拨打和接听电话
  • 有一台运行 FreePBX 的服务器,用于管理电话系统和接收来电
  • 局域网内有若干手机和电脑上的 SIP 软电话,用于拨打和接听电话

希望实现以下功能:

  • 电话机和软电话有独立的分机号,可以互相拨打
  • 电话机和软电话可以通过 PSTN 线路拨打外线
  • PSTN 线路接收到来电时,所有电话机和软电话同时响铃,任意一台设备可以接听
  • PSTN 线路支持来电显示和通话录音

硬件准备

HT813 上共有 5 个接口,分别为:

  • 12V 电源接口
  • WAN 网络接口
  • LAN 网络接口
  • FXS 接口:连接传统电话机
  • FXO 接口:连接 PSTN 线路

HT813 具有 WAN 和 LAN 两个 RJ45 网络接口,自身可作为一台带有 NAT 功能的路由器。在本文中,我们不使用 HT813 的路由功能,将 HT813 的 WAN 接口和 LAN 接口配置成交换机模式,即 HT813 仅作为语音网关使用。HT813、FreePBX 服务器和所有 SIP 设备都连接到同一个局域网中。此模式下,HT813 的任何一个网络接口都可以用来连接局域网,另一个网口可再连接一个局域网内交换机或者其他设备。

HT813 配置

HT813 的 WAN 接口默认通过 DHCP 获取 IP 地址,LAN 接口作为一个 DHCP 服务器,分配 IP 地址给连接到 LAN 接口的设备。WAN 侧可通过路由器管理面板查看 HT813 的 IP 地址,如果二手 HT813 找不到 IP 地址,可以长按 HT813 的 RESET 按钮恢复出厂设置。局域网内浏览器访问 HT813 的 IP 地址,输入默认用户名和密码 adminadmin 登录。

HT813 登陆界面
HT813 登陆界面

信息页

下图是 HT813 的信息页。

HT813 信息页
HT813 信息页

红框内显示 HT813 的接口状态,图中是所有配置完成正常工作的状态。只有 HT813 的 FXS FXO 物理接口已连接,且 VOIP 服务器已注册,前面板的灯才会亮起。FXS 和 FXO 接口的状态可以通过前面板的灯和网页上的状态显示来判断。

基本设置页

主要是网络配置和无条件呼叫转移设置。

上网设置
上网设置

按照需要配置成 DHCP 客户端或静态 IP 地址。由于后续需要在 FreePBX 中配置 HT813 的 IP 地址,建议设置成静态 IP 地址,或在路由器中配置 DHCP 绑定。

语言和时区
语言和时区

建议设成英文,网上的教程大多是英文的。

NAT 模式
NAT 模式

不需要 NAT 功能,设成桥接模式。

无条件呼叫转移
无条件呼叫转移

为了把外线呼入转移到 FreePBX,需要设置无条件呼叫转移。User ID 编一个特殊的号码,如 0123456789,SIP Server 设置成 FreePBX 的 IP 地址。

改完配置后,点 Update 保存,点 Apply 生效, 部分配置按照提示需要重启 HT813 才能生效。

高级设置页

没有需要特别设置的选项。

备份和恢复
备份和恢复

最下面的备份和恢复功能可以备份 HT813 的配置,以防止配置丢失。注意只能导入 XML 格式的配置文件,如果要导入来自其他 HT813 的配置,需要把 XML 文件中的 MAC 地址改成当前 HT813 的 MAC 地址或者删掉 MAC 地址那一行。

Extension 和 FXS 配置

本例中 HT813 的 FXS 接口连接到传统电话机,在 FreePBX 侧看起来和一个 SIP 软电话一样是一个 Extension。

FreePBX 安装后似乎会创建一个默认的 Extension,没有截图。总之最后的结果是,我们需要在 FreePBX 中创建一个分机号为 1000, 用户名是 landline,类型为 PJSIP 的 Extension。

Extension 管理面板
Extension 管理面板

注意要创建一个 Extension,不是 User Manager

不管 User,没用
不管 User,没用
1000 分机详情页面
1000 分机详情页面

分机设置都是默认的,Secret 是 FreePBX 自动生成的密码,后续需要在 HT813 中配置这个密码。创建完分机后,左下角 Submit 保存,再点右上角红色 Apply Config 生效。

HT813 的 FXS 接口配置页面:

重试超时可以改小一点,方便调试。

端口号要改一下,防止和 FXO 的端口号冲突。

只留 PCMU 和 PCMA,其他的编码格式不需要,多了似乎会导致不出声音。

这两个地区选项可以改一下,这一页改完后点 Update 保存,再点 Apply 生效。

以上配置完成后,HT813 的 FXS 指示灯应该亮起,状态页面上显示 FXS 接口已注册。

添加 SIP 用户

再添加其他 SIP 用户,如手机上的软电话,步骤和添加 FXS Extension 类似,类型,默认 PJSIP,分机号和用户名可以随便编(最好有规律,比如 10 开头,后面会用到)。

SIP 客户端以 Linphone 为例,配置如下:

这样 SIP 客户端之间,以及 SIP 客户端和 HT813 的 FXS 接口上的固定电话之间就可以互相拨打电话了。

Trunk 和 FXO 配置

FXO 接口在 FreePBX 中作为一个 Trunk。

编个密码,后面 FreePBX 配置时会用到。

重试超时改小一点。

注意 FXO 默认端口号是 5062.

不知道为啥要改这个,反正改了。

只留 PCMU 和 PCMA。

不知道为啥要改增益,反正改了。

PSTN 挂断检测
PSTN 挂断检测

注意: 中国大陆的用户需要修改 FXO 挂断检测选项,否则不能检测到外线挂断,导致外线挂断后 FreePBX 持续响铃。此处不使用基于电流的挂断检测,而是使用基于忙音的挂断检测。按照上图的配置,中国大陆标准的忙音频率是 450Hz 单音,半周期为 350ms.

在 FreePBX 中添加一个 Trunk:

Trunk 配置页面
Trunk 配置页面

创建一个 pjsip 类型的 Trunk。

这里呼出号码前加 0,这是 HT813 的配置要求,拨打外线时要加 0。

这里填 HT813 的 IP 地址,端口号是 HT813 的 FXO 端口号,用户名和密码是 HT813 的 FXO 配置页面里设置的用户名和密码。

Codec 只留下 ulaw 和 alaw 就够了。

为了消除 Console 里的一个警告,需要在 Admin -> Config Edit 里面给 pjsip.aor_custom_post.conf 文件添加一行:

1
max_contacts=1

配到这里两边都应用设置之后,HT813 的 FXO 灯应该亮起,状态页面上显示 FXO 接口已注册。

外线呼入

记得在 HT813 的 Basic Settings 里设置了无条件呼叫转移:

无条件呼叫转移
无条件呼叫转移

为了能让所有电话都响铃,需要在 FreePBX 的 Ring Groups 里创建一个 Ring Group:

把所有电话都加进去,这样外线呼入时所有电话都会响铃。

然后转到 Inbound Routes,添加一个 Inbound Route:

在 Settings -> On Hold Music 里可以上传等待音乐,这样外线呼入时等待接听时会播放音乐。

外线呼出

在 FreePBX 的 Outbound Routes 里添加一个 Outbound Route:

这里把 10XX 的内线号码排除掉,这样 SIP 客户端可以直接拨打外线号码,不用加 0。

通话记录和录音

点击 Reports -> CDR Reports,可以看到通话记录和录音。

自动化处理通话记录

可以配置自定义的 Dial Plan,在外线呼入、通话结束等事件发生时,调用任意的程序处理通话记录,比如将通话记录推送到外部的数据库或者 API。下面是一个简单的例子。

在 Admin -> Config Edit 里面找到 extensions_custom.conf 文件,添加以下内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[macro-dial-ringall-predial-hook]
exten => s,1,Noop(Entering user defined context macro-dialout-one-predial-hook in extensions_custom.conf)
exten => s,n,TrySystem(echo "Dialing from ${CALLERID(num)}" >> /tmp/dialout.log)
exten => s,n,Set(CHANNEL(hangup_handler_push)=do-this-on-hangup,s,1)
exten => s,n,MacroExit

[do-this-on-hangup]
exten => s,1,Noop(Entering user defined context do-this-on-hangup in extensions_custom.conf)
exten => s,n,TrySystem(echo "Call from ${CALLERID(num)} ended" >> /tmp/dialout.log)
exten => s,n,ExecIf($["${DIALSTATUS}" = "CANCEL"]?TrySystem(echo "Call from ${CALLERID(num)} cancelled" >> /tmp/dialout.log))
exten => s,n,ExecIf($["${DIALSTATUS}" = "NOANSWER"]?TrySystem(echo "Call from ${CALLERID(num)} missed" >> /tmp/dialout.log))
exten => s,n,ExecIf($["${DIALSTATUS}" = "BUSY"]?TrySystem(echo "Call from ${CALLERID(num)} busy" >> /tmp/dialout.log))
exten => s,n,ExecIf($["${DIALSTATUS}" = "ANSWER"]?TrySystem(echo "Call from ${CALLERID(num)} answered" >> /tmp/dialout.log))
exten => s,n,Return

这个 Dial Plan 会在外线呼入、通话结束等事件发生时,将通话记录写入 /tmp/dialout.log 文件。按照需要编写脚本并在 TrySystem 里调用,就能实现自定义的通话记录处理。

1
2
3
4
5
6
/var/spool/asterisk/monitor/
├── 2023
│ ├── 03
│ │ ├── 27
│ │ │ ├── in-0123456789-180xxxxxxxx-20230327-160626-1679904386.9.wav
│ │ │ └── out-180xxxxxxxx-1000-20230327-160920-1679904560.17.wav

录音文件存放在 /var/spool/asterisk/monitor/ 目录下,按照通话日期整理目录,文件名包含通话的方向、被叫号码、主叫号码、通话日期(年月日)、通话时间(时分秒)、通话起始的 UNIX 时间戳。