I have a ring buffer in which I want to place some bytes received over serial port. Now these received bytes consist of a command followed by data bytes. And each of these command and data combination could be off different length. I want to implement a method in which I can copy one command from this buffer and execute it. Then the next command and so on. What would be the best (and simplest) way of doing it?
Simple byte stream will do. Actually, you can even use a wrapper over std::stringstream for your byte stream as a storage as a first step: fill it with the routine that communicates with the serial port and read from it with the instruction decoder.
When you talk about ring buffer it can be something as simple as char[ring_size_in_bytes] and current location indicator int. Reading from port should be byte by byte and when you reach end of the buffer you start from zero.
I usually use simple buffer for command and for data read from port. After copying data from port to small buffer I interpret data on the fly trying to find beginning of command and then start putting to buffer until I detect new beginning. Then I enqueue command and start over. This constitutes top half (fast one) of serice routine.
Serial port is very slow so there is no risk that you will not read data from it fast enough. Each iteration (interrupt) will give you couple of bytes ...
I would use queue of type that encapsulates your commands to store received commands list.
How complicated is your serial protocol ?
Related
I'm doing a project where I should parse incoming sensors data in my C++ application. The sensors data are sent by Arduino via serial communication to Windows. The data contain string like this:
$12.345,12.345,12.345,12.345* (+ newline and carriage return)
The sensors data could be 35-46 bytes. The serial port between these two is established using CreateFile Windows function and configured as synchronous and like this:
Baud rate: 38400
Byte size: 8
Parity: None
Stop bits: 1
I tried to see the incoming data on the Arduino IDE as well as on hterm. The data come properly as they should be. However, my application receives the data "unregular". Like sometimes, the ReadFile function read from the middle of the string + the concatenated next string:
12.345*\n\r$67.890,67.890,67.890,67.890*
Therefore, I would ask if it is possible to set the Windows serial to discard any characters which come into input buffer before the '$' symbol arrived?
Serial port communication is basically character-based communication, not packet-based delimited communication such as TCP/IP.
It is not always possible for the receiving side to read the data written once by the sending side, and it is possible that multiple written data can be received together with one read.
You must understand this, treat all received data as valid data, analyze it, and cut it out for each delimiter unit.
Data that has not reached the delimiter unit must be concatenated with data that will be received later, and data of sufficient length must be received before analysis.
Correct communication will not be possible if fragmented data is discarded.
Please discard only what appears to be noise or invalid data in the analysis results.
The Boost chat server example demonstrates handling a simple TCP message protocol in which each message is preceded by a fixed-size header which tells you the size of the message which follows. This means you always know exactly how many bytes to read in your next call to async_read(); you alternate between reading a header whose size is always the same, and a message whose size is given in the header. This works well with the Boost i/o service model, which promises to call a handler when exactly the expected number of bytes have been received from the socket.
How can I use Boost to run a TCP protocol which doesn't use a header like this? My client has a protocol which uses special byte sequences to represent the start and end of each message, so I won't know how many bytes to read in each call to async_read(); I have to just get bytes from the socket as they arrive and watch for the special byte sequences. If I pick a sensible buffer size like 256 bytes, and if my handler will only be called when that many bytes have been read, I believe the i/o service will generally end up receiving the last few bytes of the most recent message from the network, but not passing them to my handler until the next message comes along and brings the byte total up to the number I'm expecting. The next message may not arrive for some time, and I want to handle the current message as soon as it arrives.
Reading one byte at a time isn't a good idea for performance reasons, correct?
http://www.boost.org/doc/libs/1_45_0/doc/html/boost_asio/examples.html
There is few options:
You can use async_read_until to read until your "ending
sequence"(so until end of message).
If your "ending sequence" depends
on "starting sequence", you can make it to read fixed buffer (equal
to starting sequence length); calculate the ending sequence; and then
setup async_read_until.
Also, you can make call to async_read_some to read any amount of bytes which arrived into socket buffer. Then check your buffer with your own function for containing complete packet or need to read next part.
I cannot find the answer for this one: what will happen if I read from socket 4bytes (I set the limit for 4 bytes) but there are actually 256bytes awaiting to be read? Will they be lost or will they wait until the next call of read function?
If it's a TCP socket, then no data will get lost; it'll get queued up.
Bear in mind that you have to be prepared to deal with partial reads, i.e. where you get fewer bytes than requested and have to call read() again to get more.
It depends what kind of socket you use. If it is stream socket (created with SOCK_STREAM), then it supports a stream of data, and you can read it even by 1 byte (though it will be not efficient), on another side you may request 1024 bytes but get only 1. And that almost irrelevant by what portions sender put them into stream (there is dependency, but you should not rely on that). So with stream you need to define end of data by higher level protocol. You may send strings with \n at the end, or use zero terminated string, or send some bytes of size of coming data before that data.
On another side if you use datagram protocol (created with SOCK_DGRAM) you will get data by packets - whatever size sender sent them. If you provide smaller buffer than data available, it will be truncated and remaining data is discarded.
EDIT!
Just read that read will block until the buffer is full. How on earth to I receive smaller packets with out having to send 1MB (my max buffer length) each time? What If I want to send arbitrarily length messages?
In Java you seem to be able to just send a char array without any worries. But in C++ with the boost sockets I seem to either have to keep calling socket.read(...) until I think I have everything or send my full buffer length of data which seems wasteful.
Old original question for context.
Yet again boost sockets has me completely stumped. I am using
boost::asio::ssl::stream<boost::asio::ip::tcp::socket> socket; I
used the boost SSL example for guidance but I have dedicated a thread
to it rather than having the async calls.
The first socket.read_some(...) of the socket is fine and it reads
all the bytes. After that it reads 1 byte and then all the rest on the
next socket.read_some(...) which had me really confused. I then
noticed that read_some typically has this behaviour. So I moved to
boost::asio::read as socket does have a member function read which
surprised me. However noticed boost::asio has a read function that
takes a socket and buffer. However it is permanently blocking.
//read blocking data method
//now
bytesread = boost::asio::read(socket,buffer(readBuffer, max_length)); << perminatly blocks never seems to read.
//was
//bytesread = socket.read_some(buffer(readBuffer, max_length)); << after the 1st read it will always read one byte and need another
socket.read_some(...) call to read the rest.
What do I need to do make boost::asio::read(...) work?
note .. I have used wireshark to make sure that the server is not
sending the data broken up. The server is not faulty.
Read with read_some() in a loop merging the buffers until you get a complete application message. Assume you can get back anything between 1 byte and full length of your buffer.
Regarding "knowing when you are finished" - that goes into your application level protocol, which could use either delimited messages, fixed length messages, fixed length headers that tell payload length, etc.
I am writing an application on Ubuntu Linux in C++ to read data from a serial port. It is working successfully by my code calling select() and then ioctl(fd,FIONREAD,&bytes_avail) to find out how many bytes are available before finally obtaining the data using read().
My question is this: Every time select returns with data, the number of bytes available is reported as 8. I am guessing that this is a buffer size set somewhere and that select returns notification to the user when this buffer is full.
I am new to Linux as a developer (but not new to C++) and I have tried to research (without success) if it is possible to change the size of this buffer, or indeed if my assumptions are even true. In my application timing is critical and I need to be alerted whenever there is a new byte on the read buffer. Is this possible, without delving into kernel code?
You want to use the serial IOCTL TIOCSSERIAL which allows changing both receive buffer depth and send buffer depth (among other things). The maximums depend on your hardware, but if a 16550A is in play, the max buffer depth is 14.
You can find code that does something similar to what you want to do here
The original link went bad: http://www.groupsrv.com/linux/about57282.html
The new one will have to do until I write another or find a better example.
You can try to play with the VMIN and VTIME values of the c_cc member of the termios struct.
Some info here, especially in the section 3.2.