How to replicate Tera Term SerialPort command in C#? - c#

In Tera Term I'm connecting to a serial device over USB (on startup select radiobutton "serial" and correct port). Once connected I only change the default speed to 115200 (in setup=> serial port).
After this, tera term asks me to fill in commands like so:
Command>
I fill in the device specific command. In this case it's "PC" and I receive an expected response ie. "ABC"
Now I'm trying to do the same in C#. Unfortunately the response I get is always the same as the command I actually type in.
So If I type in "PC", the response is "PC", but I expect "ABC". Other commands have the same problem. Command "?" responds with "?" while I expect "CBA".
If I type in a faulty command => then I get the message "Unknown command"
So I suspect the device actually gets the right command.
I'm using the following code:
SerialPort COMport = new SerialPort(Port_Name, Baud_Rate); //Create a new SerialPort Object (defaullt setting -> 8N1)
COMport.DataReceived += new SerialDataReceivedEventHandler(sPort_dataReceived);
COMport.ErrorReceived += new SerialErrorReceivedEventHandler(sPort_ErrorReceived);
COMport.BaudRate = 115200;
COMport.Parity = Parity.None;
COMport.DataBits = 8;
COMport.StopBits = StopBits.One;
COMport.RtsEnable = true;
COMport.Handshake = Handshake.None;
COMport.Open();
COMport.WriteLine(Data);
Thread.Sleep(1000); // Just discovered after a lot of testing that this is necessary to read the response before the Comport closes
COMport.Close();
Then I do the following:
private void sPort_dataReceived(object sender, SerialDataReceivedEventArgs e)
{
SerialPort sp = (SerialPort)sender;
string indata = sp.ReadExisting();
Console.WriteLine("Data Received:");
Console.Write(indata);
MessageBox.Show(indata);
}
I've tried different things, but I can't get this to work. Hopefully it's because I'm new to this. I've never worked with Tera term before.
Thanks in advance,
Some (but definately not all) things I've tried:
tried this guys advise and code: https://www.sparxeng.com/blog/software/must-use-net-system-io-ports-serialport
downloaded and tried from here: https://www.xanthium.in/building-opensource-gui-based-serial-port-communication-program-dot-net-framework-and-arduino#simple-serial-source-code (Although my device is not arduino)
Tried to add "\r\n" : C# Errors with SerialPort WriteLine commands
EDIT EDIT EDIT EDIT
So I found out more. If I use the following code (Write instead of WriteLine), I do get good results but not every time:
Sending the full command now: "Command>PC"
string Command1 = txtCommand.Text;
Command1 = Command1 + "\r\n";
string CommandSent;
int Length, j = 0;
Length = Command1.Length;
for (int i = 0; i < Length; i++)
{
CommandSent = Command1.Substring(j, 1);
ComPort.Write(CommandSent);
j++;
}
The first time, now I get good results. The second time I get "Unknow Command", the 3rd time => good results, 4th = "Unknown Command"... etc...
It always seems to work 1 time well, then 1 time not.
I can only get it to work consistently if I switch the command formatting:
First time command: "Command>PC"
Second time command: "PC"
Third time command : "Command>PC"
Fourth time command: "PC"
etc...
I've already tried to clear the buffer before sending but no effect.
ComPort.DiscardInBuffer();
ComPort.DiscardOutBuffer();

The Newline seemed to be a problem.
I needed to use Comport.Write (instead of WriteLine). Then Also I needed to append a carriage return "\r" but NO newline '\n' as I previously thought. (the incoming data showed a newline after the "Command>" making it impossible to send another meaningfull command => the cause of this was '\n' => removing it solved the problem)
This is my current code that seems to work (I no longer need to append "Command>", just sending the command as is):
if (thecommand == "")
{
ComPort.Write("\r"); //start from a clean slate
return;
}
ComPort.DiscardInBuffer();
ComPort.DiscardOutBuffer();
string Command1 = thecommand + "\r";
ComPort.Write(Command1);

Related

AT+CMGL="ALL" return OK only

