Skip to content
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

std::cin should be implemented in terms of linenoise (IDFGH-8199) #9692

Closed
frak0d opened this issue Sep 1, 2022 · 10 comments
Closed

std::cin should be implemented in terms of linenoise (IDFGH-8199) #9692

frak0d opened this issue Sep 1, 2022 · 10 comments
Labels
Resolution: Done Issue is done internally Status: Done Issue is done internally Type: Feature Request Feature request for IDF

Comments

@frak0d
Copy link

frak0d commented Sep 1, 2022

Is your feature request related to a problem?

std::cin doesn't work. it doesn't read anything from serial console. everyone says "use linenoise", but why not just implement std::cin using linenoise ? if std::cout works over serial, then std::cin should also work over serial.

Describe the solution you'd like.

std::cin should be implemented in terms of linenoise.

Describe alternatives you've considered.

No response

Additional context.

No response

@frak0d frak0d added the Type: Feature Request Feature request for IDF label Sep 1, 2022
@espressif-bot espressif-bot added the Status: Opened Issue is new label Sep 1, 2022
@github-actions github-actions bot changed the title std::cin should be implemented in terms of linenoise std::cin should be implemented in terms of linenoise (IDFGH-8199) Sep 1, 2022
@igrr
Copy link
Member

igrr commented Sep 1, 2022

Hi @0xb00b,
By default, ESP-IDF sets up the standard I/O streams (stdin, stdout, stderr) to use the simple non-interrupt-driven UART driver (docs. This driver provides a blocking stdout and non-blocking stdin. Most C standard library functions (as well as C++ functions built on top of them) expect stdin to be blocking. This is why functions such as scanf (and the equivalent C++ functions) don't behave as expected by default.

Applications which require a blocking stdin behavior need to set up the interrupt-driven UART driver (uart_driver_install) and reconfigure the console streams to work with that driver (esp_vfs_dev_uart_use_driver). The code snippet for doing this can be found here.

While I agree that it's annoying that std::cin doesn't work "out of the box", it is unlikely that we will be modifying the standard library to perform such initialization automatically.

@frak0d
Copy link
Author

frak0d commented Oct 8, 2022

@igrr thanks, that almost works. I can't see my input while typing in serial console, but otherwise it works.

I suggest adding this information from your comment, to documentation as a highlighted note for others like me.

@frak0d frak0d closed this as completed Oct 11, 2022
@finger563
Copy link

@0xb00b did you figure out how to get the input to show when typing (when using std::cin / std::getline / etc.)?

@frak0d
Copy link
Author

frak0d commented Apr 5, 2023

@0xb00b did you figure out how to get the input to show when typing (when using std::cin / std::getline / etc.)?

No, i didn't bother with it.

Perhaps you can print out characters manually as you recieve them one at a time. There must be some low level function to read serial input in realtime without needing to press enter key.

@finger563
Copy link

Yea I ended up using

        char c;
        while (in.get(c)) {
          line += c;
          cli::Cli::cout() << c;
          if (c == '\n')
            break;
        }

instead of the simpler std::getline(in, line) interface, but it doesn't handle backspace and such well :/

@espressif-bot espressif-bot added Status: Done Issue is done internally Resolution: Done Issue is done internally and removed Status: Opened Issue is new labels Apr 26, 2023
@joaotavora
Copy link

After using the linked code, local echo works fine as long as the dev is configured properly and a simple client such as socat is used:

❯ stty -F /dev/ttyUSB0
speed 115200 baud; line = 0;
min = 0; time = 0;
-brkint -icrnl -imaxbel
-opost -onlcr
-isig -icanon -iexten -echo -echoe -echok -echoctl -echoke

I think the "echo" properties there are important. The loop I'm using is straightforward and does use std::getline(in, line)

  std::string s;

  std::cout << "Prompt: ";
  while (std::getline(std::cin, s)) {
    std::cout << "Read: '" << s << "'\nPrompt:";
  }
  std::cout << "Bye bye!" << s;

With pyserial's miniterm you can also set local echo. The screenshot is from socat though. Haven't figured out what to send to break the loop cleanly yet.

Peek 2023-06-30 19-08

@Bobobel
Copy link

Bobobel commented Jan 6, 2024

I am having the same problem with unblocking stdin but with preferable 'usb-serial-jtag' (and ESP-BOX-3). I have tried the example init from "esp_zigbee_gateway.c", but without any blocking.
I would very much appreciate some additions to the documentation!

IGRR code snippet from </examples/common_components/protocol_examples_common/stdin_out.c> together with "CONFIG_ESP_CONSOLE_UART_DEFAULT=y" failed with:
"Writing to serial is timing out. Please make sure that your application supports an interactive console and that you have picked the correct console for serial communication."
Maybe "esp_vfs_dev_uart_register();" is missing? I had a try: No!
I am realy frustrated: with BOX-3 almost any example shows severe errors! HELP!

@igrr
Copy link
Member

igrr commented Jan 7, 2024

@Bobobel if you are using usb_serial_jtag interface, my suggestion doesn't apply literally, as it was written for the UART interface. Instead, you need to select the USB_SERIAL_JTAG as the primary console output in menuconfig, initialize the usb_serial_jtag driver and then call esp_vfs_usb_serial_jtag_use_driver.

@Bobobel
Copy link

Bobobel commented Jan 7, 2024

Dear Ivan,
thank you very much. As always, you feel responcible and answer quickly. I am very happy again >:->
I tried all that: set jtag in menuconfig and initialize the usb_serial_jtag driver and then call esp_vfs_usb_serial_jtag_use_driver.
setting uart in menuconfig and doing the uart setup as explained above in issues/9692. For output I had to add the 'esp_vfs_dev_uart_register();'.
For jtag I used a second uart and esp_vfs_dev_uart_register(); for output, otherwise I did not see any output. Funny effect: Now I see a write timeout dispite the setup of no watchdog at all (as far as I do understand and see) in menuconfig.
No I am trying 'esp consol system', but that overkill for my opinion.

@igrr
Copy link
Member

igrr commented Jan 7, 2024

For jtag I used a second uart and esp_vfs_dev_uart_register();

I'm sorry, I'm failing to understand what you are trying to achieve. Please open a new issue and describe the original problem you want to solve, as well as mention the IDF version you are using.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Resolution: Done Issue is done internally Status: Done Issue is done internally Type: Feature Request Feature request for IDF
Projects
None yet
Development

No branches or pull requests

6 participants