Nanopb在SEE中的应用
什么是nanopb
napopb是一种新的类似pb(protocol buffer)的协议吗?
nanopb和pb有什么区别?
nanopb的基本概念
proto file是个接口描述语言,类似android中aldl, 会发现接口描述语言很多,还有yaml, 只要有对应的解析脚本把解析后的结果能集成到使用环境就行。
protoco文件中样式如下,这里的1并不是对变量赋值为1,是说类型为uint32的变量step_count标号的fiedl_number为1, 是个键值对。
message sns_step_event{
required uint32 step_count = 1;
}
这里有个不熟悉的概念wire type, 不是常说的数据类型,比如variint包括各种int 和bool,enum等。变量的field_number和对应的wire_type一起形成pb编码的Tag.
Stream用于编解pb码, 实际的函数是callback, ostream callback 操作需要编码的数据, istream callback 解码到xxx如 memory buffer.
pb_encode/decode callback和iostream callback有什么关系那?
pb_encode提供了encode、decode要操作的数据, 并调用iostream callback的具体实现。
nanopb在SEE的使用方式
send_data:
pb_send_event是个封装,把要编码的数据封装在sns_sensor_event中通过event进行传输,具体的细节如下:
sns_rc
sns_pedometer_instance_send_data(sns_sensor_instance *const this) {
sns_rc rc = SNS_RC_SUCCESS;
sns_pedometer_instance_state *state =
(sns_pedometer_instance_state*) this->state->state;
sns_pedometer_step_event event = sns_pedometer_step_event_init_default;
event.step_count = state->step_count;
if (!pb_send_event(this, sns_pedometer_step_event_fields, &event,
sns_get_system_time(), SNS_PEDOMETER_MSGID_SNS_PEDOMETER_STEP_EVENT,
&pedometer_suid)
) {
SNS_INST_PRINTF(ERROR, this,
"sns_pedometer_instance_notify_event - Error in sending event");
rc = SNS_RC_INVALID_STATE;
}
return rc;
}
xx.protoco -> xx.pb.h -> xx.pb.c
message -> typedef struct: default value: fields -> fields赋值
fields是什么?可能是pb编码格式相关的结构体。
要编码的数据是c_struct*, 数据的长度是:pb_get_encoded_size
pb编码后放到哪里?
sns_sensor_event 结构体的event[1]是个指针,指向分配的内存;
pb_ostream_from_buffer就是把编码后的数据写到buffer里, 具体实现就是创建 pb_ostream_t
static bool checkreturn buf_write(pb_ostream_t *stream, const pb_byte_t *buf, size_t count)
{
size_t i;
pb_byte_t *dest = (pb_byte_t*)stream->state;
stream->state = dest + count;
for (i = 0; i < count; i++)
dest[i] = buf[i];
return true;
}
pb_ostream_t pb_ostream_from_buffer(pb_byte_t *buf, size_t bufsize)
{
pb_ostream_t stream;
#ifdef PB_BUFFER_ONLY
stream.callback = (void*)1; /* Just a marker value */
#else
stream.callback = &buf_write;
#endif
stream.state = buf;
stream.max_size = bufsize;
stream.bytes_written = 0;
#ifndef PB_NO_ERRMSG
stream.errmsg = NULL;
#endif
return stream;
}
pb_encode
pb_encode(&stream, fields, c_struct)
SEE中pb的解码
通过sns_sensor_event机制把传输的编码后的数据得到,创建istream得到pb_decoded后的数据
解码并没有封装好的pb_send_event对应函数,要自己创建istream, 代码有点乱,但理解了这个过程,代码就容易理解了。