北京合众恒跃科技有限公司
直播中

jf_50393217

5年用户 227经验值
擅长:可编程逻辑 嵌入式技术
私信 关注

【HZ-T536开发板免费体验】6、使用protoc-gen-gorm生成标准化的数据结构

在设计espnow协议的时候,考虑到我需要在esp32,Linux设备,web上使用相同的数据结构,那就需要考虑一下,是否使用一个通用的跨平台序列化数据结构。这时候我想起了protobuf,这个就是我需要的。

我之前在esp32上使用过protobuf(nanopb),用起来也是比较简单的。

这里我先初步大致写了一下espnow自定义协议需要使用的一些数据结构。

syntax = "proto3";

import "options/gorm.proto";
import "protos/SMN_type.proto";

package smn;
option go_package = "./smn";

// Shrimp Mesh NetInfo Data
// 网络数据包结构体
message NetInfo {
  option (gorm.opts) = { ormable: true };
  uint32 device_id                = 1 [(gorm.field).tag = {type: "uuid" primary_key: true}];    //  节点ID
  uint32 group_id                 = 2;    //  组ID
  uint32 level                    = 3;    //  节点层级
  uint32 status                   = 4;    //  设备状态
  SMNDevice device_type           = 10;   //  设备类型
  bytes node_mac                  = 11;   //  节点设备mac地址
  uint32 rssi                     = 15;   //  信号强度
  uint32 response_time            = 16;   //  平均响应时间
  uint32 packet_loss_rate         = 20;   //  丢包率
  Bandwidth bandwidth_type        = 24;   //  设备带宽类型
  uint32 heartbeat_interval       = 25;   //  设备心跳间隔时间(ms级)
  uint32 latest_heartbeat_time    = 26;   //  最后心跳上报时间
}

// SystemInfo Data
// 系统信息数据包结构体
message SystemInfo {
  uint32 device_id                = 1;    //  节点ID
  uint32 cpu_temperature          = 2;    //  cpu温度
  uint32 cpu0_load                = 3;    //  cpu0使用率
  uint32 cpu1_load                = 4;    //  cpu1使用率
  uint32 ram_load                 = 5;    //  内存使用率
  uint32 free_ram                 = 6;    //  剩余内存
  uint32 uptime                   = 10;   //  上电时间(秒级)
}

// EspnowDevice Data
// 设备信息数据包结构体
message EspnowDevice {
  uint32 device_id                = 1;    //  节点ID
  string device_name              = 2;    //  设备名称
  string alias_name               = 4;    //  设备别名
  string manufacturer             = 10;   //  厂家
  string model                    = 11;   //  设备型号
  string hardware_version         = 15;   //  硬件版本
  string firmware_version         = 20;   //  固件版本
}

// Device Model
// 设备模型数据结构体
message DeviceModel {
  DeviceModelType type          = 1;    //  设备类型
  uint32 num                    = 2;    //  有多少个
}

// Device Model Data
// 设备模型清单
message DeviceModelList {
  DeviceModel data              = 1;    //  设备类型
}

以及基本的类型和枚举定义

syntax = "proto3";

package smn;
option go_package = "./smn";

// Shrimp Mesh Network Command
// 层级:物理层 → 网络层 → 应用层
enum SMNCommand {
  // 设备发现与连接管理
  ADV_BROADCAST        = 0;   // 广播
  SCAN_DEVICES         = 1;   // 扫描设备
  DEVICE_AUTHORIZATION = 2;   // 设备授权
  
  // 安全配对与密钥交换
  PAIR_NET             = 10;  // 设备配网
  KEY_UPDATE           = 12;  // 动态更新会话密钥

  // 数据路由与转发
  ROUTE_DISCOVERY      = 20;  // 路由发现请求
  ROUTE_REPLY          = 21;  // 路由响应
  DATA_FORWARD         = 22;  // 数据包转发

  // 属性协议(类似BLE ATT层)
  ATT_READ             = 30;  // 读取节点属性
  ATT_WRITE            = 31;  // 写入属性
  ATT_NOTIFY           = 32;  // 异步通知
  ATT_INDICATE         = 33;  // 指示

  // 网络维护与QoS
  HEARTBEAT            = 50;  // 心跳包
  TOPOLOGY_UPDATE      = 51;  // 拓扑更新广播
  PRIORITY_DATA        = 52;  // 高优先级数据
  TIME_SYNC            = 53;  // 设备校时

  // 观察者相关指令
  OBSERVER_REGISTER    = 70;  // 注册OBS设备
  OBSERVER_REPORT      = 71;  // OBS信息上报
  DATA_SUBSCRIBE       = 72;  // 订阅特定数据流 
  DIAGNOSTICS_TRIGGER  = 73;  // 触发诊断
}

