2018-04-20 22:03:29 +00:00
|
|
|
#include "Serial.h"
|
2019-01-23 18:41:12 +00:00
|
|
|
#include "StreamBasedLauncher.h"
|
2018-04-20 22:03:29 +00:00
|
|
|
#include "Utilities.h"
|
|
|
|
#include "Stream.h"
|
2018-04-22 09:23:08 +00:00
|
|
|
#include "ReliableStream.h"
|
2018-05-05 16:53:27 +00:00
|
|
|
#include "ServerProtocol.h"
|
2018-04-24 20:06:32 +00:00
|
|
|
#include <termios.h>
|
2018-04-20 22:03:29 +00:00
|
|
|
#include <unistd.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <arpa/inet.h>
|
|
|
|
#include <poll.h>
|
2018-05-05 16:41:38 +00:00
|
|
|
#include <chrono>
|
2018-04-23 23:42:36 +00:00
|
|
|
#include <iostream>
|
2018-04-20 22:03:29 +00:00
|
|
|
|
2018-05-05 16:41:38 +00:00
|
|
|
namespace po = boost::program_options;
|
|
|
|
using namespace std::literals::chrono_literals;
|
2018-04-20 22:03:29 +00:00
|
|
|
|
2019-01-23 18:41:12 +00:00
|
|
|
class SerialStream : public WaitableStream
|
2018-04-20 22:03:29 +00:00
|
|
|
{
|
|
|
|
static const long kReadBufferSize = 4096;
|
|
|
|
uint8_t readBuffer[kReadBufferSize];
|
|
|
|
public:
|
|
|
|
int fd;
|
2018-05-05 16:41:38 +00:00
|
|
|
int baud;
|
2018-04-20 22:03:29 +00:00
|
|
|
|
|
|
|
virtual void write(const void* p, size_t n) override;
|
|
|
|
|
2019-01-23 18:41:12 +00:00
|
|
|
virtual void wait() override;
|
2018-04-20 22:03:29 +00:00
|
|
|
|
|
|
|
SerialStream(po::variables_map &options);
|
|
|
|
~SerialStream();
|
|
|
|
};
|
|
|
|
|
2019-01-23 18:41:12 +00:00
|
|
|
class SerialLauncher : public StreamBasedLauncher
|
2018-04-20 22:03:29 +00:00
|
|
|
{
|
|
|
|
SerialStream stream;
|
2018-04-22 09:23:08 +00:00
|
|
|
ReliableStream rStream;
|
2018-04-20 22:03:29 +00:00
|
|
|
public:
|
2019-08-18 11:21:00 +00:00
|
|
|
SerialLauncher(po::variables_map& options);
|
2018-04-20 22:03:29 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
SerialStream::SerialStream(po::variables_map &options)
|
|
|
|
{
|
|
|
|
std::string port = options["serial-port"].as<std::string>();
|
2018-05-05 16:41:38 +00:00
|
|
|
baud = options["serial-baud"].as<int>();
|
2018-04-20 22:03:29 +00:00
|
|
|
fd = open(port.c_str(), O_RDWR | O_NOCTTY | O_NDELAY );
|
|
|
|
if(fd < 0)
|
|
|
|
throw std::runtime_error("Cannot open serial port.\n");
|
|
|
|
|
|
|
|
struct termios tios;
|
|
|
|
tcgetattr(fd,&tios);
|
|
|
|
|
2018-04-24 20:06:32 +00:00
|
|
|
tios.c_cflag = CRTSCTS | CS8 | CLOCAL | CREAD;
|
|
|
|
|
|
|
|
switch(baud)
|
|
|
|
{
|
|
|
|
case 9600: tios.c_cflag |= B9600; break;
|
|
|
|
case 19200: tios.c_cflag |= B19200; break;
|
|
|
|
case 38400: tios.c_cflag |= B38400; break;
|
|
|
|
case 57600: tios.c_cflag |= B57600; break;
|
|
|
|
case 115200: tios.c_cflag |= B115200; break;
|
|
|
|
case 230400: tios.c_cflag |= B230400; break;
|
|
|
|
default:
|
|
|
|
throw std::runtime_error("Unsupported baud rate.\n");
|
|
|
|
}
|
|
|
|
|
2018-04-20 22:03:29 +00:00
|
|
|
tios.c_iflag = 0;//IGNPAR | ICRNL;
|
|
|
|
tios.c_lflag = 0;
|
|
|
|
tios.c_oflag = 0;
|
|
|
|
tios.c_cc[VTIME] = 0; /* inter-character timer unused */
|
2018-04-22 09:23:08 +00:00
|
|
|
tios.c_cc[VMIN] = 1; /* blocking read until 1 chars received */
|
2018-04-20 22:03:29 +00:00
|
|
|
tcsetattr(fd,TCSANOW,&tios);
|
|
|
|
usleep(500000);
|
|
|
|
}
|
|
|
|
SerialStream::~SerialStream()
|
|
|
|
{
|
2018-04-23 23:42:36 +00:00
|
|
|
tcdrain(fd);
|
|
|
|
usleep(500000);
|
2018-04-20 22:03:29 +00:00
|
|
|
close(fd);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SerialStream::write(const void* p, size_t n)
|
|
|
|
{
|
|
|
|
while(n)
|
|
|
|
{
|
|
|
|
struct pollfd pfd;
|
|
|
|
pfd.fd = fd;
|
|
|
|
pfd.events = POLLOUT;
|
|
|
|
pfd.revents = 0;
|
|
|
|
poll(&pfd, 1, 1000);
|
|
|
|
if(pfd.revents & POLLOUT)
|
|
|
|
{
|
|
|
|
ssize_t written = ::write(fd, p, n);
|
|
|
|
if(written > 0)
|
|
|
|
{
|
|
|
|
p = (const void*) ( (const char*)p + written );
|
|
|
|
n -= written;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void SerialStream::wait()
|
|
|
|
{
|
|
|
|
struct pollfd pfd;
|
|
|
|
pfd.fd = fd;
|
|
|
|
pfd.events = POLLIN;
|
|
|
|
pfd.revents = 0;
|
|
|
|
poll(&pfd, 1, 1000);
|
|
|
|
if(pfd.revents & POLLIN)
|
|
|
|
{
|
|
|
|
ssize_t n = ::read(fd, readBuffer, kReadBufferSize);
|
|
|
|
if(n > 0)
|
|
|
|
{
|
2018-04-22 09:23:08 +00:00
|
|
|
notifyReceive(readBuffer, n);
|
2018-04-20 22:03:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
SerialLauncher::SerialLauncher(po::variables_map &options)
|
2019-01-23 18:41:12 +00:00
|
|
|
: StreamBasedLauncher(options), stream(options), rStream(&stream)
|
2018-04-20 22:03:29 +00:00
|
|
|
{
|
2019-01-23 18:41:12 +00:00
|
|
|
SetupStream(&stream, &rStream);
|
2018-04-20 22:03:29 +00:00
|
|
|
|
2018-05-05 16:41:38 +00:00
|
|
|
do
|
|
|
|
{
|
2018-05-05 16:53:27 +00:00
|
|
|
rStream.reset(1);
|
2018-05-05 16:41:38 +00:00
|
|
|
std::cerr << "Connecting... (" << stream.baud << " baud)" << std::endl;
|
|
|
|
using clock = std::chrono::steady_clock;
|
|
|
|
auto startTime = clock::now();
|
|
|
|
while(!rStream.resetResponseArrived() && clock::now() - startTime < 5s)
|
2018-05-05 16:53:27 +00:00
|
|
|
stream.wait();
|
2018-05-05 16:41:38 +00:00
|
|
|
} while(!rStream.resetResponseArrived());
|
2018-04-23 23:42:36 +00:00
|
|
|
|
2018-05-05 16:41:38 +00:00
|
|
|
std::cerr << "Connected." << std::endl;
|
2018-04-24 05:57:43 +00:00
|
|
|
}
|
2018-04-20 22:03:29 +00:00
|
|
|
|
|
|
|
void Serial::GetOptions(options_description &desc)
|
|
|
|
{
|
|
|
|
desc.add_options()
|
|
|
|
("serial-port", po::value<std::string>()->default_value("/dev/ttyUSB0"), "serial port to use")
|
2018-04-24 20:06:32 +00:00
|
|
|
("serial-baud", po::value<int>()->default_value(19200), "serial port speed")
|
2018-04-20 22:03:29 +00:00
|
|
|
;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Serial::CheckOptions(variables_map &options)
|
|
|
|
{
|
2019-08-18 11:21:00 +00:00
|
|
|
return true;
|
2018-04-20 22:03:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
std::unique_ptr<Launcher> Serial::MakeLauncher(variables_map &options)
|
|
|
|
{
|
2019-08-18 11:21:00 +00:00
|
|
|
return std::unique_ptr<Launcher>(new SerialLauncher(options));
|
2018-04-20 22:03:29 +00:00
|
|
|
}
|