pixix4/ev3dev-lang-rust

Button Event Listeners.

Natejoestev opened this issue · 10 comments

I noticed that the Ev3Button.proccess function says to call any button event listeners depending on if the button's state has changed.
what does this mean? because i can't find any part of ev3dev-lang-rust crate that lets you create event listeners.

I might have missed something.
but, this would be a great feature to have.

Oh, that seems to be a documentation error. There is currently no support for event handlers/callbacks. The python library had this feature, but I haven't implemented it yet. At the moment you have to manually check the button states after each process() call.

I took a quick look at the implementation and it should be relatively easy to add such a feature. I think I can do it next weekend.

sounds great.
because right now i have to make my own:

let state = BtnState {
  up: false, ...
}

loop {
  buttons.proccess();
  
  if buttons.is_up() && ! state.up {
    f();
  }
  state.up = buttons.is_up();
}

for each button i need.

also, would these events be called on the Ev3Button.proccess call?

Yes, the call to process() will remain necessary. A variant that automatically checks for new events would require something like multithreading and in my opinion that is an implementation detail that is out of scope for this library.

i know that process would still be necessary. but would the event listeners be called on the process call? or on a separate thread.

The event listener would be called as part of the process call (in the same thread). So the process() finishes execution after all event listeners were executed.

A new version 0.14.0 with support for event handlers is now published (the documentation should be automatically available within the next few hours). In this version you can set handlers for each button that is called by the process() function. An example for this can be found here:

https://github.com/pixix4/ev3dev-lang-rust/blob/master/examples/button_handlers.rs

This is great, thank you. Just one thing though, wouldn't it be better to pass a HashMap<enum BUTTON_TYPE, bool> to change_listener? that way you can see what button changed to what. instead of just which button changed.
@pixix4

I also thought about it, but decided against it. The problem with a HashMap is that it is relatively "heavy". It consumes much more memory than a simple key-value array. And since this HasMap would have to be recreated for each event, I wanted to avoid this allocation. And in this case, a HashMap is not absolutely necessary. Since it would be a boolean HashMap, it is functionally equivalent to a HashSet or even a simple array in which the presence of a button can be checked. For this use case, you can use set_change_handler to check whether the button is present in pressed_buttons. If the button is pressed, it is present in the array. Otherwise it is not.
However, this variant has the disadvantage that you cannot simply use set_change_handler to check which button has changed. If you need to do this, you have to compare the previous and new state of pressed_buttons or use the button-specific functions such as set_left_handler.

so does the Hashset only contain the ones that are pressed, or just the ones that were changed?

It contains the buttons that are pressed.