63 sms-短信
作者:王城钧 | 最后修改:2026-09-01
声明:本介绍为技术支持页面,禁止用于非法用途,请遵守国家法律法规要求。
短信转发为中性物联网技术,仅限本人实名登记 SIM 卡,用于企业合法内部运维。严禁用于代他人接收短信、接码、批量注册账号等违法行为,使用者承担全部法律责任。
一、概述
sms 库提供了短信相关功能,包括异步发送短信、同步发送短信、设置新短信回调函数、设置长短信自动合并模式以及清除长短信缓存的功能
1、对于电信卡来说,SMS 短信功能跟核心库 CC(VoLTE 通话)是伴生关系,只有支持 CC 核心库的固件才支持电信卡的 SMS 短信功能;
2、对于移动/联通卡来说,SMS 短信功能合宙所有全网通 4G 模组都默认支持;
3、对于某些只支持单一运营商的型号,比如只支持移动运营商的 Air700ECH/Air700ECT,则相应的也只支持移动卡的 SMS 短信功能;
4、有些流量卡可能没有开通 SMS 短信功能,请咨询卡商或运营商确认,无法确认时建议用自己的手机卡测试确认;
5、再次提醒!由于合宙二次开发型号模组支持多种固件版本,使用电信卡 SMS 短信功能时请务必选择同时支持 CC(VoLTE 通话)的固件版本;
短信编码说明(GSM7 与 UCS2)
6、短信内容在发送时,底层会根据内容自动选择编码方式:
-
若短信内容全部为 ASCII 可见字符(纯英文/数字/符号),则使用 GSM7 编码(7bit GSM Default);
-
若短信内容包含非 ASCII 字符(如中文、emoji 等),则自动切换为 UCS2 编码(16bit Unicode);
7、接收短信时,底层同样支持 GSM7 和 UCS2 两种编码的自动解析,无需用户手动处理编码格式;
8、发送和接收短信的 GSM7/UCS2 自适应编码功能,从780EXX/8000 v2034 固件版本开始支持;

