Serial communication Zebra GC420t - Not receiving - c#

I'm trying to communicate with the GC420t via serial port in c#.
I need to get the status of the printer.
I want to send the command ~HQES and receive the status.
I'm able to write commands: I've tryied to print succesfully some qrcodes.
But when I write the status info command I don't get any answer.
This is my test code:
//define serial port
static SerialPort _serialPort = new SerialPort("COM7", 9600, Parity.None, 8, StopBits.One);
public Serial()
{
try
{
_serialPort.Open();
WriteCommand();
ReadStatus();
}
catch (Exception ex)
{
_serialPort.Close();
}
}
public void WriteCommand()
{
string qrcode = "^XA^FO,20,20^BQ,2,10^FDD03048F,LM,N0123456789,A12AABB,B0006qrcode^FS^XZ";
string statusInfo = " ~HQES";
_serialPort.Write(statusInfo);
}
public void ReadStatus()
{
_serialPort.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);
}
private static void DataReceivedHandler(
object sender,
SerialDataReceivedEventArgs e)
{
SerialPort sp = (SerialPort)sender;
string indata = sp.ReadExisting();
Console.WriteLine("Data Received:");
Console.Write(indata);
}
EDIT:
It will be fine for me also to be able to get that info on request:
WriteCommand();
int timeout = 3000;
while (timeout > 0)
{
Thread.Sleep(10);
timeout--;
// Timeout
string status = _serialPort.ReadExisting();
}

You should check ifs the printer configured to use any form of handshaking? Particularly XON/XOFF or DTR .
Ref page 24 of User Guide. https://www.uline.com/PDF/IH-7246VND.PDF
In the event the link breaks - the relevant text is
"The printer has a DCE serial communication port for hardware compatibility with legacy 888 printers. The required cable must have a nine-pin "D" type (DB-9P) male connector on one end which plugs into the mating (DB-9S) serial port located on the back of the printer. The other end of this signal interface cable connects to a serial port on the host computer. The cable is a Null-Modem (cross-over signal connections) cable. For pinout information, refer to Appendix A.
The serial port communication settings between the printer and host (typically a PC) must match for reliable communication. The Bits per second (or Baud rate) and Flow control are the most common settings that get changed. The host (typically a Windows PC) needs to have the data Flow control changed to match the printer's default communication method: Hardware and is noted by the Host Handshake setting DTR/Xon/Xoff. This combined hardware (DTR) and software (Xon/Xoff) mode may need to change depending{ upon use with non-Zebra application software or the serial cable variation in use."

You need to hook up the DataReceived handler before you make any calls, otherwise it might have answered before you hook it up.
Move ReadStatus up 1 line so that it comes straight after the constructor.
_serialPort.Open();
ReadStatus();
WriteCommand();

Related

C# Reading data from a SerialPort COM port through USB

So I'm trying to read data from a COM port that is connected to my laptop through USB. I know that the connection is successful and that the port is opened when calling on the Connect() method, however when I send a command to the port, it sends to the port, but once ReadLine() is called, it just hangs out in the terminal doing nothing. I've done some research on this issue and I see that many people have issues with SerialPort, but I can't seem to solve my own instance of the problem.
An example of a command I might send to the machine I'm working with is something as simple as "son" where I send the string to the port and the shaker device should simply turn on and start shaking. So I should send this command to the port and receive something back like "ok" to show that it is running correctly, but right now nothing happens once the code reaches the ReadLine().
Can someone please help me walk through where I might be going wrong in trying to read data from this port? Any help would be much appreciated.
private void SerialPortDataReceived(object sender, SerialDataReceivedEventArgs e)
{
string data = Port.ReadExisting();
}
public void Connect()
{
//MessageBox.Show(Port.IsOpen.ToString());
Port = new SerialPort(Comport, 9600, Parity.None, 8, StopBits.One);
Port.DtrEnable = true;
Port.DataReceived += SerialPortDataReceived;
Port.Open();
MessageBox.Show(Port.IsOpen.ToString());
Port.NewLine = Environment.NewLine;
}
public string SendCommand(string command)
{
Port.Write(command + "\r");
string result = Port.ReadLine().Trim();
if (result == "e")
{
string errorList = GetErrorList();
throw new InvalidOperationException("BioShake error: " + errorList);
}
return result;
}

SteamSocket TCP to check for device connectivity