// Shrimp Mesh Network Device
// 设备类型:路由、节点、观察者等等
enum SMNDevice {
  SMN_EMPTY            = 0;   // 空
  ROUTER               = 1;   // 路由节点
  LEAF                 = 2;   // 叶节点
  LP_LEAF              = 4;   // 低功耗叶节点
  FRIEND               = 8;   // 友邻节点,负责存储低功耗设备的信息
  PROXY                = 16;  // 代理节点,BLE或者蓝牙访问
  OBSERVER             = 32;  // 观察者
  GATEWAY              = 64;  // 网关
  COORDINATOR          = 128; // 调整者(用于升级设备或者抓取设备debug信息)
}

// Network Device Bandwidth Type
// 设备带宽类型:独占、重度、轻量等等
enum Bandwidth {
  DEDICATED            = 0;   // 独占型设备,如烧录器,串口转发,网络摄像头等等
  HEAVY                = 1;   // 重度带宽占用
  MODERATE             = 2;   // 中等带宽占用
  LIGHTWEIGHT          = 8;   // 轻量级,如常见物联设备,灯,开关等
  MINIMAL              = 10;  // 极低占用,如温湿度传感器、节能门铃等等
}


// Device Model Type
// 设备模型类型:
enum DeviceModelType {
  TYPE_EMPTY           = 0;   // 空
  //  常见开关类型
  LIGHT                = 1;   // 灯
  COLOR_LIGHT          = 2;   // 彩色灯
  SWITCH               = 3;   // 开关

  // 传感器类(30-49)
  TEMPERATURE_SENSOR   = 30;  // 温度传感器
  HUMIDITY_SENSOR      = 31;  // 湿度传感器
  SMOKE_SENSOR         = 32;  // 烟雾传感器
  MOTION_SENSOR        = 33;  // 人体传感器
  WATER_LEAK_SENSOR    = 34;  // 水浸传感器
  WATER_LEVEL_SENSOR   = 35;  // 水位传感器

  // 屏幕类型设备
  OLED_SCREEN          = 50;  // 单色OLED屏
  COLOR_LCD            = 51;  // 彩色屏幕

  // 时钟类设备
  CLOCK                = 60;  // 时钟设备

  // 风扇类型设备
  FAN_SIMPLE           = 70;  // 简单风扇类型设备
  FAN_PWM              = 71;  // PWM风扇类型设备

  //  加热类型
  PCB_HOT_PLATE        = 90;  // PCB加热台

  //  开发板类型
  LED                  = 100; // 板载LED
  COLORLED             = 101; // 板载彩色LED
  GPIO_CONTROLLER      = 102; // GPIO控制器
}

// Shrimp Mesh Heatbeat Data
// 心跳数据包结构体
message Heatbeat {
  uint32 device_id                = 1;    //  节点ID
  uint32 group_id                 = 2;    //  组ID
  uint32 level                    = 3;    //  节点层级
  SMNDevice device_type           = 10;   //  设备类型
  bytes node_mac                  = 11;   //  节点设备mac地址
}

// TimeInfo Data
// 时间数据包结构体
message TimeInfo {
  uint32 device_id                = 1;    //  节点ID
  uint32 time                     = 2;    //  Unix时间戳
  uint32 msec                     = 3;    //  毫秒数据
  uint32 sntp_time                = 4;    //  SNTP校时时间
}

安装protoc编译器,使用protobuf的话,需要安装这个编译器,用来生成对应语言的序列化代码。

我们在github上的链接上,下载对应平台的压缩包。
https://github.com/protocolbuffers/protobuf/releases

image.png

下载解压缩后,需要添加对应的环境变量

# protocexport 
PROTOC_PATH=$MYBIN/tools/bin/protocexport 
PATH=$PROTOC_PATH/bin:$PATH

然后,需要安装protobuf的go插件(生成常规的序列化数据结构)

go get -u github.com/golang/protobuf/protoc-gen-go

以及gorm的插件(生成gorm对应的数据库)

go get github.com/infobloxopen/protoc-gen-gorm

然后,我们需要编写一个脚本,来完成对应文件的生成工作。

protoc  \
  -I.  \
  -I$PROTOC_PATH/include/  \
  -I$(go env GOPATH)/pkg/mod/github.com/infobloxopen/protoc-gen-gorm@v1.1.4/proto/  \
  -I$(go env GOPATH)/pkg/mod/github.com/infobloxopen/protoc-gen-gorm@v1.1.4/third_party/proto/  \
  --go_out=.  \
  --gorm_out=.  \
  protos/SMN_proto.proto protos/SMN_type.proto

对应参数需要反复测试和尝试,找到对应的文件才能使用,网络上的资料也是比较少的,所以,写成脚本测试会更简单一些(也方便记录,万一以后忘记了就麻烦了)。

生成的文件如截图
gorm的存储数据结构
image.png
常规的数据结构和序列化、解序列方法
image.png

然后使用这些,就可以简单写一些保存espnow设备数据的服务程序了。

更多回帖

发帖
×
20
完善资料,
赚取积分