-
Notifications
You must be signed in to change notification settings - Fork 16
Getting Started
There are 2 ways to add hsmcpp library to your project:
- compile, install and use library through pkg-config;
- add hsmcpp repository as a subfolder in your project and compile it together with your project.
- CMake 3.14+
- Python 3
Simplest way to build hsmcpp is to run build.sh script:
git clone https://github.com/igor-krechetov/hsmcpp.git
cd ./hsmcpp
./build.sh
You can build hsmcpp with any tools that you have, but provided script build_vs.cmd requires Visual Studio 2015 or newer. Make sure to set correct path to your Visual Studio directory in build_vs.cmd:
call "c:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" x86
By default only STD based dispatcher is enabled. To enable Qt based one uncomment following lines and change path to match your Qt directory:
set Qt5_DIR=C:\Qt\5.9\5.9.2\msvc2015\lib\cmake\Qt5
cmake -DHSMBUILD_DISPATCHER_GLIB=OFF -DHSMBUILD_DISPATCHER_GLIBMM=OFF ..
To build GLib and GLibmm based dispatchers you will need to provide pkg-config and corresponding libraries yourself.
- HSMBUILD_VERBOSE: Enable/disable HSM verbosity (usually OFF since it's only needed for hsmcpp development)
- HSMBUILD_STRUCTURE_VALIDATION: Enable/disable HSM structure validation
- HSMBUILD_THREAD_SAFETY: Enable/disable HSM thread safety
- HSMBUILD_DEBUGGING: Enable/disable support for HSM debugging using hsmdebugger (recommended to turn off in production build)
- HSMBUILD_DISPATCHER_GLIB: Enable GLib dispatcher
- HSMBUILD_DISPATCHER_GLIBMM: Enable GLibmm dispatcher
- HSMBUILD_DISPATCHER_STD: Enable std::thread based dispatcher
- HSMBUILD_DISPATCHER_QT: Enable Qt based dispatcher
- HSMBUILD_TESTS: Build unittests
- HSMBUILD_EXAMPLES: Build examples
Options can be applied when calling cmake:
cmake -DHSMBUILD_TESTS=OFF -DHSMBUILD_EXAMPLES=OFF ..
Let's create the smallest state machine which would represent a switch button:
For more complex examples see /examples folder.
For simplicity we are going to use STD dispatcher to avoid additional dependencies. Source code is available in /examples/00_helloworld/00_helloworld_std.cpp
#include <chrono>
#include <thread>
#include <hsmcpp/hsm.hpp>
#include <hsmcpp/HsmEventDispatcherSTD.hpp>
using namespace std::chrono_literals;
enum class States
{
OFF,
ON
};
enum class Events
{
SWITCH
};
int main(const int argc, const char**argv)
{
std::shared_ptr<HsmEventDispatcherSTD> dispatcher = std::make_shared<HsmEventDispatcherSTD>();
HierarchicalStateMachine<States, Events> hsm(States::OFF);
hsm.initialize(dispatcher);
hsm.registerState(States::OFF, [&hsm](const VariantVector_t& args)
{
printf("Off\n");
std::this_thread::sleep_for(1000ms);
hsm.transition(Events::SWITCH);
});
hsm.registerState(States::ON, [&hsm](const VariantVector_t& args)
{
printf("On\n");
std::this_thread::sleep_for(1000ms);
hsm.transition(Events::SWITCH);
});
hsm.registerTransition(States::OFF, States::ON, Events::SWITCH);
hsm.registerTransition(States::ON, States::OFF, Events::SWITCH);
hsm.transition(Events::SWITCH);
dispatcher->join();
return 0;
}
To use hsmcpp as a pkg-config module you can follow template: /examples/cmake_templates/CMakeLists_pkgconfig.txt
# This is example showing how to use hsmcpp through pkg-config
cmake_minimum_required(VERSION 2.6)
project(example)
set(BINARY_NAME "example")
set(CMAKE_CXX_STANDARD 14)
# Find HSMCPP package
include(FindPkgConfig)
pkg_check_modules(HSMCPP REQUIRED hsmcpp_std)
# Apply HSMCPP definitions
add_definitions(${HSMCPP_CFLAGS_OTHER})
add_executable(${BINARY_NAME} main.cpp)
# Add HSMCPP include directory
target_include_directories(${BINARY_NAME} PUBLIC ${HSMCPP_INCLUDE_DIRS})
# Link with HSMCPP library
target_link_libraries(${BINARY_NAME} PUBLIC ${HSMCPP_LDFLAGS})
To compile hsmcpp together with your project you can follow template: /examples/cmake_templates/CMakeLists_pkgconfig.txt
# This is an example showing how to use hsmcpp library as a source code
cmake_minimum_required(VERSION 2.6)
project(example)
set(BINARY_NAME "example")
set(CMAKE_CXX_STANDARD 14)
# Configure HSMCPP library
SET(HSMBUILD_EXAMPLES OFF CACHE BOOL "Disable HSM examples")
SET(HSMBUILD_TESTS OFF CACHE BOOL "Disable HSM tests")
SET(HSMBUILD_DISPATCHER_GLIB OFF CACHE BOOL "Disable Glib dispatcher")
SET(HSMBUILD_DISPATCHER_GLIBMM OFF CACHE BOOL "Disable Glibmm dispatcher")
SET(HSMBUILD_DISPATCHER_QT OFF CACHE BOOL "Disable Qt dispatcher")
SET(HSMBUILD_DISPATCHER_STD ON CACHE BOOL "Enable STD dispatcher")
# Include hsmcpp directory (this is folder where hsmcpp code was checked out from Git)
add_subdirectory(hsmcpp)
# Apply compiler flags needed for HSMCPP
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${HSMCPP_CXX_FLAGS}")
# Apply HSMCPP definitions
add_definitions(${HSM_DEFINITIONS_STD})
add_executable(${BINARY_NAME} main.cpp)
# Add HSMCPP include directory
target_include_directories(${BINARY_NAME} PUBLIC ${HSMCPP_STD_INCLUDE})
# Link with HSMCPP library
target_link_libraries(${BINARY_NAME} PUBLIC ${HSMCPP_STD_LIB})
Maybe the easiest option to use hsmcpp in your project is to download it directly from GitHub and compile it together with your application. The downsides of this approach are:
- dependency on Internet connection availability and GitHub;
- a bit longer clean build time due to the necessity to download hsmcpp library files (since files are stored in your temporary build folder).
You can use this CMake template: /examples/cmake_templates/CMakeLists_fetch.txt
# This is an example showing how to use hsmcpp library directly from GitHub
cmake_minimum_required(VERSION 2.6)
project(example)
set(BINARY_NAME "example")
set(CMAKE_CXX_STANDARD 14)
# wrapper function to download hsmcpp
function(installHsmcpp)
include(FetchContent)
message("Downloading hsmcpp...")
FetchContent_Declare(hsmcpp
GIT_REPOSITORY https://github.com/igor-krechetov/hsmcpp.git
GIT_TAG main
)
FetchContent_MakeAvailable(hsmcpp)
endfunction()
# Configure and install HSMCPP library
SET(HSMBUILD_EXAMPLES OFF CACHE BOOL "Disable HSM examples")
SET(HSMBUILD_TESTS OFF CACHE BOOL "Disable HSM tests")
SET(HSMBUILD_DISPATCHER_GLIB OFF CACHE BOOL "Disable Glib dispatcher")
SET(HSMBUILD_DISPATCHER_GLIBMM OFF CACHE BOOL "Disable Glibmm dispatcher")
SET(HSMBUILD_DISPATCHER_QT OFF CACHE BOOL "Disable Qt dispatcher")
SET(HSMBUILD_DISPATCHER_STD ON CACHE BOOL "Enable STD dispatcher")
installHsmcpp()
# ----------------------------------------------------------------------
# Application specific code. This is just an example it there are no restrictions to use it specifically in this way
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${HSMCPP_CXX_FLAGS}")
set(BINARY_NAME "myapplication")
# add defined needed by HSMCPP (based on your dispatcher type)
add_definitions(${HSM_DEFINITIONS_STD})
add_executable(${BINARY_NAME} main.cpp ${GEN_SRC})
# generate state machine code (optional)
set(GEN_DIR ${CMAKE_BINARY_DIR}/gen)
file(MAKE_DIRECTORY ${GEN_DIR})
generateHsm(GEN_HSM ./statemachine.scxml "MyStateMachine" ${GEN_DIR} "GEN_SRC")
add_dependencies(${BINARY_NAME} GEN_HSM)
# generate state machine diagram (optional)
set(GEN_DIR_DIAGRAM ${CMAKE_BINARY_DIR}/gen_diagram)
file(MAKE_DIRECTORY ${GEN_DIR_DIAGRAM})
generateHsmDiagram(GEN_HSM_DIAGRAM ./statemachine.scxml ${GEN_DIR_DIAGRAM}/statemachine.plantuml)
add_dependencies(${BINARY_NAME} GEN_HSM_DIAGRAM)
target_include_directories(${BINARY_NAME}
PRIVATE
${HSMCPP_STD_INCLUDE} # add HSMCPP to include path
${CMAKE_BINARY_DIR}
)
# link with HSMCPP library (based on used dispatcher)
target_link_libraries(${BINARY_NAME} PRIVATE ${HSMCPP_STD_LIB})
# set compiler options for HSMCPP library (based on used dispatcher)
target_compile_options(${BINARY_NAME} PRIVATE ${HSMCPP_STD_CXX_FLAGS})