16 #define CEREAL_EXCEPT(except, msg, ...) \ 19 snprintf(buf, 1000, msg " (in cereal::CerealPort::%s)" , ##__VA_ARGS__, __FUNCTION__); \ 41 fd_ =
::open(port_name, O_RDWR | O_NONBLOCK | O_NOCTTY);
45 const char *extra_msg =
"";
49 extra_msg =
"You probably don't have premission to open the port for reading and writing.";
53 extra_msg =
"The requested port does not exist. Is the hokuyo connected? Was the port name misspelled?";
56 CEREAL_EXCEPT(cereal::Exception,
"Failed to open port: %s. %s (errno = %d). %s", port_name, strerror(errno), errno, extra_msg);
63 fl.l_whence = SEEK_SET;
68 if(fcntl(
fd_, F_SETLK, &fl) != 0)
69 CEREAL_EXCEPT(cereal::Exception,
"Device %s is already locked. Try 'lsof | grep %s' to find other processes that currently have the port open.", port_name, port_name);
72 struct termios newtio;
73 tcgetattr(
fd_, &newtio);
74 memset (&newtio.c_cc, 0, sizeof (newtio.c_cc));
75 newtio.c_cflag = CS8 | CLOCAL | CREAD;
76 newtio.c_iflag = IGNPAR;
79 cfsetspeed(&newtio, baud_rate);
83 tcflush(
fd_, TCIFLUSH);
84 if(tcsetattr(
fd_, TCSANOW, &newtio) < 0)
85 CEREAL_EXCEPT(cereal::Exception,
"Unable to set serial port attributes. The port you specified (%s) may not be a serial port.", port_name);
88 catch(cereal::Exception& e)
106 CEREAL_EXCEPT(cereal::Exception,
"Failed to close port properly -- error = %d: %s\n", errno, strerror(errno));
112 int len = length==-1 ? strlen(data) : length;
115 int origflags = fcntl(
fd_, F_GETFL, 0);
116 fcntl(
fd_, F_SETFL, origflags & ~O_NONBLOCK);
118 fcntl(
fd_, F_SETFL, origflags | O_NONBLOCK);
120 if(retval == len)
return retval;
128 struct pollfd ufd[1];
131 ufd[0].events = POLLIN;
133 if(timeout == 0) timeout = -1;
135 if((retval = poll(ufd, 1, timeout)) < 0)
CEREAL_EXCEPT(cereal::Exception,
"poll failed -- error = %d: %s", errno, strerror(errno));
137 if(retval == 0)
CEREAL_EXCEPT(cereal::TimeoutException,
"timeout reached");
139 if(ufd[0].revents & POLLERR)
CEREAL_EXCEPT(cereal::Exception,
"error on socket, possibly unplugged");
143 if(ret == -1 && errno != EAGAIN && errno != EWOULDBLOCK)
CEREAL_EXCEPT(cereal::Exception,
"read failed");
153 struct pollfd ufd[1];
156 ufd[0].events = POLLIN;
158 if(timeout == 0) timeout = -1;
160 while(current < length)
162 if((retval = poll(ufd, 1, timeout)) < 0)
CEREAL_EXCEPT(cereal::Exception,
"poll failed -- error = %d: %s", errno, strerror(errno));
164 if(retval == 0)
CEREAL_EXCEPT(cereal::TimeoutException,
"timeout reached");
166 if(ufd[0].revents & POLLERR)
CEREAL_EXCEPT(cereal::Exception,
"error on socket, possibly unplugged");
168 ret =
::read(
fd_, &buffer[current], length-current);
170 if(ret == -1 && errno != EAGAIN && errno != EWOULDBLOCK)
CEREAL_EXCEPT(cereal::Exception,
"read failed");
182 struct pollfd ufd[1];
185 ufd[0].events = POLLIN;
187 if(timeout == 0) timeout = -1;
189 while(current < length-1)
192 if(buffer[current-1] ==
'\n')
195 if((retval = poll(ufd, 1, timeout)) < 0)
CEREAL_EXCEPT(cereal::Exception,
"poll failed -- error = %d: %s", errno, strerror(errno));
197 if(retval == 0)
CEREAL_EXCEPT(cereal::TimeoutException,
"timeout reached");
199 if(ufd[0].revents & POLLERR)
CEREAL_EXCEPT(cereal::Exception,
"error on socket, possibly unplugged");
201 ret =
::read(
fd_, &buffer[current], length-current);
203 if(ret == -1 && errno != EAGAIN && errno != EWOULDBLOCK)
CEREAL_EXCEPT(cereal::Exception,
"read failed");
207 CEREAL_EXCEPT(cereal::Exception,
"buffer filled without end of line being found");
214 struct pollfd ufd[1];
217 ufd[0].events = POLLIN;
219 if(timeout == 0) timeout = -1;
222 while(buffer->size() < buffer->max_size()/2)
225 ret = buffer->find_first_of(
'\n');
229 buffer->erase(ret+1, buffer->size()-ret-1);
233 if((retval = poll(ufd, 1, timeout)) < 0)
CEREAL_EXCEPT(cereal::Exception,
"poll failed -- error = %d: %s", errno, strerror(errno));
235 if(retval == 0)
CEREAL_EXCEPT(cereal::TimeoutException,
"timeout reached");
237 if(ufd[0].revents & POLLERR)
CEREAL_EXCEPT(cereal::Exception,
"error on socket, possibly unplugged");
239 char temp_buffer[128];
242 if(ret == -1 && errno != EAGAIN && errno != EWOULDBLOCK)
CEREAL_EXCEPT(cereal::Exception,
"read failed");
245 try{ buffer->append(temp_buffer, ret); }
246 catch(std::length_error& le)
248 CEREAL_EXCEPT(cereal::Exception,
"buffer filled without reaching end of data stream");
251 CEREAL_EXCEPT(cereal::Exception,
"buffer filled without end of line being found");
258 struct pollfd ufd[1];
259 static std::string erased;
262 ufd[0].events = POLLIN;
264 if(timeout == 0) timeout = -1;
268 while(buffer->size() < buffer->max_size()/2)
270 if((retval = poll(ufd, 1, timeout)) < 0)
CEREAL_EXCEPT(cereal::Exception,
"poll failed -- error = %d: %s", errno, strerror(errno));
272 if(retval == 0)
CEREAL_EXCEPT(cereal::TimeoutException,
"timeout reached");
274 if(ufd[0].revents & POLLERR)
CEREAL_EXCEPT(cereal::Exception,
"error on socket, possibly unplugged");
281 buffer->append(erased);
284 catch(std::length_error& le)
286 CEREAL_EXCEPT(cereal::Exception,
"failed to append erased to buffer");
293 if(ret == -1 && errno != EAGAIN && errno != EWOULDBLOCK)
CEREAL_EXCEPT(cereal::Exception,
"read failed");
296 try{ buffer->append(temp_buffer, ret); }
297 catch(std::length_error& le)
299 CEREAL_EXCEPT(cereal::Exception,
"buffer filled without reaching end of data stream");
303 ret = buffer->find_first_of(start);
305 if(ret == -1) buffer->clear();
307 else if(ret > 0) buffer->erase(0, ret);
310 ret = buffer->find_first_of(end);
314 erased = buffer->substr(ret+1, buffer->size()-ret-1);
316 buffer->erase(ret+1, buffer->size()-ret-1);
320 CEREAL_EXCEPT(cereal::Exception,
"buffer filled without reaching end of data stream");
325 int retval = tcflush(
fd_, TCIOFLUSH);
326 if(retval != 0)
CEREAL_EXCEPT(cereal::Exception,
"tcflush failed");
349 struct pollfd ufd[1];
351 ufd[0].events = POLLIN;
357 if(poll(ufd, 1, 10) > 0)
359 if(!(ufd[0].revents & POLLERR))
396 catch(cereal::Exception& e)
430 catch(cereal::Exception& e)
bool startReadBetweenStream(boost::function< void(std::string *)> f, char start, char end)
Start a stream of readBetween()
bool stream_stopped_
Whether streaming is stopped or not.
void stopStream()
Stop streaming.
void readBetweenThread(char start, char end)
Thread for a stream of readBetween()
bool portOpen()
Check whether the port is open or not.
int readBytes(char *data, int length, int timeout=-1)
Read a fixed number of bytes from the serial port.
void open(const char *port_name, int baud_rate=115200)
Open the serial port.
int write(const char *data, int length=-1)
Write to the port.
bool readBetween(std::string *data, char start, char end, int timeout=-1)
Read from the serial port between a start char and an end char.
boost::function< void(char *, int)> readCallback
Stream read callback boost function.
bool startReadStream(boost::function< void(char *, int)> f)
Start a stream of read()
void close()
Close the serial port.
int read(char *data, int max_length, int timeout=-1)
Read from the port.
void readThread()
Thread for a stream of read()
bool stream_paused_
Whether streaming is paused or not.
boost::function< void(std::string *)> readLineCallback
Stream readLine callback boost function.
boost::function< void(std::string *)> readBetweenCallback
Stream readBetween callback boost function.
void resumeStream()
Resume streaming.
int flush()
Wrapper around tcflush.
bool startReadLineStream(boost::function< void(std::string *)> f)
Start a stream of readLine(std::string*, int)
void readLineThread()
Thread for a stream of readLine(std::string*, int)
boost::thread * stream_thread_
Stream thread.
int readLine(char *data, int length, int timeout=-1)
Read a line from the serial port.
void pauseStream()
Pause streaming.
#define CEREAL_EXCEPT(except, msg,...)
Macro for throwing an exception with a message, passing args.