jfjlaros / simpleRPC

Simple RPC implementation for Arduino.
MIT License
50 stars 17 forks source link

Void methods: Wait for response? #40

Open h-huss opened 4 months ago

h-huss commented 4 months ago

Is your feature request related to a problem? Please describe. I've just noticed that calling void methods / methods without a return value does not block, they seem to return immediately. This caused errors, as I was expecting that the arduino method was done when the method returned.

Describe the solution you'd like It would be nice to document that void method dont block. Alternatively, void methods could block, to behave similar to all other functions (this would be a breaking change).

jfjlaros commented 4 months ago

A void function is called just like any other function. The only difference is that no result is written after the function has finished. You can test this by adding a large delay() to such a function and see whether it returns directly or not.

What kind of errors are you experiencing and can you share a minimal example so I can reproduce these errors?

h-huss commented 4 months ago

Thank you for your quick response. I was a bit unconcrete: The Arduino function is called fine, however, the python function returns before the arduino function is done:

Arduino (ESP32)

void longDelay(){
  delay(5000);
}

boolean longDelayWithReturn(){
  delay(5000);
  return true;
}

void loop(void)
{
  interface(
      Serial,
      longDelay, "longDelay: ",
      longDelayWithReturn, "longDelayWithReturn: @return ret:"
  );
}

Python:

with Interface("/dev/ttyUSB0", baudrate=50000) as mcu:   
    start = time.time()
    mcu.longDelayWithReturn()
    print(time.time()-start) # 5.002 => As expected, we wait for the result

    start = time.time()
    mcu.longDelay()
    print(time.time()-start) # 0.0002 => We return almost immediatly. This is unexpected
    # At this point, the arduino function is still running, but the python function has returned.

    start = time.time()
    mcu.longDelayWithReturn()
    print(time.time()-start) #10.004 => 2*5 seconds, as we have to wait for the previous delay to be finished

This is most likely caused by https://github.com/jfjlaros/arduino-simple-rpc/blob/2a78a493031dfa06e826f42d3ec419686676eede/simple_rpc/simple_rpc.py#L186-L188 , void methods dont wait

jfjlaros commented 4 months ago

Indeed, the client has no way of knowing whether a void function has finished.

I guess we could let a void function write one byte to implement blocking behaviour, or we could implement it ourselves by changing the return type or, if this is not an option, by adding a wait function. E.g.,

On the device:

bool wait() {
  return true;
}

void loop() {
  interface(
    Serial,
    wait, "wait: Wait for the previous command to finish. @return: True."",
    // ...
  );
}

and client side:

mcu.longDelay()
mcu.wait()

I am not sure if this is a feature or a bug.

h-huss commented 4 months ago

The wait function is an interesting idea :)

I would leave it as-is, as it could be an useful feature, but there should be a warning somewhere.

jfjlaros commented 4 months ago

I will give it some more thought.

I will leave this issue open as a reminder.