I currently have a working "one character" serial menu system that processes one character at a time and is designed to be nonblocking, so other periodical tasks keep running.
My original code is:
if (Console0.available()) inbyte = Console0.read();
Then inbyte is processed and finally set to 0 upon completing the task.
I can enter a one character command at a time, or even stack a series of characters.
They get processed one after the other using several cycles.
I want to make a telnet version of this system.
The way ESPtelnet.h processes input is however different: it takes always a full line. telnet.onInputReceived([](String str);
So my original idea is to take that string and, at each cycle, extract the left character to inbyte and store the shortened string for the next cycle, returning to telnet.onInputReceived once the string is empty.
That will probably work, but looks a bit clumsy and string processing is known to be problematic.
Have you got a better idea how to do it more elegantly?
Telnet is a line based protocol. So modifying the library to be non line based won't work. Perhaps a better way to express your problem, is that the library is blocking? Then you need to make the library non-blocking. That's different.
I am working with several esp32 models.
Using your own example slightly simplified (the TimeLib is not required), commenting out the
// TelnetStream.stop();
and adding
delay(500);
TelnetStream.println("Still there?");:
#include <WiFi.h>
#include <TelnetStream.h>
const long gmtOffset_sec = 3600;
const int daylightOffset_sec = 3600;
tm* timeinfo; //localtime returns a pointer to a tm struct static int Second;
time_t now;
const char ssid[] = "PawsAway"; // your network SSID (name)
const char pass[] = "Secret"; // your network password (use for WPA, or use as key for WEP)
void setup() {
Serial.begin(115200);
Serial.print("Attempting to connect to WPA SSID: ");
Serial.println(ssid);
WiFi.begin(ssid, pass);
if (WiFi.waitForConnectResult() != WL_CONNECTED) {
Serial.println("Failed to connect.");
while (1) {
delay(10);
}
}
configTime(gmtOffset_sec, daylightOffset_sec, "pool.ntp.org");
time_t now = time(nullptr);
while (now < 1629050852) {
delay(100);
now = time(nullptr);
}
timeinfo = localtime(&now);
IPAddress ip = WiFi.localIP();
Serial.println();
Serial.println("Connected to WiFi network.");
Serial.print("Connect with Telnet client to ");
Serial.println(ip);
TelnetStream.begin();
}
void loop() {
switch (TelnetStream.read()) {
case 'R':
TelnetStream.stop();
delay(100);
ESP.restart();
break;
case 'C':
TelnetStream.println("bye bye");
TelnetStream.flush();
// TelnetStream.stop();
delay(500);
TelnetStream.println("Still there?");
break;
}
static unsigned long next;
if (millis() - next > 5000) {
next = millis();
log();
}
}
void log() {
static int i = 0;
char timeStr[20];
strftime(timeStr, sizeof(timeStr), " %R %d%b ", timeinfo);
TelnetStream.print(i++);
TelnetStream.print(" ");
TelnetStream.println (timeStr);
}
The bootlog on Serial:
Attempting to connect to WPA SSID: PawsAway
Connected to WiFi network.
Connect with Telnet client to 192.168.188.77
Here the Telnet protocol (Debian on WSL)
rin67630@My-Laptop:~$ telnet 192.168.188.77
Trying 192.168.188.77...
Connected to 192.168.188.77.
Escape character is '^]'.
7 20:25 15Aug
8 20:25 15Aug
9 20:25 15Aug
C
bye bye
Connection closed by foreign host.
rin67630@My-Laptop:~$
Hmm, no it does not work on en ESP8266 neither.
It does not disconnect, but nor does it flush:
$ telnet 192.168.188.51
Trying 192.168.188.51...
Connected to 192.168.188.51.
Escape character is '^]'.
4 21:00 15Aug
CCCCCCCCCCCCCCCCCC5 21:00 15Aug
bye bye
Still there?
bye bye
Still there?
bye bye
Still there?
bye bye
Still there?
bye bye
Still there?
6 21:00 15Aug
bye bye
Still there?
bye bye
cu at the GitHub issue....
I have meanwhile found a workaround: I am reading the buffer until \n into a dummy variable.
That leaves the buffer empty too...