Getting Started - igor-krechetov/hsmcpp Wiki

Original URL: https://github.com/igor-krechetov/hsmcpp/wiki/Getting-Started

Contents

Overview

There are 2 ways to add hsmcpp library to your project:

Building

Requirements

Ubuntu

Simplest way to build hsmcpp is to run build.sh script:

git clone https://github.com/igor-krechetov/hsmcpp.git
cd ./hsmcpp
./build.sh

Windows

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.

Possible build options

Options can be applied when calling cmake:

cmake -DHSMBUILD_TESTS=OFF -DHSMBUILD_EXAMPLES=OFF ..

Hello World!

Let's create the smallest state machine which would represent a switch button:

00_helloworld

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;
}

CMake script (pkg-config)

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})

CMake script (as source code)

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})

CMake script (download from GitHub)

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:

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})