Smart Door Lock State Machine with Enums and Guards
Level: Difficult
Concepts: Enums, State Machines, Guard Conditions, Counters
Scenario
You are implementing a smart door lock controller. The lock reacts to commands, motor feedback, sensor events, and battery status. Safety guards (low‑power, forced‑open, timeout, etc.) must be evaluated before normal state transitions. The function must compute the next lock state, the action to perform, and update the command‑attempt counter.
Problem Statement
Create a deterministic, guard‑first state‑step function that, given the current state, an incoming event, battery status, and the current attempt count, returns the next state, the required action, and the updated attempt counter. All enums and pointers must be validated; on error no output values are modified.
Requirements
-
Enumerations
enum LockState { ST_LOCKED, ST_UNLOCKED, ST_MOVING_LOCK, ST_MOVING_UNLOCK, ST_ALARM, ST_LOWPOWER }; enum LockEvent { EV_LOCK_CMD, EV_UNLOCK_CMD, EV_MOTOR_DONE_OK, EV_MOTOR_STALL, EV_FORCED_OPEN, EV_TIMEOUT, EV_BATTERY_LOW, EV_BATTERY_OK }; enum Action { ACT_NONE, ACT_START_LOCK, ACT_START_UNLOCK, ACT_SOUND_ALARM, ACT_ENTER_SLEEP }; -
Guard / policy handling (evaluated first)
- If
battery_low == trueand the current state is notST_ALARM, anyEV_BATTERY_LOWforces transition toST_LOWPOWERwith actionACT_ENTER_SLEEP. - From
ST_LOWPOWER,EV_BATTERY_OK→ST_UNLOCKED, actionACT_NONE. - Any state receiving
EV_FORCED_OPEN→ST_ALARM, actionACT_SOUND_ALARM. - In moving states (
ST_MOVING_LOCK,ST_MOVING_UNLOCK) the following apply:EV_MOTOR_DONE_OK→ respective locked/unlocked state, actionACT_NONE.EV_MOTOR_STALL→ST_ALARM, actionACT_SOUND_ALARM.EV_TIMEOUT→ST_ALARM, actionACT_SOUND_ALARM.
- If
-
Command handling
ST_UNLOCKED+EV_LOCK_CMD→ST_MOVING_LOCK, actionACT_START_LOCK.ST_LOCKED+EV_UNLOCK_CMD→ST_MOVING_UNLOCK, actionACT_START_UNLOCK.
-
Attempt counter
- If
attempts >= 3and the incoming event is a command (EV_LOCK_CMDorEV_UNLOCK_CMD), the command is ignored: stay in the current state, actionACT_NONE, andattemptsis unchanged. - When a command is accepted, increment
attemptsby one and return the new value viaout_attempts_next. - Upon successful motor completion (
EV_MOTOR_DONE_OK) or any transition to a non‑moving state (ST_LOCKED,ST_UNLOCKED,ST_ALARM,ST_LOWPOWER), resetattemptsto 0.
- If
-
Validation
- All enum arguments must be within their defined ranges.
- Pointers
out_next,out_action, andout_attempts_nextmust be non‑NULL. - On any validation failure, return
-1and leave output parameters unchanged.
Function Details
Name
lock_step
Arguments
enum LockState curr– current lock state.enum LockEvent ev– incoming event.bool battery_low– current battery status (true = low).int attempts– current consecutive command‑attempt count (≥ 0).enum LockState *out_next– pointer to receive the next state.enum Action *out_action– pointer to receive the action to perform.int *out_attempts_next– pointer to receive the updated attempts count.
Return Value
int – 0 on success, -1 on invalid arguments or invalid enum values.
Description
The function first checks the guard conditions (battery‑low, forced‑open, etc.),
then processes state‑specific transitions. It updates the attempt counter
according to the rules above, writes the results through the provided pointers,
and returns 0. If any validation fails, it returns -1 without modifying the
output parameters.
Solution Approach
- Validate pointers (
out_next,out_action,out_attempts_next). - Validate enums by ensuring the integer values fall within the defined ranges of each enumeration.
- Handle battery‑low guard: if
battery_low && ev == EV_BATTERY_LOW && curr != ST_ALARM, set next stateST_LOWPOWER, actionACT_ENTER_SLEEP, attempts unchanged, return success. - Handle low‑power recovery: if
curr == ST_LOWPOWER && ev == EV_BATTERY_OK, transition toST_UNLOCKED, actionACT_NONE. - Handle forced‑open: any state +
EV_FORCED_OPEN→ST_ALARM, actionACT_SOUND_ALARM. - Process command events (
EV_LOCK_CMD,EV_UNLOCK_CMD):- If
attempts >= 3, ignore command (stay incurr, actionACT_NONE, attempts unchanged). - Otherwise, apply the command mapping (unlock → moving‑unlock, lock → moving‑lock), increment attempts, and set the corresponding start action.
- If
- Process motor feedback for moving states:
EV_MOTOR_DONE_OK→ locked/unlocked state, actionACT_NONE, attempts reset to 0.EV_MOTOR_STALLorEV_TIMEOUT→ST_ALARM, actionACT_SOUND_ALARM, attempts reset to 0.
- Default – if no rule matches, remain in current state with
ACT_NONEand attempts unchanged. - Write results to the output pointers and return
0.
Tasks to Perform
- Define the three enumerations (
LockState,LockEvent,Action). - Implement
lock_stepexactly as described, using onlyint,bool, andenumtypes. - Ensure no fall‑through in
switchstatements; each case must end with abreakor explicitreturn. - Write unit tests covering all guard conditions, normal commands, attempt‑limit handling, motor feedback, timeout, forced‑open, low‑power entry and exit, and invalid‑argument cases.
Test Cases
-
Normal lock command
Input:curr = ST_UNLOCKED,ev = EV_LOCK_CMD,battery_low = false,attempts = 0
Expected: return 0,*out_next = ST_MOVING_LOCK,*out_action = ACT_START_LOCK,*out_attempts_next = 1. -
Motor completes lock
Input:curr = ST_MOVING_LOCK,ev = EV_MOTOR_DONE_OK,battery_low = false,attempts = 1
Expected: return 0,*out_next = ST_LOCKED,*out_action = ACT_NONE,*out_attempts_next = 0. -
Command ignored due to attempt limit
Input:curr = ST_LOCKED,ev = EV_UNLOCK_CMD,battery_low = false,attempts = 3
Expected: return 0,*out_next = ST_LOCKED,*out_action = ACT_NONE,*out_attempts_next = 3. -
Timeout while moving
Input:curr = ST_MOVING_UNLOCK,ev = EV_TIMEOUT,battery_low = false,attempts = 1
Expected: return 0,*out_next = ST_ALARM,*out_action = ACT_SOUND_ALARM,*out_attempts_next = 0. -
Forced open security breach
Input:curr = ST_LOCKED,ev = EV_FORCED_OPEN,battery_low = false,attempts = 0
Expected: return 0,*out_next = ST_ALARM,*out_action = ACT_SOUND_ALARM,*out_attempts_next = 0. -
Enter low‑power mode
Input:curr = ST_UNLOCKED,ev = EV_BATTERY_LOW,battery_low = true,attempts = 0
Expected: return 0,*out_next = ST_LOWPOWER,*out_action = ACT_ENTER_SLEEP,*out_attempts_next = 0. -
Recover from low‑power
Input:curr = ST_LOWPOWER,ev = EV_BATTERY_OK,battery_low = false,attempts = 0
Expected: return 0,*out_next = ST_UNLOCKED,*out_action = ACT_NONE,*out_attempts_next = 0. -
Invalid enum argument
Input:curr = (enum LockState)99,ev = EV_LOCK_CMD,battery_low = false,attempts = 0, any valid pointer arguments.Expected: return -1, no modification of output parameters.