8000 added .serial_bytes_available [was added timeout to input()] by ATMakersBill · Pull Request #1193 · adafruit/circuitpython · GitHub
[go: up one dir, main page]

Skip to content

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

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

Merged
merged 5 commits into from
Oct 10, 2018

Conversation

ATMakersBill
Copy link
Collaborator
@ATMakersBill 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 mentioned this pull request Sep 16, 2018
@ATMakersBill
Copy link
Collaborator Author

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
Copy link
Member
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
Copy link
Collaborator Author

I get it - I have no problem with that

@ATMakersBill
Copy link
Collaborator Author

@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
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
Copy link
Collaborator Author

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()

Copy link
Member
@tannewt tannewt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

@ATMakersBill
Copy link
Collaborator Author

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
Copy link
Collaborator Author

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

@tannewt
Copy link
Member
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
@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
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants
0