I'm trying to refactor/update some legacy serial comm code. I've got this:
private SerialPort cereal;
private String receivedData;
private FileXferLegacy()
{
cereal = new SerialPort("COM1", 9600);
cereal.PortName = "7727";
cereal.DataReceived += new SerialDataReceivedEventHandler(port_DataReceived);
// Is this just as well, as the elided part is grayed out above?: cereal.DataReceived += port_DataReceived;
}
...but am getting the err msg "The port '7727:' does not exist" when I try to connect and send a ping:
public void SendDataContentsAsXML(string destinationPath, string XMLData)
{
byte[] stuff;
ExceptionLoggingService.Instance.WriteLog("Reached FileXferLegacy.SendDataContentsAsXML"); // <= This is written to the log file
cereal.Open();
stuff = System.Text.UTF8Encoding.UTF8.GetBytes("PING" + "\n");
cereal.Write(stuff, 0, stuff.Length);
stuff = System.Text.UTF8Encoding.UTF8.GetBytes(XMLData + "\n");
cereal.Write(stuff, 0, stuff.Length);
}
7727 is the same port that is successfully used in the legacy app.
I do see that there is a colon appended, and wonder if that is the problem - why is it seeing "7727:" instead of plain old "7727", and how can I disabuse it of the notion of having an appended colon if that is indeed a problem?
Because PortName refers to the serial port name, not a port number. In your code you're creating your SerialPort object
cereal = new SerialPort("COM1", 9600);
So COM1 is already being assigned to PortName. Your next statement is just overriding it unnecessarily and incorrectly.
Related
I am using System.IO.Ports.
I send messages to device and want to wait for all messages from it.
I am trying do it like this:
message = Console.ReadLine();
_serialPort.Write(message);
Console.WriteLine(_serialPort.ReadExisting());
But it returns only the first line.
I have tried using port.BytesToRead, but I get the same results.
When I use ReadLine() it doesn't return anything.
Edit:
To see all line use Event handler.
Solution for my problem is use \r (enter) on the end line.
ReadExisting return the available bytes available at the exacte time, put a delay befor you read the buffer, a work around would be
message = Console.ReadLine();
_serialPort.Write(message);
Thread.Sleep(200);
Console.WriteLine(_serialPort.ReadExisting());
Edit 2 :
here is how i do it on my projects
private SerialPort port;
string DataReceived = string.Empty;
public string OpenPort(string PortName, int BaudRate)
{
// if the port is already used by other window then return the same instance
if (port != null)
if(port.IsOpen)
return "True";
port = new SerialPort(PortName, BaudRate, Parity.None, 8, StopBits.One);
// Attach a method to be called when there
// is data waiting in the port's buffer
port.DataReceived += new
SerialDataReceivedEventHandler(port_DataReceived);
// Begin communications
try
{
port.Open();
}
catch(Exception ex)
{
return ex.Message;
}
return "True";
}
private void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
Thread.sleep(200);
DataReceived = port.ReadExisting();
}
in your main
message = Console.ReadLine();
_serialPort.Write(message);
//use Stopwatch to calculate time befor you can exit from the loop
while(true)
{
if(!string.IsNullOrWhiteSpace(DataReceived))
break;
// Todo : Check stopwatch for timeout
}
Maybe you have a new line issue expected from your serial device try:
message = Console.ReadLine();
_serialPort.WriteLine(message);
Console.WriteLine(_serialPort.ReadExisting()); # try debug here replace with string test = _serialPort.ReadLine();
Im trying to get IMEI of a Samsung S7 device. I tried with AT+CGSN via Putty which worked perfectly. When I tried the same with C# SerialPort returns empty string.
Sending AT\r\n on C# SerialPort giving "OK" as expected and all other AT commands are also working except this
It looks bit wired for me on why it was not working for the specific commands where others are working.
Here is the sample.
private static string GetMobileSerialNumber(string PortName)
{
string Serial = "";
SerialPort serialPort = new SerialPort();
serialPort.PortName = PortName;
serialPort.BaudRate = 154200;
serialPort.Handshake = Handshake.None;
serialPort.ReadBufferSize = 16384;
try
{
if (!(serialPort.IsOpen))
serialPort.Open();
serialPort.Write("AT+CGSN\r\n");
Thread.Sleep(1000);
Serial = serialPort.ReadExisting();
serialPort.Close();
Console.WriteLine(Serial);
return Serial;
}
catch (Exception ex)
{
//MessageBox.Show("Error in opening/writing to serial port :: " + ex.Message, "Error!");
return "";
}
}
Sample also available here
PuTTY and teraterm filtering /n /r similar parameters CR LF byte commands.
your cmd wrong
I have application with several windows (actually its two almost same windows with some functions). One of that function is reading data from COM port (read weight from weighting machine). Problem is that, it works perfect on first window, but when im closing it and opening another window, then clicking same function (lets call it calculate weight), im getting this error message:
Access to the port 'COM1' is denied.
Code:
private void calculateWeight_Click(object sender, RoutedEventArgs e)
{
sp = new SerialPort("COM1", 9600, Parity.None, 8, StopBits.One);
tekst = string.Empty;
sp.Open();
sp.WriteLine(((char)5).ToString());
sp.WriteLine(((char)17).ToString());
sp.DataReceived += new SerialDataReceivedEventHandler(sp_DataReceived);
}
private delegate void UpdateUi(string s);
void sp_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
tekst += sp.ReadExisting();
if (tekst.Contains('S') && tekst.Length > 14)
Dispatcher.Invoke(DispatcherPriority.Send, new UpdateUi(czytajWage), tekst);
}
string tekst = string.Empty;
void czytajWage(string s)
{
string w = "";
for (int i = 5; i < 14; i++)
{
w += s[i];
}
MessageBox.Show(w);
w = "";
tekst = "";
sp.DataReceived -= sp_DataReceived;
}
Anyone can help? ;)
Method calculateWeight_Click opens serial port. So I assume that you get your exception on Open call as documentation states UnauthorizedAccessException can be thrown when:
The current process, or another process on the system, already has the specified COM port open either by a SerialPort instance or in unmanaged code.
So solution for you is to Close and Dispose sp after you are done or use IsOpen if you want to reuse existing instance.
I am using Visual Studio 2010 and programing in C# (.NET 3.5).
I want to write/read data from COM10.
Here is the simple code for that:
static void Main(string[] args)
{
String Portname = String.Empty;
/* List out all COM ports present on the computer. */
foreach (string ports in SerialPort.GetPortNames())
{
Console.WriteLine(ports);
/* If COM10 exists, copy the name for further use. */
if (ports == "COM10")
{
Portname = ports; //I also tried this: "\\.\\COM10";
}
}
/* If COM10 not found, return */
if (Portname == String.Empty)
{
Console.WriteLine("Exiting");
return;
}
SerialPort Port = new SerialPort(Portname,
9600, // Baudrate
Parity.None, //Parity
8, //DataBits
StopBits.One); //Stop Bits
Port.Open();
for (int count = 0; count < 5; count++)
{
Port.WriteLine("\nHello");
}
Port.Close();
while (true);
}
Whenever I use Portname as "COM10" in SerialPort Port = new SerialPort(Portname,9600,.....);, it gives an error as
The port 'COM10' does not exist
On Port.Open(), it should not even reach to command Port.Open() if COM10 doesn't exist.
Another way, I tried Portname as "\.\COM10". It gives an error as
The given port name does not start with COM/com or does not resolve to a valid serial port.
This happens with any port number greater than COM9.
Is there a way out?
The reason why you can't open a serial port greater than 10 is because FCL SerialPort implemented like in the following sample:
[MonitoringDescription("PortName")]
[Browsable(true)]
[DefaultValue("COM1")]
public string PortName
{
[TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")] get
{
return this.portName;
}
set
{
if (value == null)
throw new ArgumentNullException("PortName");
if (value.Length == 0)
throw new ArgumentException(SR.GetString("PortNameEmpty_String"), "PortName");
if (value.StartsWith("\\\\", StringComparison.Ordinal))
throw new ArgumentException(SR.GetString("Arg_SecurityException"), "PortName");
if (this.IsOpen)
throw new InvalidOperationException(SR.GetString("Cant_be_set_when_open", new object[1]
{
(object) "PortName"
}));
else
this.portName = value;
}
}
As you see, standard SerialPort does not allow you to use \\.\ notation in the port name. And I don't know why they did this. With \\.\ notation, ports greater than 10 can be opened. So, the only way is to implement your own SerialPort component.
I don't think GetPortNames() or Open() are causing your issue: my bet is that it's hardware-related. Have you tried your code on a different machine?
Unfortunately, i don't have direct experience with your scenario, since two-digit ports have always worked for me... But there's one thing i'd like to note: i've learned in time that it's better to be safe than sorry, and thus i've increased my usage of try-catch blocks. In your case, i'd do this:
static System.Diagnostics.Stopwatch timer = new System.Diagnostics.Stopwatch();
private static int defaultBaudRate = 9600, defaultDataBits = 8;
static System.IO.Ports.SerialPort TryOpeningPort(string portName)
{
System.IO.Ports.SerialPort port = null;
timer.Start();
try
{
port = new System.IO.Ports.SerialPort(portName,
defaultBaudRate, System.IO.Ports.Parity.None, defaultDataBits, System.IO.Ports.StopBits.One);
port.Open();
port.Close();
/**/Console.WriteLine(portName + " : OK");
}
catch (Exception exceptionInfo) //most common is System.UnauthorizedAccessException
{
port = null;
/**/Console.WriteLine(portName + " -- " + exceptionInfo.GetType().ToString() + " : " + exceptionInfo.Message);
}
timer.Stop();
//Console.WriteLine("Elapsed time : " + timer.ElapsedMilliseconds + "ms" + System.Environment.NewLine);
timer.Reset();
return port;
}
You can call this either directly, as in:
TryOpeningPort("COM10");
or using your initial-check approach:
foreach (string portName in System.IO.Ports.SerialPort.GetPortNames())
if (portName.Equals("Com10", StringComparison.InvariantCultureIgnoreCase))
TryOpeningPort(portName);
For port smaller or equal to 9: new SerialPort("COM9")
For port greater than 9: new SerialPort("\\\\.\\COM10")
I tested the use of the property serialArduino.PortName = ... for ports greater than 9, but this was always leading to errors, so I used the constructor new SerialPort().
I'm using C#'s SerialPort class to try and send a AT command to a device and get a response back. I've verified it works correctly in HyperTerminal, if I send a command of AT it responds back with OK. However, in my console app, if I send AT, it replies back with an echo AT. The code is below, any insight into what I'm doing wrong in my receiving code would be greatly appreciated:
ComPort.DataReceived += new SerialDataReceivedEventHandler(ComPort_DataReceived);
public void Open()
{
Console.WriteLine();
//close port if already open.
if (ComPort.IsOpen)
{
ComPort.Close();
}
//setup port.
ComPort.PortName = ConfigurationManager.AppSettings["PortName"].ToString();
ComPort.BaudRate = Convert.ToInt32(ConfigurationManager.AppSettings["BaudRate"]);
ComPort.Parity = Parity.None;
ComPort.StopBits = StopBits.One;
ComPort.DataBits = 8;
ComPort.DtrEnable = true;
ComPort.RtsEnable = true;
if (Convert.ToBoolean(ConfigurationManager.AppSettings["HWFlowControlEnabled"]))
{
ComPort.Handshake = Handshake.RequestToSend;
}
//open port.
Console.WriteLine("Opening port " + ComPort.PortName + "...");
ComPort.Open();
Console.WriteLine("Opened port " + ComPort.PortName);
}
void ComPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
string message = ComPort.ReadExisting();
Console.WriteLine("RECEIVED: " + message);
if (message.IndexOf("OK") > -1)
{
ReceivedOK = true;
}
}
I think the default is to echo your commands back to you, then the OK. Send an ATE0 first to turn off echo:
http://tigger.cc.uic.edu/depts/accc/network/dialin/modem_codes.html
By default, the device (a modem I guess) is configured to echo all communication back. There are AT commands to turn echo on and off. Also, several hardware signalling approaches exist to control the flow of data. Have a look here for a basic overview.
It's quite a while (> 10 years actually) since I was doing modem communications, so I'm sorry in case my answer isn't 100% precise.