imt-atlantique/YACL

How to read CBOR_BYTES

gh0st42 opened this issue · 5 comments

How does one read cbor_bytes? So far I am getting a raw buffer and skipping the first one or two bytes, which does not feel correct :)

Example for such raw bytes encoded would be 830200479F8207008101FF

Or for a two byte code: 8302005818414141414141414141414141414141414141414141414141

Hello @gh0st42,

following your example I used a little function to compute the head size of the cbor encoding, in order to skip the info bytes, and then go directly to the encoded data.

I don't know if it is correct... it was fun, at least....

Here is the code, hope it helps.

cheers!

#include "YACL.h"


unsigned char get_cbor_head_size(uint8_t first_cbor_byte)
{
  unsigned char offset = 0;
  char add_inf = first_cbor_byte&0b00011111;
  if (add_inf < 24)
  {
    offset = 1+0;
  }else if(add_inf == 24){
    offset = 1+1;
  }else if(add_inf == 25){
    offset = 1+2;
  }else if(add_inf == 26){
    offset = 1+4;
  }else if(add_inf == 27){
    offset = 1+8;
  }
  return offset;
}

void setup()
{
	Serial.begin(115200);
	Serial.println("Let say that we received the CBOR data: 0x830200479F8207008101FF");
	uint8_t cbor_data[11] = {0x83, 0x02, 0x00, 0x47, 0x9F, 0x82, 0x07, 0x00, 0x81, 0x01, 0xFF};

  // Serial.println("Let say that we received the CBOR data: 0x8302005818414141414141414141414141414141414141414141414141");
  // uint8_t cbor_data[29] = {0x83, 0x02, 0x00, 0x58, 0x18, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 
  //                          0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 
  //                          0x41, 0x41, 0x41, 0x41, 0x41};

  // to show the decoded object it's importatn to know the structure
  if (!CBOR::is_pair(cbor_data)) {
    Serial.println("Trying to decode received data:");
  }


	// Read the CBOR object, it's importat to know the number of bytes to read
	CBOR data = CBOR(cbor_data, 11, true);
  if(data[0].is_uint8())
  {
    Serial.print("data[0] = ");
    Serial.println((int)data[0]);  
  }

  if(data[1].is_uint8())
  {
    Serial.print("data[1] = ");
    Serial.println((int)data[1]);
  }

  uint8_t len = data[2].length();
  uint8_t* bytes_buff = data[2].get_buffer();
  uint8_t offset = get_cbor_head_size(bytes_buff[0]);

  
  
  Serial.print("offset: ");
  Serial.println(offset);

  Serial.print("data[2] = ");
  Serial.print("0x");
  for(int i=offset; i<len; i++)
  {
    if(bytes_buff[i]<=0xF)
    {
      Serial.print(0);
    }
    Serial.print(bytes_buff[i], HEX);
  }
  Serial.println("");
  
}

void loop()
{
}

As a workaround this works! Thank you!
At least for the test packets I'm decoding I do not see a problem, not as clean as a nice API call but it gets the job done.

For anyone else stumbling upon this solution, to reduce the chance of unwanted bugs, you might want to alter the original variables by the offset.

len -= offset;
bytes_buff += offset;

Otherwise, one might just use len and be off-by-one or off-by-two etc. which can lead to catastrophic results ;)

Hello @gh0st42,

I just added CBOR_BYTES support in v1.0.2.

With this new version, something like this should do the trick:

#include "YACL.h"

void setup() {
  Serial.begin(115200);

  const uint8_t cbor_data[] = {0x83, 0x02, 0x00, 0x58, 0x18, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41};
  uint8_t bytestr[24] = {0};
  
  CBORArray arr = CBORArray(cbor_data, 29);
  arr[2].get_bytestring(bytestr);

  for (int i=0 ; i < 24 ; ++i) {
    Serial.print((char)bytestr[i]);
  }
  
}

void loop() {

}

I just tested the new method get_bytestring, and work very well. There is also the get_bytestring_len() to retrieve the length of the data-bytes.

These are also useful for my project.

Thank very much to both of you.

Perfect! Thank you!