找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

2701

积分

0

好友

356

主题
发表于 2 小时前 | 查看: 2| 回复: 0

LuatOS技术宣传图

Protocol Buffers(简称Protobuf)是由 Google 开发的一种高效、跨平台、语言无关的结构化数据序列化协议。它凭借体积小、解析快、扩展性强的优势,在网络通信、数据存储等场景中广泛应用。

合宙 LuatOS 对其底层 Protobuf 编解码功能进行了轻量级封装,提供了高效易用的核心库。开发者通过调用简洁的 API 接口,就能轻松实现高性能的结构化数据序列化与反序列化,这大大降低了通信协议对接的复杂度,同时提升了代码的可维护性和执行效率。

目前,Protobuf 库已全面支持 LuatOS 开发系列产品,开发者可以根据项目实际需求,灵活选用并进行快速集成。

一、Protobuf核心库速览

LuatOS 的 Protobuf 核心库支持加载由 protoc 编译生成的二进制描述文件(.pb 文件),提供完整的数据编码(encode)、解码(decode)等功能。它支持 Proto2 和 Proto3 协议版本,能够根据输入的 protobuf 定义自动识别并处理相应版本的消息格式,非常适用于设备与云端、模块间进行高效数据交换等典型物联网应用场景。

最新 API 文档详见:https://docs.openluat.com/osapi/core/protobuf/

在 LuatOS 开发中,主要使用以下四个函数来处理 Protobuf 数据。

1.1 protobuf.load(pbdata)

函数功能:
加载 Protocol Buffers 二进制定义数据到系统中,使其可以用于后续的编码和解码操作。

注意事项:

  • 同一个文件只需要加载一次,除非调用过 protobuf.clear() 清除已加载的定义。
  • 加载的数据必须是通过 protoc.exe 程序转换得到的二进制数据。

简要示例:

Lua代码示例:使用protobuf.load加载PB文件

-- 加载 pb 文件,这个是从 pbtxt 转换得到的;
-- 下载资源到模块时不需要下载 pbtxt;
-- 转换命令:protoc.exe -operson.pb person.pbtxt
-- protoc.exe 下载地址:https://github.com/protocolbuffers/protobuf/releases
local pb_file = "/luadb/person.pb"
if io.exists(pb_file) then
    local success, bytesRead = protobuf.load(io.readFile(pb_file))
    if not success then
        log.info("protobuf", "加载 protobuf 定义失败,已读取 ".. bytesRead .. " 字节")
    else
        log.info("protobuf", "加载 protobuf 定义成功,共解析 ".. bytesRead .. " 字节")
    end
else
    log.info("protobuf","pb 文件不存在")
end

1.2 protobuf.clear()

函数功能:
清除所有已加载的 Protocol Buffers 二进制定义数据。

注意事项:

  • 清除所有定义数据后,可以通过调用 protobuf.load() 重新加载新的定义数据。
  • 清除后,任何依赖已删除类型的序列化/反序列化操作将失败。
  • 该函数总是成功执行,没有返回错误的情况。

简要示例:

Lua代码示例:使用protobuf.clear清除定义

-- 清除所有已加载的定义数据
protobuf.clear()
log.info("protobuf", "所有 protobuf 定义已清除")

1.3 protobuf.encode(tpname, data)

函数功能:
将符合 Protocol Buffer 消息定义的 Lua 表(table)数据,按照指定的消息类型进行序列化,生成二进制编码后的字符串。

注意事项:

  • 编码前必须先使用 protobuf.load() 加载对应的 Protocol Buffer 定义数据。
  • 待编码的 table 内容必须符合 .pb 文件里的定义。
  • 编码结果为二进制字符串,可能包含不可打印字符,调试时建议使用十六进制(如 :toHex())或 Base64 查看。
  • 如果编码失败,函数会返回 nil

简要示例:

Lua代码示例:使用protobuf.encode编码数据

-- 准备待编码的数据
local tbdata = {
    name = "wendal",
    id = 123,
    email = "abc@qq.com"
}

