sms
作者:王城钧
一、概述
sms 库提供了短信相关功能,包括异步发送短信、同步发送短信、设置新短信回调函数、设置长短信自动合并模式以及清除长短信缓存的功能
1、对于电信卡来说,SMS 短信功能跟核心库 CC(VoLTE 通话)是伴生关系,只有支持 CC 核心库的固件才支持电信卡的 SMS 短信功能;
2、对于移动/联通卡来说,SMS 短信功能合宙所有全网通 4G 模组都默认支持;
3、对于某些只支持单一运营商的型号,比如只支持移动运营商的 Air700ECH/Air700ECT,则相应的也只支持移动卡的 SMS 短信功能;
4、有些流量卡可能没有开通 SMS 短信功能,请咨询卡商或运营商确认,无法确认时建议用自己的手机卡测试确认;
5、再次提醒!由于合宙二次开发型号模组支持多种固件版本,使用电信卡 SMS 短信功能时请务必选择同时支持 CC(VoLTE 通话)的固件版本;
二、核心示例
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 1 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_SEND_RESULT"
消息类型:string
消息含义:表示短信发送操作的最终结果通知,包含发送成功或失败的状态信息。
注意事项:普通短信(非长短信):
每发送一条短信,当网络返回发送结果后立即触发一次该消息。
由于 sms.send() 是异步操作,其返回值仅表示发送请求是否成功提交,而非实际发送结果。
长短信(多条短信组成的完整消息):
仅在所有短信片段全部发送完成后才会触发一次该消息。
不会对每个短信片段单独触发消息,确保应用层只收到一次完整的发送结果。
对于长短信,建议使用 sms.sendLong().wait() 方式获取发送结果。
参数示例:-- 发送短信并等待结果
local function sendSmsWithResult()
local result = sms.sendLong("+8613416121234", "这是一条测试短信").wait()
if result then
log.info("sms", "短信发送成功")
else
log.info("sms", "短信发送失败")
end
end
sys.taskInit(sendSmsWithResult)
四、函数详解
sms.send(phone, msg, auto_phone_fix)
功能
异步发送短信,通过返回值确认任务启动状态,底层"SMS_SEND_RESULT"消息获取最终发送结果。
参数
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;
返回值
local result = sms.send(phone, msg, auto_phone_fix)
result
含义说明:短信发送结果,
sms.send 的同步结果仅表示任务启动成功,
最终发送状态需通过异步事件 "SMS_SEND_RESULT" 获取;
数据类型:boolean;
取值范围:true或者false;
注意事项:暂无;
返回示例:true;
示例
sms.send("10010", "101")
sms.sendLong(phone, msg, auto_phone_fix).wait()
功能
同步发送短信,只可以在 task 中运行,支持长级联短信;
参数
phone
参数含义:表示电话号码;
数据类型:string;
取值范围:暂无;
是否必选:必须传入此参数;
注意事项:暂无;
参数示例:"13188888888";
msg
参数含义:短信内容,编码格式编码格式为UTF-8字符串;
数据类型:string;
取值范围:暂无;
是否必选:必须传入此参数;
注意事项:支持长短信,长短信单分片大小最大134字节,
最大分片数量128片,
一个英文算一个字节,一个中文算2个字节,
与 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 核心库。