init: Air780EPM 官方 LuatOS 项目代码基线

- 来源: 合宙 LuatOS 官方仓库 air780epm 模块完整代码
- 路径: luatos/air780epm/module/Air780EPM/demo 含官方 demo(含 mqtt/mqtts/socket/uart 等)
- 后续: 基于 demo 开发 UART<->MQTT 数据上报功能
This commit is contained in:
wangfq
2026-08-31 08:53:49 +08:00
commit 173dd6874f
813 changed files with 125484 additions and 0 deletions
@@ -0,0 +1,276 @@
--[[
@module json_app
@summary json 序列化与反序列化功能模块
@version 1.0
@date 2025.11.05
@author 马梦阳
@usage
本功能模块演示的内容为:
1.将 Lua 对象 转为 JSON 字符串:
示例一:Lua string 转为 JSON string
示例二:Lua number 转为 JSON string
示例三:Lua boolean 转为 JSON string
示例四:Lua table 转为 JSON string
示例五:Lua nil 转为 JSON string
序列化失败示例和指定浮点数示例;
2.将 JSON 字符串 转为 Lua 对象:
示例一:JSON string 转为 Lua string
示例二:JSON number 转为 Lua number
示例三:JSON boolean 转为 Lua boolean
示例四:JSON table 转为 Lua table
示例五:JSON nil 转为 Lua nil
反序列化失败示例;
空表(empty table)转换为 JSON 时的说明;
字符串中包含控制字符(如 \r\n)的 JSON 序列化与反序列化说明;
json.null 的语义与比较行为说明:
本文件没有对外接口,直接在 main.lua 中 require "json_app" 就可以加载运行;
]]
-- json库支持将 Lua 对象 转为 JSON 字符串, 或者反过来, JSON 字符串 转 Lua 对象
-- 若转换失败, 会返回nil值, 强烈建议在使用时添加额外的判断,如下列演示代码中所示
local function main_task()
while true do
sys.wait(1000)
-- 序列化成功示例:
-- 示例一:Lua string 转为 JSON string
local data = "test"
local json_str, err_msg = json.encode(data)
if json_str == nil then
-- 序列化失败时, 会返回 nil 值, 并通过 err_msg 参数返回错误信息
log.info("string_string_test1","序列化失败:", err_msg)
-- 执行错误处理逻辑,如使用默认值、重试或中止操作
else
-- 序列化成功时, 会返回 JSON 字符串
log.info("string_string_test1","序列化成功:", json_str)
end
-- 示例二:Lua number 转为 JSON string
local data = 123456789
local json_str, err_msg = json.encode(data)
if json_str == nil then
-- 序列化失败时, 会返回 nil 值, 并通过 err_msg 参数返回错误信息
log.info("number_string_test1","序列化失败:", err_msg)
-- 执行错误处理逻辑,如使用默认值、重试或中止操作
else
-- 序列化成功时, 会返回 JSON 字符串
log.info("number_string_test1","序列化成功:", json_str)
end
-- 示例三:Lua boolean 转为 JSON string
local data = true
local json_str, err_msg = json.encode(data)
if json_str == nil then
-- 序列化失败时, 会返回 nil 值, 并通过 err_msg 参数返回错误信息
log.info("boolean_string_test1","序列化失败:", err_msg)
-- 执行错误处理逻辑,如使用默认值、重试或中止操作
else
-- 序列化成功时, 会返回 JSON 字符串
log.info("boolean_string_test1","序列化成功:", json_str)
end
-- 示例四:Lua table 转为 JSON string
local data = {abc = 123, def = "123", ttt = true}
local json_str, err_msg = json.encode(data)
if json_str == nil then
-- 序列化失败时, 会返回 nil 值, 并通过 err_msg 参数返回错误信息
log.info("table_string_test1","序列化失败:", err_msg)
-- 执行错误处理逻辑,如使用默认值、重试或中止操作
else
-- 序列化成功时, 会返回 JSON 字符串
-- 由于 Lua 表在遍历时键的顺序是不确定的(尤其是字符串键)
-- 而 JSON 对象本身也是无序的
-- 因此序列化后的 JSON 字符串中键的顺序可能与 Lua 源码中的书写顺序不同,属于正常情况
log.info("table_string_test1","序列化成功:", json_str)
end
-- 示例五:Lua nil 转为 JSON string
local data = nil
local json_str, err_msg = json.encode(data)
if json_str == nil then
-- 序列化失败时, 会返回 nil 值, 并通过 err_msg 参数返回错误信息
log.info("nil_string_test1","序列化失败:", err_msg)
-- 执行错误处理逻辑,如使用默认值、重试或中止操作
else
-- 序列化成功时, 会返回 JSON 字符串
-- 注意:此时返回值是一个空字符串 ""
log.info("nil_string_test1","序列化成功:", json_str)
end
-- 序列化失败示例:
-- Lua table 中包含 function
local data = {abc = 123, def = "123", ttt = true, err = function() end}
local json_str, err_msg = json.encode(data)
if json_str == nil then
-- 序列化失败时, 会返回 nil 值, 并通过 err_msg 参数返回错误信息
log.info("table_string_test2","序列化失败:", err_msg)
-- 执行错误处理逻辑,如使用默认值、重试或中止操作
else
-- 序列化成功时, 会返回 JSON 字符串
log.info("table_string_test2","序列化成功:", json_str)
end
-- 指定浮点数示例:
-- 指定保留三位小数,不足时补零,超出时四舍五入;
local data = {abc = 1234.56789}
local json_str, err_msg = json.encode(data, "3f")
if json_str == nil then
-- 序列化失败时, 会返回 nil 值, 并通过 err_msg 参数返回错误信息
log.info("table_string_test3","序列化失败:", err_msg)
-- 执行错误处理逻辑,如使用默认值、重试或中止操作
else
-- 序列化成功时, 会返回 JSON 字符串
log.info("table_string_test3","序列化成功:", json_str)
end
-- 反序列化成功示例:
-- 示例一:JSON string 转为 Lua string
local str = '"test"'
-- local str = "\"test\""
local obj, result, err = json.decode(str)
if result == false then
-- 反序列化失败时, 会返回 nil 值, 并通过 err 参数返回错误信息
log.info("string_string_test1","反序列化失败:", err)
-- 执行错误处理逻辑,如使用默认值、重试或中止操作
else
-- 反序列化成功时, 会返回 Lua string
log.info("string_string_test1","反序列化成功:", obj)
end
-- 示例二:JSON string 转为 Lua number
local str = "123456789"
local obj, result, err = json.decode(str)
if result == false then
-- 反序列化失败时, 会返回 nil 值, 并通过 err 参数返回错误信息
log.info("string_number_test1","反序列化失败:", err)
-- 执行错误处理逻辑,如使用默认值、重试或中止操作
else
-- 反序列化成功时, 会返回 Lua number
log.info("string_number_test1","反序列化成功:", obj)
end
-- 示例三:JSON string 转为 Lua boolean
local str = "true"
local obj, result, err = json.decode(str)
if result == false then
-- 反序列化失败时, 会返回 nil 值, 并通过 err 参数返回错误信息
log.info("string_boolean_test1","反序列化失败:", err)
-- 执行错误处理逻辑,如使用默认值、重试或中止操作
else
-- 反序列化成功时, 会返回 Lua boolean
log.info("string_boolean_test1","反序列化成功:", obj)
end
-- 示例四:JSON string 转为 Lua table
local str = "{\"abc\":1234545}"
local obj, result, err = json.decode(str)
if result == false then
-- 反序列化失败时, 会返回 nil 值, 并通过 err 参数返回错误信息
log.info("string_table_test1.2","反序列化失败:", err)
-- 执行错误处理逻辑,如使用默认值、重试或中止操作
else
-- 反序列化成功时, 会返回 Lua table
-- 注意:此时 obj 是一个 Lua table
-- 若直接打印 obj,会输出 table: 01C9A490 类似的内存地址
log.info("string_table_test1.2","反序列化成功:", obj)
-- 需要添加具体的字段名称,才能正确输出
log.info("string_table_test1.2","反序列化成功:", obj.abc)
end
-- 反序列化失败示例:
-- JSON string 不是合法的 JSON 格式;
local str = "{\"def\":}"
local obj, result, err = json.decode(str)
if result == false then
-- 反序列化失败时, 会返回 nil 值, 并通过 err 参数返回错误信息
log.info("string_table_test2","反序列化失败:", err)
-- 执行错误处理逻辑,如使用默认值、重试或中止操作
else
-- 反序列化成功时, 会返回 Lua table
log.info("string_table_test2","反序列化成功:", obj)
end
-- empty table(空表) 转换为 JSON 时的说明:
-- 原生 Lua 中的 table 是数组(sequence)和哈希表(map)的统一数据结构;
-- 空表 {} 在转换为 JSON 时存在歧义:无法确定应输出为空数组 [] 还是空对象 {};
-- 由于 Lua 中只有包含连续正整数索引(从 1 开始)的表才被视为数组,而空表不满足这一条件;
-- 因此 JSON 库默认将其序列化为 {}(空对象);
local data = {abc = {}}
local json_str, err_msg = json.encode(data)
if json_str == nil then
-- 序列化失败时, 会返回 nil 值, 并通过 err_msg 参数返回错误信息
log.info("table_string_test3","序列化失败:", err_msg)
-- 执行错误处理逻辑,如使用默认值、重试或中止操作
else
-- 序列化成功时, 会返回 JSON 字符串
log.info("table_string_test3","序列化成功:", json_str)
end
-- 字符串中包含控制字符(如 \r\n)的 JSON 序列化与反序列化说明:
-- 在 Lua 中,字符串可以包含任意字符,包括回车(\r)、换行(\n)等控制字符;
-- 当使用 json.encode() 对包含此类字符的字符串进行序列化时;
-- JSON 库会自动将其转义为标准的 JSON 字符串字面量形式(例如 \r 转为 "\r"\n 转为 "\n");
-- 以确保生成的 JSON 符合规范且可安全传输;
-- 反序列化时(json.decode()),这些转义序列会被正确还原为原始的控制字符;
-- 因此解码后的字符串与原始字符串在内容上完全一致(逐字节相等);
-- 需要注意的是:日志输出函数(如 log.info)在打印包含 \r\n 的字符串时;
-- 会实际执行回车换行操作,导致日志在终端上分行显示;
-- 这可能造成“输出格式混乱”或“多出缩进/空格”的视觉错觉(例如 true 前有一个空格长度);
-- 但这只是日志显示效果,并非字符串内容本身发生变化;
-- 实际比较(tmp3.str == tmp)结果为 true,证明序列化与反序列化过程是无损且正确的;
local tmp = "ABC\r\nDEF\r\n"
local tmp2, err_msg = json.encode({str=tmp})
if tmp2 == nil then
-- 序列化失败时, 会返回 nil 值, 并通过 err_msg 参数返回错误信息
log.info("json","序列化失败:", err_msg)
-- 执行错误处理逻辑,如使用默认值、重试或中止操作
else
-- 序列化成功时, 会返回 JSON 字符串
log.info("json","序列化成功:", tmp2)
end
local tmp3, result, err = json.decode(tmp2)
if result == false then
-- 反序列化失败时, 会返回 nil 值, 并通过 err 参数返回错误信息
log.info("json","反序列化失败:", err)
-- 执行错误处理逻辑,如使用默认值、重试或中止操作
else
-- 反序列化成功时, 会返回 Lua table
-- 注意:此时 tmp3 是一个 Lua table
-- 直接打印 tmp3 显示的是内存地址,需要添加对应字段
-- true前存在一个空格长度,这是日志输出格式导致的,与字符串内容本身无实际差异
log.info("json","反序列化成功:", tmp3.str, tmp3.str == tmp)
end
-- json.null 的语义与比较行为说明:
-- 在标准 JSON 中,null 是一个合法的字面量,表示“空值”或“无值”;
-- 然而,Lua 语言本身没有 null 类型,只有 nil 用于表示未定义或空值;
-- 为在 Lua 中准确表示 JSON 的 null,json 库提供了一个特殊占位符:json.null;
-- json.null 通常是一个轻量级的 userdata 或 table,具体实现依赖库版本;
-- 当使用 json.encode() 序列化包含 json.null 的字段时,该字段会被正确转换为 JSON 中的 null;
-- 反之,json.decode() 在解析 JSON 中的 null 时,会将其还原为 json.null,而非 Lua 的 nil
-- 这是因为:若将 JSON 的 null 直接转为 nil,会导致 table 中对应键被删除;
-- 从而丢失原始 JSON 的结构信息;
-- 因此,json.decode('{"abc":null}').abc 的结果是 json.null,而不是 nil
-- 由于 json.null 是一个具体的值(非 nil),它与 nil 比较结果为 false;
-- 只有与 json.null 自身比较时,结果才为 true;
-- 开发者应始终使用 == json.null 来判断某个字段是否为 JSON 的 null;
-- 而不要用 == nil,否则逻辑将出错;
log.info("json.null", json.encode({name=json.null}))
-- 日志输出:{"name":null}
log.info("json.null", json.decode("{\"abc\":null}").abc == json.null)
-- 日志输出:true
log.info("json.null", json.decode("{\"abc\":null}").abc == nil)
-- 日志输出:false
end
end
-- 启动主任务
sys.taskInit(main_task)
@@ -0,0 +1,83 @@
--[[
@module main
@summary LuatOS用户应用脚本文件入口,总体调度应用逻辑
@version 1.0
@date 2025.11.05
@author 马梦阳
@usage
本demo演示的核心功能为:
1.将 Lua 对象 转为 JSON 字符串:
示例一:Lua string 转为 JSON string
示例二:Lua number 转为 JSON string
示例三:Lua boolean 转为 JSON string
示例四:Lua table 转为 JSON string
示例五:Lua nil 转为 JSON string
序列化失败示例和指定浮点数示例;
2.将 JSON 字符串 转为 Lua 对象:
示例一:JSON string 转为 Lua string
示例二:JSON number 转为 Lua number
示例三:JSON boolean 转为 Lua boolean
示例四:JSON table 转为 Lua table
示例五:JSON nil 转为 Lua nil
反序列化失败示例;
空表(empty table)转换为 JSON 时的说明;
字符串中包含控制字符(如 \r\n)的 JSON 序列化与反序列化说明;
json.null 的语义与比较行为说明:
更多说明参考本目录下的 readme.md 文件;
]]
--[[
必须定义PROJECT和VERSION变量,Luatools工具会用到这两个变量,远程升级功能也会用到这两个变量
PROJECT:项目名,ascii string类型
可以随便定义,只要不使用,就行
VERSION:项目版本号,ascii string类型
如果使用合宙iot.openluat.com进行远程升级,必须按照"XXX.YYY.ZZZ"三段格式定义:
X、Y、Z各表示1位数字,三个X表示的数字可以相同,也可以不同,同理三个Y和三个Z表示的数字也是可以相同,可以不同
因为历史原因,YYY这三位数字必须存在,但是没有任何用处,可以一直写为999
如果不使用合宙iot.openluat.com进行远程升级,根据自己项目的需求,自定义格式即可
]]
PROJECT = "json"
VERSION = "001.999.000"
-- 在日志中打印项目名和项目版本号
log.info("main", PROJECT, VERSION)
-- 如果内核固件支持errDump功能,此处进行配置,【强烈建议打开此处的注释】
-- 因为此功能模块可以记录并且上传脚本在运行过程中出现的语法错误或者其他自定义的错误信息,可以初步分析一些设备运行异常的问题
-- 以下代码是最基本的用法,更复杂的用法可以详细阅读API说明文档
-- 启动errDump日志存储并且上传功能,600秒上传一次
-- if errDump then
-- errDump.config(true, 600)
-- end
-- 使用LuatOS开发的任何一个项目,都强烈建议使用远程升级FOTA功能
-- 可以使用合宙的iot.openluat.com平台进行远程升级
-- 也可以使用客户自己搭建的平台进行远程升级
-- 远程升级的详细用法,可以参考fota的demo进行使用
-- 启动一个循环定时器
-- 每隔3秒钟打印一次总内存,实时的已使用内存,历史最高的已使用内存情况
-- 方便分析内存使用是否有异常
-- sys.timerLoopStart(function()
-- log.info("mem.lua", rtos.meminfo())
-- log.info("mem.sys", rtos.meminfo("sys"))
-- end, 3000)
-- 加载 json 应用模块
require "json_app"
-- 用户代码已结束---------------------------------------------
-- 结尾总是这一句
sys.run()
-- sys.run()之后后面不要加任何语句!!!!!
@@ -0,0 +1,84 @@
## 演示模块概述
1、main.lua:主程序入口;
2、json_app.luajson 序列化与反序列化功能模块;
## 演示功能概述
使用 Air780EPM 核心板搭配 json 库演示 json 序列化与反序列化功能;
演示分为两部分:
1、将 Lua 对象 转为 JSON 字符串:
- 示例一:Lua string 转为 JSON string
- 示例二:Lua number 转为 JSON string
- 示例三:Lua boolean 转为 JSON string
- 示例四:Lua table 转为 JSON string
- 示例五:Lua nil 转为 JSON string
- 序列化失败示例和指定浮点数示例;
2、将 JSON 字符串 转为 Lua 对象:
- 示例一:JSON string 转为 Lua string
- 示例二:JSON number 转为 Lua number
- 示例三:JSON boolean 转为 Lua boolean
- 示例四:JSON table 转为 Lua table
- 示例五:JSON nil 转为 Lua nil
- 反序列化失败示例;
- 空表(empty table)转换为 JSON 时的说明;
- 字符串中包含控制字符(如 \r\n)的 JSON 序列化与反序列化说明;
- json.null 的语义与比较行为说明:
## 演示硬件环境
1、Air780EPM 核心板一块
2、TYPE-C USB数据线一根
## 演示软件环境
1、[Luatools下载调试工具](https://docs.openluat.com/air8000/luatos/common/download/)
2、[Air780EPM V2016 版本](https://docs.openluat.com/air780epm/luatos/firmware/version/)(理论上最新版本固件也可以,如果使用最新版本的固件不可以,可以烧录 V2016-1 固件对比验证)
## 演示核心步骤
1、搭建好硬件环境
2、Luatools 工具烧录内核固件和 demo 脚本代码
3、烧录成功后,自动开机运行
4、正常运行情况时的日志如下:
```
[00000001.009] I/user.string_string_test1 序列化成功: "test"
[00000001.009] I/user.number_string_test1 序列化成功: 123456789
[00000001.010] I/user.boolean_string_test1 序列化成功: true
[00000001.010] I/user.table_string_test1 序列化成功: {"abc":123,"ttt":true,"def":"123"}
[00000001.010] I/user.nil_string_test1 序列化成功:
[00000001.011] I/user.table_string_test2 序列化失败: Cannot serialise function: type not supported
[00000001.011] I/user.table_string_test3 序列化成功: {"abc":1234.568}
[00000001.011] I/user.string_string_test1 反序列化成功: test
[00000001.011] I/user.string_number_test1 反序列化成功: 123456789
[00000001.011] I/user.string_boolean_test1 反序列化成功: true
[00000001.011] I/user.string_table_test1.2 反序列化成功: table: 01FE5010
[00000001.011] I/user.string_table_test1.2 反序列化成功: 1234545
[00000001.011] I/user.string_table_test2 反序列化失败: Expected value but found T_OBJ_END at character 8
[00000001.012] I/user.table_string_test3 序列化成功: {"abc":{}}
[00000001.012] I/user.json 序列化成功: {"str":"ABC\r\nDEF\r\n"}
[00000001.012] I/user.json 反序列化成功: ABC
DEF
true
[00000001.012] I/user.json.null {"name":null}
[00000001.012] I/user.json.null true
[00000001.012] I/user.json.null false
```