I have 1 gsm 32 port with name is xr21v1414 USB UART
I have tested another AT COMMAND which works fine like
AT
USSD
but if i use COMMAND :
serialPort.WriteLine("AT" + System.Environment.NewLine);
Thread.Sleep(200);
serialPort.WriteLine("AT+CMGF=1" + System.Environment.NewLine);
Thread.Sleep(200);
serialPort.WriteLine("AT+CMGL=\"ALL\"" + System.Environment.NewLine);
Thread.Sleep(200);
responded with
serialPort.ReadExisting();
is empty (OK only)
AT
OK
AT+CMGF=1
OK
AT+CMGL="ALL"
OK
But if I switch to another gsm, Command work fine. I have list SMS.
This is my setting :
SerialPort serialPort = new SerialPort();
serialPort.PortName = m.ToString();
serialPort.BaudRate = 115200;
serialPort.DataBits = 8;
serialPort.Handshake = Handshake.XOnXOff;
serialPort.StopBits = StopBits.One;
serialPort.Parity = Parity.None;
serialPort.ReadTimeout = 20000;
serialPort.WriteTimeout = 20000;
serialPort.WriteBufferSize = 1024;
serialPort.DtrEnable = true;
serialPort.RtsEnable = true;
How could i resolve the problem ,please ?
I am quite sure that the OK response you get is because you have aborted the current command line by using Thread.Sleep(200) instead of reading and parsing the response you get back from the modem, waiting for the Final Result Code before sending the next command.
The first linked answer above is to a question whose code which is slightly worse because it does not even have a sleep, but even having one is utterly wrong. Just as you would not write a HTTP client that ignores the responses a HTTP server send it, you should not write a AT command program that ignores the responses the modems sends it.
TL;DR You MUST change your code to read and parse every single response line that the modem sends you, waiting for the Final Result Code before sending the next command. See the linked answers for more details.

Sending Ctrl+break sequence through Plink

I am trying to automate the remote server shell commands through Plink. And one of the things which I did is grep command.
Now suppose if results lots of data then I just want to break the command.
Generally from PuTTY you just do Ctrl-C or Ctrl-Break and it will break the command.
What's the alternative for Plink?
Do not run Plink from C# application to implement SSH. Use a native .NET implementation of SSH, like SSH.NET. – It will give you a complete control over the connection and you won't have have to use hacks like sending Ctrl+C.
var client = new SshClient("example.com", "username", "password");
client.Connect();
SshCommand command = client.CreateCommand("grep pattern file");
IAsyncResult result = command.BeginExecute();
using (var outputReader = new StreamReader(command.OutputStream))
using (var extendedReader = new StreamReader(command.ExtendedOutputStream))
{
int read = 0;
while (read < 10240)
{
string s;
s = outputReader.ReadToEnd();
read += s.Length;
Console.Write(s);
s = extendedReader.ReadToEnd();
read += s.Length;
Console.Write(s);
}
}
command.CancelAsync();
Also, you can use -m switch to stop grep after certain number of matches.

Using Process to connect via mstsc.exe failes