I am using 'StreamSocket' 'Tcp' connection to communicate between my host and client devices on Windows IoT Core. Currently I am using polling every second to check for connectivity status of client devices. I would like to know if there is any better and efficient way of doing it. Thanks.
As I know there is no better way to do that. There are two ways of detect StreamSocket disconnect:
send heartbeat message to monitor if the other side(server) is closed.
read 0-length means end of the stream.
In addition, you can detect the network connection via NetworkInformation.NetworkStatusChanged.By this, the app is able to know if the network is invalid, as the main reason causes the StreamSocket disconnected. More information please see Reacting to network status changes.
If you change the host as server, all of your device as a client which connected to your host, you can start listening a tcp port via StreamSocketListener. The event ConnectionReceived could detect the connection incoming and status changed.
StreamSocketListener listener = new StreamSocketListener();
listener.ConnectionReceived += OnConnection;
private async void OnConnection(
StreamSocketListener sender,
StreamSocketListenerConnectionReceivedEventArgs args)
{
DataReader reader = new DataReader(args.Socket.InputStream);
try
{
while (true)
{
// Read first 4 bytes (length of the subsequent string).
uint sizeFieldCount = await reader.LoadAsync(sizeof(uint));
if (sizeFieldCount != sizeof(uint))
{
// The underlying socket was closed before we were able to read the whole data.
//Detect disconnection
return;
}
// Read the string.
uint stringLength = reader.ReadUInt32();
uint actualStringLength = await reader.LoadAsync(stringLength);
if (stringLength != actualStringLength)
{
// The underlying socket was closed before we were able to read the whole data.
//Detect disconnection
return;
}
//TO DO SOMETHING
}
}
catch (Exception exception)
{
//TO DO SOMETHING
}
}

Is it possible to receive COM port event when the COM port is closed?

I'm on my laptop and unable to check this right now, I'm wondering if I open a COM2 connection, and add a receive event for COM2 port, then close the COM2 connection via "serial.Close()" in the program, will I still be able to receive a receive event on COM2 port? Let say if it can still receive, I think I will open the COM2 port connection at the receive event and read the data, can it be done this way?
SerialPort serial = new SerialPort()
{
PortName = "com2",
BaudRate = 9600,
Handshake = System.IO.Ports.Handshake.None,
Parity = Parity.None,
DataBits = 8,
StopBits = StopBits.One,
ReadTimeout = 400,
WriteTimeout = 200,
};
serial.DataReceived += new System.IO.Ports.SerialDataReceivedEventHandler(Receive);
private void Receive(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
using (SerialPort serialPort = serial)
{
if (serialPort.IsOpen)
serialPort.Close();
try
{
serialPort.Open();
received_data = serialPort.ReadExisting();
Dispatcher.Invoke(DispatcherPriority.Send, new UpdateUiTextDelegate(WriteMyData), received_data);
}
catch (Exception ex)
{
}
finally
{
if (serialPort != null)
{
if (serialPort.IsOpen)
{
serialPort.Close();
}
Thread.Sleep(5);
//serialPort.Dispose();
}
Thread.Sleep(5);
}
}
}
public void SerialCmdSendByte(byte[] hexstring)
{
using (SerialPort serialPort = serial)
{
if (serialPort.IsOpen)
serialPort.Close();
try
{
serialPort.Open();
foreach (byte hexval in hexstring)
{
byte[] _hexval = new byte[] { hexval };
serialPort.Write(_hexval, 0, 1);
Thread.Sleep(3);
}
}
catch (IOException ex)
{
}
finally
{
if (serialPort != null)
{
if (serialPort.IsOpen)
{
serialPort.Close();
}
Thread.Sleep(5);
//serialPort.Dispose();
}
Thread.Sleep(5);
}
}
}
The idea is to only open a connection when I want to send from C# program and close it straight-away, but the same COM port is actually need to listen for communication from PIC-based microcontroller. Currently we are having issue where previously the program never try to close connection (unlike above code), but sometimes the receiving part from PIC-based microcontroller works but the sending part from program doesnt work. This only happens sometime, as normally the program work just fine...
Restarting the system seem to reset this OK. So I was thinking making the code like above will help in my situation(to be able to send, and listen on same COM port)?
Unfortunately, no. Only 1 connection to the COM port can be open at a time.
If you have a device listening on that port, then nothing else will be able to send on it.
If you have access to the code that the microcontroller uses to listen on the device, you could always write something that allows you to send a message to the microcontroller and have that device send your COM message.
Otherwise, the only thing you could do is have the microcontroller stop listening on the port, send your message from your code, receive any response that comes back from sending your message, and then reenable the microcontroller's listen features.
EDIT:
Just a note about your code. The using statement is designed to dispose of an object after closing all of its connections when it goes out of scope.
In your code, you are creating a reference to your serial port instance in a using block. If this works as defined, that serial port instance will need to be instantiated before you can call it again.
As a complement to jp2code answer and since imagination is the limit, you might want to try a more "out of the box" solution, something similar to Man-In-The-Middle.
THIS POST might give you a better idea about what I'm talking about.
You cannot communicate or listen on serial port when the port is closed.
So the code you have written is absolutely wrong.
Ideally you should not turn off the COM port.
Following can be the reasons why your communication fails.
1.This one seems to be the most probable answer: If the COM port is not closed properly in the previous run, the communication will not take place. In this case you have to reset the system. This takes place when the system gets crashed in between.
When the connectors are not tight, this can occur.
Check if the ground connections are proper.
Let me know if you need help in changing the code.

How can I discover if a device is connected to a specific serial (COM) port?

