I'm trying to send a sms via a Nokia phone over serial which is easy enough via putty. The commands from the nokia documentation works fine.
However, trying to send the same commands from a c# application fails miserably. I've run Sysinternals PortMon and can see the commands come through OK, the only difference I can see is in the way it connects but I am having trouble finding the commands that would iron out those differences.
The code I'm running looks a little bit like this
using (SerialPort port = new SerialPort(comPort, 9600, Parity.None, 8, StopBits.One))
{
port.DataReceived += new SerialDataReceivedEventHandler(port_DataReceived);
port.ErrorReceived += new SerialErrorReceivedEventHandler(port_ErrorReceived);
//port.ReceivedBytesThreshold = 1;
port.DtrEnable = true;
port.RtsEnable = true;
port.ReadTimeout = 1;
port.Handshake = Handshake.XOnXOff;
try
{
port.Open();
port.WriteLine("AT");
port.WriteLine("AT+CMGF=1");
port.WriteLine("AT+CMGS=\"" + number + "\"");
port.WriteLine(message);
port.Write(new byte[] { (byte)26 }, 0, 1);
}
finally
{
if (port.IsOpen)
{
port.Close();
}
}
The differences I'm seeing in the trace from the serial port are
At the start
0.00001844 aspnet_wp.exe IOCTL_SERIAL_SET_HANDFLOW USBSER001 SUCCESS Shake:1 Replace:43 XonLimit:4096 XoffLimit:4096
And at the very end
0.00061153 aspnet_wp.exe IOCTL_SERIAL_PURGE USBSER001 SUCCESS Purge: RXABORT RXCLEAR
0.00004442 aspnet_wp.exe IOCTL_SERIAL_PURGE USBSER001 SUCCESS Purge: TXABORT TXCLEAR
Has anyone got any tips on how to iron out these issues? I also notice that the phone is not responding back to the application with any acknowledgement when I issue a command so I suspect the problem is with the connection, not those messages at the end.
Try to see if you can read out the serial communication from the phone. After you send 'AT', the phone should respond with 'OK'. It might be a good idea to verify that the serial communication is working before taking on the SMS bit.
From what I remember, I think that after AT+CMGS the message should be entered and followed by ctrl-z, and no newline is needed. Could you try changing the WriteLine(message) to Write(message)?
Hope this helps!
You need to wait for the ">" before writing out the message. Also, don't terminate the message with a CR/LF (WriteLine).
Related
I recently purchased a modem, which attaches via USB and appears to the operating system as a serial port device: COM19
To ensure the modem was OK, I first tried using PuTTY in serial mode. From there, I have no problem issuing AT commands and receiving responses from the modem. According to PuTTY configuration, my default options for controlling local serial lines are (at the time):
Speed (baud): 9600
Data bits: 8
Stop bits: 1
Parity: None
Flow control: XON/XOFF
Here's what I see in PuTTY (when I type the AT command):
AT
OK
^BOOT:30645964,0,0,0,75
However, when I try to access the same COM port from .NET (not at the same time as running PuTTY) I never receive the "OK" responses. I do still receive (what appears to be) echo, and the occasional unsolicited message from the modem, so I can see that I'm connected to the correct device. Sometimes the modem will respond to a malformed command with "ERROR", but never "OK". Here's the C# snippet where I initialize the COM port:
var commandPort = new SerialPort(portName, 9600, Parity.None, 8, StopBits.One);
commandPort.DataReceived += CommandPort_DataReceived;
commandPort.Handshake = Handshake.XOnXOff;
commandPort.Open();
commandPort.Write("AT\n");
for (var i = 0; i < 30; i++)
{
Thread.Sleep(1000);
}
And this is the event handler:
private static void CommandPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
Console.Write(((SerialPort)sender).ReadExisting());
}
This is what's printed back to the console of the C# application (note that I'm not explicitly writing the command to the console, it's added by the CommandPort_DataReceived event handler):
AT
^BOOT:30645964,0,0,0,75
None of the AT commands issued by the .NET application perform any action, though their equivalents in PuTTY are able to query modem state, place calls, etc. What am I doing wrong?
Use the SerialPort class's NewLine property. By default it's set to "\n". This needs to be "\r", then you can use the WriteLine(...) method to send AT commands.
commandPort.NewLine = "\r";
commandPort.Open();
commandPort.WriteLine("AT");
I try connect to scale via rs232 cable. When I try write "ENQ" to port then scale turn off and receive nothing. This is my code. Sorry my bad English :(
class ScaleCAS
{
private SerialPort port = new SerialPort("COM4", 9600, Parity.None, 8, StopBits.One);
public string result = null;
public ScaleCAS()
{
port.DataReceived += new SerialDataReceivedEventHandler(port_DataReceived);
port.Open();
}
private void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
this.result = port.ReadExisting();
}
}
ADD
In another class I try write into port
Scale.port.write("ENQ");
Console.Write(Scale.result);
You are not waiting for your scale to answer, you read the value of result a way lot faster then it get filled with data.
A good way to communicate using SerialPort is with ReadLine and WriteLine, check out that NewLine was set correctly according to you device programming manual (which would be nice to add to the question if you are asking question about specific device).
Some general troubleshooting of RS232 communications:
Check baud rate and all other serial port configuration
Check what is the EOL (End of Line) character, and use it to terminate writing statements and to know how to stop reading input messages (or use ReadLine and WriteLine)
Check the communication manually using TeraTerm or some other serial terminal
so I have an C# WinForm that use
SerialPort SerialPort1 = new SerialPort("COM1", 9600, Parity.None, 8, StopBits.One);
SerialPort1.Open()
SerialPort1.DataReceived += new SerialDataReceivedEventHandler(...)
to listen on several Virtual COM Ports that Created by other Software(I can't control it)
So generally it goes well except When the other Software is dead or gone, the Virtual COM port it created is also gone or missing
So my WinForm App fail because there is no COM1 to listen to
Question: How should I handle this error when there is no COM port to listen
Thank you so much for your reply
Put it in a try - catch statement and print a message to the user if something bad happened.
try
{
SerialPort SerialPort1 = new SerialPort("COM1", 9600, Parity.None, 8, StopBits.One);
SerialPort1.Open()
SerialPort1.DataReceived += new SerialDataReceivedEventHandler(...)
}
catch(Exception e)
{
//Print error to user
}
For finer granularity on the exception, see the msdn documentation of the serial port here.
Well, no, virtual serial ports are emulated by software. If that software fails then of course there's no functional serial port anymore. Nothing you can do about that other than finding better software.
If this is the common failure mode, jerking out the connector of a USB device while a program is talking to it then just don't bother. Whomever does that needs to be learned the Hard Way that using the Windows "Safely Remove Hardware" tray icon option is not optional. It tends to take a bit of reinforcement to get them to realize what "Unsafely Remove Hardware" does. Albeit, oddly, that it tends to be programmers that do this, rarely regular users. Could be site bias and regular users just tend to figure out by themselves that doing this isn't a good idea. It isn't, these drivers count on humans being cooperative. Necessary since serial ports are not plug & play devices, there's no way for the driver to deliver a "device is gone, stop using" notification. Well, other than hard-crashing your program intentionally.
If the only problem is that the number of the port is unpredictable you could detect all the available ports as shown below and the try them one at a time. I once had this problem when a usb device sometimes showed up as COM1 and other times as COM5
string[] availablePorts = SerialPort.GetPortNames();
foreach (string strPortName in availablePorts)
{
try
{
SerialPort SerialPort1 = new SerialPort(strPortName, 9600, Parity.None, 8, StopBits.One);
SerialPort1.Open();
}
catch (Exception e)
{
//Print error to user
}
}
I have a WPF/C# app that is launched as part of the "Startup" group on a Windows Embedded Standard machine. One of the first things the app does (in its static App() method) is create a new SerialPort object for COM1. COM1 is a hardwired serial port, not a USB virtual port or anything like that.
My problem is that every so often (maybe 1 out of 12) on startup, I get an exception:
System.UnauthorizedAccessException: Access to the port 'COM1' is denied.
There are no other applications using this port. Also, when I relaunch the app following this error, it grabs the port just fine. It's as if the com port isn't ready/set up for my app sometimes.
I'm clueless on this one! Any insight is appreciated!
UPDATE: I added a call to SerialPort.GetPortNames() and printout all available ports before attempting to open the port. In the failure case COM1 is indeed THERE! So, it's not that the port isn't ready. It looks like something in Windows is actually grabbing the port temporarily and blocking me.
A few responders at Microsoft seem to think that the kernel grabs COM1 temporarily at startup for debug reasons. They say the best approach is to essentially work around the issue... catch the exception and try again. Boooo.
I modified my code to retry opening the port a few times before giving up, which seems to work around this issue.
Old code:
_port = new SerialPort(port, 9600, Parity.None, 8, StopBits.One);
_port.Open(); // This can throw an exception
New code:
const int PORT_OPEN_MAX_ATTEMPTS = 10;
bool portOpened = false;
int portOpenAttempts = 0;
_port = new SerialPort(port, 9600, Parity.None, 8, StopBits.One);
while (!portOpened)
{
try
{
_port.Open();
portOpened = true; // Only get here if no exception
}
catch (UnauthorizedAccessException ex)
{
// Log, close, then try again
if (portOpenAttempts++ < PORT_OPEN_MAX_ATTEMPTS)
{
_logger.Debug("Port UnauthorizedAccessException. Attempt - " + portOpenAttempts);
Thread.Sleep(100);
_port.Close();
}
else
{
throw(ex);
}
}
}
The objectve is to find which Serial port is phyisically connected to other machine. I want to Search my system to find the available serial ports and send a test message using all the ports and wait for the response. And get the port numbers of Which ever ports get a response is connected to the other machine. How to do?? Thanks.
The SerialPort.GetPortNames() method returns an array of the COM port names of all available serial ports. You could iterate it and try to Open() them. Expect failure, the port might already be opened by another program.
You don't want to send something to a device that doesn't expect it. Using the DsrHolding property is a reasonable test to see if a device is attached that's powered up.
Your ultimate nemesis is going to be the Baudrate property. You cannot guess the proper value. Serial ports are way too primitive to support plug-and-play style device discovery. Avoid using something that cannot work reliably, allow you user to configure your program with the settings you need. It is the normal practice.
Use System.IO.Ports.
public static void OnSerialDataReceived(object sender,
SerialDataReceivedEventArgs args)
{
string data = ComPort.ReadExisting();
Console.Write(data.Replace("\r", "\n"));
}
private static void InitializeComPort(string port, int baud)
{
ComPort = new SerialPort(port, baud);
// ComPort.PortName = port;
// ComPort.BaudRate = baud;
ComPort.Parity = Parity.None;
ComPort.StopBits = StopBits.One;
ComPort.DataBits = 8;
ComPort.Handshake = Handshake.None;
ComPort.DataReceived += OnSerialDataReceived;
ComPort.Open();
}
more on Mark Michaelis' blog
SerialPort.GetPortNames() method is static methods for SerialPort .Do you sure communication between them have flow control?