Search code examples
pythonc++serial-portpyserialesp32

C send struct over UART to Python


I'm trying to send a struct over UART (from an ESP32) to be processed by Python by using this guide.

// we send this to the host, to be processed by python script
struct package {
   uint8_t modifier;
   uint8_t keyboard_keys[6];
};

// instantiate struct
package to_send = {};

// send the contents of keyboard_keys and keyboard_modifier_keys
// https://folk.uio.no/jeanra/Microelectronics/TransmitStructArduinoPython.html
void usb_keyboard_send(void)
{

   to_send.modifier = keyboard_modifier_keys;
   for(uint8_t i = 0; i < 6; i++) {
      to_send.keyboard_keys[i] = keyboard_keys[i];
   }

   printf("S");
   printf((uint8_t *)&to_send, sizeof(to_send));
   printf("E");
}

However I get the error: invalid conversion from 'uint8_t* {aka unsigned char*}' to 'const char*' [-fpermissive]

I'm pretty new to C++, and I've tried all sorts of casting, but I just can't get it to work. Could someone offer guidance please?


Solution

  • Setting aside that it's generally a bad idea to mix ASCII and raw binary, your code is almost right.

    You have 2 major errors:

    // instantiate struct
    package to_send = {};
    

    should be:

    // instantiate struct
    struct package to_send = {};
    

    Also, to write directly (not formatted text) to STDOUT you want to use fwrite()

    i.e.

    printf("S");
    fwrite((uint8_t *)&to_send, sizeof(uint8_t), sizeof(struct_package), STDOUT);
    printf("E");
    

    As an aside, after fixing these 2 errors you may be surprised to find that your struct isn't the number of bytes you expect. The compiler may optimize it to make memory accesses faster by padding fields to word sized boundaries (32 bits on ESP32). sizeof() will return the correct value taking in to account whatever optimizations are done, but your Python code may not expect that. To fix this you probably wan to use a compiler hint, e.g. __attribute__((__packed__)). See here for a general guide to structure packing.