-- 编码数据
local pbdata = protobuf.encode("Person", tbdata)
if pbdata then
    -- 编码成功,编码后的数据通常包含不可见字符
    -- 打印长度和十六进制内容(便于调试)
    log.info("protobuf", "编码成功,数据长度:" .. #pbdata)
    log.info("protobuf", "十六进制内容:" .. pbdata:toHex())
else
    log.info("protobuf", "编码失败:数据格式或类型不匹配")
end

1.4 protobuf.decode(tpname, data)

函数功能:
将 Protocol Buffer 二进制编码的数据(字符串)按照指定的消息类型进行反序列化,还原为 Lua 表(table)结构。

注意事项:

  • 在调用此接口前,必须先通过 protobuf.load() 加载对应的 Protocol Buffers 定义数据。
  • 输入数据 data 必须是有效的 protobuf 二进制编码字符串,且与 tpname 对应的消息格式兼容。
  • Lua table 内容无法直接打印出来,建议搭配 json.encode() 查看。

简要示例:

Lua代码示例:使用protobuf.decode解码数据

-- 假设已通过 protobuf.load() 加载了 Person 类型定义
-- 例如通过 protobuf.encode() 生成的返回值变量为 pbdata

-- 数据解码
local tbdata = protobuf.decode("Person", pbdata)
if tbdata then
    -- 解码后的数据为 Lua table 格式,需要转化为 json 进行显示
    log.info("protobuf", "解码成功,数据内容:", json.encode(tbdata))
else
    log.info("protobuf", "解码失败")
end

二、开源示例快速上手

理论结合实践,才能更快掌握。完整的 Protobuf 使用示例已开源在合宙 LuatOS 官方代码仓库,你可以直接参考或使用。

以合宙低功耗模组 Air780EHV(音频全能系列)为例,可选用其配套核心板或开发板进行快速实操验证。

该 Protobuf 示例涵盖了以下核心功能要点:

  • 加载 protobuf 定义文件(.pb 文件)。
  • 将符合 protobuf 定义的 Lua table 数据编码为二进制数据。
  • 使用 json 编码同样的数据,并对比两者编码后的大小,直观展示 Protobuf 的体积优势。
  • 将二进制数据解码回 Lua table 数据。
  • 清除所有已加载的定义数据。

其核心逻辑代码示例如下,完整示例请参考源码仓库中的最新文件。

完整的Protobuf示例代码

--[[
 本功能模块演示的内容为:
 1. 加解密
 2. 将符合protobuf定义的Lua table数据编码为二进制数据;
 3. 使用json编码同样的Lua table数据后,对比protobuf和json编码后数据的大小;
 4. 将二进制数据解码为Lua table数据;
 5. 演示所有已知的定义数据;
]]

local function main_task()
    -- 加载pb文件,这个是通过protoc生成的二进制文件
    -- 下载资源模块时不能下载protobuf
    -- 转换命令:protoc -o person.pb.proto
    -- protoc.exe 下载地址:https://github.com/protocolbuffers/protobuf/releases
    local pb_file = "/luadb/person.pb"

    local tbdta = {
        name = "Wendal",
        id = 123,
        email = "abc@qq.com"
    }

    if io.exists(pb_file) then
        local success, bytesRead = protobuf.load(io.readfile(pb_file))
        if not success then
            log.info("protobuf", "加载 protobuf 定义失败,已读取 ".. bytesRead .. " 字节")
            return
        else
            log.info("protobuf", "加载 protobuf 定义成功,共解析 ".. bytesRead .. " 字节")
        end
    else
        log.info("protobuf", "pb 文件不存在")
        return
    end

    -- 编码数据:
    local pbdata = protobuf.encode("Person", tbdta)
    if pbdata then
        -- 编码成功,编码后的数据通常包含不可见字符
        -- 打印关键和十六进制内容(避免乱码)
        log.info("protobuf", "十六进制内容: ".. pbdata)
        log.info("protobuf", "十六进制内容: ".. pbdata:toHex())
    else
        log.info("protobuf", "编码失败:数据格式或类型不匹配!")
    end

    -- 对比 protobuf 编码和 json 编码的大小:
    local data = json.encode(tbdta)
    if data then
        log.info("json", "编码成功,数据长度: ".. #data)
        log.info("json", "数据内容: ".. data)
    else
        log.info("json", "编码失败:数据格式或类型不匹配!")
    end

    -- 可见,protobuf比 json 节省更多空间;

    -- 数据解码:
    local tbdta = protobuf.decode("Person", pbdata)
    if tbdta then
        -- 解码后的数据为 Lua table 格式,需要转化为 json 进行显示;
        log.info("protobuf", "解码成功,数据内容: ".. json.encode(tbdta))
    else
        log.info("protobuf", "解码失败")
    end

    -- 清除所有已知的定义数据;
    protobuf.clear()
    log.info("protobuf", "所有 protobuf 定义已清除!")
end

-- 创建并启动一个 task
-- 用于运行 main_task 函数
sys.taskInit(main_task)

通过上述介绍和示例,我们可以看到在 LuatOS 中集成和使用 Protobuf 是非常清晰的。这种高效的序列化方案对于资源受限的嵌入式设备尤其有价值。如果你想深入了解其他物联网开发技巧或查看更多技术文档,欢迎在云栈社区进行交流探讨。




上一篇:Spring Boot 4与Project Leyden前瞻:Java启动性能革命及其对云原生场景的影响分析
下一篇:Java工程师四个月求职复盘:从高并发业务到AI应用,我这样上岸
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-3-31 09:38 , Processed in 0.587203 second(s), 40 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2026 云栈社区.

快速回复 返回顶部 返回列表