Search code examples
cspi

How to parse received data with variable length


Let us say I am receiving a packet with variable length data payload.

**byte_num**    **size**     **type**
   0             1        Length
   1             1        SrcArsDev
   2             4        Src_ID
   6             1        DstArsDev
   7             4        Dst_ID
  11             4        Session
  15             1        CMD
  16             N        N bytes payload N<=96
 16+N            2        CRC

The data will be received over SPI communication. What is the general method for parsing the packets so I can later manipulate the distinct elements?

Can you please show me a simple function/routine that fills the structure elements?


Solution

  • One approach is to define a packed struct which represents the largest possible packet size:

    #pragma pack(push,1) // make sure everything is packed to byte level
    typedef struct {
        uint8_t        Length;
        uint8_t        SrcArsDev;
        uint32_t       Src_ID;
        uint8_t        DstArsDev;
        uint32_t       Dst_ID;
        uint32_t       Session;
        uint8_t        CMD;
        uint8_t        payload[96 + 2]; // payload + CRC
    } Message;
    #pragma pack(pop)    // restore struct packing
    

    Your read routine then reads directly to such a struct, and then all the elements of the message can subsequently be accessed as fields within the struct.

    The only tricky part is that you'll need to work out where the actual CRC bytes are based on Length and then extract these from the payload[] buffer, but this is not too difficult:

    Message msg;
    
    ssize_t n = read(fd, &msg, sizeof(msg));            // read data into `msg`
    
    uint16_t crc = *(int16_t*)&msg.payload[msg.Length]; // extract CRC
    
    // validate CRC + perhaps also verify that n is consistent with msg.Length
    
    // then access elements as needed:
    
    src_id = msg.Src_ID;
    dst_id = msg.Dst_ID;