Closed boneskull closed 9 years ago
@dtex Writes:
@boneskull At the IO layer create a buffer for each pin. The buffer could hold reads & writes until the pin mode is set (confirmed by the callback from octalbonescript). Only the IO layer would need to be aware of the callbacks and you would not have to make any changes to Johnny-Five or octalbonescript. @boneskull First, I shouldn’t have said “buffer” since that’s a thing. Let’s use “queue” instead. Yes, this would all happen in beaglebone-io
So it sounds like no change needs to happen in johnny-five. If someone doesn't think this will work, please let me know, but I'm going to close this.
I started writing this response about an hour ago, the information is still relevant and useful. @dtex's buffer/queue solution is ideal.
In practice, what happens is when you construct objects in johnny-five with an octalbonescript backend, johnny-five attempts to access the GPIO pins before they are fully configured, resulting in EPERM errors.
An IO Plugin using octalbonescript should just pre-allocate all of the GPIO objects as part of board initialization that, on completion, produces the "ready" event. This is how Nino-IO (and Galileo-IO gen 1's sysfs support) works and there are never file pr permission related errors. There is an acceptable amount of process blocking (sync io, whatever) allowed for initialization when a program first starts up and when a component is first initialized (the same rationale used for require()
).
So, octalbonescript's pinMode() (for example) is asynchronous. But johnny-five's is not. It appears serial port writes of all types do not use callbacks.
An operation does not need to have a callback to be asynchronous—it only needs a callback if there is some need to know that the operation is complete. The entire ecosystem shares a common protocol (firmata) to define behaviors and the protocol has no "response" command (whether success or failure), so there is no formalized way to determine operation completed-ness. Presumably the lack of a formal "response" in the protocol is to keep wire/radio/bluetooth/network/io traffic to a minimum. If every command had a "response", traffic would double for all commands that don't currently imply a response (implied response: anything that "reads").
johnny-five should accept callbacks for all functions performing serial port writes.
Consider the explanation above and this becomes unrealistic :\
Additionally:
I have a bit of a dilemma. I wish to use johnny-five with package beaglebone-io. Package beaglebone-io depends on package bonescript, which is like firmata for the BeagleBone.
bonescript is buggy, incomplete, and its implementation is broken. There's a new kid in town, which is octalbonescript. octalbonescript uses asynchronous I/O, because of the nature of controlling pins on a BeagleBone.
To do something like change the pin mode on a BeagleBone, you have to access the filesystem and write to no fewer than two files. As
root
. This can take time. So, octalbonescript'spinMode()
(for example) is asynchronous.But johnny-five's is not. It appears serial port writes of all types do not use callbacks.
In practice, what happens is when you construct objects in johnny-five with an octalbonescript backend, johnny-five attempts to access the GPIO pins before they are fully configured, resulting in
EPERM
errors. This resolves itself after the second run of your script, because the pins are now configured. However, this makes it impossible to reliably run any scripts at boot time.This is a pretty big roadblock to using johnny-five with a BeagleBone.
What I'd like to see happen:
johnny-five should accept callbacks for all functions performing serial port writes.
I realize this is a lot of work, but it'd be good for the library to expand support for more alternative
io
implementations.(I can hack beaglebone-io to use octalbonescript and use callbacks myself--that's not a big deal--but johnny-five is a much larger library)