rzetterberg / elmobd

A Go library for talking to cars over OBD-II
MIT License
221 stars 41 forks source link

Add async support with callbacks and goroutines #45

Closed paulnegz closed 5 months ago

paulnegz commented 5 months ago

Description

Add supports for asynchronous watching of OBDCommands and running a callback function when changes there is a change to the value of the OBDCommands being watched.

Checklist

rzetterberg commented 5 months ago

@paulnegz this looks really cool! 👀

Would you mind explaining a bit about the problem you're solving with this and how it works, from a bird's-eye view?

paulnegz commented 5 months ago

OBDCommands use a req/res model. However, I'll like to add Events! In additions to a req/res model, Events implement an event driven model. Events are made up of a Trigger & Action

There's an event loop constantly checking values of all OBDCommands being watched with appropriate delay. The status of the Event.trigger.callback is also determined in the event loop.

Whenever an Event.trigger.callback is positive, a list of Event.actions.callbacks functions are called.

An example, to set a speed limit of 100 mph, there's a need to continuously check speed's value for moments when the limit of 100 mph is exceeded. Then send an email + display a warning as a response to over-speeding.

To achieve this, add a watch Event on speed command, made up of a Trigger & Action.

Event.trigger.callback should return true when speed value > 100 mph. All Event.actions.callback are called as a response to a positive Event.trigger.callback

Event.actions.callback will

  1. send an email
  2. display a warning.

Example usages is shown in example6

Inspired by: OBD asynchronous python

paulnegz commented 5 months ago

@paulnegz this looks really cool! 👀

Would you mind explaining a bit about the problem you're solving with this and how it works, from a bird's-eye view?

Do you need more information?

rzetterberg commented 5 months ago

Thanks for explaining!

I think it's a well implemented idea, but I don't think it should be included in this library. My vision for this library is that it should only be a thin wrapper over the hardware, that only have the same capabilities as the hardware. That's the reason I didn't want to merge the automatic retries in PR #29, for example. I actually think it was wrong of me to implement setting the protocol automatically when a new device is created.

The reason why I didn't turn this PR down directly was because I thought that the hardware itself had asynchronous support, and that your changes was implementing that capability. But after reading your explanation and refreshing my memory on how the low level device control works, I realized: even though your implementation is using asynchronous capabilities, the hardware doesn't have that capability and can only process one request at a time. The mutex of RealDevice makes sure that all goroutines will have to wait their turn before they can send a request. That's why I consider the changes of this PR to be extra functionality that should be implemented outside of this library.

I appreciate the work you'd done to implement your idea and create this PR. Sorry I had to turn it down.