#ifndef SERIAL_PORT_H #define SERIAL_PORT_H #include #include #include #include #include #include #include #include #include #include #include #include #include // recv_buf below is a std::array; without this, any TU that doesn't // pull in transitively (e.g. via Eigen) fails to compile. class SerialPort { public: using SharedPtr = std::shared_ptr; SerialPort(std::string port, speed_t baudrate, int timeout_ms = 2) { set_timeout(timeout_ms); Init(port, baudrate); } ~SerialPort() { close(fd_); } ssize_t send(const uint8_t* data, size_t len) { ssize_t ret = ::write(fd_, data, len); return ret; } ssize_t recv(uint8_t* data, size_t len) { FD_ZERO(&rSet_); FD_SET(fd_, &rSet_); ssize_t recv_len = 0; timeval tv = timeout_; // local copy: select() mutates the timeval, keep timeout_ intact switch (select(fd_ + 1, &rSet_, NULL, NULL, &tv)) { case -1: // error // std::cout << "communication error" << std::endl; break; case 0: // timeout // std::cout << "timeout" << std::endl; break; default: recv_len = ::read(fd_, data, len); break; } return recv_len; } void set_timeout(int timeout_ms) { timeout_.tv_sec = timeout_ms / 1000; timeout_.tv_usec = (timeout_ms % 1000) * 1000; } void flush() { tcflush(fd_, TCIFLUSH); } // discard buffered/echoed input private: void Init(std::string port, speed_t baudrate) { int ret; // Open serial port fd_ = open(port.c_str(), O_RDWR | O_NOCTTY); if (fd_ < 0) { printf("Open serial port %s failed\n", port.c_str()); exit(-1); } // Set attributes struct termios option; memset(&option, 0, sizeof(option)); ret = tcgetattr(fd_, &option); option.c_oflag = 0; option.c_lflag = 0; option.c_iflag = 0; cfsetispeed(&option, baudrate); cfsetospeed(&option, baudrate); option.c_cflag &= ~CSIZE; option.c_cflag |= CS8; // 8 option.c_cflag &= ~PARENB; // no parity option.c_iflag &= ~INPCK; // no parity option.c_cflag &= ~CSTOPB; // 1 stop bit option.c_cc[VTIME] = 0; option.c_cc[VMIN] = 0; option.c_lflag |= CBAUDEX; ret = tcflush(fd_, TCIFLUSH); ret = tcsetattr(fd_, TCSANOW, &option); } int fd_; fd_set rSet_; timeval timeout_; std::queue recv_queue; std::array recv_buf; }; #endif // SERIAL_PORT_H