Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Open sidebar
Kestrel Collaboration
Kestrel Firmware
serial
Commits
05fa4b8d
Commit
05fa4b8d
authored
13 years ago
by
William Woodall
Browse files
Options
Download
Email Patches
Plain Diff
Removing serial listener, next make sure I can compile without boost completely.
parent
f7cee5e1
Changes
9
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
164 additions
and
1684 deletions
+164
-1684
Findserial.cmake
Findserial.cmake
+1
-1
Makefile
Makefile
+0
-6
examples/serial_listener_example.cc
examples/serial_listener_example.cc
+0
-93
include/serial/serial_listener.h
include/serial/serial_listener.h
+0
-931
serial.cmake
serial.cmake
+124
-149
serial.makefile
serial.makefile
+1
-1
serial_ros.cmake
serial_ros.cmake
+38
-48
src/serial_listener.cc
src/serial_listener.cc
+0
-217
tests/serial_listener_tests.cc
tests/serial_listener_tests.cc
+0
-238
No files found.
Findserial.cmake
View file @
05fa4b8d
find_path
(
serial_INCLUDE_DIRS serial.h
serial_listener.h
/usr/include/serial
find_path
(
serial_INCLUDE_DIRS serial.h /usr/include/serial
/usr/local/include/serial
"$ENV{NAMER_ROOT}"
)
find_library
(
serial_LIBRARIES serial /usr/lib /usr/local/lib
...
...
This diff is collapsed.
Click to expand it.
Makefile
View file @
05fa4b8d
# # ash_gti's dumb downed makefile so I can more easily test stuff
# CXX=clang++
# CXXFLAGS=-g -I./include -ferror-limit=5 -O3 -Wall -Weffc++ -pedantic -pedantic-errors -Wextra -Wall -Waggregate-return -Wcast-align -Wcast-qual -Wchar-subscripts -Wcomment -Wconversion -Wdisabled-optimization -Wfloat-equal -Wformat -Wformat=2 -Wformat-nonliteral -Wformat-security -Wformat-y2k -Wimplicit -Wimport -Winit-self -Winline -Winvalid-pch -Wlong-long -Wmissing-braces -Wmissing-field-initializers -Wmissing-format-attribute -Wmissing-include-dirs -Wmissing-noreturn -Wpacked -Wparentheses -Wpointer-arith -Wredundant-decls -Wreturn-type -Wsequence-point -Wshadow -Wsign-compare -Wstack-protector -Wstrict-aliasing -Wstrict-aliasing=2 -Wswitch -Wswitch-default -Wswitch-enum -Wtrigraphs -Wuninitialized -Wunknown-pragmas -Wunreachable-code -Wunused -Wunused-function -Wunused-label -Wunused-parameter -Wunused-value -Wunused-variable -Wvariadic-macros -Wvolatile-register-var -Wwrite-strings
#
# test: tests/serial_tests.o src/serial.o src/impl/unix.o
# $(CXX) -o test tests/serial_tests.o src/serial.o src/impl/unix.o
ifdef
ROS_ROOT
include
$(shell rospack find mk)/cmake.mk
else
...
...
This diff is collapsed.
Click to expand it.
examples/serial_listener_example.cc
deleted
100644 → 0
View file @
f7cee5e1
#include <iostream>
#include <serial/serial.h>
#include <serial/serial_listener.h>
using
namespace
serial
;
void
default_handler
(
std
::
string
token
)
{
std
::
cout
<<
"default_handler got a: "
<<
token
<<
std
::
endl
;
}
void
callback
(
std
::
string
token
)
{
std
::
cout
<<
"callback got a: "
<<
token
<<
std
::
endl
;
}
int
run
()
{
// Assuming this device prints the string 'pre-substr-post\r' at 100Hz
Serial
serial
(
"/dev/tty.usbserial-A900cfJA"
,
115200
);
SerialListener
listener
;
listener
.
startListening
(
serial
);
// Set the tokenizer
// This is the same as the default delimeter, so an explicit call to
// setTokenizer is not necessary if your data is \r delimited.
// You can create your own Tokenizer as well.
listener
.
setTokenizer
(
SerialListener
::
delimeter_tokenizer
(
"
\r
"
));
// Method #1:
// comparator, callback - async
FilterPtr
f1
=
listener
.
createFilter
(
SerialListener
::
startsWith
(
"pre"
),
callback
);
SerialListener
::
sleep
(
15
);
// Sleep 15ms, to let the data come in
listener
.
removeFilter
(
f1
);
// Not scoped, must be removed explicity
// Method #2:
// comparator - blocking
{
BlockingFilterPtr
f2
=
listener
.
createBlockingFilter
(
SerialListener
::
endsWith
(
"post"
));
for
(
size_t
i
=
0
;
i
<
3
;
i
++
)
{
std
::
string
token
=
f2
->
wait
(
100
);
// Wait for 100 ms or a matched token
if
(
token
!=
""
)
std
::
cout
<<
"Found something ending with 'post'"
<<
std
::
endl
;
else
std
::
cout
<<
"Did not find something ending with 'post'"
<<
std
::
endl
;
}
}
// BlockingFilter is scoped and will remove itself, so no removeFilter
// required, but a call like `listener.removeFilter(BlockingFilter) will
// remove it from the filter list so wait will always timeout.
// Method #3:
// comparator, token buffer size - blocking
{
// Give it a comparator, then a buffer size of 10
BufferedFilterPtr
f3
=
listener
.
createBufferedFilter
(
SerialListener
::
contains
(
"substr"
),
10
);
SerialListener
::
sleep
(
75
);
// Sleep 75ms, should have about 7
std
::
cout
<<
"Caught "
<<
f3
->
count
();
std
::
cout
<<
" tokens containing 'substr'"
<<
std
::
endl
;
for
(
size_t
i
=
0
;
i
<
20
;
++
i
)
{
std
::
string
token
=
f3
->
wait
(
5
);
// Pull message from the buffer
if
(
token
==
""
)
// If an empty string is returned, a timeout occured
break
;
}
f3
->
clear
();
// Empties the buffer
if
(
f3
->
wait
(
0
)
==
""
)
// Non-blocking wait
std
::
cout
<<
"We won the race condition!"
<<
std
::
endl
;
else
std
::
cout
<<
"We lost the race condition..."
<<
std
::
endl
;
// The buffer is circular, so the oldest matches will be dropped first
}
// BufferedFilter is scoped and will remove itself just like BlockingFilter.
// Method #4:
// callback - async
// Gets called if a token doesn't match a filter
listener
.
setDefaultHandler
(
default_handler
);
SerialListener
::
sleep
(
25
);
// Sleep 25 ms, so some default callbacks occur
return
0
;
}
int
main
(
void
)
{
try
{
return
run
();
}
catch
(
std
::
exception
&
e
)
{
std
::
cerr
<<
e
.
what
()
<<
std
::
endl
;
return
1
;
}
}
This diff is collapsed.
Click to expand it.
include/serial/serial_listener.h
deleted
100644 → 0
View file @
f7cee5e1
This diff is collapsed.
Click to expand it.
serial.cmake
View file @
05fa4b8d
macro
(
build_serial
)
## Project Setup
cmake_minimum_required
(
VERSION 2.4.6
)
if
(
COMMAND cmake_policy
)
cmake_policy
(
SET CMP0003 NEW
)
endif
(
COMMAND cmake_policy
)
project
(
Serial
)
## Configurations
# Use clang if available
IF
(
EXISTS /usr/bin/clang
)
set
(
CMAKE_CXX_COMPILER /usr/bin/clang++
)
set
(
CMAKE_OSX_DEPLOYMENT_TARGET
""
)
# set(CMAKE_CXX_FLAGS "-ferror-limit=5 -std=c++0x -stdlib=libc++")
set
(
CMAKE_CXX_FLAGS
"-ferror-limit=5 -Wall -Weffc++ -pedantic -pedantic-errors -Wextra -Wall -Waggregate-return -Wcast-align -Wcast-qual -Wchar-subscripts -Wcomment -Wconversion -Wdisabled-optimization -Wfloat-equal -Wformat -Wformat=2 -Wformat-nonliteral -Wformat-security -Wformat-y2k -Wimplicit -Wimport -Winit-self -Winline -Winvalid-pch -Wlong-long -Wmissing-braces -Wmissing-field-initializers -Wmissing-format-attribute -Wmissing-include-dirs -Wmissing-noreturn -Wpacked -Wparentheses -Wpointer-arith -Wredundant-decls -Wreturn-type -Wsequence-point -Wshadow -Wsign-compare -Wstack-protector -Wstrict-aliasing -Wstrict-aliasing=2 -Wswitch -Wswitch-default -Wswitch-enum -Wtrigraphs -Wuninitialized -Wunknown-pragmas -Wunreachable-code -Wunused -Wunused-function -Wunused-label -Wunused-parameter -Wunused-value -Wunused-variable -Wvariadic-macros -Wvolatile-register-var -Wwrite-strings"
)
set
(
CMAKE_BUILD_TYPE Debug
)
ENDIF
(
EXISTS /usr/bin/clang
)
option
(
SERIAL_BUILD_TESTS
"Build all of the Serial tests."
OFF
)
option
(
SERIAL_BUILD_EXAMPLES
"Build all of the Serial examples."
OFF
)
# Allow for building shared libs override
IF
(
NOT BUILD_SHARED_LIBS
)
set
(
BUILD_SHARED_LIBS OFF
)
ENDIF
(
NOT BUILD_SHARED_LIBS
)
# Set the default path for built executables to the "bin" directory
IF
(
NOT
DEFINED
(
EXECUTABLE_OUTPUT_PATH
))
set
(
EXECUTABLE_OUTPUT_PATH
${
PROJECT_SOURCE_DIR
}
/bin
)
ENDIF
(
NOT
DEFINED
(
EXECUTABLE_OUTPUT_PATH
))
# set the default path for built libraries to the "lib" directory
IF
(
NOT
DEFINED
(
LIBRARY_OUTPUT_PATH
))
set
(
LIBRARY_OUTPUT_PATH
${
PROJECT_SOURCE_DIR
}
/lib
)
ENDIF
(
NOT
DEFINED
(
LIBRARY_OUTPUT_PATH
))
## Configure the build system
# Add the include folder to the include path
include_directories
(
${
PROJECT_SOURCE_DIR
}
/include
)
# Add default source files
set
(
SERIAL_SRCS src/serial.cc src/impl/unix.cc src/serial_listener.cc
)
# Add default header files
set
(
SERIAL_HEADERS include/serial/serial.h include/serial/serial_listener.h
)
IF
(
UNIX
)
list
(
APPEND SERIAL_SRCS src/impl/unix.cc
)
list
(
APPEND SERIAL_HEADERS include/serial/impl/unix.h
)
ELSE
(
UNIX
)
ENDIF
(
UNIX
)
# Find Boost, if it hasn't already been found
IF
(
NOT Boost_FOUND OR NOT Boost_SYSTEM_FOUND OR NOT Boost_FILESYSTEM_FOUND OR NOT Boost_THREAD_FOUND
)
find_package
(
Boost COMPONENTS system filesystem thread REQUIRED
)
ENDIF
(
NOT Boost_FOUND OR NOT Boost_SYSTEM_FOUND OR NOT Boost_FILESYSTEM_FOUND OR NOT Boost_THREAD_FOUND
)
link_directories
(
${
Boost_LIBRARY_DIRS
}
)
include_directories
(
${
Boost_INCLUDE_DIRS
}
)
set
(
SERIAL_LINK_LIBS
${
Boost_SYSTEM_LIBRARY
}
${
Boost_FILESYSTEM_LIBRARY
}
${
Boost_THREAD_LIBRARY
}
)
## Build the Serial Library
# Compile the Library
add_library
(
serial
${
SERIAL_SRCS
}
${
SERIAL_HEADERS
}
)
target_link_libraries
(
serial
${
SERIAL_LINK_LIBS
}
)
IF
(
WIN32
)
target_link_libraries
(
serial wsock32
)
ENDIF
(
)
## Build Examples
# If asked to
IF
(
SERIAL_BUILD_EXAMPLES
)
# Compile the Serial Test program
add_executable
(
serial_example examples/serial_example.cc
)
# Link the Test program to the Serial library
target_link_libraries
(
serial_example serial
)
# Compile the Serial Listener Test program
add_executable
(
serial_listener_example
examples/serial_listener_example.cc
)
# Link the Test program to the Serial library
target_link_libraries
(
serial_listener_example serial
)
ENDIF
(
SERIAL_BUILD_EXAMPLES
)
## Build tests
# If asked to
IF
(
SERIAL_BUILD_TESTS
)
# Find Google Test
enable_testing
()
find_package
(
GTest REQUIRED
)
include_directories
(
${
GTEST_INCLUDE_DIRS
}
)
# Compile the Serial Listener Test program
add_executable
(
serial_listener_tests tests/serial_listener_tests.cc
)
add_executable
(
serial_tests tests/serial_tests.cc
)
# Link the Test program to the serial library
target_link_libraries
(
serial_listener_tests
${
GTEST_BOTH_LIBRARIES
}
serial
)
target_link_libraries
(
serial_tests
${
GTEST_BOTH_LIBRARIES
}
serial
)
# # See: http://code.google.com/p/googlemock/issues/detail?id=146
# add_definitions(-DGTEST_USE_OWN_TR1_TUPLE=1)
add_test
(
AllTestsIntest_serial serial_listener_tests
)
add_test
(
AllTestsIntest_serial serial_tests
)
ENDIF
(
SERIAL_BUILD_TESTS
)
## Setup install and uninstall
# Unless asked not to...
IF
(
NOT SERIAL_DONT_CONFIGURE_INSTALL
)
# Configure make install
IF
(
NOT CMAKE_INSTALL_PREFIX
)
SET
(
CMAKE_INSTALL_PREFIX /usr/local
)
ENDIF
(
NOT CMAKE_INSTALL_PREFIX
)
## Project Setup
cmake_minimum_required
(
VERSION 2.4.6
)
if
(
COMMAND cmake_policy
)
cmake_policy
(
SET CMP0003 NEW
)
endif
(
COMMAND cmake_policy
)
project
(
Serial
)
## Configurations
# Use clang if available
IF
(
EXISTS /usr/bin/clang
)
set
(
CMAKE_CXX_COMPILER /usr/bin/clang++
)
set
(
CMAKE_OSX_DEPLOYMENT_TARGET
""
)
set
(
SERIAL_BUILD_WARNINGS TRUE
)
IF
(
SERIAL_BUILD_WARNINGS
)
set
(
CMAKE_CXX_FLAGS
"-ferror-limit=5 -Wall -Weffc++ -pedantic -pedantic-errors -Wextra -Wall -Waggregate-return -Wcast-align -Wcast-qual -Wchar-subscripts -Wcomment -Wconversion -Wdisabled-optimization -Wfloat-equal -Wformat -Wformat=2 -Wformat-nonliteral -Wformat-security -Wformat-y2k -Wimplicit -Wimport -Winit-self -Winline -Winvalid-pch -Wlong-long -Wmissing-braces -Wmissing-field-initializers -Wmissing-format-attribute -Wmissing-include-dirs -Wmissing-noreturn -Wpacked -Wparentheses -Wpointer-arith -Wredundant-decls -Wreturn-type -Wsequence-point -Wshadow -Wsign-compare -Wstack-protector -Wstrict-aliasing -Wstrict-aliasing=2 -Wswitch -Wswitch-default -Wswitch-enum -Wtrigraphs -Wuninitialized -Wunknown-pragmas -Wunreachable-code -Wunused -Wunused-function -Wunused-label -Wunused-parameter -Wunused-value -Wunused-variable -Wvariadic-macros -Wvolatile-register-var -Wwrite-strings"
)
ELSE
(
SERIAL_BUILD_WARNINGS
)
set
(
CMAKE_CXX_FLAGS
"-ferror-limit=5"
)
ENDIF
(
SERIAL_BUILD_WARNINGS
)
set
(
CMAKE_BUILD_TYPE Debug
)
ENDIF
(
EXISTS /usr/bin/clang
)
option
(
SERIAL_BUILD_TESTS
"Build all of the Serial tests."
OFF
)
option
(
SERIAL_BUILD_EXAMPLES
"Build all of the Serial examples."
OFF
)
# Allow for building shared libs override
IF
(
NOT BUILD_SHARED_LIBS
)
set
(
BUILD_SHARED_LIBS OFF
)
ENDIF
(
NOT BUILD_SHARED_LIBS
)
# Set the default path for built executables to the "bin" directory
IF
(
NOT
DEFINED
(
EXECUTABLE_OUTPUT_PATH
))
set
(
EXECUTABLE_OUTPUT_PATH
${
PROJECT_SOURCE_DIR
}
/bin
)
ENDIF
(
NOT
DEFINED
(
EXECUTABLE_OUTPUT_PATH
))
# set the default path for built libraries to the "lib" directory
IF
(
NOT
DEFINED
(
LIBRARY_OUTPUT_PATH
))
set
(
LIBRARY_OUTPUT_PATH
${
PROJECT_SOURCE_DIR
}
/lib
)
ENDIF
(
NOT
DEFINED
(
LIBRARY_OUTPUT_PATH
))
## Configure the build system
# Add the include folder to the include path
include_directories
(
${
PROJECT_SOURCE_DIR
}
/include
)
# Add default source files
set
(
SERIAL_SRCS src/serial.cc
)
IF
(
WIN32
)
list
(
APPEND SERIAL_SRCS src/impl/windows.cc
)
ELSE
(
WIN32
)
list
(
APPEND SERIAL_SRCS src/impl/unix.cc
)
ENDIF
(
WIN32
)
# Add default header files
set
(
SERIAL_HEADERS include/serial/serial.h
)
## Build the Serial Library
# Compile the Library
add_library
(
serial
${
SERIAL_SRCS
}
)
## Build Examples
# If asked to
IF
(
SERIAL_BUILD_EXAMPLES
)
# Compile the Serial Test program
add_executable
(
serial_example examples/serial_example.cc
)
# Link the Test program to the Serial library
target_link_libraries
(
serial_example serial
)
ENDIF
(
SERIAL_BUILD_EXAMPLES
)
## Build tests
# If asked to
IF
(
SERIAL_BUILD_TESTS
)
# Find Google Test
enable_testing
()
find_package
(
GTest REQUIRED
)
include_directories
(
${
GTEST_INCLUDE_DIRS
}
)
# Compile the Serial Test program
add_executable
(
serial_tests tests/serial_tests.cc
)
# Link the Test program to the serial library
target_link_libraries
(
serial_tests
${
GTEST_BOTH_LIBRARIES
}
serial
)
add_test
(
AllTestsIntest_serial serial_tests
)
ENDIF
(
SERIAL_BUILD_TESTS
)
## Setup install and uninstall
# Unless asked not to...
IF
(
NOT SERIAL_DONT_CONFIGURE_INSTALL
)
# Configure make install
IF
(
NOT CMAKE_INSTALL_PREFIX
)
SET
(
CMAKE_INSTALL_PREFIX /usr/local
)
ENDIF
(
NOT CMAKE_INSTALL_PREFIX
)
INSTALL
(
TARGETS serial
RUNTIME DESTINATION bin
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
)
INSTALL
(
TARGETS serial
RUNTIME DESTINATION bin
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
)
INSTALL
(
FILES include/serial/serial.h
include/serial/serial_listener.h
DESTINATION include/serial
)
INSTALL
(
FILES include/serial/serial.h
DESTINATION include/serial
)
IF
(
NOT CMAKE_FIND_INSTALL_PATH
)
set
(
CMAKE_FIND_INSTALL_PATH
${
CMAKE_ROOT
}
)
ENDIF
(
NOT CMAKE_FIND_INSTALL_PATH
)
IF
(
NOT CMAKE_FIND_INSTALL_PATH
)
set
(
CMAKE_FIND_INSTALL_PATH
${
CMAKE_ROOT
}
)
ENDIF
(
NOT CMAKE_FIND_INSTALL_PATH
)
INSTALL
(
FILES Findserial.cmake DESTINATION
${
CMAKE_FIND_INSTALL_PATH
}
/Modules/
)
INSTALL
(
FILES Findserial.cmake
DESTINATION
${
CMAKE_FIND_INSTALL_PATH
}
/Modules/
)
ADD_CUSTOM_TARGET
(
uninstall @echo uninstall package
)
ADD_CUSTOM_TARGET
(
uninstall @echo uninstall package
)
IF
(
UNIX
)
ADD_CUSTOM_COMMAND
(
COMMENT
"uninstall package"
COMMAND xargs ARGS rm < install_manifest.txt
IF
(
UNIX
)
ADD_CUSTOM_COMMAND
(
COMMENT
"uninstall package"
COMMAND xargs ARGS rm < install_manifest.txt
TARGET uninstall
)
ELSE
(
UNIX
)
ADD_CUSTOM_COMMAND
(
COMMENT
"uninstall only implemented in unix"
TARGET uninstall
)
ENDIF
(
UNIX
)
ENDIF
(
NOT SERIAL_DONT_CONFIGURE_INSTALL
)
TARGET uninstall
)
ELSE
(
UNIX
)
ADD_CUSTOM_COMMAND
(
COMMENT
"uninstall only implemented in unix"
TARGET uninstall
)
ENDIF
(
UNIX
)
ENDIF
(
NOT SERIAL_DONT_CONFIGURE_INSTALL
)
endmacro
(
build_serial
)
This diff is collapsed.
Click to expand it.
serial.makefile
View file @
05fa4b8d
...
...
@@ -37,4 +37,4 @@ ifneq ($(MAKE),)
else
cd build && make
endif
cd bin && ./serial_listener_tests
\ No newline at end of file
cd bin && ./serial_tests
\ No newline at end of file
This diff is collapsed.
Click to expand it.
serial_ros.cmake
View file @
05fa4b8d
macro
(
build_serial
)
cmake_minimum_required
(
VERSION 2.4.6
)
include
(
$ENV{ROS_ROOT}/core/rosbuild/rosbuild.cmake
)
# Set the build type. Options are:
# Coverage : w/ debug symbols, w/o optimization, w/ code-coverage
# Debug : w/ debug symbols, w/o optimization
# Release : w/o debug symbols, w/ optimization
# RelWithDebInfo : w/ debug symbols, w/ optimization
# MinSizeRel : w/o debug symbols, w/ optimization, stripped binaries
set
(
ROS_BUILD_TYPE RelWithDebInfo
)
rosbuild_init
()
#set the default path for built executables to the "bin" directory
set
(
EXECUTABLE_OUTPUT_PATH
${
PROJECT_SOURCE_DIR
}
/bin
)
#set the default path for built libraries to the "lib" directory
set
(
LIBRARY_OUTPUT_PATH
${
PROJECT_SOURCE_DIR
}
/lib
)
include_directories
(
include
)
set
(
SERIAL_SRCS src/serial.cc
)
if
(
UNIX
)
list
(
APPEND SERIAL_SRCS src/impl/unix.cc
)
else
(
UNIX
)
list
(
APPEND SERIAL_SRCS src/impl/windows.cc
)
endif
(
UNIX
)
list
(
APPEND SERIAL_SRCS src/serial_listener.cc
)
# Build the serial library
rosbuild_add_library
(
${
PROJECT_NAME
}
${
SERIAL_SRCS
}
)
# Add boost dependencies
rosbuild_add_boost_directories
()
rosbuild_link_boost
(
${
PROJECT_NAME
}
system filesystem thread
)
# Build example
rosbuild_add_executable
(
serial_example examples/serial_example.cc
)
target_link_libraries
(
serial_example
${
PROJECT_NAME
}
)
rosbuild_add_executable
(
serial_listener_example
examples/serial_listener_example.cc
)
target_link_libraries
(
serial_listener_example
${
PROJECT_NAME
}
)
# Create unit tests
rosbuild_add_gtest
(
serial_tests tests/serial_tests.cc
)
target_link_libraries
(
serial_tests
${
PROJECT_NAME
}
)
rosbuild_add_gtest
(
serial_listener_tests tests/serial_listener_tests.cc
)
target_link_libraries
(
serial_listener_tests
${
PROJECT_NAME
}
)
cmake_minimum_required
(
VERSION 2.4.6
)
include
(
$ENV{ROS_ROOT}/core/rosbuild/rosbuild.cmake
)
# Set the build type. Options are:
# Coverage : w/ debug symbols, w/o optimization, w/ code-coverage
# Debug : w/ debug symbols, w/o optimization
# Release : w/o debug symbols, w/ optimization
# RelWithDebInfo : w/ debug symbols, w/ optimization
# MinSizeRel : w/o debug symbols, w/ optimization, stripped binaries
set
(
ROS_BUILD_TYPE RelWithDebInfo
)
rosbuild_init
()
#set the default path for built executables to the "bin" directory
set
(
EXECUTABLE_OUTPUT_PATH
${
PROJECT_SOURCE_DIR
}
/bin
)
#set the default path for built libraries to the "lib" directory
set
(
LIBRARY_OUTPUT_PATH
${
PROJECT_SOURCE_DIR
}
/lib
)
include_directories
(
include
)
set
(
SERIAL_SRCS src/serial.cc
)
if
(
UNIX
)
list
(
APPEND SERIAL_SRCS src/impl/unix.cc
)
else
(
UNIX
)
list
(
APPEND SERIAL_SRCS src/impl/winows.cc
)
endif
(
UNIX
)
# Build the serial library
rosbuild_add_library
(
${
PROJECT_NAME
}
${
SERIAL_SRCS
}
)
# Build example
rosbuild_add_executable
(
serial_example examples/serial_example.cc
)
target_link_libraries
(
serial_example
${
PROJECT_NAME
}
)
# Create unit tests
rosbuild_add_gtest
(
serial_tests tests/serial_tests.cc
)
target_link_libraries
(
serial_tests
${
PROJECT_NAME
}
)
endmacro
(
build_serial
)
This diff is collapsed.
Click to expand it.
src/serial_listener.cc
deleted
100644 → 0
View file @
f7cee5e1
/* Copyright 2012 William Woodall and John Harrison */
#include "serial/serial_listener.h"
/***** Inline Functions *****/
inline
void
defaultExceptionCallback
(
const
std
::
exception
&
error
)
{
std
::
cerr
<<
"SerialListener Unhandled Exception: "
<<
error
.
what
();
std
::
cerr
<<
std
::
endl
;
}
inline
bool
defaultComparator
(
const
std
::
string
&
token
)
{
return
token
==
token
;
}
using
namespace
serial
;
/***** Listener Class Functions *****/
void
SerialListener
::
default_handler
(
const
std
::
string
&
token
)
{
if
(
this
->
_default_handler
)
this
->
_default_handler
(
token
);
}
SerialListener
::
SerialListener
()
:
listening
(
false
),
chunk_size_
(
5
)
{
// Set default callbacks
this
->
handle_exc
=
defaultExceptionCallback
;
// Default handler stuff
this
->
_default_handler
=
NULL
;
this
->
default_comparator
=
defaultComparator
;
DataCallback
tmp
=
boost
::
bind
(
&
SerialListener
::
default_handler
,
this
,
_1
);
this
->
default_filter
=
FilterPtr
(
new
Filter
(
default_comparator
,
tmp
));
// Set default tokenizer
this
->
setTokenizer
(
delimeter_tokenizer
(
"
\r
"
));
}
SerialListener
::~
SerialListener
()
{
if
(
this
->
listening
)
{
this
->
stopListening
();
}
}
void
SerialListener
::
callback
()
{
try
{
// <filter id, token>
std
::
pair
<
FilterPtr
,
TokenPtr
>
pair
;
while
(
this
->
listening
)
{
if
(
this
->
callback_queue
.
timed_wait_and_pop
(
pair
,
10
))
{
if
(
this
->
listening
)
{
try
{
if
(
pair
.
first
!=
NULL
&&
pair
.
second
!=
NULL
)
{
pair
.
first
->
callback_
((
*
pair
.
second
));
}
}
catch
(
std
::
exception
&
e
)
{
this
->
handle_exc
(
e
);
}
// try callback
}
// if listening
}
// if popped
}
// while (this->listening)
}
catch
(
std
::
exception
&
e
)
{
this
->
handle_exc
(
SerialListenerException
(
e
.
what
()));
}
}
void
SerialListener
::
startListening
(
Serial
&
serial_port
)
{
if
(
this
->
listening
)
{
throw
(
SerialListenerException
(
"Already listening."
));
return
;
}
this
->
listening
=
true
;
this
->
serial_port_
=
&
serial_port
;
if
(
!
this
->
serial_port_
->
isOpen
())
{
throw
(
SerialListenerException
(
"Serial port not open."
));
return
;
}
listen_thread
=
boost
::
thread
(
boost
::
bind
(
&
SerialListener
::
listen
,
this
));
// Start the callback thread
callback_thread
=
boost
::
thread
(
boost
::
bind
(
&
SerialListener
::
callback
,
this
));
}
void
SerialListener
::
stopListening
()
{
// Stop listening and clear buffers
listening
=
false
;
listen_thread
.
join
();
callback_thread
.
join
();
this
->
data_buffer
=
""
;
this
->
serial_port_
=
NULL
;
}
size_t
SerialListener
::
determineAmountToRead
()
{
// TODO: Make a more intelligent method based on the length of the things
// filters are looking for. e.g.: if the filter is looking for 'V=XX\r'
// make the read amount at least 5.
return
this
->
chunk_size_
;
}
void
SerialListener
::
filter
(
std
::
vector
<
TokenPtr
>
&
tokens
)
{
// Lock the filters while filtering
boost
::
mutex
::
scoped_lock
lock
(
filter_mux
);
// Iterate through each new token and filter them
std
::
vector
<
TokenPtr
>::
iterator
it
;
for
(
it
=
tokens
.
begin
();
it
!=
tokens
.
end
();
it
++
)
{
TokenPtr
token
=
(
*
it
);
// If it is empty then pass it
if
(
token
->
empty
())
{
continue
;
}
bool
matched
=
false
;
// Iterate through each filter
std
::
vector
<
FilterPtr
>::
iterator
itt
;
for
(
itt
=
filters
.
begin
();
itt
!=
filters
.
end
();
itt
++
)
{
FilterPtr
filter
=
(
*
itt
);
if
(
filter
->
comparator_
((
*
token
)))
{
callback_queue
.
push
(
std
::
make_pair
(
filter
,
token
));
matched
=
true
;
break
;
}
}
// for (itt=filters.begin(); itt!=filters.end(); itt++)
// If matched is false then send it to the default handler
if
(
!
matched
)
{
callback_queue
.
push
(
std
::
make_pair
(
default_filter
,
token
));
}
}
// for (it=tokens.begin(); it!=tokens.end(); it++)
}
void
SerialListener
::
listen
()
{
try
{
while
(
this
->
listening
)
{
// Read some data
std
::
string
temp
;
this
->
readSomeData
(
temp
,
determineAmountToRead
());
// If nothing was read then we
// don't need to iterate through the filters
if
(
temp
.
length
()
!=
0
)
{
// Add the new data to the buffer
this
->
data_buffer
+=
temp
;
// Call the tokenizer on the updated buffer
std
::
vector
<
TokenPtr
>
new_tokens
;
this
->
tokenize
(
this
->
data_buffer
,
new_tokens
);
// Put the last token back in the data buffer
this
->
data_buffer
=
(
*
new_tokens
.
back
());
new_tokens
.
pop_back
();
// Run the new tokens through existing filters
this
->
filter
(
new_tokens
);
}
// Done parsing lines and buffer should now be set to the left overs
}
// while (this->listening)
}
catch
(
std
::
exception
&
e
)
{
this
->
handle_exc
(
SerialListenerException
(
e
.
what
()));
}
}
/***** Filter Functions *****/
FilterPtr
SerialListener
::
createFilter
(
ComparatorType
comparator
,
DataCallback
callback
)
{
FilterPtr
filter_ptr
(
new
Filter
(
comparator
,
callback
));
boost
::
mutex
::
scoped_lock
l
(
filter_mux
);
this
->
filters
.
push_back
(
filter_ptr
);
return
filter_ptr
;
}
BlockingFilterPtr
SerialListener
::
createBlockingFilter
(
ComparatorType
comparator
)
{
return
BlockingFilterPtr
(
new
BlockingFilter
(
comparator
,
(
*
this
)));
}
BufferedFilterPtr
SerialListener
::
createBufferedFilter
(
ComparatorType
comparator
,
size_t
buffer_size
)
{
return
BufferedFilterPtr
(
new
BufferedFilter
(
comparator
,
buffer_size
,
(
*
this
)));
}
void
SerialListener
::
removeFilter
(
FilterPtr
filter_ptr
)
{
boost
::
mutex
::
scoped_lock
l
(
filter_mux
);
filters
.
erase
(
std
::
find
(
filters
.
begin
(),
filters
.
end
(),
filter_ptr
));
}
void
SerialListener
::
removeFilter
(
BlockingFilterPtr
blocking_filter
)
{
this
->
removeFilter
(
blocking_filter
->
filter_ptr
);
}
void
SerialListener
::
removeFilter
(
BufferedFilterPtr
buffered_filter
)
{
this
->
removeFilter
(
buffered_filter
->
filter_ptr
);
}
void
SerialListener
::
removeAllFilters
()
{
boost
::
mutex
::
scoped_lock
l
(
filter_mux
);
filters
.
clear
();
callback_queue
.
clear
();
}
This diff is collapsed.
Click to expand it.
tests/serial_listener_tests.cc
deleted
100644 → 0
View file @
f7cee5e1
/* To run these tests you need to change the define below to the serial port
* with a loop back device attached.
*
* Alternatively you could use an Arduino:
*
* void setup()
* {
* Serial.begin(115200);
* }
*
* void loop()
* {
* while (Serial.available() > 0) {
* Serial.write(Serial.read());
* }
* }
*
*/
// #define SERIAL_PORT_NAME "/dev/tty.usbserial-A900cfJA"
#define SERIAL_PORT_NAME "p0"
#include "gtest/gtest.h"
#include <boost/bind.hpp>
// OMG this is so nasty...
#define private public
#define protected public
#include "serial/serial_listener.h"
using
namespace
serial
;
static
size_t
global_count
,
global_listen_count
;
static
bool
matched
;
void
filter_handler
(
std
::
string
token
)
{
global_listen_count
++
;
std
::
cout
<<
"filter_handler got: "
<<
token
<<
std
::
endl
;
}
void
default_handler
(
std
::
string
line
)
{
global_count
++
;
std
::
cout
<<
"default_handler got: "
<<
line
<<
std
::
endl
;
}
namespace
{
void
my_sleep
(
long
milliseconds
)
{
boost
::
this_thread
::
sleep
(
boost
::
posix_time
::
milliseconds
(
milliseconds
));
}
class
SerialListenerTests
:
public
::
testing
::
Test
{
protected:
virtual
void
SetUp
()
{
port1
=
new
Serial
(
"/dev/pty"
SERIAL_PORT_NAME
,
115200
,
10
);
port2
=
new
Serial
(
"/dev/tty"
SERIAL_PORT_NAME
,
115200
,
250
);
listener
.
setDefaultHandler
(
default_handler
);
listener
.
startListening
((
*
port1
));
}
virtual
void
TearDown
()
{
listener
.
stopListening
();
delete
port1
;
delete
port2
;
}
SerialListener
listener
;
Serial
*
port1
;
Serial
*
port2
;
};
TEST_F
(
SerialListenerTests
,
handlesPartialMessage
)
{
global_count
=
0
;
std
::
string
input_str
=
"?$1E
\r
$1E=Robo"
;
std
::
cout
<<
"writing: ?$1E<cr>$1E=Robo"
<<
std
::
endl
;
port2
->
write
(
input_str
);
// Allow time for processing
my_sleep
(
50
);
ASSERT_EQ
(
1
,
global_count
);
input_str
=
"?$1E
\r
$1E=Roboteq
\r
"
;
std
::
cout
<<
"writing: ?$1E<cr>$1E=Roboteq<cr>"
<<
std
::
endl
;
port2
->
write
(
input_str
);
// Allow time for processing
my_sleep
(
50
);
ASSERT_EQ
(
3
,
global_count
);
}
TEST_F
(
SerialListenerTests
,
normalFilterWorks
)
{
global_count
=
0
;
global_listen_count
=
0
;
std
::
string
input_str
=
"?$1E
\r
$1E=Robo
\r
V=1334:1337
\r
T=123"
;
// Setup filter
FilterPtr
filt_1
=
listener
.
createFilter
(
SerialListener
::
startsWith
(
"V="
),
filter_handler
);
std
::
cout
<<
"writing: ?$1E<cr>$1E=Robo<cr>V=1334:1337<cr>T=123"
;
std
::
cout
<<
std
::
endl
;
port2
->
write
(
input_str
);
// Allow time for processing
my_sleep
(
50
);
ASSERT_EQ
(
2
,
global_count
);
ASSERT_EQ
(
1
,
global_listen_count
);
}
void
run_blocking_filter
(
BlockingFilterPtr
filt_1
)
{
// Wait 100 ms for a match
std
::
string
temp
=
filt_1
->
wait
(
100
);
if
(
temp
.
empty
())
{
return
;
}
std
::
cout
<<
"blocking filter matched: "
<<
temp
<<
std
::
endl
;
global_listen_count
++
;
matched
=
true
;
}
TEST_F
(
SerialListenerTests
,
blockingFilterWorks
)
{
global_count
=
0
;
global_listen_count
=
0
;
matched
=
false
;
std
::
string
input_str
=
"?$1E
\r
$1E=Robo
\r
V=1334:1337
\r
T=123"
;
// Setup blocking filter
BlockingFilterPtr
filt_1
=
listener
.
createBlockingFilter
(
SerialListener
::
startsWith
(
"$1E="
));
boost
::
thread
t
(
boost
::
bind
(
run_blocking_filter
,
filt_1
));
std
::
cout
<<
"writing: ?$1E<cr>$1E=Robo<cr>V=1334:1337<cr>T=123"
;
std
::
cout
<<
std
::
endl
;
port2
->
write
(
input_str
);
// Allow time for processing
my_sleep
(
50
);
using
boost
::
posix_time
::
milliseconds
;
ASSERT_TRUE
(
t
.
timed_join
(
milliseconds
(
10
)));
ASSERT_EQ
(
2
,
global_count
);
ASSERT_EQ
(
1
,
global_listen_count
);
ASSERT_TRUE
(
matched
);
}
TEST_F
(
SerialListenerTests
,
blockingFilterTimesOut
)
{
global_count
=
0
;
global_listen_count
=
0
;
matched
=
false
;
std
::
string
input_str
=
"?$1E
\r
$1E=Robo
\r
V=1334:1337
\r
T=123"
;
// Setup blocking filter
BlockingFilterPtr
filt_1
=
listener
.
createBlockingFilter
(
SerialListener
::
startsWith
(
"T="
));
boost
::
thread
t
(
boost
::
bind
(
run_blocking_filter
,
filt_1
));
std
::
cout
<<
"writing: ?$1E<cr>$1E=Robo<cr>V=1334:1337<cr>T=123"
;
std
::
cout
<<
std
::
endl
;
port2
->
write
(
input_str
);
// Allow time for processing
my_sleep
(
50
);
using
boost
::
posix_time
::
milliseconds
;
// First one should not be within timeout, should be false
ASSERT_FALSE
(
t
.
timed_join
(
milliseconds
(
10
)));
// Second one should capture timeout and return true to join
ASSERT_TRUE
(
t
.
timed_join
(
milliseconds
(
60
)));
ASSERT_EQ
(
3
,
global_count
);
ASSERT_EQ
(
0
,
global_listen_count
);
ASSERT_FALSE
(
matched
);
}
void
write_later
(
Serial
*
port
,
std
::
string
input_str
,
long
wait_for
)
{
my_sleep
(
wait_for
);
port
->
write
(
input_str
);
}
TEST_F
(
SerialListenerTests
,
bufferedFilterWorks
)
{
global_count
=
0
;
std
::
string
input_str
=
"?$1E
\r
+
\r
$1E=Robo
\r
V=1334:1337
\r
T=123"
;
// Setup buffered filter, buffer size 3
BufferedFilterPtr
filt_1
=
listener
.
createBufferedFilter
(
SerialListener
::
exactly
(
"+"
),
3
);
// Write the string to the port 10 ms in the future
boost
::
thread
t
(
boost
::
bind
(
write_later
,
port2
,
input_str
,
10
));
// This should be empty because of a timeout
ASSERT_TRUE
(
filt_1
->
wait
(
2
).
empty
());
// Make sure wait works properly
ASSERT_EQ
(
"+"
,
filt_1
->
wait
(
20
));
// This should be empty cause there was only one
ASSERT_TRUE
(
filt_1
->
wait
(
2
).
empty
());
// The queue in the filter should be empty
ASSERT_EQ
(
0
,
filt_1
->
queue
.
size
());
ASSERT_EQ
(
3
,
global_count
);
t
.
join
();
}
TEST_F
(
SerialListenerTests
,
bufferedFilterQueueWorks
)
{
global_count
=
0
;
std
::
string
input_str
=
"?$1E$
\r
+
\r
$1E=Robo$
\r
V=1334:1337$
\r
T=123$
\r
"
;
// Setup buffered filter, buffer size 3
BufferedFilterPtr
filt_1
=
listener
.
createBufferedFilter
(
SerialListener
::
endsWith
(
"$"
),
3
);
// write the string
port2
->
write
(
input_str
);
my_sleep
(
20
);
// Let things process
// There should have been four matches
// therefore the first one should the second match.
ASSERT_EQ
(
"$1E=Robo$"
,
filt_1
->
wait
(
1
));
ASSERT_EQ
(
"V=1334:1337$"
,
filt_1
->
wait
(
1
));
ASSERT_EQ
(
"T=123$"
,
filt_1
->
wait
(
1
));
ASSERT_EQ
(
0
,
filt_1
->
queue
.
size
());
ASSERT_EQ
(
1
,
global_count
);
}
}
// namespace
int
main
(
int
argc
,
char
**
argv
)
{
try
{
::
testing
::
InitGoogleTest
(
&
argc
,
argv
);
return
RUN_ALL_TESTS
();
}
catch
(
std
::
exception
&
e
)
{
std
::
cerr
<<
"Unhandled Exception: "
<<
e
.
what
()
<<
std
::
endl
;
}
return
1
;
}
This diff is collapsed.
Click to expand it.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment