Skip to content

Commit

Permalink
Added protocol buffers support using nanopb. (#2217)
Browse files Browse the repository at this point in the history
  • Loading branch information
slaff authored Feb 18, 2021
1 parent ffa376e commit 11836eb
Show file tree
Hide file tree
Showing 6 changed files with 133 additions and 0 deletions.
4 changes: 4 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,10 @@
path = Sming/Libraries/MultipartParser/multipart-parser
url = https://github.com/iafonov/multipart-parser-c.git
ignore = dirty
[submodule "Libraries.nanopb"]
path = Sming/Libraries/nanopb/nanopb
url = https://github.com/nanopb/nanopb.git
ignore = dirty
[submodule "Libraries.RapidXML"]
path = Sming/Libraries/RapidXML
url = https://github.com/mikee47/Sming-RapidXML
Expand Down
56 changes: 56 additions & 0 deletions Sming/Libraries/nanopb/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
Nano Protocol-Buffer
====================

Introduction
------------

This component adds support for `Nano Protocol-Buffer <https://github.com/nanopb/nanopb/>`_ implementation.

Nanopb is a small code-size `Protocol Buffers <https://developers.google.com/protocol-buffers>`_ implementation in ansi C. It is especially suitable for use in microcontrollers, but fits any memory restricted system.


C file generation from Proto files
----------------------------------

Once this component is installed you can use it to add Nano Protocol-Buffer support to your project and generate C and header files from Proto files.
One possible way to call the generator is to go to the directory where the proto file is located and run the generator. As shown below::

make -C $SMING_HOME fetch nano-pb
cd <folder-with-proto-file>
python $SMING_HOME/Libraries/nanopb/nanopb/generator/nanopb_generator.py <desired-proto-file>.proto

After the generator tool is run you will have newly generated C and header files that can be used in your Sming application.

Using
-----

1. Add ``COMPONENT_DEPENDS += nanopb`` to your application componenent.mk file.
2. Add these lines to your application::

#include <PbUtils.h>
// The line below should be replaced with the generated header file
#include "cast_channel.pb.h"

3. Example::

#include <PbUtils.h>
#include "cast_channel.pb.h"

void doSomething(const uint8_t* data, size_t length)
{
// ...

extensions_api_cast_channel_CastMessage message = extensions_api_cast_channel_CastMessage_init_default;

message.protocol_version = extensions_api_cast_channel_CastMessage_ProtocolVersion_CASTV2_1_0;
message.source_id.funcs.encode = &pbEncodeData;
message.source_id.arg = new PbData(sourceId);
message.destination_id.funcs.encode = &pbEncodeData;
message.destination_id.arg = new PbData(destinationId);
message.nameSpace.funcs.encode = &pbEncodeData;
message.nameSpace.arg = new PbData(ns);
message.payload_type = extensions_api_cast_channel_CastMessage_PayloadType_STRING;
message.payload_utf8.funcs.encode = &pbEncodeData;
message.payload_utf8.arg = new PbData((uint8_t*)data, length);
// ...
}
4 changes: 4 additions & 0 deletions Sming/Libraries/nanopb/component.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
COMPONENT_SRCDIRS := nanopb src
COMPONENT_INCDIRS := $(COMPONENT_SRCDIRS)

COMPONENT_SUBMODULES += nanopb
1 change: 1 addition & 0 deletions Sming/Libraries/nanopb/nanopb
Submodule nanopb added at 049485
41 changes: 41 additions & 0 deletions Sming/Libraries/nanopb/src/PbUtils.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#include "PbUtils.h"

// See: https://iam777.tistory.com/538

bool pbEncodeData(pb_ostream_t *stream, const pb_field_t *field, void * const *arg)
{
PbData *data = (PbData*) *arg;
if(data == nullptr) {
return false;
}

if (!pb_encode_tag_for_field(stream, field)) {
return false;
}

return pb_encode_string(stream, (uint8_t*)data->value, data->length);
}

bool pbDecodeData(pb_istream_t *stream, const pb_field_t *field, void **arg)
{
uint8_t buffer[1024] = {0};

/* We could read block-by-block to avoid the large buffer... */
if (stream->bytes_left > sizeof(buffer) - 1) {
return false;
}

size_t available = stream->bytes_left;
if (!pb_read(stream, buffer, stream->bytes_left)) {
return false;
}


MemoryDataStream* data = (MemoryDataStream*) *arg;
if(data == nullptr) {
data = new MemoryDataStream();
*arg = (void*)data;
}
data->write(buffer, available);
return true;
}
27 changes: 27 additions & 0 deletions Sming/Libraries/nanopb/src/PbUtils.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#pragma once

#include <SmingCore.h>
#include <Data/Stream/MemoryDataStream.h>
#include <pb_encode.h>
#include <pb_decode.h>

class PbData
{
public:
uint8_t* value = nullptr;
size_t length = 0;

PbData(const String& text)
{
PbData((uint8_t *)text.c_str(), text.length());
}

PbData(uint8_t* data, size_t length)
{
value = data;
this->length = length;
}
};

bool pbEncodeData(pb_ostream_t *stream, const pb_field_t *field, void * const *arg);
bool pbDecodeData(pb_istream_t *stream, const pb_field_t *field, void **arg);

0 comments on commit 11836eb

Please sign in to comment.