Using SerialPort to discard RF Device Buffer - c#

I'm writting a small application that automatically connects to the correct serial port by sending a list of commands, and then waiting for a response back from the serial device (RF Transmitter). The serial port objects sends certain commands in decimal format, a reset, login and then a query command.
When the query command is sent, the device then replies back with a response - when this response is received I know I have the correct serial port connection.
All of this works fine, but sometimes I receive an error back from the device - Error 130: TX Queue Overflow. This error can be resolved by simply restarted the device (RF Transmitter), but the frequency of this error is just silly.
Am I correct in thinking that a TX Overflow error would be caused when the buffer on the hardware becomes full? I thought a simple DiscardInBuffer just after opening a connection to the device would fix this - but it doesn't.
When should I use the DiscardInBuffer, am I using it in the correct context?
-- Edit
After some more comments and thoughts, I've come to the conclusion that the SerialPort.DiscardInBuffer won't do anything for my current situation, rather I need to discard the buffer on the actual RF Device - Hence why inplugging it works.

You've sent too much data to the device, and its output queue has overflowed, meaning it is not able to forward the data as fast as you're providing it.
There's no method you can call on the SerialPort class to fix this, these are two completely different buffers we're talking about. Calling SerialPort.DiscardOutBuffer will only discard the output data pending for your serial port, not the device.
To temporarily fix the issue, the manual indicates that you can:
Use the command “reset txqueue” to clear the queue.
The better solution, however, is to prevent the issue and not flood the device with data. The exact way to do this will depend on your hardware.
One way might be to introduce some sort of CommandQueue class which has an associated SerialPort object to push the commands to the hardware. In this class, you could queue up commands to be sent, and send them out a configurable maximum rate. You would use a timer, and only send commands out if one hasn't been sent in the last X msec.
Another way would be to implement some sort of software flow control. It appears that your device supports querying the queue length with the "?STATE" command (page 13). It will respond with:
STATE x1/x2 x3 x4
x1: Number of datapackets in TX queue
x2: Size of TX queue
x3: Status byte (8 bit hexadecimal)
Normal state: status byte = 0
Bit 0 = 1: Error in transceiver
Bit 1 = 1: Error in EEPROM
x4: Current value of the dataset counter (number of last received and saved datapacket)
You could query this before attempting to send a data packet, and simply sleep while the queue is full.
Having written a lot of code to interface with finicky hardware (Serial, Ethernet, etc.) in C#, I can offer the following advice:
Implement an abstract class TN9000DeviceBase which has abstract methods for all of the commands supported by the device.
Derive a class TN9000SerialDevice : TN9000DeviceBase which executes the command using serial port.
This will allow you to come back and implement it via Ethernet when requirements change.

Related

Does RtsEnable or DtrEnable properties send a signal?

I want to know if I put these in my code, does computer send any kind of signal to the device?
SerialPort myport = new SerialPort("COM1");
myport.DtrEnable = true;
myport.RtsEnable = true;
I'm required to send a signal on specific pins to the device. As I know Dtr and Rts use pins 4 and 7. So when I write the code above, will my computer send a signal on pins 4 and 7? Or is there a simple way to send a signal on a specific pin?
Sure, these properties control the state of the handshake signals. Their use is not arbitrary, a properly designed serial port device pays attention to them. DTR is Data Terminal Ready, normally connected to DSR (Data Set Ready) on the device. The device assumes that your computer is simply not turned on or the cable is disconnected when DSR is off. It won't send anything and ignores anything you send to it when the signal is off.
RTS is Request To Send, normally connected to CTS (Clear To Send) on the device. Normally used for flow control, it prevents the device from sending too much data and overflow the receive buffer. A nasty problem that is very hard to recover from, the data is entirely lost.
You should normally set the SerialPort.Handshake property to HandShake.RequestToSend so the driver does this automatically. A very common bug is to leave it set to Handshake.None, now you have to turn on these signals yourself. And you'll risk buffer overflow of course, albeit that you'd have to write very slow code to ever get in the danger zone. It has been done.
These signals can be used in hobby projects to control, say, a reed relay. Do beware that the voltages on the signal lines are unpredictable (swings between +/- 5 to 24 Volts) and can't supply a lot of amps (usually 20 milliamps max). You need at least a diode, typically a transistor to switch a heavier load. Ask about it at electronics.stackexchange.com
In theory: Yes. Whatever you have connected to your serial port will see something. It won't be data, but if it is checking its pin states, it will know that you have done something.
In practice: Maybe. Being able to accurately detect these pin states is heavily dependent on the cable being used. Here is a recent post that goes over the cable related issues with these pin states.