I have created a small tool where I want to connect to remote desktop via mstsc.exe.
I found a lot of samples and obviously they all work. But for some reaons my doesnt! :(
Actually its a small code
private void RunRDP(object sender, EventArgs e)
{
Process rdcProcess = new Process();
//Add/Change Credentials
/**
rdcProcess.StartInfo.FileName = Environment.ExpandEnvironmentVariables(#"%SystemRoot%\system32\cmdkey.exe");
rdcProcess.StartInfo.Arguments = String.Format(#"/generic:TERMSRV/{0} /user:{1} /pass:{2}", tbServer.Text, tbUsername.Text, tbPassword.Text);
rdcProcess.Start();
*/
//Perform mstsc
rdcProcess.StartInfo.FileName = Environment.ExpandEnvironmentVariables(#"%SystemRoot%\system32\mstsc.exe");
rdcProcess.StartInfo.Arguments = string.Format(#"/v {0}", tbServer.Text);
rdcProcess.Start();
}
I took out the adding credentials just to test the connection... still fails.
When I comment the line
rdcProcess.StartInfo.Arguments = string.Format(#"/v {0}", tbServer.Text);
It at least opens mstsc.exe
In any other case I receive the error
Invalid connection File
The error must be some like this. Translating this from german to english doesnt bring any similar error descriptions :D
Why does my programm fails ?
running 'mstsc /?' gives me:
/v:<server[:port]> -- Specifies the remote computer to which you want to connect.
So I guess you should change it to:
rdcProcess.StartInfo.Arguments = string.Format(#"/v:{0}", tbServer.Text);

Receiving carriage return through Serial Port

So I am developing a console application which is able to read and write to/from Arduino through Serial Port. At the moment I got a switch statement to read incoming data from Arduino and depending on the incoming data I will write to the Arduino a couple of messages.
string incoming = port.ReadExisting();
string questionMark = "?";
string carriageReturn = "\r";
string text = string.Empty;
switch (incoming)
{
case "#r\r":
port.Write(questionMark+ "*" + carriageReturn);
break;
case "#{":
port.Write("#" + text);
break;
default:
Console.WriteLine("Unknown command sent by the Arduino\n Command: " + incoming);
break;
}
Now, I am testing out the application with another application to read and write it and when I send to the console application the "#r\r" it will give
Unknown command sent by the Arduino\n Command: "#r\r".
I've found the problem and it comes from the carriage return or \r.
Do you have any idea how could I solve this problem? I want to receive the carriage return because it is the end of it.

C# Handle on SQL Server Message Output [duplicate]

This question already has answers here:
Capture Stored Procedure print output in .NET
(3 answers)
Closed 6 years ago.
When executing scripts in SQL Server Management Studio, messages are often generated that display in the message window. For example when running a backup of a database:
10 percent processed.
20 percent processed.
Etc...
Processed 1722608 pages for database 'Sample', file 'Sampe' on file 1.
100 percent processed.
Processed 1 pages for database 'Sample', file 'Sample_Log' on file 1.
BACKUP DATABASE successfully processed 1722609 pages in 202.985
seconds (66.299 MB/sec).
I would like to be able to display these message in a C# application that is running SQL scripts against a database. However, I cannot figure out how to get a handle on the message output from SQL as it is generated. Does anybody know how to do this? It doesn't matter to me which connection framework I have to use. I'm relatively comfortable with LINQ, NHibernate, Entity Framework, ADO.Net, Enterprise Library, and am happy to learn new ones.
Here is the example code I tried and it works for me.
http://www.dotnetcurry.com/ShowArticle.aspx?ID=344
Note the code you need is actually this part :
cn.Open();
cn.InfoMessage += delegate(object sender, SqlInfoMessageEventArgs e)
{
txtMessages.Text += "\n" + e.Message;
};
It's the e.Message keeps returning the message back to txtMessages (You can replace as TextBox or Label).
You may also refer to this article:
Backup SQL Server Database with progress
An example of my code is in the following:
//The idea of the following code is to display the progress on a progressbar using the value returning from the SQL Server message.
//When done, it will show the final message on the textbox.
String connectionString = "Data Source=server;Integrated Security=SSPI;";
SqlConnection sqlConnection = new SqlConnection(connectionString);
public void DatabaseWork(SqlConnection con)
{
con.FireInfoMessageEventOnUserErrors = true;
//con.InfoMessage += OnInfoMessage;
con.Open();
con.InfoMessage += delegate(object sender, SqlInfoMessageEventArgs e)
{
//Use textBox due to textBox has Invoke function. You can also utilize other way.
this.textBox.Invoke(
(MethodInvoker)delegate()
{
int num1;
//Get the message from e.Message index 0 to the length of first ' '
bool res = int.TryParse(e.Message.Substring(0, e.Message.IndexOf(' ')), out num1);
//If the substring can convert to integer
if (res)
{
//keep updating progressbar
this.progressBar.Value = int.Parse(e.Message.Substring(0, e.Message.IndexOf(' ')));
}
else
{
//Check status from message
int succ;
succ = textBox.Text.IndexOf("successfully");
//or succ = e.Message.IndexOf("successfully"); //get result from e.Message directly
if (succ != -1) //If IndexOf find nothing, it will return -1
{
progressBar.Value = 100;
MessageBox.Show("Done!");
}
else
{
progressBar.Value = 0;
MessageBox.Show("Error, backup failed!");
}
}
}
);
};
using (var cmd = new SqlCommand(string.Format(
"Your SQL Script"//,
//QuoteIdentifier(databaseName),
//QuoteString(Filename)//,
//QuoteString(backupDescription),
//QuoteString(backupName)
), con))
{
//Set timeout = 1200 seconds (equal 20 minutes, you can set smaller value for shoter time out.
cmd.CommandTimeout = 1200;
cmd.ExecuteNonQuery();
}
con.Close();
//con.InfoMessage -= OnInfoMessage;
con.FireInfoMessageEventOnUserErrors = false;
}
In order to get the progressbar working, you need to implement this with a backgroundworker, which your application won't freeze and get 100% done suddenly.
The SqlConnection.InfoMessage event occurs when SQL Servers returns a warning or informational message. This website shows a possible implementation.

Categories

Resources