Skip to content

SIP SMS VoIP Configuration.zh cn

github-actions[bot] edited this page Sep 14, 2026 · 2 revisions

SIP、SMSD 与 VoIP 配置

qmodem-sipd 是独立的实验性 SIP 传输服务。它可以只连接 qmodem-voip、只连接 qmodem-smsd,或同时连接两者。入站 SIP 和出站 SIP 拥有独立配置与 procd 实例, 可以分别启停,也可以同时运行。

安装和服务

apk add qmodem-voip qmodem-smsd qmodem-sipd
/etc/init.d/qmodem_voip enable
/etc/init.d/qmodem-smsd enable
/etc/init.d/qmodem_voip_sipd enable

三个服务可独立启动。启用了某个方向的 VoIP 连接时,sipd 会等待 qmodem_voip 就绪;SMS 接口则在收到 SIP MESSAGE 时动态检查 qmodem.sms。状态可通过以下命令查看:

ubus call qmodem_voip status
ubus call qmodem.sms status
ubus call qmodem.sip status

LuCI 页面地址如下(主机名可替换为设备管理地址):

  • SMS:http://openwrt.lan/cgi-bin/luci/admin/modem/qmodem/sms
  • VoIP:http://openwrt.lan/cgi-bin/luci/admin/modem/qmodem/qmodem-voip
  • SIPD:http://openwrt.lan/cgi-bin/luci/admin/modem/qmodem/qmodem-sipd

SIPD 使用独立页面和独立的 qmodem_sip 配置,不再出现在 VoIP 页面中。

从旧版升级时,原 qmodem_voip.sip 配置会按原模式迁移到 qmodem_sip.inboundqmodem_sip.outbound,迁移成功后删除旧配置段和旧防火墙 include。

QModem 与 SMSD

main 分支中新建的 modem 配置默认使用 ubus AT 通道。已有配置只有在缺少 use_ubus 时才会迁移为 1,显式配置的 0 会保留。

uci set qmodem.modem_1.use_ubus='1'
uci set qmodem.modem_1.sms_mode='database_poll'
uci commit qmodem
/etc/init.d/qmodem-smsd restart

SIP MESSAGE 转蜂窝短信必须使用 SMSD 数据库模式,并通过带幂等 request_idqmodem.sms send_managed 调用。sms_mode='direct' 不支持该路径。

VoIPD

qmodem-voip 只负责蜂窝通话状态、AT 控制和媒体,不再管理 SIP 监听或注册参数:

uci set qmodem_voip.main.enabled='1'
uci set qmodem_voip.main.web_enabled='0'
uci set qmodem_voip.main.interface='lan'
uci commit qmodem_voip
/etc/init.d/qmodem_voip restart

支持范围仍由 modem profile 决定;不支持的硬件会失败关闭,安装软件包或 SIP 注册成功 都不能替代真实设备上的双向音频验证。

入站 SIP

入站模式在指定 OpenWrt 网络接口上监听 UDP/TCP。只有启用入站方向时,防火墙脚本 才在该接口地址上开放 SIP 端口和 RTP 范围。

uci set qmodem_sip.inbound.enabled='1'
uci set qmodem_sip.inbound.interface='lan'
uci set qmodem_sip.inbound.listen_port='5060'
uci set qmodem_sip.inbound.transport='udp_tcp'
uci set qmodem_sip.inbound.voip_enabled='1'
uci set qmodem_sip.inbound.sms_enabled='1'
uci set qmodem_sip.inbound.sms_modem='modem_1'
uci set qmodem_sip.inbound.username='qmodem'
uci set qmodem_sip.inbound.password='REPLACE_WITH_A_STRONG_PASSWORD'
uci commit qmodem_sip
/etc/init.d/qmodem_voip_sipd restart

也可以生成一次性显示的新密码;密码会写入入站配置,但不会出现在状态接口中:

ubus call qmodem.sip generate_credentials '{"username":"qmodem"}'

收到经过认证的 text/plain SIP MESSAGE 后,Request-URI 的 user 部分会作为短信号码, 正文作为短信内容。只有 send_managed 返回成功时 sipd 才响应 SIP 200。

出站 SIP

出站模式仅支持带服务端证书校验的 TLS,并向指定 SIP 服务注册:

