New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added .serial_bytes_available [was added timeout to input()] #1193

Merged
merged 5 commits into from Oct 10, 2018

Conversation

Projects
None yet
3 participants
@ATMakersBill
Copy link
Collaborator

ATMakersBill commented Sep 16, 2018

I have added a second optional parameter to input() that acts like a timeout.

When input("PROMPT>", 10) is called with a timeout parameter, it will return in that number of milliseconds if there is no data available on the USB serial connection.

This is not a true async serial read, it's just a workaround to let allow other tasks to occur while waiting for serial input to start. Once a keystroke is read, the method drops into readline processing allowing for command history etc. And whatever activity is in the loop will stop.

However, this bridges a gap that caused problems for one of our projects. We want to be able to take serial commands over USB to change colors as well as have modes like blink, "throb", "wheel", "cycle" etc. that run between changes.

With this change, we can do that with the following code:

while True:
    inColor = input("", 0)
#result will be None if timeout occurs
    if (inColor is None):
        runMode()
        continue
    if (inColor.lower().startswith("red")):
        targetColor = (255, 0, 0)
        if (mode == "wheel"):
            mode="solid"
    elif (inColor.lower().startswith("green")):
        targetColor = (0, 255, 0)
        if (mode == "wheel"):
            mode="solid"
    elif (inColor.lower().startswith("yellow")):
        targetColor = (200, 200, 0)
        if (mode == "wheel"):
            mode="solid"
    elif (inColor.lower().startswith("@")):
        mode= inColor[1:]
    elif (inColor.startswith("#")):
        hexcode = inColor[1:]
        targetColor = hex2rgb(hexcode)
        if (mode == "wheel"):
            mode="solid"
    else:
        targetColor =(50, 50, 50)
        if (mode == "wheel"):
            mode="solid"
    pixels.fill(targetColor)
    pixels.show()

In our case, we used a timeout of zero, but any positive time works. Sending False is identical to sending 0. If the parameter is omitted, input() behaves exactly like the original.

An alternative approach (arguably better) would be to add a builtin function that is a passthrough to "usb_bytes_available()". I'm fine with that approach as well.

I'd love any feedback.

@ATMakersBill ATMakersBill referenced this pull request Sep 16, 2018

Open

'getch()' #231

@ATMakersBill

This comment has been minimized.

Copy link
Collaborator Author

ATMakersBill commented Sep 16, 2018

I see from the Travis build that this fails on some ports that don't have usb_bytes_available().

If there is a desire to go forward, I can add checks for particular architectures or features that work. For our (short-term) needs the M0 will work for us (which doesn't imply anything for accepting the PR of course - we can build from our fork)

@tannewt

This comment has been minimized.

Copy link
Collaborator

tannewt commented Sep 17, 2018

I don't want to add this as is because it breaks compatibility with CPython because input only takes in a prompt. https://docs.python.org/3/library/functions.html#input

You could add this as a custom function in a custom module. It gets it closer to the second usb serial api that would be good in the long term. Let me know if you want help with that.

@ATMakersBill

This comment has been minimized.

Copy link
Collaborator Author

ATMakersBill commented Sep 17, 2018

I get it - I have no problem with that

@ATMakersBill

This comment has been minimized.

Copy link
Collaborator Author

ATMakersBill commented Sep 19, 2018

@tannewt (or whoever), I think I'd like to go ahead and add a module for this. It's trivial - just one method that checks whether there is input available on the console. In theory, it should be temporary as the updated async IO code would replace it. However, I think there are some use cases (including two of mine now) where this one feature is blocking other solutions.

So, the question is where this code should live. My first thought was under ports/atmel-samd... but then I saw that the ESP8266 (and presumably the ESP32 and NRF) DO have the equivalent of "usb_bytes_available()" just implemented differently. So this COULD be done cross-platform (with IFDEFs). I think that means it should go under shared_bindings.

Thoughts?

@dhalbert

This comment has been minimized.

Copy link
Collaborator

dhalbert commented Oct 3, 2018

Yes, please put something under shared-bindings and if it's not available, then it would throw an error that it's not implemented. Also would be done for the nrf port as well. You could use pyserial as an example of what the API might be. We added stuff to UART that mimics pyserial as well.

@ATMakersBill

This comment has been minimized.

Copy link
Collaborator Author

ATMakersBill commented Oct 9, 2018

Per request moved this to supervisor.runtime...
Implemented on atsamd and nrf ports (only tested on atsamd).

This is just a simple attribute that can be tested before calling input()

    if(supervisor.runtime.serial_bytes_available):
          value = input()
@tannewt
Copy link
Collaborator

tannewt left a comment

Yay! Just a documentation request and then it'll be good. Thanks!

Show resolved Hide resolved shared-bindings/supervisor/Runtime.c Outdated
@ATMakersBill

This comment has been minimized.

Copy link
Collaborator Author

ATMakersBill commented Oct 10, 2018

I have added the documentation as requested and pushed it to my fork - hopefully that's all that's needed (still figuring out this process)

@ATMakersBill

This comment has been minimized.

Copy link
Collaborator Author

ATMakersBill commented Oct 10, 2018

If there's anything else you need from me let me know asap - I'm headed to NYC for my 20th anniversary :-)

@tannewt

This comment has been minimized.

Copy link
Collaborator

tannewt commented Oct 10, 2018

I made one tweak to the location and will merge after travis gives the ok.

@tannewt tannewt merged commit df80ad8 into adafruit:master Oct 10, 2018

1 check passed

continuous-integration/travis-ci/pr The Travis CI build passed
Details

@dhalbert dhalbert changed the title added timeout to input() added .serial_bytes_available [was added timeout to input()] Nov 3, 2018

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment