[Nanopb] String/Bytes type proto - Encode example code 2

Posted by [하늘이]
2020. 1. 30. 14:13 IT/C, C++
반응형

[Nanopb for Google protobuf] String/Bytes type proto - Encode example code 2


※ 관련글

  • Google Protobuf
  1. [Google Protobuf] For Java in Android Studio - 설치 및 proto 파일 컴파일
  2. [Google Protobuf] For Java in Android Studio - Gen Java 파일 Android Studio 적용
  3. [Google Protobuf] For Java in Android Studio - Basic example code 기본 소스 코드 사용 샘플
  4. [Google Protobuf] For C++ in Linux - Settings C++ 빌드 환경 만들기
  5. [Google Protobuf] For C++ in Linux - Basic example code 기본 소스 코드 사용 샘플
  • Nanopb Basic type value example
  1. [Nanopb for Google protobuf] Basic type proto sample
  2. [Nanopb for Google protobuf] Basic type proto sample - Sample proto file
  3. [Nanopb for Google protobuf] Basic type proto sample - Encode sample code
  4. [Nanopb for Google protobuf] Basic type proto sample - Decode sample code
  • Nanopb String / bytes value example
  1. [Nanopb for Google protobuf] String/Bytes type proto
  2. [Nanopb for Google protobuf] String/Bytes type proto - Sample proto file 
  3. [Nanopb for Google protobuf] String/Bytes type proto - Encode example code 1
  4. [Nanopb for Google protobuf] String/Bytes type proto - Encode example code 2
  5. [Nanopb for Google protobuf] String/Bytes type proto - Decode example code
  • Nanopb basic submsg example
  1. [Nanopb for Google protobuf] Sub message - Example proto file
  2. [Nanopb for Google protobuf] Sub message - Encode example code
  3. [Nanopb for Google protobuf] Sub message - Decode example code
  • Nanopb array submsg value example

  1. [Nanopb for Google protobuf] Array Sub message - Example proto file
  2. [Nanopb for Google protobuf] Array Sub message - Encode example code
  3. [Nanopb for Google protobuf] Array Sub message - Decode example code

StringBytes Encode sample code 2

* Encode 방법 1과 2의 차이점은 proto Gen으로 생성된 message struct 에 데이터를 넣는 방법이다.

방법1은 arg 변수에 바로 string / byte array를 넣었고, 방법2 는 Struct 타입을 선언 후 변수를 생성하여 전달하는 방식이다.

방법 1 / 2 는 경우 따라서 유동적으로 사용하면 될 것으로 판단된다.


* String Encode 를 위한 callback api 등록 함수를 선언한다.

핵심은 arg 변수를 내부 선언 struct 타입으로 변경하여 데이터를 맵핑한 것이다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
bool encode_stringWithStruct(pb_ostream_t *stream, const pb_field_t *field, void * const *arg)
{
    //arg 값을 struct 형으로 변경.
    TestStrBtsStuct * sourceStruct = (TestStrBtsStuct*)(*arg);
 
    Serial.print("encode_stringWithStruct start @@@");
    Serial.println("");
 
    if(arg == NULL){
        Serial.print("encode_stringWithStruct failed. Str is Null");
        Serial.println("");
        return false;
    }
 
    if (!pb_encode_tag_for_field(stream, field)){
        Serial.print("encode_stringWithStruct encode failed:");
        Serial.print(PB_GET_ERROR(stream));
        Serial.println("");
        return false;
    }
 
    // encode 시 사용되는 데이터를 내부 struct 변수의 값으로 사용한다.
    return pb_encode_string(stream, sourceStruct->testString, strlen(sourceStruct->testString));
}
cs

* Bytes Encode 를 위한 callback api 등록 함수를 선언한다.

