I was developing a C# Console app
to interact with firmware on SAS Expander card.
The card was connected via RS232
Port.
I have already sent a command and had a result on the Console App.
Now I want to have a function to record command.
When I use PuTTY
to send command,
I realize that when I press UpArrow
key, it will show the last command.
Here is PuTTY
's result:
before press UpArrow Key
→
after press UpArrow Key
→
Here is my code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections;
using System.IO.Ports;
using System.Threading;
namespace ConsoleApp3
{
class Program
{
[STAThread]
static void Main()
{
SerialPort mySerialPort = new SerialPort("COM5");
mySerialPort.BaudRate = 115200;
mySerialPort.Parity = Parity.None;
mySerialPort.StopBits = StopBits.One;
mySerialPort.DataBits = 8;
mySerialPort.Handshake = Handshake.None;
mySerialPort.RtsEnable = true;
mySerialPort.DtrEnable = true;
mySerialPort.ReadTimeout = 2000;
mySerialPort.WriteTimeout = 1500;
mySerialPort.Open();
if (mySerialPort.IsOpen)
{
mySerialPort.Write("\r");
}
mySerialPort.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);
while (true)
{
if (Console.KeyAvailable)
{
ConsoleKeyInfo userResponse = Console.ReadKey(true);
List<string> Command = new List<string>();
if (userResponse.KeyChar.ToString() == "s")
{
Command.Add("s");
mySerialPort.Write("s");
}
else if (userResponse.KeyChar.ToString() == "y")
{
Command.Add("y");
mySerialPort.Write("y");
}
else if (userResponse.Key == ConsoleKey.UpArrow)
{
for (int i = 0; i < Command.Count; i++)
{
Console.WriteLine(Command[i]);
}
Console.ReadLine();
Command.Clear();
}
else
{
mySerialPort.Write("\r");
}
}
}
}
private static void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
{
SerialPort sp = (SerialPort)sender;
string indata = sp.ReadExisting();
Console.Write(indata);
}
}
}
What the code's result:
When I press UpArrow
key twice, the app shows up two space to enter.
That was the second bp1>
in the picture.
The picture looks like:
After I press enter
Key, it comes out bp1>
again.
I started to send sys
command and it didn't get response, but it came up a space to enter.
After I press Enter
and UpArrow
key again, the sys
command shows up.
What is the problem with my code?
Is there another way to improve?
My console App is using .Net Framework 4.7.2
.
The better way is to use the mono/LineEditor, how kunif said in the comments. A other way is like this:
using System;
using System.Collections.Generic;
using System.IO.Ports;
namespace ConsoleApp3
{
class Program
{
static void Main()
{
SerialPort mySerialPort = new SerialPort("COM5");
mySerialPort.BaudRate = 115200;
mySerialPort.Parity = Parity.None;
mySerialPort.StopBits = StopBits.One;
mySerialPort.DataBits = 8;
mySerialPort.Handshake = Handshake.None;
mySerialPort.RtsEnable = true;
mySerialPort.DtrEnable = true;
mySerialPort.ReadTimeout = 2000;
mySerialPort.WriteTimeout = 1500;
// mySerialPort.NewLine = "\r"; // implement this if you use "string indata = sp.ReadLine();" in event handler
mySerialPort.Open();
//if (mySerialPort.IsOpen)
//{
// mySerialPort.Write("\r");
//}
List<string> Commands = new List<string>();
string command = "";
int counter = 0;
//mySerialPort.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);
while (true)
{
ConsoleKeyInfo consoleInput = Console.ReadKey();
if (consoleInput.KeyChar == '\r')
{
Commands.Add(command);
counter = Commands.Count - 1;
//mySerialPort.Write(command + "\r");
ClearCurrentConsoleLine();
command = "";
}
else if (consoleInput.Key == ConsoleKey.UpArrow)
{
if ((counter >= 0) && (counter < Commands.Count))
{
ClearCurrentConsoleLine();
Console.Write(Commands[counter]);
}
if (counter > 0)
{
counter--;
}
else
{
counter = Commands.Count - 1;
}
}
else
{
command += consoleInput.KeyChar.ToString();
}
}
}
private static void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
{
SerialPort sp = (SerialPort)sender;
string indata = sp.ReadExisting(); // it might be better to use --> string indata = sp.ReadLine();
Console.Write(indata);
}
private static void ClearCurrentConsoleLine()
{
int currentLineCursor = Console.CursorTop;
Console.SetCursorPosition(0, Console.CursorTop);
Console.Write(new string(' ', Console.WindowWidth));
Console.SetCursorPosition(0, currentLineCursor);
}
}
}
I tested the code without the serial communication. The serial communication should work if you clear my comments.