Files
mobile_comm/luatos/air780epm/module/Air780EPM/demo/sms/sms_app.lua
T
wangfq 173dd6874f init: Air780EPM 官方 LuatOS 项目代码基线
- 来源: 合宙 LuatOS 官方仓库 air780epm 模块完整代码
- 路径: luatos/air780epm/module/Air780EPM/demo 含官方 demo(含 mqtt/mqtts/socket/uart 等)
- 后续: 基于 demo 开发 UART<->MQTT 数据上报功能
2026-08-31 08:53:49 +08:00

205 lines
8.8 KiB
Lua

--[[
@module sms_forward
@summary 短信信息转发驱动模块
@version 1.0
@date 2025.10.15
@author 王城钧
@usage
本文件为来电信息转发驱动模块,核心业务逻辑为:
1、配置飞书,钉钉,企业微信机器人的webhook和secret(加签)。
2、send_sms(),发送短信的功能函数,等待IP_READY消息后,手机卡可以进行收发短信。
3、receive_sms(),接收短信处理的功能函数,收到短信后获取来信号码和短信内容,通过回调函数sms_handler(num, txt)转发到指定的机器人。
本文件没有对外接口,直接在main.lua中require "sms_forward"就可以加载运行;
]]
-- webhook_feishu和secret_feishu要换成你自己机器人的值
-- webhook_feishu是钉钉分配给机器人的URL
-- secret_feishu是选取 "加签", 自动生成的密钥
-- 下面的给一个测试群发消息, 随时可能关掉, 请换成你自己的值
local webhook_feishu = "https://open.feishu.cn/open-apis/bot/v2/hook/673d1e1d-0c7e-4d34-b7f0-48bdb4c4d03a"
local secret_feishu = "qlf8UXrJc7RYtJLx77jRVh"
local webhook_dingding =
"https://oapi.dingtalk.com/robot/send?access_token=bf9fe5c74194b9556cff401b87ac5de46a92bbf15cc226b73d14c28773b86f3b"
local secret_dingding = "SEC1bec4c6416b14c945806fa658840c7fbc64c3257aacd0c72f6cad5d22e3d29a4"
--local webhook_weixin = "https://work.weixin.qq.com/wework_admin/common/openBotProfile/24caa08b3a985454055047454d883fc98f"
local webhook_weixin = "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=a9dec355-3e0f-45bf-a0b1-0f8813fe6b7d"
-- 飞书关于机器人的文档 https://open.feishu.cn/document/ukTMukTMukTM/ucTM5YjL3ETO24yNxkjN?lang=zh-CN
--1.功能函数:短信转发到飞书
local function feishu_post_sms(num, rctxt)
local rheaders = {}
rheaders["Content-Type"] = "application/json"
-- LuatOS的时间戳只到秒,飞书也只需要秒
local timestamp = tostring(os.time())
local sign = crypto.hmac_sha256("", timestamp .. "\n" .. secret_feishu):fromHex():toBase64()
log.info("timestamp", timestamp)
log.info("sign", sign)
-- 注意, 这里的参数跟钉钉不同, 钉钉有个access_token参数, 飞书没有
local url = webhook_feishu
log.info("url", url)
-- json格式也需要按飞书的来
local data = { msg_type = "text" }
data["timestamp"] = timestamp
data["sign"] = sign
-- text就是要发送的文本内容, 其他格式按飞书的要求拼接table就好了
local text = "我的id是" ..
tostring(device_id) .. "," .. (os.date()) .. "," .. rtos.bsp() .. ", " .. num .. "发来短信,内容是:" .. rctxt
data["content"] = { text = text }
local rbody = (json.encode(data))
log.info("feishu", rbody)
local code, headers, body = http.request("POST", url, rheaders, rbody, { timeout = 5000 }).wait()
-- 正常会返回 200, {"errcode":0,"errmsg":"ok"}
-- 其他错误, 一般是密钥错了, 仔细检查吧
log.info("飞书机器人",
code==200 and "success" or "error",
code,
json.encode(headers or {}),
body and (body:len()>512 and body:len() or body) or "nil")
end
--2.功能函数:短信转发到钉钉
local function dingding_post(num, rctxt)
local rheaders = {}
rheaders["Content-Type"] = "application/json"
-- LuatOS的时间戳只到秒,但钉钉需要毫秒,补3个零
local timestamp = tostring(os.time()) .. "000"
local sign = crypto.hmac_sha256(timestamp .. "\n" .. secret_dingding, secret_dingding):fromHex():toBase64()
:urlEncode()
log.info("timestamp", timestamp)
log.info("sign", sign)
local url = webhook_dingding .. "&timestamp=" .. timestamp .. "&sign=" .. sign
log.info("url", url)
local data = { msgtype = "text" }
-- content就是要发送的文本内容, 其他格式按钉钉的要求拼接table就好了
local content = "我的id是" ..
tostring(device_id) .. "," .. (os.date()) .. "," .. rtos.bsp() .. ", " .. num .. "发来短信,内容是:" .. rctxt
data["text"] = { content = content }
local rbody = (json.encode(data))
log.info("dingding", rbody)
local code, headers, body = http.request("POST", url, rheaders, (json.encode(data))).wait()
-- 正常会返回 200, {"errcode":0,"errmsg":"ok"}
-- 其他错误, 一般是密钥错了, 仔细检查吧
log.info("钉钉机器人",
code==200 and "success" or "error",
code,
json.encode(headers or {}),
body and (body:len()>512 and body:len() or body) or "nil")
end
--3.功能函数:短信转发到企业微信
local function weixin_post(num, rctxt)
local rheaders = {}
rheaders["Content-Type"] = "application/json"
local timestamp = tostring(os.time()) .. "000"
log.info("timestamp", timestamp)
local url = webhook_weixin .. "&timestamp=" .. timestamp
log.info("url", url)
local data = { msgtype = "text" }
-- content就是要发送的文本内容, 其他格式按钉钉的要求拼接table就好了
local content = "我的id是" ..
tostring(device_id) .. "," .. (os.date()) .. "," .. rtos.bsp() .. ", " .. num .. "发来短信,内容是:" .. rctxt
data["text"] = { content = content }
local rbody = (json.encode(data))
log.info("weixin", rbody)
local code, headers, body = http.request("POST", url, rheaders, (json.encode(data))).wait()
-- 正常会返回 200, {"errcode":0,"errmsg":"ok"}
-- 其他错误, 一般是密钥错了, 仔细检查吧
log.info("企业微信机器人",
code==200 and "success" or "error",
code,
json.encode(headers or {}),
body and (body:len()>512 and body:len() or body) or "nil")
end
--4.功能函数:接收短信的回调函数
local function sms_handler(num, txt)
-- num 给我发短信的手机号码
-- txt 收到的短信文本内容
log.info("转发到飞书")
feishu_post_sms(num, txt)
--等待1秒, 非必须
sys.wait(1000)
log.info("转发到钉钉")
dingding_post(num, txt)
--等待1秒, 非必须
sys.wait(1000)
log.info("转发到微信")
weixin_post(num, txt)
end
--------------------------------------------------------------------
--5. 功能函数:接收短信
local function receive_sms()
while 1 do
local ret, num, txt = sys.waitUntil("SMS_INC", 30000)
log.info("收到来自短信:", num)
if num then
log.info("num是", num)
log.info("收到来自" .. num .. "的短信:" .. txt)
--local isReady1, index1 = socket.adapter()
log.info("当前网络", socket.adapter())
sms_handler(num, txt)
end
end
end
-------------------------------------------------------------------
-- 6.功能函数:发送短信, 直接调用sms.send就行, 是不是task无所谓
local function send_sms()
--按照规范的做法,这里应该等待"SMS_READY"消息,
--目前内核固件正在开发支持"SMS_READY"消息功能,
--等开发好了之后,再使用"SMS_READY"消息,
--当前阶段,先使用"IP_READY"替代
sys.waitUntil("IP_READY")
sys.wait(5000)
-- 当前阶段等待5s,使得sms准备就绪,待"SMS_READY"消息开发完成后,删除如上两行代码使用sys.waitUntil("SMS_READY")替代
log.info("发送短信准备就绪")
local cont = 1
log.info("开始发短信")
while 1 do
log.info("现在可以收发短信")
--获取本机号码,如果卡商没写入会返回nil
log.info("mobile.number(id) = ", mobile.number())
--获取本机iccid,如果卡商没写入会返回nil
log.info("mobile.iccid(id) = ", mobile.iccid())
--获取本机simid,如果卡商没写入会返回nil
log.info("mobile.simid(id) = ", mobile.simid())
--获取本机imsi,如果卡商没写入会返回nil
log.info("mobile.imsi(index) = ", mobile.imsi())
-- 注意:以下查话费的三行代码只需根据自己卡的运营商打开其一即可,其余两行关闭,不要全部打开
-- 电信卡查话费
local result = sms.send("10001", "102")
-- 中移动卡查短信
-- local result = sms.send("10086", "301")
-- 联通卡查话费
-- local result = sms.send("10010", "101")
-- 注意:V2018及更高版本固件才有"SMS_SENT"系统消息
if result then
local wait_msg, success = sys.waitUntil("SMS_SENT", 10000)
log.info("发送查询短信", "这是第" .. cont .. "次发送", " 发送结果:", wait_msg and (success and "成功" or "失败") or "超时")
else
log.info("发送查询短信", "这是第" .. cont .. "次发送", " 发送结果:同步发送失败")
end
log.info("等待10分钟")
cont = cont + 1
sys.wait(10 * 60 * 1000)
end
end
--发送短信
sys.taskInit(send_sms)
--接收短信
sys.taskInit(receive_sms)