State machine definition

Asset Tracker Template

tags
Asset Tracker Template

SMF supports defining a hierarchy of states. For example, the network module's states can be graphically described as follows:

Network module state diagram

In the diagram, the black dots with arrows indicate initial transitions. In this case, the initial state of the machine is set to the top-level STATE_RUNNING state. In the state definitions, initial transitions are configured such that the state machine ends up in STATE_DISCONNECTED_SEARCHING when first initialized.

In SMF, a single state is defined using the SMF_CREATE_STATE macro. You can specify the following parameters:

  • Entry function: Called when entering the state.
  • Run function: Called when processing a message while in the state.
  • Exit function: Called when leaving the state.
  • Parent state: Another state to which this state is subordinate.
  • Initial state transition: Another state to transition to immediately after entry.

The following shows the definitions of all the states in the Network module from app/src/modules/network/network.c, with parent states and initial transitions as shown in the diagram:

static const struct smf_state states[] = {
        [STATE_RUNNING] =
                SMF_CREATE_STATE(state_running_entry, state_running_run, NULL,
                                 NULL,  /* No parent state */
                                 &states[STATE_DISCONNECTED]),
        [STATE_DISCONNECTED] =
                SMF_CREATE_STATE(state_disconnected_entry, state_disconnected_run, NULL,
                                 &states[STATE_RUNNING],
                                 &states[STATE_DISCONNECTED_SEARCHING]),
        [STATE_DISCONNECTED_IDLE] =
                SMF_CREATE_STATE(NULL, state_disconnected_idle_run, NULL,
                                 &states[STATE_DISCONNECTED],
                                 NULL), /* No initial transition */
        [STATE_DISCONNECTED_SEARCHING] =
                SMF_CREATE_STATE(state_disconnected_searching_entry,
                                 state_disconnected_searching_run, NULL,
                                 &states[STATE_DISCONNECTED],
                                 NULL), /* No initial transition */
        [STATE_CONNECTED] =
                SMF_CREATE_STATE(state_connected_entry, state_connected_run, NULL,
                                 &states[STATE_RUNNING],
                                 NULL), /* No initial transition */
        [STATE_DISCONNECTING] =
                SMF_CREATE_STATE(state_disconnecting_entry, state_disconnecting_run, NULL,
                                 &states[STATE_RUNNING],
                                 NULL), /* No initial transition */
};