How can I discover, using C#'s SerialPort class, whether a device is connected to a specific serial (COM) port?
Note: that class's Open method opens the port even if there is no device connected to the port.
1.WMI: SELECT * FROM Win32_SerialPort:
ManagementObjectSearcher manObjSearch = new ManagementObjectSearcher("Select * from Win32_SerialPort");
ManagementObjectCollection manObjReturn = manObjSearch.Get();
foreach (ManagementObject manObj in manObjReturn)
{
//int s = manObj.Properties.Count;
//foreach (PropertyData d in manObj.Properties)
//{
// Console.WriteLine(d.Name);
//}
Console.WriteLine(manObj["DeviceID"].ToString());
Console.WriteLine(manObj["Name"].ToString());
Console.WriteLine(manObj["Caption"].ToString());
}
2. If device send response back: System.IO.Ports.SerialPort.GetPortNames()
and sending basic command:
foreach (string portname in SerialPort.GetPortNames())
{
var sp = new SerialPort(portname, 4800, Parity.Odd, 8, StopBits.One);
try
{
sp.Open();
sp.Write("Your known command to device");
Thread.Sleep(500);
string received = sp.ReadLine();
if (received == "expected response")
{
Console.WriteLine("device connected to: " + portname);
break;
}
}
catch (Exception)
{
Console.WriteLine("device NOT connected to: " + portname);
}
finally
{
sp.Close();
}
}
The answer depends on the device and the cable.
In some cases, DSR (SerialPort.DsrHolding) or even CTS (SerialPort.CtsHolding) will be raised when the device is connected.
But in some cases you may only have Tx / Rx connected, and the only way to tell is to attempt to communicate with the device.
You need to look at the documentation for your device and its cable.
There's no general solution that works for any device.
Couple of things you can try
Create Serial port object and open a port, now when a device is
connected, OS should send CDChanged event.
You ping the serial port, and if you receive a response back, assume it is connected.
You can do it by opening serial port and sending most basic command your device support and check the response. For example for GSM modem you open port and sent at command and receive ok in response.

C# - readin from serial port buffer

I am trying to read data from an RS-232 port. Does anyone have an example of how I get the data from the port/buffer and make sure that I have all the data as it can be multiline data.
Do I simply read it as follows ?
string Rxstring = port.ReadLine();
Console.WriteLine(Rxstring);
Q: how to get the date from the port/buffer, or input data from your connected device. AND make sure that you have all the data.
A: i have worked extensively with .net serial port class drivers where i was tasked to create reliable, robust code. this means that a connected device under test has to run and NOT fail over a LONG period of time. Serial port can AND does lose data! don't forget that.
//from top of the head;
using System.Port.IO;
using System.Port;
private class mywindowsForm: Form
{
StringBuilder sbReceived = new StringBuilder();
string Received = string.Empty;
int byteCOUNT = 0;
System.Windows.Timers.Timer serialTimer;
//Default constructor
myWindowsForm()
{
//assume that you clicked and dragged serial port in
serialPort1 = new SerialPort();//create new serial port instance
serialPort1.Baud = 9600;
serialPort1.DataReceived+=<Tab><Enter>
//serial port timer
serialTimer = new System.Windows.Timers.Timer(500);//set to 500ms time delay
serialTimer.Elapsed+=<TAB><ENTER>
}
void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
//serial port has detected input data
//however, we only want to get serial data so,
if(e.EventType !=SerialData.Chars) return;
//good design practice dictates that we have an event handler that we invoke
this.BeginInvoke(new eventhandler(AddReceive));//beginInvoke is designed to deal with asynchronous processes like serial port data.
}
private void AddReceive(object s, EventArg e)
{
byteCOUNT=serialPort1.BytesToRead;//count the number of bytes in RX buffer
if(byteCOUNT > 0)
{
string ST = serialPort1.ReadTo("\n");//lets get one line at a time
sbReceived.Append(ST);//add whatever has been RX'd to our container.
serialPort1.Interval =100;
serialPort1.Start();//to be sure we have all data, check to see for stragglers.
}
}
void serialTimer(object Sender, TimerElapsedEventArgs e)
{
serialTimer.Stop();
this.BeginInvoke(new EventHandler(ReadData));
}
void ReadData(object Sender, EventArgs e)
{
//parse output for required data and output to terminal display (build one using rich text box)
Received = sbReceived.ToString();
//and if we have ANY MORE incoming data left over in serial buffer
if(Received.Length > 0)
{
//your data
}
}
}
this should be plenty to get you started. this is result of years of creating customized terminal emulators in c#. there are other things that can be done, particularly if you have large amount of i/o data you need to set up handshaking with device. you have to let the device handle at a rate that the device is happy with. in cases where larger data has to be transferred consider setting up a simple packet passing protocol and command semaphore construct - or use a protocol as defined that the controller / device is designed to work with.
Try this:
using System.IO.Ports;
...
private SerialPort port = new SerialPort("COM1", 9600, Parity.None, 8, StopBits.One);
Console.WriteLine(port.ReadExisting());
Details can be found at Coad's Code.

Categories

Resources