# 10. Adjust State Machine Code to Process Events Manually

Date: 2023-03-13

## Status

Accepted (in favor of ADR 0007).

## Context

- State processing code must change to work with the event system.
- The CPF state processing code works with concepts of "System States" and "Actions".
	+ Essentially, the system is operating as a hierarchical state machine (HSM), although it is using alternate terminology.
	+ Actions are effectively sub-states of each system state. 
		* The state repeatedly runs a specific action until a set of conditions are true, and then it moves on to the next action.
- State-based code is currently scattered throughout the system, rather than being contained within the state machine region.
	+ For example, `gps.getFix` contains logic for multiple cases. The action repeatedly re-runs the same function call until the expected return value is received.
		* Generating a request for a new fix (returning a specific value indicating the operation did not complete)
		* Parsing a received fix and returning it (returning a specific value to indicate the operation did complete)

## Decision

We will not opt for a full-on HSM model, but will preserve the existing terminology and general form of the existing CPF state processing structure.

- StateBase will have a `process()` function that takes an event input and passes it to the state machine's `receive()` function
- Actions for each state will be defined as enumerations. Each State's `doStateActions` will receive a message and forward it to the appropriate handling function for the current action.
- The `process` function will receive an `etl::imessage&` input. 
	+ The derived class can handle the event however it wants, such as in a `switch/case` or in an array of function pointers accessed via the current action index. 
	+ For events without data, you can identify what the event type is by checking the ID (`event.get_message_id()`).
	+ For events with data, you must check the ID, and then cast the event to the appropriate type. Making it manual presents risk of introducing errors, e.g. casting to the incorrect type.

## Consequences

This makes it easy to process events while working in the “old way” of the CPF state implementation (a function with switch/case based on the current action, rather than treating actions as states). This has the benefit of being the closest to the previous incarnations of the system.

This design will still require a refinement in how actions are thought about. For example, more action states will need to be defined as part of the relocation of state logic into the state system. Partially, this is due to a lack of polling in general, but it is also due to the lack of a separate `checkEvents` context.