confused when receiving data from serial port

I encountered a problem that took me too much time, but without resolving it.soI really want you to help me.
I have an application built with c # wpf, and communicates with ovens via serial port.
the frame I need to send have following form: [EOT] (GID) (UID) (Temp) [ENQ]
gid uid: group identifier and unit identifier (address of the machine).
(eof),(enq) :frames the message.
(temp) means: give me the temperature value.
the only machine that has the same address can answer (master slave architecture).
the form of the response message is: [STX] (Temp) <DATA> [ETX].
the field contain only the temperature value
stx start text. etx end text.
I have no problem with sending and receiving of data, and I can display the value of temperature for a single machine connected.
but when I connect More machines, I do not know which machine has answered the frame that I sent, because the response frame does not have any adress so that I can determine which oven have respond.
So the situation in brief is:
-I send Data to ovens.
- I received data.
- I can not decide which oven answered.
please any one have an idea.
PS: I work with the protocol:EI-BISYNCH of eurotherm EuroTherm
If needed: EI-Bisynch ASCII Sequence Diagrams
In these conditions, the typical solution is:
Send the request to the current device
Wait for an answer for a defined timeout
If we receive an an answer within the timeout, the device responded.
If we do not receive an answer, the device is offline, mark it as such.
Switch to the next device, goto 1
Basically you should be able to wrap into a loop the code described here:
Providing Asynchronous Serial Port Communication
That is a sample that works with an AutoResetEvent. One of the .Net multithreading that allows synchronizing threads (the threads that sends the request in the loop, and the threads that receive the message in the loop)
IN these situations, the machine that you addressed is responding (or at least its assumed to be) Single Master - Multi Slaves. Meaning :-
Master -> Hey #1 tell me your temp -> #1 SIR! YES SIR! 23 degrees!
Master -> Hey #2...
The idea is no other slave will respond. By convention of the protocol.
Its pretty hard to do anything but this kind of system on serial.
In terms of Design if you create something like a command queue. Each command knows what device it wants to talk to, and what question it wants to ask. You process each command, send the serial message, get the response, and give it back to the command. Now you have a command, which knows which device it talked to, and what the response of that device was.
As long as you only have one "in-flight" command to which you are waiting for a response, and you know which device you sent the command to, you can assume that the device that responds next is the device you asked to respond. Now this won't necessarily always be true if it is possible for your device to send un-prompted responses.