二、核心示例
1、核心示例是指:使用本库文件提供的核心 API,开发的基础业务逻辑的演示代码;
2、核心示例的作用是:帮助开发者快速理解如何使用本库,所以核心示例的逻辑都比较简单;
3、更加完整和详细的 demo,请参考 LuatOS 仓库 中各个产品目录下的 demo/sms
-- LuaTools需要PROJECT和VERSION这两个信息
PROJECT = "smsdemo"
VERSION = "001.000.001"
log.info("main", PROJECT, VERSION)
if wdt then
--添加硬狗防止程序卡死,在支持的设备上启用这个功能
wdt.init(9000)--初始化watchdog设置为9s
sys.timerLoopStart(wdt.feed, 3000)--3s喂一次狗
end
log.info("main", "sms demo")
-- 辅助发送http请求, 因为http库需要在task里运行
function http_post(url, headers, body)
local function http()
local code, headers, body = http.request("POST", url, headers, body).wait()
log.info("resp", code)
end
sys.taskInit(http)
end
function sms_handler(num, txt)
-- num 手机号码
-- txt 文本内容
log.info("sms", num, txt, txt:toHex())
-- http演示1, 发json
local body = json.encode({phone=num, txt=txt})
local headers = {}
headers["Content-Type"] = "application/json"
log.info("json", body)
http_post("http://www.luatos.com/api/sms/blackhole", headers, body)
-- http演示2, 发表单的
headers = {}
headers["Content-Type"] = "application/x-www-form-urlencoded"
local body = string.format("phone=%s&txt=%s", num:urlEncode(), txt:urlEncode())
log.info("params", body)
http_post("http://www.luatos.com/api/sms/blackhole", headers, body)
-- http演示3, 不需要headers,直接发
http_post("http://www.luatos.com/api/sms/blackhole", nil, num .. "," .. txt)
-- 如需发送到钉钉, 参考 demo/dingding
-- 如需发送到飞书, 参考 demo/feishu
end
--------------------------------------------------------------------
-- 接收短信, 支持多种方式, 选一种就可以了
-- 1. 设置回调函数
--sms.setNewSmsCb(sms_handler)
-- 2. 订阅系统消息
--sys.subscribe("SMS_INC", sms_handler)
-- 3. 在task里等着
local function sms_sub()
while true do
local ret, num, txt = sys.waitUntil("SMS_INC", 300000)
if num then
-- 方案1, 交给自定义函数处理
sms_handler(num, txt)
-- 方案2, 因为这里是task内, 可以直接调用http.request
-- local body = json.encode({phone=num, txt=txt})
-- local headers = {}
-- headers["Content-Type"] = "application/json"
-- log.info("json", body)
-- local code, headers, body = http.request("POST", "http://www.luatos.com/api/sms/blackhole", headers, body).wait()
-- log.info("resp", code)
end
end
end
sys.taskInit(sms_sub)
-------------------------------------------------------------------
-- 发送短信, 直接调用sms.send就行, 是不是task无所谓
local function sms_send()
sys.wait(10000)
-- 中移动卡查短信
sms.send("+8610086", "301")
-- 联通卡查话费
-- sms.send("10010", "101")
end
sys.taskInit(sms_send)
-- 用户代码已结束---------------------------------------------
-- 结尾总是这一句
sys.run()
-- sys.run()之后后面不要加任何语句!!!!!
三、常量详解
核心库常量,顾名思义是由合宙 LuatOS 内核固件中定义的、不可重新赋值或修改的固定值,在脚本代码中不需要声明,可直接调用;
每个常量对应的常量取值仅做日志打印时查询使用,不要将这个常量取值用做具体的业务逻辑判断,因为LuatOS内核固件可能会变更每个常量对应的常量取值;
如果用做具体的业务逻辑判断,一旦常量取值发生改变,业务逻辑就会出错;
"SMS_INC"
消息类型:string
消息含义:表示收到短信内容
注意事项:普通短信(非长短信):
每收到一条短信,立即执行回调函数。
长短信(多条短信组成的完整消息):
必须所有短信片段接收完成后才会执行一次回调,不会每收到一条片段就触发回调。
参数示例:
-- 接收短信, 支持多种方式, 选一种就可以了
-- 1. 设置回调函数
local function handleNewSms(phone, sms)
log.info("sms", phone, sms)
end
sms.setNewSmsCb(handleNewSms)
-- 2. 订阅系统消息
local function handleSmsInc(phone, sms)
log.info("sms", phone, sms)
end
sys.subscribe("SMS_INC", handleSmsInc)
"SMS_READY"
消息类型:string
消息含义:表示短信功能初始化完成,此时可以正常收发短信。
注意事项:建议在发送或接收短信前先等待该消息,确保短信模块已就绪。
SM 卡注册网络后底层才会发出此消息,未插卡或未注册网络时不会触发。
参数示例:-- 等待短信就绪后发送短信
sys.subscribe("SMS_READY", function(id)
log.info("sms", "ready, sim id:", id)
sms.send("10010", "101")
end)
"SMS_SENT"
消息类型:string
消息含义:表示短信发送操作的最终结果通知,包含发送成功或失败的状态信息。
注意事项:普通短信(非长短信):
每发送一条短信,当网络返回发送结果后立即触发一次该消息。
由于 sms.send() 是异步操作,其返回值仅表示发送请求是否成功提交,而非实际发送结果。
长短信(多条短信组成的完整消息):
仅在所有短信片段全部发送完成后才会触发一次该消息。
不会对每个短信片段单独触发消息,确保应用层只收到一次完整的发送结果。
对于长短信,建议使用 sms.sendLong().wait() 方式获取发送结果。
回调参数:
result
参数含义:短信向SMSC提交的整体结果;
数据类型:boolean;
取值范围:true、false;
是否必选:回调固定输出;
注意事项:true代表短信中心已接收短信;true仅代表提交成功,不等于收件人收到短信;
false代表提交失败;
参数示例:true;
rp_cause
参数含义:3GPP RP‑Cause协议错误码;
数据类型:number;
取值范围:0‑255;
是否必选:回调固定输出;
注意事项:RP层协议错误,仅 error_code=0 并且 result=false 场景下有效;
用于识别空号、停机等运营商侧返回业务错误;
1、30表示空号;
10、50表示停机;
27表示用户不在线;
参数示例:0;
rp_cause_str
参数含义:RP‑Cause错误码对应的文本描述;
数据类型:string;
取值范围:暂无;
是否必选:回调固定输出;
注意事项:对rp_cause的可读文字说明,方便日志排查;
参数示例:SUCCESS;
msg_ref
参数含义:短信消息参考编号;
数据类型:number;
取值范围:0‑255;
是否必选:回调固定输出;
注意事项:短信唯一标识,用于和SMS_REPORT回执事件做消息匹配;多条并发短信依靠此字段一一对应回执;
参数示例:123;
error_code
参数含义:SDK层短信错误码;
数据类型:number;
取值范围:0、300、330、331、332、500;
0表示提交成功,短信中心接受;
300表示设备故障;
330表示短信中心地址未知;
331表示无网络服务 / SIM 未开通短信业务;
332表示网络超时;
500表示未知错误;
是否必选:回调固定输出;
注意事项:业务判断优先使用此字段;0代表提交成功,非0代表 网络/SIM/设备类故障;
参数示例:0;
参数示例:-- 短信提交事件完整回调示例
local function sms_sent_cb(result, rp_cause, rp_cause_str, msg_ref, error_code)
log.info("SMS_SENT", "result=", result, "rp_cause=", rp_cause, "str=", rp_cause_str, "msg_ref=", msg_ref, "error_code=", error_code)
end
sys.subscribe("SMS_SENT", sms_sent_cb)
"SMS_REPORT"
消息类型:string
消息含义:表示短信状态回执事件,返回接收方手机真实投递结果(送达/失败)。
注意事项:该消息V2048及以后版本支持
必须在调用 sms.send() 将回执参数设置为 true,才会收到该事件;否则不会触发。
msg_ref 用于和 SMS_SENT 的 msg_ref 做消息匹配,多条并发短信依赖该编号区分对应回执。
status=0x46 代表消息超过VP有效期被短信中心丢弃,与 setVp / send接口vp参数配置强相关。
回调参数:
msg_ref
参数含义:短信消息参考编号;
数据类型:number; 取值范围:0‑255;
是否必选:回调固定输出;
注意事项:与SMS_SENT回调输出的msg_ref一一对应,用于匹配对应短信的投递回执;
参数示例:12;
status
参数含义:短信投递ST状态码;
数据类型:number;
取值范围:0x00、0x20、0x22、0x23、0x43、0x46;
0x00表示成功送达;
0x20表示网络拥塞临时失败;
0x22表示用户关机/不在线无响应;
0x23表示服务拒绝,大概率停机;
0x43表示不可达,空号/停机;
0x46表示超过VP有效期,消息丢弃;
是否必选:回调固定输出;
注意事项:0x00为成功送达,其余为各类投递失败状态;
参数示例:0x00;
status_str
参数含义:ST状态码对应的文本描述;
数据类型:string;
取值范围:暂无;
是否必选:回调固定输出;
注意事项:status的可读文字说明,用于日志排查;
参数示例:"SUCCESS";
phone
参数含义:短信接收方手机号码;
数据类型:string;
取值范围:暂无;
是否必选:回调固定输出;
注意事项:目标接收号码;
参数示例:"13800138000";
discharge_time
参数含义:送达或投递失败发生的时间;
数据类型:string;
取值范围:暂无;
是否必选:回调固定输出;
注意事项:短信中心上报事件的时间;
参数示例:"2026‑08‑19 15:20:30";
参数示例:-- 短信提交事件完整回调示例
local function sms_report_cb(msg_ref, status, status_str, phone, discharge_time)
log.info("SMS_REPORT", "msg_ref=", msg_ref, "status=", status, "str=", status_str, "phone=", phone, "time=", discharge_time)
end
sys.subscribe("SMS_REPORT", sms_report_cb)
四、函数详解
sms.send(phone, msg, auto_phone_fix, need_report ,vp)
功能
异步发送短信,通过返回值确认任务启动状态,底层"SMS_SENT"消息获取最终发送结果。
参数
phone
参数含义:表示电话号码;
数据类型:string;
取值范围:暂无;
是否必选:必须传入此参数;
注意事项:暂无;
参数示例:"13188888888";
msg
参数含义:短信内容,编码格式为UTF-8的字符串;
数据类型:string;
取值范围:暂无;
是否必选:必须传入此参数;
注意事项:单条短信最大为140字节,一个英文算一个字节,一个中文算2个字节;
与sendLong的主要差异为异步发送模式;
参数示例:"101";
auto_phone_fix
参数含义:用于控制是否自动修正电话号码格式,
当auto_phone_fix=true时(默认值)
系统会对电话号码进行智能处理,具体规则如下:
1.如果电话号码以'+'开头(例如"+8613416121234"),会自动移除'+'号,保留后面的部分
2.如果电话号码不以'86'开头(中国国家代码),会自动在号码前面添加'86'
3.如果电话号码已经以'86'开头,则保持不变
当auto_phone_fix=false时
系统会直接使用用户传入的电话号码,不做任何自动处理和格式调整
-- 自动处理模式
-- 输入:sms.send("+8613416121234", "Hello",true)
-- auto_phone_fix=true(默认)
-- 实际发送的号码:"8613416121234"(自动去掉'+'号)
-- 禁用自动处理
-- 输入:sms.send("+8613416121234", "Hello", false)
-- 实际发送的号码:"+8613416121234"(保持原样)
默认true;
数据类型:boolean;
取值范围:true/false;
是否必选:可选传入此参数;
注意事项:暂无;
参数示例:true;
need_report
参数含义:表示是否请求短信回执(状态报告),默认false不请求,
设置为true后,无论短信最终是成功送达还是投递失败、超时丢弃,均会触发SMS_REPORT事件上报投递状态;
数据类型:boolean;
取值范围:true/false;
是否必选:可选传入此参数;
注意事项:暂无;
参数示例:true;
vp
参数含义:短信中心最大重试有效期,短信下发后,接收方关机 / 无信号时,短信中心会在该时间内持续尝试投递;
超时未送达则短信直接丢弃;
数据类型:number;
取值范围:0‑255;
是否必选:可选传入此参数;
注意事项: 该参数在V2050及以后版本支持
该值是协议标准编码值,不是直接填小时 / 天数,需要按照下表公式换算得到实际时长
最终生效时间受短信中心最大上限约束,即使 VP 算出来 7 天,
若运营商 SMSC 上限只有 72 小时,则实际按 72 小时生效;
与回执参数无关:回执 boolean 只控制是否上报送达报告,VP 控制消息在网关侧保存多久
参数示例:169,计算:169‑166 =3天 =72小时;
参数示例:169;
VP 完整换算表
| vp 值 | 计算公式 | 实际有效期范围 |
|---|---|---|
| 0‑143 | (vp+1) ×5 分钟 | 5 分钟~12 小时 |
| 144‑167 | 12h + (vp‑143) ×30 分钟 | 12 ~ 24 小时 |
| 168‑196 | (vp‑166) 天 | 2 ~ 30 天 |
| 197‑255 | (vp‑192) 周 | 5 周~63 周 |
返回值
local result = sms.send(phone, msg, auto_phone_fix, need_report ,vp)
result
含义说明:短信发送结果,
sms.send 的同步结果仅表示任务启动成功,
最终发送状态需通过异步事件 "SMS_SENT" 获取;
数据类型:boolean;
取值范围:true或者false;
注意事项:暂无;
返回示例:true;
示例
sms.send("10010", "101", true, true, 169)
sms.sendLong(phone, msg, auto_phone_fix).wait()
功能
同步发送短信,只可以在 task 中运行,支持长级联短信;
参数
phone
参数含义:表示电话号码;
数据类型:string;
取值范围:暂无;
是否必选:必须传入此参数;
注意事项:暂无;
参数示例:"13188888888";
msg
参数含义:短信内容,编码格式为UTF-8的字符串;
数据类型:string;
取值范围:暂无;
是否必选:必须传入此参数;
注意事项:支持长短信(长级联短信),底层会根据内容自动选择编码方式:
1. 纯ASCII字符(英文/数字/符号)→ GSM7编码;
2. 包含非ASCII字符(如中文)→ UCS2编码;
长短信单分片大小最大134字节,最大分片数量128片;
与 sms.send 相比,核心差异在于同步发送模式,支持长级联短信自动拆分;
如果超过最长限制,会出现下列情况:
1. 直接返回失败,表示发送任务未启动。
2. 自动截断并发送部分内容
3. 触发模块内部错误调用后无返回(卡死)
或抛出异常(如内存不足、缓冲区溢出)
参数示例:"祝你天天开心!";
auto_phone_fix
参数含义:用于控制是否自动修正电话号码格式,
当auto_phone_fix=true时(默认值)
系统会对电话号码进行智能处理,具体规则如下:
1.如果电话号码以'+'开头(例如"+8613416121234"),会自动移除'+'号,保留后面的部分
2.如果电话号码不以'86'开头(中国国家代码),会自动在号码前面添加'86'
3.如果电话号码已经以'86'开头,则保持不变
当auto_phone_fix=false时
系统会直接使用用户传入的电话号码,不做任何自动处理和格式调整
-- 自动处理模式
-- 输入:sms.send("+8613416121234", "Hello",true)
-- auto_phone_fix=true(默认)
-- 实际发送的号码:"8613416121234"(自动去掉'+'号)
-- 禁用自动处理
-- 输入:sms.send("+8613416121234", "Hello", false)
-- 实际发送的号码:"+8613416121234"(保持原样)
默认true;
数据类型:boolean;
取值范围:true/false;
是否必选:可选传入此参数;
注意事项:暂无;
参数示例:true;
返回值
local result = sms.sendLong(phone, msg, auto_phone_fix).wait()
result
含义说明:短信发送结果;
数据类型:boolean;
取值范围:true或者false;
注意事项:暂无;
返回示例:true;
示例
sms.sendLong("10010", "101").wait()
sms.setNewSmsCb(func)
功能
设置接收到新短信的回调函数,
- 普通短信(非长短信):每收到一条短信,立即执行回调函数。
- 长短信(多条短信组成的完整消息):必须所有短信片段接收完成后才会执行一次回调,不会每收到一条片段就触发回调。
参数
func
参数含义:接收到新短信时触发的回调函数,支持处理普通短信与长短信两种模式
普通短信:每收到一条立即执行,参数为(num, txt, metas)
长短信:所有分段接收完成后执行一次,metas包含完整分段元数据
回调函数格式为:
function callback(num, txt, metas)
-- num: string类型,表示电话号码
-- txt:string类型,表示发送的文本信息
-- metas(短信):year(年)、mon(月)、 day(日)、hour(时)、min(分)、sec(秒)、tz(时区)
-- metas(短信):refNum:长短信的参考编号
- seqNum :当前短信分片的序号
- maxNum :长短信的总分片数
数据类型:function;
取值范围:暂无;
是否必选:必须传入此参数;
注意事项:暂无;
参数示例:local function smscb(num, txt, metas)
log.info("sms", num, txt, metas and json.encode(metas) or "")
end
sms.setNewSmsCb(smscb)
-- 普通短信示例:
-- local function smscb1("+8613800138000","+8613800138000",
-- {year=2025,mon=10,day=11,hour=15,min=30,sec=45,tz=480})
-- sms.setNewSmsCb(smscb1)
-- 长短信示例:
-- local function smscb2("+8613900139000", txt="这是一条长短信合并后的完整内容",
-- metas={refNum=123,seqNum=3,maxNum=3,year=2025,mon=10,day=11,hour=15,min=32,sec=00,tz=480})
-- sms.setNewSmsCb(smscb2)
返回值
nil
示例
local function smscb(num, txt, metas)
-- num 手机号码
-- txt 文本内容
-- metas 短信的元数据
-- 普通短信的metas结构:
-- {
-- refNum = nil, -- 无长短信编号
-- seqNum = 1, -- 固定为1
-- maxNum = 1, -- 固定为1
-- }
-- 长短信合并后的metas结构:
-- {
-- refNum = 123, -- 长短信唯一ID
-- seqNum = 1, -- 当前为第1段
-- maxNum = 3, -- 共3段
-- year = 2025, mon = 10, day = 11,
-- hour = 15, min = 30, sec = 45,
-- tz = 480 -- +8:00时区
-- }
-- 时间戳字段同上
-- 注意, 如果开启了长短信自动合并功能,
-- 长短信会自动合并成一条txt
log.info("sms", num, txt, metas and json.encode(metas) or "")
end)
sms.setNewSmsCb(smscb)
sms.autoLong(mode)
功能
设置长短信的自动合并功能
参数
mode
参数含义:是否自动合并,true为自动合并,为默认值;
数据类型:boolean;
取值范围:暂无;
是否必选:可选传入此参数;
注意事项:暂无;
参数示例:true;
返回值
local result = sms.autoLong(true)
含义说明:设置长短信的自动合并功能结果;
数据类型:boolean;
取值范围:true或者false;
注意事项:暂无;
返回示例:true;
示例
sms.autoLong(false)
sms.clearLong()
功能
清除长短信缓存
使用场景如下:
- 长短信分片未完全接收导致缓存残留
- 缓存池溢出风险
- 内存资源紧张
- 异常状态重置
参数
nil
返回值
local num = sms.clearLong()
num
含义说明:清理掉的片段数量;
数据类型:number;
取值范围:暂无;
注意事项:暂无;
返回示例:1;
示例
sms.clearLong()
sms.debug(enable)
功能
设置短信模块的调试模式
参数
enable
含义说明:enable 是否启用调试模式,true为启用,false为禁用;
数据类型:boolean;
取值范围:ture或false;
注意事项:暂无;
参数示例:true;
返回值
nil
示例
-- 启用短信调试模式,会输出更多日志信息
sms.debug(true)
-- 禁用短信调试模式
sms.debug(false)
sms.setVp(vp)
功能
设置全局短信有效期,即短信中心最大重试保存时长。
该函数在V2050及以后版本支持
参数
vp
参数含义:短信中心最大重试有效期,短信下发后,接收方关机 / 无信号时,短信中心会在该时间内持续尝试投递;
超时未送达则短信直接丢弃;
数据类型:number;
取值范围:0‑255;
是否必选:可选传入此参数;
注意事项:该值是协议标准编码值,不是直接填小时 / 天数,需要按照下表公式换算得到实际时长
最终生效时间受短信中心最大上限约束,即使 VP 算出来 7 天,
若运营商 SMSC 上限只有 72 小时,则实际按 72 小时生效;
与回执参数无关:回执 boolean 只控制是否上报送达报告,VP 控制消息在网关侧保存多久
参数示例:169,计算:169‑166 =3天 =72小时;
参数示例:169;
VP 完整换算表
| vp 值 | 计算公式 | 实际有效期范围 |
|---|---|---|
| 0‑143 | (vp+1) ×5 分钟 | 5 分钟~12 小时 |
| 144‑167 | 12h + (vp‑143) ×30 分钟 | 12 ~ 24 小时 |
| 168‑196 | (vp‑166) 天 | 2 ~ 30 天 |
| 197‑255 | (vp‑192) 周 | 5 周~63 周 |
返回值
local value = sms.setVp(vp)
value
含义说明:返回设置完成后生效的全局短信vp编码值;
数据类型:number;
取值范围:0‑255;
注意事项:暂无;
返回示例:169;
示例
sms.setVp(169)
五、产品支持说明
不同产品的LuatOS固件,对sms核心库的支持情况如下:
1、Air780EX2/Air700ECP/Air780EPM/Air780EGP 1号、2号、103-106号固件支持(均支持移动/联通,部分支持电信);
2、Air700ECH/Air780EHM/EHV/EGH/EGG/EHU/EHN/Air8000系列 均支持移动/联通,部分支持电信;
3、Air8101系列 不支持;
4、Air1601 / Air1602 都不支持;
各产品固件支持核心库列表详细说明参考下面链接:
Air780EX2/Air700ECP/Air780EPM/Air780EGP固件支持列表