nanopb / nanopb

Protocol Buffers with small code size
https://jpa.kapsi.fi/nanopb/
zlib License
4.34k stars 855 forks source link

Missing the data during serialize. #444

Closed tasilio closed 5 years ago

tasilio commented 5 years ago

Hi all!

I got a problem while implementing nanopb on Arduino.

.proto

syntax = "proto2";

message Service {   
    required bool Request = 1; 
    optional bool Setparam = 2; 
} 
message DateTime { 
    optional sint32 Year = 1; 
    optional sint32 Month = 2; 
    optional sint32 Day = 3; 
    optional sint32 Hours = 4;
    optional sint32 Minutes = 5;
    optional sint32 Seconds = 6;
} 
message Coord { 
    optional sint32 Lat = 1; 
    optional sint32 Latdec = 2;
    optional sint32 Lon = 3; 
    optional sint32 Londec = 4;
} 
message Prog { 
    optional sint32 Num = 1; 
    optional bool Astro = 2; 
    optional bool Sunrise = 3;
    optional bool Advance = 4;
    optional bool Relay_state = 5;
    optional sint32 Hours = 6 ; 
    optional sint32 Minutes = 7;
    optional sint32 Dailyrep = 8;
} 

message Exch {
    required Service service = 1;
        optional DateTime datetime = 2;
        optional Coord coord = 3;
        optional Prog prog = 4;
}

When executing this code, everything goes fine.

#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>
#include <ds3231.h>
#include "src/unitimer.pb.h"
#include <pb_common.h>
#include <pb.h>
#include <pb_encode.h>

uint8_t buff_io[128]; 
uint8_t lenght = 0;

WiFiServer server(8888); 
WiFiClient client;  

void setup() 
{

  initHardware();
  setupWiFi();
  server.begin();
  Exch message_curr; 
  uint8_t buff[128]; 

  message_curr.service.Request = 1;  
  message_curr.service.Setparam = 1;  

  message_curr.datetime.Year = 2019;  
  message_curr.datetime.Month = 10; 
  message_curr.datetime.Day = 18;
  message_curr.datetime.Hours = 15; 
  message_curr.datetime.Minutes = 1;  
  message_curr.datetime.Seconds = 1;

  message_curr.coord.Lat = 55;
  message_curr.coord.Latdec = 45; 
  message_curr.coord.Lon = 37;  
  message_curr.coord.Londec = 37; 

  message_curr.prog.Num = 1;  
  message_curr.prog.Astro = 1; 
  message_curr.prog.Sunrise = 1;  
  message_curr.prog.Advance = 1;  
  message_curr.prog.Relay_state = 1;  
  message_curr.prog.Hours = 2;  
  message_curr.prog.Minutes = 12; 
  message_curr.prog.Dailyrep = 1; 

  pb_ostream_t stream = pb_ostream_from_buffer(buff, sizeof(buff)); 

  delay(100);

  bool stat = pb_encode(&stream, Exch_fields, &message_curr); 

  lenght = stream.bytes_written;

  for(int i = 0; i<lenght; i++){
               buff_io[i]= buff[i];
             }

}

void loop() 
{

  if (client.connected()) { 
            client.print("Message Length: ");
            client.print(lenght);
            client.print(" ");
            client.print("Message: ");
            Serial.print("Message Length: ");
            Serial.print(lenght);
            Serial.print(" ");
            Serial.print("Message: ");       

            for(int i = 0; i<lenght; i++){
                Serial.printf("%02X",buff_io[i]);
            }
            Serial.println();
             for(int i = 0; i<lenght; i++){
               client.printf("%02X",buff_io[i]);
             }
             client.println();
             delay(1000);

   }
   else { 
     client = server.available(); 

        }
 }

 void setupWiFi()
 {
   WiFi.mode(WIFI_AP);
   WiFi.softAP("ap1", "ConnectAPD");
 }

 void initHardware()
 {
   Serial.begin(115200);
 }

Serial output: 'Message Length: 49 Message: 0A0408011001120D08C61F10141824201E280230021A08086E105A184A204A221008021001180120012801300438184002 Socket output: Message Length: 49 Message: 0A0408011001120D08C61F10141824201E280230021A08086E105A184A204A221008021001180120012801300438184002`

As soon as I transfer the part of the code responsible for working with the proto-stream from "setup" to "loop". The proto-parcel becomes shorter and the online decoder shows the disappearance of some fields of the original structure.

#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>
#include <ds3231.h>
#include "src/unitimer.pb.h"
#include <pb_common.h>
#include <pb.h>
#include <pb_encode.h>

WiFiServer server(8888); 
WiFiClient client; 

void setup() 
{

  initHardware();
  setupWiFi();
  server.begin();

}

