Files
BR_YKC/4G/tools/resource/soc_script/v2025.12.31.22/lib/exfotawifi.lua
2026-03-31 15:46:04 +08:00

230 lines
7.8 KiB
Lua
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
--[[
@module exfotawifi
@summary 用于Air8000/8000A/8000W型号模组自动升级WIFI
@version 1.0.3
@date 2025.9.23
@author 拓毅恒
@usage
使用时在创建的一个task处理函数中直接调用exfotawifi.request()即可开始执行WiFi升级任务
升级完毕后最好取消调用,防止后期版本升级过高导致程序使用不稳定
-- 用法实例
local exfotawifi = require("exfotawifi")
local function fota_wifi_task()
-- ...此处省略很多代码
local result = exfotawifi.request()
if result then
log.info("exfotawifi", "升级任务执行成功")
else
log.info("exfotawifi", "升级任务执行失败")
end
-- ...此处省略很多代码
end
-- 启动WiFi自动更新任务
sys.taskInit(fota_wifi_task)
]]
local exfotawifi = {}
local is_request = false -- 标记是否正在执行request任务
local fota_result = false -- 记录fota任务的执行结果
-- 判断是否为空
local function is_nil(s)
return s == nil or s == ""
end
-- 判断json是否合法
local function is_json(str)
local success, result = pcall(json.decode, str)
return success and type(result) == "table"
end
-- 解析服务器响应的json数据
local function parse_response(body)
if not body or body == "" then
log.error("exfotawifi", "返回的body为空")
return nil
end
local success, json_body = pcall(json.decode, body)
if success and type(json_body) == "table" then
log.info("exfotawifi", "解析服务器响应成功")
return json_body
else
log.error("exfotawifi", "解析服务器响应失败body内容:", body)
return nil
end
end
-- 判断是否需要升级返回true或false
local function need_fota(version, server_version)
local version_num = tonumber(version)
local server_version_num = tonumber(server_version)
if version_num < server_version_num then
return true
end
return false
end
-- 下载升级文件,支持断点续传
local function download_file(url)
local download_dir = "/http_download/"
local result, reason = io.mkdir(download_dir)
if not result then
log.error("download_file","io.mkdir error", reason)
end
local file_path = download_dir.."fotawifi.bin"
local downloaded_size = 0
-- 检查文件是否存在,获取已下载的大小
if io.exists(file_path) then
downloaded_size = io.fileSize(file_path)
log.info("exfotawifi", "检测到未完成的下载,已下载大小:", downloaded_size)
end
-- 设置请求头,支持断点续传
local headers = {}
if downloaded_size > 0 then
headers["Range"] = "bytes=" .. downloaded_size .. "-"
end
local code, headers, body = http.request("GET", url, headers, nil, nil).wait()
if code == 200 or code == 206 then
-- 开始写入文件
local file_mode = downloaded_size > 0 and "a+" or "w+"
local file = io.open(file_path, file_mode)
if file then
file:seek("end", downloaded_size)
file:write(body)
file:close()
-- 判断文件是否下载完整
local file_size = io.fileSize(file_path)
local content_length = tonumber(headers["content-length"] or headers["Content-Length"])
if file_size >= (content_length or file_size) then
log.info("exfotawifi", "下载升级文件成功,文件路径:", file_path)
return file_path
else
log.info("exfotawifi", "下载中...当前大小:", file_size, "目标大小:", content_length)
end
else
log.error("exfotawifi", "无法创建文件")
-- 删除不完整的文件
os.remove(file_path)
end
else
log.error("exfotawifi", "下载失败,状态码:", code)
-- 删除不完整的文件
if io.exists(file_path) then
os.remove(file_path)
end
end
return nil
end
-- 执行升级操作
local function fota_start(file_path)
-- 检查文件是否存在
if not io.exists(file_path) then
log.error("exfotawifi", "升级文件不存在")
return false
end
-- 检查文件大小是否超过256K (256 * 1024 Bytes)
local file_size = io.fileSize(file_path)
if file_size < 256 * 1024 then
log.error("exfotawifi", "升级文件大小不足256K文件大小:", file_size)
return false
end
-- 执行airlink.sfota操作
local result = airlink.sfota(file_path)
if result then
log.info("exfotawifi", "升级成功")
-- 释放文件占用的空间
-- 因为sfota是异步执行的所以这里不能用os.remove()删除文件
file_path = nil
return true
else
log.error("exfotawifi", "升级失败")
os.remove(file_path)
return false
end
end
function exfotawifi.request()
local result, ip, adapter = sys.waitUntil("IP_READY", 30000)
if result then
log.info("exfotawifi", "开始执行升级任务")
if is_request then
log.warn("exfotawifi", "升级任务正在执行中,请勿重复调用")
return false
end
is_request = true
fota_result = false
-- 构建请求URL
local url = "http://wififota.openluat.com/air8000/update.json"
local imei = is_nil(mobile.imei()) and "未知imei" or mobile.imei()
local version = is_nil(airlink.sver()) and "未知版本" or airlink.sver()
local muid = is_nil(mobile.muid()) and "未知muid" or mobile.muid()
local hw = is_nil(hmeta.hwver()) and "未知硬件版本" or hmeta.hwver()
local coreversion = is_nil(rtos.version()) and "未知4G固件版本" or rtos.version()
local model = is_nil(hmeta.model()) and "未知4G设备型号" or hmeta.model()
local request_url = string.format("%s?imei=%s&version=%s&muid=%s&hw=%s&coreversion=%s&model=%s", url, imei, version, muid, hw, coreversion, model)
log.info("exfotawifi", "正在请求升级信息, URL:", request_url)
-- 发送HTTP请求获取服务器响应
local code, headers, body = http.request("GET", request_url, {}, nil, {timeout = 30000}).wait()
if code == 200 then
log.info("exfotawifi", "获取服务器响应成功")
-- 打印返回的body内容
-- log.info("exfotawifi", "body:", body)
-- 解析服务器响应的json数据
local response = parse_response(body)
if response then
-- 获取服务器返回的版本号和下载链接
local server_version = response.version
local download_url = response.url
-- 获取本地版本号
local local_version = airlink.sver()
-- 判断是否需要升级
if need_fota(local_version, server_version) then
log.info("exfotawifi", "需要升级, 本地版本:", local_version, "服务器版本:", server_version)
-- 下载升级文件
local file_path = download_file(download_url)
if file_path then
-- 开始升级
fota_result = fota_start(file_path)
end
else
log.info("exfotawifi", "当前已是最新WIFI固件")
fota_result = true
end
else
log.error("exfotawifi", "解析服务器响应失败")
end
else
log.error("exfotawifi", "获取服务器响应失败,状态码:", code)
end
else
log.error("当前正在升级WIFI&蓝牙固件请插入可以上网的SIM卡并重新启动")
end
-- 释放请求标记
is_request = false
return fota_result
end
return exfotawifi