Zakladna test verzia
This commit is contained in:
6
.gitignore
vendored
Normal file
6
.gitignore
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
.vscode/
|
||||
CMakeFiles/
|
||||
CMakeCache.txt
|
||||
timeout
|
||||
cmake_install.cmake
|
||||
serial-port/
|
||||
15
CMakeLists.txt
Executable file
15
CMakeLists.txt
Executable file
@@ -0,0 +1,15 @@
|
||||
|
||||
cmake_minimum_required(VERSION 3.1)
|
||||
project(TEST)
|
||||
|
||||
## Target
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
set(TEST_SRCS main.cpp TimeoutSerial.cpp)
|
||||
add_executable(timeout ${TEST_SRCS})
|
||||
|
||||
## Link libraries
|
||||
set(BOOST_LIBS date_time system)
|
||||
find_package(Boost COMPONENTS ${BOOST_LIBS} REQUIRED)
|
||||
target_link_libraries(timeout ${Boost_LIBRARIES})
|
||||
find_package(Threads REQUIRED)
|
||||
target_link_libraries(timeout ${CMAKE_THREAD_LIBS_INIT})
|
||||
208
Makefile
Normal file
208
Makefile
Normal file
@@ -0,0 +1,208 @@
|
||||
# CMAKE generated file: DO NOT EDIT!
|
||||
# Generated by "Unix Makefiles" Generator, CMake Version 3.16
|
||||
|
||||
# Default target executed when no arguments are given to make.
|
||||
default_target: all
|
||||
|
||||
.PHONY : default_target
|
||||
|
||||
# Allow only one "make -f Makefile2" at a time, but pass parallelism.
|
||||
.NOTPARALLEL:
|
||||
|
||||
|
||||
#=============================================================================
|
||||
# Special targets provided by cmake.
|
||||
|
||||
# Disable implicit rules so canonical targets will work.
|
||||
.SUFFIXES:
|
||||
|
||||
|
||||
# Remove some rules from gmake that .SUFFIXES does not remove.
|
||||
SUFFIXES =
|
||||
|
||||
.SUFFIXES: .hpux_make_needs_suffix_list
|
||||
|
||||
|
||||
# Suppress display of executed commands.
|
||||
$(VERBOSE).SILENT:
|
||||
|
||||
|
||||
# A target that is always out of date.
|
||||
cmake_force:
|
||||
|
||||
.PHONY : cmake_force
|
||||
|
||||
#=============================================================================
|
||||
# Set environment variables for the build.
|
||||
|
||||
# The shell in which to execute make rules.
|
||||
SHELL = /bin/sh
|
||||
|
||||
# The CMake executable.
|
||||
CMAKE_COMMAND = /usr/bin/cmake
|
||||
|
||||
# The command to remove a file.
|
||||
RM = /usr/bin/cmake -E remove -f
|
||||
|
||||
# Escaping for special characters.
|
||||
EQUALS = =
|
||||
|
||||
# The top-level source directory on which CMake was run.
|
||||
CMAKE_SOURCE_DIR = /home/jaro/serialport-downloader
|
||||
|
||||
# The top-level build directory on which CMake was run.
|
||||
CMAKE_BINARY_DIR = /home/jaro/serialport-downloader
|
||||
|
||||
#=============================================================================
|
||||
# Targets provided globally by CMake.
|
||||
|
||||
# Special rule for the target rebuild_cache
|
||||
rebuild_cache:
|
||||
@$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake to regenerate build system..."
|
||||
/usr/bin/cmake -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR)
|
||||
.PHONY : rebuild_cache
|
||||
|
||||
# Special rule for the target rebuild_cache
|
||||
rebuild_cache/fast: rebuild_cache
|
||||
|
||||
.PHONY : rebuild_cache/fast
|
||||
|
||||
# Special rule for the target edit_cache
|
||||
edit_cache:
|
||||
@$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "No interactive CMake dialog available..."
|
||||
/usr/bin/cmake -E echo No\ interactive\ CMake\ dialog\ available.
|
||||
.PHONY : edit_cache
|
||||
|
||||
# Special rule for the target edit_cache
|
||||
edit_cache/fast: edit_cache
|
||||
|
||||
.PHONY : edit_cache/fast
|
||||
|
||||
# The main all target
|
||||
all: cmake_check_build_system
|
||||
$(CMAKE_COMMAND) -E cmake_progress_start /home/jaro/serialport-downloader/CMakeFiles /home/jaro/serialport-downloader/CMakeFiles/progress.marks
|
||||
$(MAKE) -f CMakeFiles/Makefile2 all
|
||||
$(CMAKE_COMMAND) -E cmake_progress_start /home/jaro/serialport-downloader/CMakeFiles 0
|
||||
.PHONY : all
|
||||
|
||||
# The main clean target
|
||||
clean:
|
||||
$(MAKE) -f CMakeFiles/Makefile2 clean
|
||||
.PHONY : clean
|
||||
|
||||
# The main clean target
|
||||
clean/fast: clean
|
||||
|
||||
.PHONY : clean/fast
|
||||
|
||||
# Prepare targets for installation.
|
||||
preinstall: all
|
||||
$(MAKE) -f CMakeFiles/Makefile2 preinstall
|
||||
.PHONY : preinstall
|
||||
|
||||
# Prepare targets for installation.
|
||||
preinstall/fast:
|
||||
$(MAKE) -f CMakeFiles/Makefile2 preinstall
|
||||
.PHONY : preinstall/fast
|
||||
|
||||
# clear depends
|
||||
depend:
|
||||
$(CMAKE_COMMAND) -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 1
|
||||
.PHONY : depend
|
||||
|
||||
#=============================================================================
|
||||
# Target rules for targets named timeout
|
||||
|
||||
# Build rule for target.
|
||||
timeout: cmake_check_build_system
|
||||
$(MAKE) -f CMakeFiles/Makefile2 timeout
|
||||
.PHONY : timeout
|
||||
|
||||
# fast build rule for target.
|
||||
timeout/fast:
|
||||
$(MAKE) -f CMakeFiles/timeout.dir/build.make CMakeFiles/timeout.dir/build
|
||||
.PHONY : timeout/fast
|
||||
|
||||
TimeoutSerial.o: TimeoutSerial.cpp.o
|
||||
|
||||
.PHONY : TimeoutSerial.o
|
||||
|
||||
# target to build an object file
|
||||
TimeoutSerial.cpp.o:
|
||||
$(MAKE) -f CMakeFiles/timeout.dir/build.make CMakeFiles/timeout.dir/TimeoutSerial.cpp.o
|
||||
.PHONY : TimeoutSerial.cpp.o
|
||||
|
||||
TimeoutSerial.i: TimeoutSerial.cpp.i
|
||||
|
||||
.PHONY : TimeoutSerial.i
|
||||
|
||||
# target to preprocess a source file
|
||||
TimeoutSerial.cpp.i:
|
||||
$(MAKE) -f CMakeFiles/timeout.dir/build.make CMakeFiles/timeout.dir/TimeoutSerial.cpp.i
|
||||
.PHONY : TimeoutSerial.cpp.i
|
||||
|
||||
TimeoutSerial.s: TimeoutSerial.cpp.s
|
||||
|
||||
.PHONY : TimeoutSerial.s
|
||||
|
||||
# target to generate assembly for a file
|
||||
TimeoutSerial.cpp.s:
|
||||
$(MAKE) -f CMakeFiles/timeout.dir/build.make CMakeFiles/timeout.dir/TimeoutSerial.cpp.s
|
||||
.PHONY : TimeoutSerial.cpp.s
|
||||
|
||||
main.o: main.cpp.o
|
||||
|
||||
.PHONY : main.o
|
||||
|
||||
# target to build an object file
|
||||
main.cpp.o:
|
||||
$(MAKE) -f CMakeFiles/timeout.dir/build.make CMakeFiles/timeout.dir/main.cpp.o
|
||||
.PHONY : main.cpp.o
|
||||
|
||||
main.i: main.cpp.i
|
||||
|
||||
.PHONY : main.i
|
||||
|
||||
# target to preprocess a source file
|
||||
main.cpp.i:
|
||||
$(MAKE) -f CMakeFiles/timeout.dir/build.make CMakeFiles/timeout.dir/main.cpp.i
|
||||
.PHONY : main.cpp.i
|
||||
|
||||
main.s: main.cpp.s
|
||||
|
||||
.PHONY : main.s
|
||||
|
||||
# target to generate assembly for a file
|
||||
main.cpp.s:
|
||||
$(MAKE) -f CMakeFiles/timeout.dir/build.make CMakeFiles/timeout.dir/main.cpp.s
|
||||
.PHONY : main.cpp.s
|
||||
|
||||
# Help Target
|
||||
help:
|
||||
@echo "The following are some of the valid targets for this Makefile:"
|
||||
@echo "... all (the default if no target is provided)"
|
||||
@echo "... clean"
|
||||
@echo "... depend"
|
||||
@echo "... rebuild_cache"
|
||||
@echo "... edit_cache"
|
||||
@echo "... timeout"
|
||||
@echo "... TimeoutSerial.o"
|
||||
@echo "... TimeoutSerial.i"
|
||||
@echo "... TimeoutSerial.s"
|
||||
@echo "... main.o"
|
||||
@echo "... main.i"
|
||||
@echo "... main.s"
|
||||
.PHONY : help
|
||||
|
||||
|
||||
|
||||
#=============================================================================
|
||||
# Special targets to cleanup operation of make.
|
||||
|
||||
# Special rule to run CMake to check the build system integrity.
|
||||
# No rule that depends on this can have commands that come from listfiles
|
||||
# because they might be regenerated.
|
||||
cmake_check_build_system:
|
||||
$(CMAKE_COMMAND) -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 0
|
||||
.PHONY : cmake_check_build_system
|
||||
|
||||
9
Makefile.windows
Normal file
9
Makefile.windows
Normal file
@@ -0,0 +1,9 @@
|
||||
#Using MinGW distro from http://nuwen.net/mingw.html that contains boost precompiled
|
||||
|
||||
all:
|
||||
g++ -O2 -std=c++11 -c main.cpp -D_WIN32_WINNT=0x0501
|
||||
g++ -O2 -std=c++11 -c TimeoutSerial.cpp -D_WIN32_WINNT=0x0501
|
||||
g++ -o timeout.exe main.o TimeoutSerial.o -s -lwsock32 -lws2_32 -lboost_system
|
||||
|
||||
clean:
|
||||
del timeout.exe main.o TimeoutSerial.o
|
||||
265
TimeoutSerial.cpp
Executable file
265
TimeoutSerial.cpp
Executable file
@@ -0,0 +1,265 @@
|
||||
/*
|
||||
* File: TimeoutSerial.cpp
|
||||
* Author: Terraneo Federico
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* Created on September 12, 2009, 3:47 PM
|
||||
*
|
||||
* v1.06: C++11 support
|
||||
*
|
||||
* v1.05: Fixed a bug regarding reading after a timeout (again).
|
||||
*
|
||||
* v1.04: Fixed bug with timeout set to zero
|
||||
*
|
||||
* v1.03: Fix for Mac OS X, now fully working on Mac.
|
||||
*
|
||||
* v1.02: Code cleanup, speed improvements, bug fixes.
|
||||
*
|
||||
* v1.01: Fixed a bug that caused errors while reading after a timeout.
|
||||
*
|
||||
* v1.00: First release.
|
||||
*/
|
||||
|
||||
#include "TimeoutSerial.h"
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <boost/bind.hpp>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace boost;
|
||||
|
||||
TimeoutSerial::TimeoutSerial(): io(), port(io), timer(io),
|
||||
timeout(boost::posix_time::seconds(0)) {}
|
||||
|
||||
TimeoutSerial::TimeoutSerial(const std::string& devname, unsigned int baud_rate,
|
||||
asio::serial_port_base::parity opt_parity,
|
||||
asio::serial_port_base::character_size opt_csize,
|
||||
asio::serial_port_base::flow_control opt_flow,
|
||||
asio::serial_port_base::stop_bits opt_stop)
|
||||
: io(), port(io), timer(io), timeout(boost::posix_time::seconds(0))
|
||||
{
|
||||
open(devname,baud_rate,opt_parity,opt_csize,opt_flow,opt_stop);
|
||||
}
|
||||
|
||||
void TimeoutSerial::open(const std::string& devname, unsigned int baud_rate,
|
||||
asio::serial_port_base::parity opt_parity,
|
||||
asio::serial_port_base::character_size opt_csize,
|
||||
asio::serial_port_base::flow_control opt_flow,
|
||||
asio::serial_port_base::stop_bits opt_stop)
|
||||
{
|
||||
if(isOpen()) close();
|
||||
port.open(devname);
|
||||
port.set_option(asio::serial_port_base::baud_rate(baud_rate));
|
||||
port.set_option(opt_parity);
|
||||
port.set_option(opt_csize);
|
||||
port.set_option(opt_flow);
|
||||
port.set_option(opt_stop);
|
||||
}
|
||||
|
||||
bool TimeoutSerial::isOpen() const
|
||||
{
|
||||
return port.is_open();
|
||||
}
|
||||
|
||||
void TimeoutSerial::close()
|
||||
{
|
||||
if(isOpen()==false) return;
|
||||
port.close();
|
||||
}
|
||||
|
||||
void TimeoutSerial::setTimeout(const boost::posix_time::time_duration& t)
|
||||
{
|
||||
timeout=t;
|
||||
}
|
||||
|
||||
void TimeoutSerial::write(const char *data, size_t size)
|
||||
{
|
||||
asio::write(port,asio::buffer(data,size));
|
||||
}
|
||||
|
||||
void TimeoutSerial::write(const std::vector<char>& data)
|
||||
{
|
||||
asio::write(port,asio::buffer(&data[0],data.size()));
|
||||
}
|
||||
|
||||
void TimeoutSerial::writeString(const std::string& s)
|
||||
{
|
||||
asio::write(port,asio::buffer(s.c_str(),s.size()));
|
||||
}
|
||||
|
||||
void TimeoutSerial::read(char *data, size_t size)
|
||||
{
|
||||
if(readData.size()>0)//If there is some data from a previous read
|
||||
{
|
||||
istream is(&readData);
|
||||
size_t toRead=min(readData.size(),size);//How many bytes to read?
|
||||
is.read(data,toRead);
|
||||
data+=toRead;
|
||||
size-=toRead;
|
||||
if(size==0) return;//If read data was enough, just return
|
||||
}
|
||||
|
||||
setupParameters=ReadSetupParameters(data,size);
|
||||
performReadSetup(setupParameters);
|
||||
|
||||
//For this code to work, there should always be a timeout, so the
|
||||
//request for no timeout is translated into a very long timeout
|
||||
if(timeout!=boost::posix_time::seconds(0)) timer.expires_from_now(timeout);
|
||||
else timer.expires_from_now(boost::posix_time::hours(100000));
|
||||
|
||||
timer.async_wait(boost::bind(&TimeoutSerial::timeoutExpired,this,
|
||||
asio::placeholders::error));
|
||||
|
||||
result=resultInProgress;
|
||||
bytesTransferred=0;
|
||||
for(;;)
|
||||
{
|
||||
io.run_one();
|
||||
switch(result)
|
||||
{
|
||||
case resultSuccess:
|
||||
timer.cancel();
|
||||
return;
|
||||
case resultTimeoutExpired:
|
||||
port.cancel();
|
||||
throw(timeout_exception("Timeout expired"));
|
||||
case resultError:
|
||||
timer.cancel();
|
||||
port.cancel();
|
||||
throw(boost::system::system_error(boost::system::error_code(),
|
||||
"Error while reading"));
|
||||
//if resultInProgress remain in the loop
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<char> TimeoutSerial::read(size_t size)
|
||||
{
|
||||
vector<char> result(size,'\0');//Allocate a vector with the desired size
|
||||
read(&result[0],size);//Fill it with values
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string TimeoutSerial::readString(size_t size)
|
||||
{
|
||||
string result(size,'\0');//Allocate a string with the desired size
|
||||
read(&result[0],size);//Fill it with values
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string TimeoutSerial::readStringUntil(const std::string& delim)
|
||||
{
|
||||
// Note: if readData contains some previously read data, the call to
|
||||
// async_read_until (which is done in performReadSetup) correctly handles
|
||||
// it. If the data is enough it will also immediately call readCompleted()
|
||||
setupParameters=ReadSetupParameters(delim);
|
||||
performReadSetup(setupParameters);
|
||||
|
||||
//For this code to work, there should always be a timeout, so the
|
||||
//request for no timeout is translated into a very long timeout
|
||||
if(timeout!=boost::posix_time::seconds(0)) timer.expires_from_now(timeout);
|
||||
else timer.expires_from_now(boost::posix_time::hours(100000));
|
||||
|
||||
timer.async_wait(boost::bind(&TimeoutSerial::timeoutExpired,this,
|
||||
asio::placeholders::error));
|
||||
|
||||
result=resultInProgress;
|
||||
bytesTransferred=0;
|
||||
for(;;)
|
||||
{
|
||||
io.run_one();
|
||||
switch(result)
|
||||
{
|
||||
case resultSuccess:
|
||||
{
|
||||
timer.cancel();
|
||||
bytesTransferred-=delim.size();//Don't count delim
|
||||
istream is(&readData);
|
||||
string result(bytesTransferred,'\0');//Alloc string
|
||||
is.read(&result[0],bytesTransferred);//Fill values
|
||||
is.ignore(delim.size());//Remove delimiter from stream
|
||||
return result;
|
||||
}
|
||||
case resultTimeoutExpired:
|
||||
port.cancel();
|
||||
throw(timeout_exception("Timeout expired"));
|
||||
case resultError:
|
||||
timer.cancel();
|
||||
port.cancel();
|
||||
throw(boost::system::system_error(boost::system::error_code(),
|
||||
"Error while reading"));
|
||||
//if resultInProgress remain in the loop
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TimeoutSerial::~TimeoutSerial() {}
|
||||
|
||||
void TimeoutSerial::performReadSetup(const ReadSetupParameters& param)
|
||||
{
|
||||
if(param.fixedSize)
|
||||
{
|
||||
asio::async_read(port,asio::buffer(param.data,param.size),boost::bind(
|
||||
&TimeoutSerial::readCompleted,this,asio::placeholders::error,
|
||||
asio::placeholders::bytes_transferred));
|
||||
} else {
|
||||
asio::async_read_until(port,readData,param.delim,boost::bind(
|
||||
&TimeoutSerial::readCompleted,this,asio::placeholders::error,
|
||||
asio::placeholders::bytes_transferred));
|
||||
}
|
||||
}
|
||||
|
||||
void TimeoutSerial::timeoutExpired(const boost::system::error_code& error)
|
||||
{
|
||||
if(!error && result==resultInProgress) result=resultTimeoutExpired;
|
||||
}
|
||||
|
||||
void TimeoutSerial::readCompleted(const boost::system::error_code& error,
|
||||
const size_t bytesTransferred)
|
||||
{
|
||||
if(!error)
|
||||
{
|
||||
result=resultSuccess;
|
||||
this->bytesTransferred=bytesTransferred;
|
||||
return;
|
||||
}
|
||||
|
||||
//In case a asynchronous operation is cancelled due to a timeout,
|
||||
//each OS seems to have its way to react.
|
||||
#ifdef _WIN32
|
||||
if(error.value()==995) return; //Windows spits out error 995
|
||||
#elif defined(__APPLE__)
|
||||
if(error.value()==45)
|
||||
{
|
||||
//Bug on OS X, it might be necessary to repeat the setup
|
||||
//http://osdir.com/ml/lib.boost.asio.user/2008-08/msg00004.html
|
||||
performReadSetup(setupParameters);
|
||||
return;
|
||||
}
|
||||
#else //Linux
|
||||
if(error.value()==125) return; //Linux outputs error 125
|
||||
#endif
|
||||
|
||||
result=resultError;
|
||||
}
|
||||
|
||||
void TimeoutSerial::setRTS(bool enabled)
|
||||
{
|
||||
int fd = port.native_handle();
|
||||
int data = TIOCM_RTS;
|
||||
if (!enabled)
|
||||
ioctl(fd, TIOCMBIC, &data);
|
||||
else
|
||||
ioctl(fd, TIOCMBIS, &data);
|
||||
}
|
||||
|
||||
void TimeoutSerial::setDTR(bool enabled)
|
||||
{
|
||||
int fd = port.native_handle();
|
||||
int data = TIOCM_DTR;
|
||||
if (!enabled)
|
||||
ioctl(fd, TIOCMBIC, &data); // Clears the DTR pin
|
||||
else
|
||||
ioctl(fd, TIOCMBIS, &data); // Sets the DTR pin
|
||||
}
|
||||
236
TimeoutSerial.h
Executable file
236
TimeoutSerial.h
Executable file
@@ -0,0 +1,236 @@
|
||||
/*
|
||||
* File: TimeoutSerial.h
|
||||
* Author: Terraneo Federico
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
*
|
||||
* Created on September 12, 2009, 3:47 PM
|
||||
*/
|
||||
|
||||
#ifndef TIMEOUTSERIAL_H
|
||||
#define TIMEOUTSERIAL_H
|
||||
|
||||
#include <stdexcept>
|
||||
#include <boost/utility.hpp>
|
||||
#include <boost/asio.hpp>
|
||||
|
||||
/**
|
||||
* Thrown if timeout occurs
|
||||
*/
|
||||
class timeout_exception: public std::runtime_error
|
||||
{
|
||||
public:
|
||||
timeout_exception(const std::string& arg): runtime_error(arg) {}
|
||||
};
|
||||
|
||||
/**
|
||||
* Serial port class, with timeout on read operations.
|
||||
*/
|
||||
class TimeoutSerial: private boost::noncopyable
|
||||
{
|
||||
public:
|
||||
TimeoutSerial();
|
||||
|
||||
/**
|
||||
* Opens a serial device. By default timeout is disabled.
|
||||
* \param devname serial device name, example "/dev/ttyS0" or "COM1"
|
||||
* \param baud_rate serial baud rate
|
||||
* \param opt_parity serial parity, default none
|
||||
* \param opt_csize serial character size, default 8bit
|
||||
* \param opt_flow serial flow control, default none
|
||||
* \param opt_stop serial stop bits, default 1
|
||||
* \throws boost::system::system_error if cannot open the
|
||||
* serial device
|
||||
*/
|
||||
TimeoutSerial(const std::string& devname, unsigned int baud_rate,
|
||||
boost::asio::serial_port_base::parity opt_parity=
|
||||
boost::asio::serial_port_base::parity(
|
||||
boost::asio::serial_port_base::parity::none),
|
||||
boost::asio::serial_port_base::character_size opt_csize=
|
||||
boost::asio::serial_port_base::character_size(8),
|
||||
boost::asio::serial_port_base::flow_control opt_flow=
|
||||
boost::asio::serial_port_base::flow_control(
|
||||
boost::asio::serial_port_base::flow_control::none),
|
||||
boost::asio::serial_port_base::stop_bits opt_stop=
|
||||
boost::asio::serial_port_base::stop_bits(
|
||||
boost::asio::serial_port_base::stop_bits::one));
|
||||
|
||||
/**
|
||||
* Opens a serial device.
|
||||
* \param devname serial device name, example "/dev/ttyS0" or "COM1"
|
||||
* \param baud_rate serial baud rate
|
||||
* \param opt_parity serial parity, default none
|
||||
* \param opt_csize serial character size, default 8bit
|
||||
* \param opt_flow serial flow control, default none
|
||||
* \param opt_stop serial stop bits, default 1
|
||||
* \throws boost::system::system_error if cannot open the
|
||||
* serial device
|
||||
*/
|
||||
void open(const std::string& devname, unsigned int baud_rate,
|
||||
boost::asio::serial_port_base::parity opt_parity=
|
||||
boost::asio::serial_port_base::parity(
|
||||
boost::asio::serial_port_base::parity::none),
|
||||
boost::asio::serial_port_base::character_size opt_csize=
|
||||
boost::asio::serial_port_base::character_size(8),
|
||||
boost::asio::serial_port_base::flow_control opt_flow=
|
||||
boost::asio::serial_port_base::flow_control(
|
||||
boost::asio::serial_port_base::flow_control::none),
|
||||
boost::asio::serial_port_base::stop_bits opt_stop=
|
||||
boost::asio::serial_port_base::stop_bits(
|
||||
boost::asio::serial_port_base::stop_bits::one));
|
||||
|
||||
/**
|
||||
* \return true if serial device is open
|
||||
*/
|
||||
bool isOpen() const;
|
||||
|
||||
/**
|
||||
* Close the serial device
|
||||
* \throws boost::system::system_error if any error
|
||||
*/
|
||||
void close();
|
||||
|
||||
/**
|
||||
* Set the timeout on read/write operations.
|
||||
* To disable the timeout, call setTimeout(boost::posix_time::seconds(0));
|
||||
*/
|
||||
void setTimeout(const boost::posix_time::time_duration& t);
|
||||
|
||||
/**
|
||||
* Write data
|
||||
* \param data array of char to be sent through the serial device
|
||||
* \param size array size
|
||||
* \throws boost::system::system_error if any error
|
||||
*/
|
||||
void write(const char *data, size_t size);
|
||||
|
||||
/**
|
||||
* Write data
|
||||
* \param data to be sent through the serial device
|
||||
* \throws boost::system::system_error if any error
|
||||
*/
|
||||
void write(const std::vector<char>& data);
|
||||
|
||||
/**
|
||||
* Write a string. Can be used to send ASCII data to the serial device.
|
||||
* To send binary data, use write()
|
||||
* \param s string to send
|
||||
* \throws boost::system::system_error if any error
|
||||
*/
|
||||
void writeString(const std::string& s);
|
||||
|
||||
/**
|
||||
* Read some data, blocking
|
||||
* \param data array of char to be read through the serial device
|
||||
* \param size array size
|
||||
* \return numbr of character actually read 0<=return<=size
|
||||
* \throws boost::system::system_error if any error
|
||||
* \throws timeout_exception in case of timeout
|
||||
*/
|
||||
void read(char *data, size_t size);
|
||||
|
||||
/**
|
||||
* Read some data, blocking
|
||||
* \param size how much data to read
|
||||
* \return the receive buffer. It iempty if no data is available
|
||||
* \throws boost::system::system_error if any error
|
||||
* \throws timeout_exception in case of timeout
|
||||
*/
|
||||
std::vector<char> read(size_t size);
|
||||
|
||||
/**
|
||||
* Read a string, blocking
|
||||
* Can only be used if the user is sure that the serial device will not
|
||||
* send binary data. For binary data read, use read()
|
||||
* The returned string is empty if no data has arrived
|
||||
* \param size hw much data to read
|
||||
* \return a string with the received data.
|
||||
* \throws boost::system::system_error if any error
|
||||
* \throws timeout_exception in case of timeout
|
||||
*/
|
||||
std::string readString(size_t size);
|
||||
|
||||
/**
|
||||
* Read a line, blocking
|
||||
* Can only be used if the user is sure that the serial device will not
|
||||
* send binary data. For binary data read, use read()
|
||||
* The returned string is empty if the line delimiter has not yet arrived.
|
||||
* \param delimiter line delimiter, default="\n"
|
||||
* \return a string with the received data. The delimiter is removed from
|
||||
* the string.
|
||||
* \throws boost::system::system_error if any error
|
||||
* \throws timeout_exception in case of timeout
|
||||
*/
|
||||
std::string readStringUntil(const std::string& delim="\n");
|
||||
|
||||
void setRTS(bool enabled);
|
||||
void setDTR(bool enabled);
|
||||
|
||||
~TimeoutSerial();
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
* Parameters of performReadSetup.
|
||||
* Just wrapper class, no encapsulation provided
|
||||
*/
|
||||
class ReadSetupParameters
|
||||
{
|
||||
public:
|
||||
ReadSetupParameters(): fixedSize(false), delim(""), data(0), size(0) {}
|
||||
|
||||
explicit ReadSetupParameters(const std::string& delim):
|
||||
fixedSize(false), delim(delim), data(0), size(0) { }
|
||||
|
||||
ReadSetupParameters(char *data, size_t size): fixedSize(true),
|
||||
delim(""), data(data), size(size) { }
|
||||
|
||||
//Using default copy constructor, operator=
|
||||
|
||||
bool fixedSize; ///< True if need to read a fixed number of parameters
|
||||
std::string delim; ///< String end delimiter (valid if fixedSize=false)
|
||||
char *data; ///< Pointer to data array (valid if fixedSize=true)
|
||||
size_t size; ///< Array size (valid if fixedSize=true)
|
||||
};
|
||||
|
||||
/**
|
||||
* This member function sets up a read operation, both reading a specified
|
||||
* number of characters and reading until a delimiter string.
|
||||
*/
|
||||
void performReadSetup(const ReadSetupParameters& param);
|
||||
|
||||
/**
|
||||
* Callack called either when the read timeout is expired or canceled.
|
||||
* If called because timeout expired, sets result to resultTimeoutExpired
|
||||
*/
|
||||
void timeoutExpired(const boost::system::error_code& error);
|
||||
|
||||
/**
|
||||
* Callback called either if a read complete or read error occurs
|
||||
* If called because of read complete, sets result to resultSuccess
|
||||
* If called because read error, sets result to resultError
|
||||
*/
|
||||
void readCompleted(const boost::system::error_code& error,
|
||||
const size_t bytesTransferred);
|
||||
|
||||
/**
|
||||
* Possible outcome of a read. Set by callbacks, read from main code
|
||||
*/
|
||||
enum ReadResult
|
||||
{
|
||||
resultInProgress,
|
||||
resultSuccess,
|
||||
resultError,
|
||||
resultTimeoutExpired
|
||||
};
|
||||
|
||||
boost::asio::io_service io; ///< Io service object
|
||||
boost::asio::serial_port port; ///< Serial port object
|
||||
boost::asio::deadline_timer timer; ///< Timer for timeout
|
||||
boost::posix_time::time_duration timeout; ///< Read/write timeout
|
||||
boost::asio::streambuf readData; ///< Holds eventual read but not consumed
|
||||
enum ReadResult result; ///< Used by read with timeout
|
||||
size_t bytesTransferred; ///< Used by async read callback
|
||||
ReadSetupParameters setupParameters; ///< Global because used in the OSX fix
|
||||
};
|
||||
|
||||
#endif //TIMEOUTSERIAL_H
|
||||
76
main.cpp
Executable file
76
main.cpp
Executable file
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* File: main.cpp
|
||||
* Author: fede.tft
|
||||
*
|
||||
* Created on September 10, 2009, 10:50 AM
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <boost/algorithm/string/split.hpp>
|
||||
#include "TimeoutSerial.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace boost;
|
||||
|
||||
typedef vector< string > split_vector_type;
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
string line;
|
||||
float temperature = NAN;
|
||||
float humidity= NAN;
|
||||
float pressure = NAN;
|
||||
|
||||
try {
|
||||
|
||||
TimeoutSerial serial("/dev/ttyUSB0",115200);
|
||||
serial.setTimeout(posix_time::seconds(10));
|
||||
serial.setDTR(false);
|
||||
serial.setRTS(false);
|
||||
sleep(5);
|
||||
//Text test
|
||||
|
||||
serial.writeString("?\r\n");
|
||||
|
||||
|
||||
line = serial.readStringUntil("\n");
|
||||
trim(line);
|
||||
cout << line << endl;
|
||||
|
||||
serial.writeString("measure\r\n");
|
||||
|
||||
for (;;) {
|
||||
line = serial.readStringUntil("\n");
|
||||
trim(line);
|
||||
if (line == "") continue;
|
||||
// cout << line << endl;
|
||||
|
||||
split_vector_type SplitVec; // #2: Search for tokens
|
||||
split( SplitVec, line, is_any_of(" "), token_compress_on ); // SplitVec == { "hello abc","ABC","aBc goodbye" }
|
||||
|
||||
for (vector<string>::iterator t=SplitVec.begin(); t!=SplitVec.end(); ++t) {
|
||||
split_vector_type kv;
|
||||
split(kv, *t, is_any_of("="), token_compress_on);
|
||||
// cout << "kv[0]=" << kv[0] << endl;
|
||||
if (kv[0] == "temperature") temperature = stof(kv[1]);
|
||||
if (kv[0] == "humidity") humidity = stof(kv[1]);
|
||||
if (kv[0] == "pressure") pressure = stof(kv[1]);
|
||||
}
|
||||
|
||||
if (pressure > 0.0) break;
|
||||
}
|
||||
|
||||
cout << "teplota = " << temperature << endl;
|
||||
cout << "vlhkost = " << humidity << endl;
|
||||
cout << "tlak = " << pressure << endl;
|
||||
|
||||
serial.close();
|
||||
|
||||
} catch(boost::system::system_error& e)
|
||||
{
|
||||
cout<<"Error: "<<e.what()<<endl;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user