Overdrivr/Telemetry

attaching function pointers with attach()

uberrice opened this issue · 2 comments

I'm using Telemetry for a project on an ESP32 running FreeRTOS (and it's working great so far, for variables), however when I call attach("testtopic",&mycallback); , mycallback seemingly never gets called. I have no debugger available, but i put a global variable change and a print to console right at the start of the mycallback function (whose signature is void (TM_msg*) ); those don't ever come out. A test of a counter I'm running in parallel on another topic comes through no problem.

Am I doing something wrong? attach(t,*funptr) should call the funptr function when something with topic t gets received, right?

I haven't touched this repo in a while, but no attach is not for functions callbacks, sorry about the confusing name.

If I'm not mistaken, there is no topic lookup for function callbacks, instead you can subscribe a single, global function that will be called every time Telemetry receives a message:

void callback_fn(TM_state* s, TM_msg* m)
{
  // Do something here with the state, it's the same variable as in main() passed by pointer
  // You can use the TM_ms variable to get the topic and the contents
}

void main () 
{
  TM_state state;
  subscribe(callback_fn, &state);


  for (;;) {
    // Update telemetry, just like you're used to
  }
}

This is not a great design, and rather confusing, but it should get you where you want.
So I'm guessing you have managed to implement the transport layer properly ?
I'm glad everything else is working well otherwise, let me know if this helps.

Thanks for your reply; and really, attach not being usable for function callbacks is all i needed to know.
I had assumed it was for function pointers because of the implementation:

void attach(const char * name, void (*callback)(TM_msg * m))
{
    install(hashtab, name, (void*)(callback), ptr_function);
}

void attach_f32(const char * name, float * variable)
{
    install(hashtab, name, (void*)(variable), ptr_f32);
}

I guess you know what I mean.

Yes, I managed to implement the transport layer easily. If anyone stumbles upon this and has problems, this is how I did it for ESP-IDF:

int32_t uart_myread(uint8_t* buf, uint32_t sizeToRead){
    uint32_t rec_size = uart_read_bytes(USED_UART_NUM,buf,sizeToRead,1000);
    return rec_size;
}

int32_t uart_mywrite(uint8_t* buf, uint32_t sizeToWrite){
    return uart_write_bytes(USED_UART_NUM,(char*)buf,sizeToWrite);
    uart_wait_tx_done(USED_UART_NUM, 100);
}

int32_t uart_myreadable(void){ //adapts uart buffered data length function to return an int32
    int32_t length = 0;
    uart_get_buffered_data_len(USED_UART_NUM, (size_t*)&length);
    return length;
}

int32_t uart_mywriteable(void){
    uart_wait_tx_done(USED_UART_NUM, 100);
    return 0xFFFFFFFF;
}
TM_transport transport;
void tel_init(void* pv){
    ser_init(); //this is a function that initializes the UART for the ESP32
    printf("serial initialized!\n");
    transport.read = uart_myread;
    transport.write = uart_mywrite;
    transport.readable = uart_myreadable;
    transport.writeable = uart_mywriteable;
    printf("telemetry data structure initialized!\n");
    init_telemetry(&transport);
    printf("Exiting telemetry initialization!\n");
}

One thing I struggled with for a while was that the TM_transport variable does not get copied or read and forgotten about when calling init_telemetry(), but needs to persist and therefore needs to be global or set in a function that loops endlessly. This is in contrast to the way the configuration structures work in ESP-IDF, which get copied (or read and set in hardware; more or less a question of definition) on call.

Thanks for making this library; it provides an excellent (way more robust than plaintext) communication channel over UART between an ESP32 and a raspberry pi for a university project 👍