Using TCP Sockets (C#), How do I detect if a message got interrupted in transit, on the receiver's end?

Im writing a server application for my iPhone app. The section of the server im working on is the relay server. This essentially relays messages between iPhones, through a server, using TCP sockets. The server reads the length of the header from the stream, then reads that number of bytes from the stream. It deserializes the header, and checks to see if the message is to be relayed on to another iPhone (rather than being processed on the server).
If it has to be relayed, it begins reading bytes from the sender's socket, 1024 bytes at a time. After each 1024 bytes are received, it adds those bytes (as a "packet" of bytes) to the outgoing message queue, which is processed in order.
This is all fine, however, but what happens if the sender gets interrupted, so it hasn't sent all its bytes (say, out of the 3,000 bytes it had to send, the sending iPhone goes into a tunnel after 2,500 bytes)?
This means that all the other devices are waiting on the remaining 500 bytes, which dont get relayed to them. Then if the sender (or anyone else for that matter) sends data to these sockets, they think the start of the new message is the end of the last one, corrupting the data.
Obviously from the description above, im using message framing, but I think im missing something. From what I can see, message framing only seems to allow the receiver to know the exact amount of bytes to read from the socket, before assembling them into an object. Wont things start to get hairy once a byte or two goes astray at some point, throwing everything out of sync? Is there a standard way of getting back in sync again?
Wont things start to get hairy once a byte or two goes astray at some point, throwing everything out of sync? Is there a standard way of getting back in sync again?
TCP/IP itself ensures that no bytes go "missing" over a single socket connection.
Things are a bit more complex in your situation, where (if I understand correctly) you're using a server as a sort of multiplexer.
In this case, here's some options off the top of my head:
Have the server buffer the entire message from point A before sending it to point B.
Close the B-side sockets if an abnormal close is detected from the A side.
Change the receiving side of the protocol so that a B-side client can detect and recover from a partial A-stream without killing and re-establishing the socket. e.g., if the server gave a unique id to each incoming A-stream, then the B client would be able to detect if a different stream starts. Or have an additional length prefix, so the B client knows both the entire length to expect and the length for that individual message.
Which option you choose depends on what kind of data you're transferring and how easy the different parts are to change.
Regardless of the solution, be sure to include detection of half-open connections.

How to safely stream data through a server socket to another socket?

I'm writing a server application for an iPhone application im designing. iPhone app is written in C# (MonoTouch) and the server is written in C# too (.NET 4.0)
I'm using asynchronous sockets for the network layer. The server allows two or more iPhones ("devices") to connect to each other and be able to send data bi-directionally.
Depending on the incoming message, the server either processes the message itself , or relays the data through to the other device(s) in the same group as the sending device. It can make this decision by decoding the header of the packet first, and deciding what type of packet it is.
This is done by framing the stream in a way that the first 8 bytes are two integers, the length of the header and the length of the payload (which can be much larger than the header).
The server reads (asynchronously) from the socket the first 8 bytes so it has the lengths of the two sections. It then reads again, up to the total length of the header section.
It then deserializes the header, and based on the information within, can see if the remaining data (payload) should be forwarded onto another device, or is something that the server itself needs to work with.
If it needs to be forwarded onto another device, then the next step is to read data coming into the socket in chunks of say, 1024 bytes, and write these directly using an async send via another socket that is connected to the recipient device.
This reduces the memory requirements of the server, as i'm not loading in the entire packet into a buffer, then re-sending it down the wire to the recipient.
However, because of the nature of async sockets, I am not guaranteed to receive the entire payload in one read, so have to keep reading until I receive all the bytes. In the case of relaying onto its final destination, this means that i'm calling BeginSend() for each chunk of bytes I receive from the sender, and forwarding that chunk onto the recipient, one chunk at a time.
The issue with this is that because I am using async sockets, this leaves the possibility of another thread doing a similar operation with the same recipient (and therefore same final destination socket), and so it is likely that the chunks coming from both threads will get mixed up and corrupt all the data going to that recipient.
For example: If the first thread sends a chunk, and is waiting for the next chunk from the sender (so it can relay it onwards), the second thread could send one of its chunks of data, and corrupt the first thread's (and the second thread's for that matter) data.
As I write this, i'm just wondering is it as simple as just locking the socket object?! Would this be the correct option, or could this cause other issues (e.g.: issues with receiving data through the locked socket that's being sent BACK from the remote device?)
Thanks in advance!
I was facing a similar scenario a while back, I don't have the complete solution anymore, but here's pretty much what I did :
I didn't use sync sockets, decided to explore the async sockets in C# - fun ride
I don't allow multiple threads to share a single resource unless I really have to
My "packets" were containing information about size, index and total packet count for a message
My packet's 1st byte was unique to signify that it's a start of a message, I used 0xAA
My packets's last 2 bytes were a result of a CRC-CCITT checksum (ushort)
The objects that did the receiving bit contained a buffer with all received bytes. From that buffer I was extracting "complete" messages once the size was ok, and the checksum matched
The only "locking" I needed to do was in the temp buffer so I could safely analyze it's contents between write/read operations
Hope that helps a bit
Not sure where the problem is. Since you mentioned servers, I assume TCP, yes?
A phone needs to communicate some of your PDU to another phone. It connects as a client to the server on the other phone. A socket-pair is established. It sends the data off to the server socket. The socket-pair is unique - no other streams that might be happening between the two phones should interrupt this, (will slow it up, of course).
I don't see how async/sync sockets, assuming implemented correctly, should affect this, either should work OK.
Is there something I cannot see here?
BTW, Maciek's plan to bolster up the protocol by adding an 'AA' start byte is an excellent idea - protocols depending on sending just a length as the first element always seem to screw up eventually and result in a node trying to dequeue more bytes that there are atoms in the universe.
Rgds,
Martin
OK, now I understand the problem, (I completely misunderstood the topology of the OP network - I thought each phone was running a TCP server as well as client/s, but there is just one server on PC/whatever a-la-chatrooms). I don't see why you could not lock the socket class with a mutex, so serializing the messages. You could queue the messages to the socket, but this has the memory implications that you are trying to avoid.
You could dedicate a connection to supplying only instructions to the phone, eg 'open another socket connection to me and return this GUID - a message will then be streamed on the socket'. This uses up a socket-pair just for control and halves the capacity of your server :(
Are you stuck with the protocol you have described, or can you break your messages up into chunks with some ID in each chunk? You could then multiplex the messages onto one socket pair.
Another alternative, that again would require chunking the messages, is introduce a 'control message', (maybee a chunk with 55 at start instead of AA), that contains a message ID, (GUID?), that the phone uses to establish a second socket connection to the server, passes up the ID and is then sent the second message on the new socket connection.
Another, (getting bored yet?), way of persuading the phone to recognise that a new message might be waiting would be to close the server socket that the phone is receiving a message over. The phone could then connect up again, tell the server that it only got xxxx bytes of message ID yyyy. The server could then reply with an instruction to open another socket for new message zzzz and then resume sending message yyyy. This might require some buffering on the server to ensure no data gets lost during the 'break'. You might want to implement this kind of 'restart streaming after break' functionality anyway since phones tend to go under bridges/tunnels just as the last KB of a 360MB video file is being streamed :( I know that TCP should take care of dropped packets, but if the phone wireless layer decides to close the socket for whatever reason...
None of these solutions is particularly satisfying. Interested to see whay other ideas crop up..
Rgds,
Martin
Thanks for the help everyone, i've realised the simpliest approach is to use synchronous send commands on the client, or at least a send command that must complete before the next item is sent. Im handling this with my own send queue on the client, rather than various parts of the app just calling send() when they need to send something.

NetworkStream.Write returns immediately - how can I tell when it has finished sending data?

Despite the documentation, NetworkStream.Write does not appear to wait until the data has been sent. Instead, it waits until the data has been copied to a buffer and then returns. That buffer is transmitted in the background.
This is the code I have at the moment. Whether I use ns.Write or ns.BeginWrite doesn't matter - both return immediately. The EndWrite also returns immediately (which makes sense since it is writing to the send buffer, not writing to the network).
bool done;
void SendData(TcpClient tcp, byte[] data)
{
NetworkStream ns = tcp.GetStream();
done = false;
ns.BeginWrite(bytWriteBuffer, 0, data.Length, myWriteCallBack, ns);
while (done == false) Thread.Sleep(10);
}
 
public void myWriteCallBack(IAsyncResult ar)
{
NetworkStream ns = (NetworkStream)ar.AsyncState;
ns.EndWrite(ar);
done = true;
}
How can I tell when the data has actually been sent to the client?
I want to wait for 10 seconds(for example) for a response from the server after sending my data otherwise I'll assume something was wrong. If it takes 15 seconds to send my data, then it will always timeout since I can only start counting from when NetworkStream.Write returns - which is before the data has been sent. I want to start counting 10 seconds from when the data has left my network card.
The amount of data and the time to send it could vary - it could take 1 second to send it, it could take 10 seconds to send it, it could take a minute to send it. The server does send an response when it has received the data (it's a smtp server), but I don't want to wait forever if my data was malformed and the response will never come, which is why I need to know if I'm waiting for the data to be sent, or if I'm waiting for the server to respond.
I might want to show the status to the user - I'd like to show "sending data to server", and "waiting for response from server" - how could I do that?
I'm not a C# programmer, but the way you've asked this question is slightly misleading. The only way to know when your data has been "received", for any useful definition of "received", is to have a specific acknowledgment message in your protocol which indicates the data has been fully processed.
The data does not "leave" your network card, exactly. The best way to think of your program's relationship to the network is:
your program -> lots of confusing stuff -> the peer program
A list of things that might be in the "lots of confusing stuff":
the CLR
the operating system kernel
a virtualized network interface
a switch
a software firewall
a hardware firewall
a router performing network address translation
a router on the peer's end performing network address translation
So, if you are on a virtual machine, which is hosted under a different operating system, that has a software firewall which is controlling the virtual machine's network behavior - when has the data "really" left your network card? Even in the best case scenario, many of these components may drop a packet, which your network card will need to re-transmit. Has it "left" your network card when the first (unsuccessful) attempt has been made? Most networking APIs would say no, it hasn't been "sent" until the other end has sent a TCP acknowledgement.
That said, the documentation for NetworkStream.Write seems to indicate that it will not return until it has at least initiated the 'send' operation:
The Write method blocks until the requested number of bytes is sent or a SocketException is thrown.
Of course, "is sent" is somewhat vague for the reasons I gave above. There's also the possibility that the data will be "really" sent by your program and received by the peer program, but the peer will crash or otherwise not actually process the data. So you should do a Write followed by a Read of a message that will only be emitted by your peer when it has actually processed the message.
TCP is a "reliable" protocol, which means the data will be received at the other end if there are no socket errors. I have seen numerous efforts at second-guessing TCP with a higher level application confirmation, but IMHO this is usually a waste of time and bandwidth.
Typically the problem you describe is handled through normal client/server design, which in its simplest form goes like this...
The client sends a request to the server and does a blocking read on the socket waiting for some kind of response. If there is a problem with the TCP connection then that read will abort. The client should also use a timeout to detect any non-network related issue with the server. If the request fails or times out then the client can retry, report an error, etc.
Once the server has processed the request and sent the response it usually no longer cares what happens - even if the socket goes away during the transaction - because it is up to the client to initiate any further interaction. Personally, I find it very comforting to be the server. :-)
In general, I would recommend sending an acknowledgment from the client anyway. That way you can be 100% sure the data was received, and received correctly.
If I had to guess, the NetworkStream considers the data to have been sent once it hands the buffer off to the Windows Socket. So, I'm not sure there's a way to accomplish what you want via TcpClient.
I can not think of a scenario where NetworkStream.Write wouldn't send the data to the server as soon as possible. Barring massive network congestion or disconnection, it should end up on the other end within a reasonable time. Is it possible that you have a protocol issue? For instance, with HTTP the request headers must end with a blank line, and the server will not send any response until one occurs -- does the protocol in use have a similar end-of-message characteristic?
Here's some cleaner code than your original version, removing the delegate, field, and Thread.Sleep. It preforms the exact same way functionally.
void SendData(TcpClient tcp, byte[] data) {
NetworkStream ns = tcp.GetStream();
// BUG?: should bytWriteBuffer == data?
IAsyncResult r = ns.BeginWrite(bytWriteBuffer, 0, data.Length, null, null);
r.AsyncWaitHandle.WaitOne();
ns.EndWrite(r);
}
Looks like the question was modified while I wrote the above. The .WaitOne() may help your timeout issue. It can be passed a timeout parameter. This is a lazy wait -- the thread will not be scheduled again until the result is finished, or the timeout expires.
I try to understand the intent of .NET NetworkStream designers, and they must design it this way. After Write, the data to send are no longer handled by .NET. Therefore, it is reasonable that Write returns immediately (and the data will be sent out from NIC some time soon).
So in your application design, you should follow this pattern other than trying to make it working your way. For example, use a longer time out before received any data from the NetworkStream can compensate the time consumed before your command leaving the NIC.
In all, it is bad practice to hard code a timeout value inside source files. If the timeout value is configurable at runtime, everything should work fine.
How about using the Flush() method.
ns.Flush()
That should ensure the data is written before continuing.
Bellow .net is windows sockets which use TCP.
TCP uses ACK packets to notify the sender the data has been transferred successfully.
So the sender machine knows when data has been transferred but there is no way (that I am aware of) to get that information in .net.
edit:
Just an idea, never tried:
Write() blocks only if sockets buffer is full. So if we lower that buffers size (SendBufferSize) to a very low value (8? 1? 0?) we may get what we want :)
Perhaps try setting
tcp.NoDelay = true

Categories

Resources