핵심은 arg 변수를 내부 선언 struct 타입으로 변경하여 데이터를 맵핑한 것이다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
bool encode_bytesWithStruct(pb_ostream_t *stream, const pb_field_t *field, void * const *arg)
{
    //arg 값을 struct 형으로 변경.
    TestStrBtsStuct * sourceStruct = (TestStrBtsStuct*)(*arg);
 
    Serial.print("encode_bytesWithStruct start @@@");
    Serial.println("");
 
    if(arg == NULL){
        Serial.print("encode_bytesWithStruct failed. Str is Null");
        Serial.println("");
        return false;
    }
 
    if (!pb_encode_tag_for_field(stream, field)){
        Serial.print("encode_bytesWithStruct encode failed:");
        Serial.print(PB_GET_ERROR(stream));
        Serial.println("");
        return false;
    }
 
    // encode 시 사용되는 데이터를 내부 struct 변수의 값으로 사용한다.
    return pb_encode_string(stream, sourceStruct->testBytes, sourceStruct->testBytesSize);
}
 
cs

* Encode main 함수

핵심 : struct 타입을 사용하여 변경할 데이터를 만든 후 arg 에 맵핑하여 callback api 호출 시 사용되도록 함.

struct 타입은 encoding / decoding 두가지 타입 다 동일한 것을 사용한다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
#define TestStrBtsStuctMaxLen 15
 
typedef struct{
    int32_t testInt32;
    char testString[TestStrBtsStuctMaxLen];
    byte testBytes[TestStrBtsStuctMaxLen];
    byte testBytesSize;
}TestStrBtsStuct;
 
void testStrBytesMain(){
    int encodeSize = 0;
    // 메시지 생성 및 초기화
    TestStrBytesTypes msg = TestStrBytesTypes_init_default;
 
    // 내부적으로 생성한 struct 타입의 변수를 사용하기 위하여 선언.
    TestStrBtsStuct testStruct;
    // Struct 변수 초기화 시킨다.
    initStruct(testStruct);
 
    // 메시지에 테스트 데이터 입력
    {
        testStruct.testInt32 = 101;
        char *tempStr = "Hello world!";
        add_String(&testStruct, tempStr, strlen(tempStr));
        byte testBytes[4= { 0x100x200x300x40 };
        add_ByteArr(&testStruct, testBytes, 4);
    }
 
    // [+] encode할 데이터 변수에 값는 넣는다.(함수를 만들어서 사용하는 것을 권장.)
    msg.testInt32 = testStruct.testInt32;
 
    // encode 를 위한 callback 함수를 등록
    msg.testString.funcs.encode = &encode_stringWithStruct;
    // encode callback 에 전달되는 arg 값으로 struct 변수를 넣는다.
    msg.testString.arg = &testStruct;
 
    // encode 를 위한 callback 함수를 등록
    msg.testBytes.funcs.encode = &encode_bytesWithStruct;
    // encode callback 에 전달되는 arg 값 넣는다.
    msg.testBytes.arg = &testStruct;
    // [-] encode할 데이터 변수에 값는 넣는다.(함수를 만들어서 사용하는 것을 권장.)
 
 
    // Decode 시키기 위한 버퍼 및 stream 생성
    uint8_t buffer[200];
    pb_ostream_t stream = pb_ostream_from_buffer(buffer, sizeof(buffer));
 
    /* stream 과 메시지로 Encode 시킨다. 실패 시 false가 리턴된다.
     * encode 호출 시 위쪽에서 등록한 callback 함수들이 호출된다.     */
    if (pb_encode(&stream, TestStrBytesTypes_fields, &msg)) {
        encodeSize = stream.bytes_written;
 
        Serial.print("TestStrBytesTypes encode OK size:");
        Serial.print(encodeSize);
        Serial.println("");
 
        Serial.print("Str Bytes types: ");
        // encode된 데이터 바이트 값 출력.
        for (int i = 0; i < encodeSize; i++) {
            Serial.print(buffer[i], 16);
            Serial.print(" ");
        }
        Serial.println("");
 
        // decode 시킨다.
        testDecodeTestStrBytesTypes(encodeSize, buffer);
    } else {
        Serial.print("TestStrBytesTypes Encoding failed: ");
        Serial.print(PB_GET_ERROR(&stream));
        Serial.println("");
        return;
    }
}
 
 
cs

 


반응형