uci set qmodem_sip.outbound.enabled='1'
uci set qmodem_sip.outbound.interface='wan'
uci set qmodem_sip.outbound.listen_port='5061'
uci set qmodem_sip.outbound.server='pbx.example.net'
uci set qmodem_sip.outbound.port='5061'
uci set qmodem_sip.outbound.transport='tls'
uci set qmodem_sip.outbound.username='device-1001'
uci set qmodem_sip.outbound.password='REPLACE_ME'
uci set qmodem_sip.outbound.realm=''
uci set qmodem_sip.outbound.register_interval='300'
uci set qmodem_sip.outbound.voip_enabled='1'
uci set qmodem_sip.outbound.sms_enabled='0'
uci commit qmodem_sip
/etc/init.d/qmodem_voip_sipd restart

入站使用 lan_sip,出站使用 external_sip 参与 qmodem_voip 的呼叫归属仲裁;两者 可以同时启用,但同一时刻仍只有一个端点能接管一通蜂窝电话。

SMS 转 SIP MESSAGE

sms-forwarder-nextapi_type='sip' 不执行外部脚本,而是调用 qmodem.sip send_message。目标方向必须正在运行;出站方向还必须已经注册,入站方向必须已有活跃 的本地 REGISTER 绑定。

uci set sms_forwarder.sms_forward.enable='1'
uci set sms_forwarder.sip_out='sms_forward_instance'
uci set sms_forwarder.sip_out.enable='1'
uci set sms_forwarder.sip_out.modem_cfg='modem_1'
uci set sms_forwarder.sip_out.poll_interval='30'
uci set sms_forwarder.sip_out.api_type='sip'
uci set sms_forwarder.sip_out.api_config='{"direction":"outbound","recipient_uri":"sip:sms@pbx.example.net"}'
uci commit sms_forwarder
/etc/init.d/sms_forwarder restart

转发成功以远端 SIP 2xx 响应为准。短信号码、内容、设备日志和配置备份不应提交到仓库。

Asterisk MESSAGE 路由

Asterisk 需要为 QModem 和电话端点分别指定消息上下文。以下示例假定 QModem 端点为 qmodem1001,电话端点为 1001

; pjsip.conf
[qmodem1001]
type=endpoint
message_context=qmodem-message
; 保留该端点已有的 transport、auth、aors 和媒体配置

[1001]
type=endpoint
message_context=phone-message
; 保留该端点已有的 transport、auth、aors 和媒体配置
; extensions.conf
[qmodem-message]
; 将 QModem 的真实短信发送方传给 SIP 客户端,客户端可直接点击回复
exten => 1001,1,Set(MESSAGE(from)=sip:${MESSAGE_DATA(X-QModem-SMS-From)}@pbx.example.net)
 same => n,MessageSend(pjsip:1001)
 same => n,NoOp(QModem message status: ${MESSAGE_SEND_STATUS})
 same => n,Hangup()

[phone-message]
exten => _X.,1,MessageSend(pjsip:PJSIP/${EXTEN}@qmodem1001)
 same => n,NoOp(Phone message status: ${MESSAGE_SEND_STATUS})
 same => n,Hangup()

phone-message 中的 ${EXTEN} 必须原样保留到 QModem 的 SIP Request-URI;SIPD 会把 其中的 user 部分作为蜂窝短信收件号码。修改 bind mount 提供的配置文件后应重启 Asterisk 容器,再检查两个端点的 Contact 都恢复为 Avail

故障诊断与验证

短信发送接口返回 success 只表示请求已进入发送流程;必须在设备日志中看到调制解调器返回 +CMGS: <id>,才算完成空口提交。若发送 PDU 以 00 开头,设备必须使用二进制长度写入, 不能用 C 字符串长度,否则会出现“接口成功但没有短信”的假成功。

长短信可能由多个 +CMTI 事件分段到达。数据库模式会保留尚未拼完整的分组,直到等待窗口 过期;同一个 UDH 引用在一条短信完成后再次出现时会新建分组,不会把新短信拼到旧消息中。

建议按以下顺序检查转发链路:

ubus call qmodem.sms status
ubus call qmodem.sip status
logread | grep 'qmodem_voip sip: outbound REGISTER'
ubus call qmodem.sms delivery_claim

出站转发要求 qmodem.sipoutbound 已运行且 registeredtrue;Asterisk 上 QModem 端点和电话端点的 Contact 也都应为 Avail。若日志显示 REGISTER 返回 503 或 registered=false,先执行 /etc/init.d/qmodem_voip_sipd restart,确认重新注册成功后再 领取并重试待投递记录。delivery_complete 只有在 SIP 端返回 2xx 后才应标记成功。

send_managed 和 SIP 转发仅适用于数据库模式;直连模式不提供持久化投递、重试或回执追踪。

Clone this wiki locally