void loop() 
{

  Exch message_curr; 
  uint8_t buff[128]; 
  uint8_t lenght = 0;

  message_curr.service.Request = 1;  
  message_curr.service.Setparam = 1;  

  message_curr.datetime.Year = 2019;  
  message_curr.datetime.Month = 10; 
  message_curr.datetime.Day = 18;
  message_curr.datetime.Hours = 15; 
  message_curr.datetime.Minutes = 1;  
  message_curr.datetime.Seconds = 1;

  message_curr.coord.Lat = 55;
  message_curr.coord.Latdec = 45; 
  message_curr.coord.Lon = 37;  
  message_curr.coord.Londec = 37; 

  message_curr.prog.Num = 1;  
  message_curr.prog.Astro = 1; 
  message_curr.prog.Sunrise = 1;  
  message_curr.prog.Advance = 1;  
  message_curr.prog.Relay_state = 1;  
  message_curr.prog.Hours = 2;  
  message_curr.prog.Minutes = 12; 
  message_curr.prog.Dailyrep = 1; 

  pb_ostream_t stream = pb_ostream_from_buffer(buff, sizeof(buff)); 

  delay(100);

  bool stat = pb_encode(&stream, Exch_fields, &message_curr); 

  lenght = stream.bytes_written;

  if (client.connected()) { 
            client.print("Message Length: ");
            client.print(lenght);
            client.print(" ");
            client.print("Message: ");
            Serial.print("Message Length: ");
            Serial.print(lenght);
            Serial.print(" ");
            Serial.print("Message: ");       

            for(int i = 0; i<lenght; i++){
                Serial.printf("%02X",buff[i]);
            }
            Serial.println();
             for(int i = 0; i<lenght; i++){
               client.printf("%02X",buff[i]);
             }
             client.println();
             delay(1000);

   }
   else { 
     client = server.available(); 

        }
 }

 void setupWiFi()
 {
   WiFi.mode(WIFI_AP);
   WiFi.softAP("ap1", "ConnectAPD");
 }

 void initHardware()
 {
   Serial.begin(115200);
 }

Serial output: Message Length: 43 Message: 0A0408011001120D08C61F10141824201E280230021A06086E184A204A220C080210012001280138184002 Socket output: Message Length: 43 Message: 0A0408011001120D08C61F10141824201E280230021A06086E184A204A220C080210012001280138184002

As you can see, some of the data was lost, what could be the problem?

PetteriAimonen commented 5 years ago

For each optional field, you'll have to set msg.has_field = true;.

Also, it is a good idea to initialize your message struct, now you are leaving some of the fields uninitialized which leads to random behavior. Use e.g. Exch message_curr = {}; or Exch message_curr = Exch_init_default;.

tasilio commented 5 years ago

Good day. Applied your recommendations. The result is lower.

#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>
#include <ds3231.h>
#include "src/unitimer.pb.h"
#include <pb_common.h>
#include <pb.h>
#include <pb_encode.h>

WiFiServer server(8888); 
WiFiClient client;  

void setup() 
{

  initHardware();
  setupWiFi();
  server.begin();

}

void loop() 
{

  Exch message_curr = {}; 
  uint8_t buff[128]; 
  uint8_t lenght = 0;

  message_curr.service.Request = 1;  
  message_curr.service.Setparam = 1;  
  message_curr.service.has_Setparam = true;

  message_curr.datetime.Year = 2019;  
  message_curr.datetime.has_Year = true;  
  message_curr.datetime.Month = 10;
  message_curr.datetime.has_Month = true; 
  message_curr.datetime.Day = 18; 
  message_curr.datetime.has_Day = true;  
  message_curr.datetime.Hours = 15; 
  message_curr.datetime.has_Hours = true;  
  message_curr.datetime.Minutes = 10;  
  message_curr.datetime.has_Minutes = true;  
  message_curr.datetime.Seconds = 1;  
  message_curr.datetime.has_Seconds = true;  

  message_curr.coord.Lat = 55;  
  message_curr.coord.has_Lat = true;
  message_curr.coord.Latdec = 45; 
  message_curr.coord.has_Latdec = true;
  message_curr.coord.Lon = 37;  
  message_curr.coord.has_Lon = true;
  message_curr.coord.Londec = 37; 
  message_curr.coord.has_Londec = true;

  message_curr.prog.Num = 1;  
  message_curr.prog.has_Num = true;
  message_curr.prog.Astro = 1; 
  message_curr.prog.has_Astro = true;
  message_curr.prog.Sunrise = 1; 
  message_curr.prog.has_Sunrise = true;
  message_curr.prog.Advance = 1;
  message_curr.prog.has_Advance = true;
  message_curr.prog.Relay_state = 1;  
  message_curr.prog.has_Relay_state = true;
  message_curr.prog.Hours = 2;  
  message_curr.prog.has_Hours = true;
  message_curr.prog.Minutes = 12;
  message_curr.prog.has_Minutes = true;
  message_curr.prog.Dailyrep = 1; 
  message_curr.prog.has_Dailyrep =true;

  pb_ostream_t stream = pb_ostream_from_buffer(buff, sizeof(buff)); 

  bool stat = pb_encode(&stream, Exch_fields, &message_curr); 

  lenght = stream.bytes_written;

  if (client.connected()) { 
            client.print("Message Length: ");
            client.print(lenght);
            client.print(" ");
            client.print("Message: ");
            Serial.print("Message Length: ");
            Serial.print(lenght);
            Serial.print(" ");
            Serial.print("Message: ");       

            for(int i = 0; i<lenght; i++){
                Serial.printf("%02X",buff[i]);
            }
            Serial.println();
             for(int i = 0; i<lenght; i++){
               client.printf("%02X",buff[i]);
             }
             client.println();
             delay(1000);

   }
   else { 
     client = server.available(); 

        }
 }

 void setupWiFi()
 {
   WiFi.mode(WIFI_AP);
   WiFi.softAP("ap1", "ConnectAPD");
 }

 void initHardware()
 {
   Serial.begin(115200);
 }

Serial out:Message Length: 6 Message: 0A0408011001 Socket out:Message Length: 6 Message: 0A0408011001

PetteriAimonen commented 5 years ago

Still missing message_curr.has_datetime = true etc. for the top-level submessages.

tasilio commented 5 years ago

Thank you, now everything works correctly!