带计时器重置的有限状态机:车库门智能家居集成状态同步问题
解决方案:基于时间追踪的FSM优化实现
核心思路是通过追踪状态时间戳和延迟关闭任务队列,完全模拟实际车库门的物理行为,解决无状态反馈下的特殊场景同步问题。以下是具体实现方案:
关键设计点
- 时间戳追踪:记录每个状态的开始时间,用于计算状态剩余时长
- 延迟关闭任务:用户触发关闭时,不立即切换状态,而是计算需要等待的总时长(当前状态剩余时间 + 保持开启时间 + 关闭时间),到点后再进入关闭状态
- 优先级处理:待执行的关闭任务优先于自动状态流转,确保用户操作覆盖默认行为
完整伪代码实现
import time # 常量定义(匹配实际门的物理参数) OPENING_DUR = 14.5 # 开门耗时(秒) OPEN_HOLD_DUR = 40 # 保持开启时长(秒) CLOSING_DUR = 14 # 关门耗时(秒) # 状态枚举 class GarageDoorState: CLOSED = "closed" OPENING = "opening" OPEN = "open" CLOSING = "closing" # 状态管理核心变量 current_state = GarageDoorState.CLOSED state_start_time = 0 # 当前状态开始的时间戳(time.time()) pending_close_trigger_time = None # 用户触发关闭的时间戳 pending_close_total_delay = None # 触发关闭后需等待的总时长(直到进入Closing状态) def send_rf_open_signal(): """发送RF开门信号的实际执行逻辑""" print("[Hardware] Sending RF open signal...") def trigger_open(): """用户通过智能家居触发开门操作""" global current_state, state_start_time, pending_close_trigger_time, pending_close_total_delay if current_state != GarageDoorState.CLOSED: return # 非关闭状态下不重复触发开门 send_rf_open_signal() current_state = GarageDoorState.OPENING state_start_time = time.time() # 取消之前的待关闭任务 pending_close_trigger_time = None pending_close_total_delay = None def trigger_close(): """用户通过智能家居触发关闭操作(实际门不会立即响应)""" global pending_close_trigger_time, pending_close_total_delay now = time.time() # 已关闭或正在关闭时,无需操作 if current_state in [GarageDoorState.CLOSED, GarageDoorState.CLOSING]: return # 计算从触发关闭到进入Closing状态的总等待时长 total_wait = 0 if current_state == GarageDoorState.OPENING: # 剩余开门时长 + 保持开启时长 + 关门时长 elapsed_opening = now - state_start_time remaining_opening = max(0.0, OPENING_DUR - elapsed_opening) total_wait = remaining_opening + OPEN_HOLD_DUR + CLOSING_DUR elif current_state == GarageDoorState.OPEN: # 剩余保持时长 + 关门时长 elapsed_hold = now - state_start_time remaining_hold = max(0.0, OPEN_HOLD_DUR - elapsed_hold) total_wait = remaining_hold + CLOSING_DUR # 记录关闭任务参数 pending_close_trigger_time = now pending_close_total_delay = total_wait def update_state(): """每间隔固定时间(如0.1s)调用,更新FSM状态""" global current_state, state_start_time, pending_close_trigger_time, pending_close_total_delay now = time.time() # 优先处理待执行的关闭任务 if pending_close_trigger_time is not None: elapsed_since_trigger = now - pending_close_trigger_time if elapsed_since_trigger >= pending_close_total_delay: # 到达延迟时间,进入Closing状态 current_state = GarageDoorState.CLOSING state_start_time = now # 清空待关闭任务 pending_close_trigger_time = None pending_close_total_delay = None return # 有pending任务时,跳过自动状态流转 # 自动状态流转逻辑(模拟门的默认行为) if current_state == GarageDoorState.OPENING: elapsed = now - state_start_time if elapsed >= OPENING_DUR: current_state = GarageDoorState.OPEN state_start_time = now elif current_state == GarageDoorState.OPEN: elapsed = now - state_start_time if elapsed >= OPEN_HOLD_DUR: current_state = GarageDoorState.CLOSING state_start_time = now elif current_state == GarageDoorState.CLOSING: elapsed = now - state_start_time if elapsed >= CLOSING_DUR: current_state = GarageDoorState.CLOSED state_start_time = now # 主循环示例 while True: update_state() print(f"Current FSM State: {current_state}") time.sleep(0.1)
特殊场景验证
- 刚触发开门就关闭:调用
trigger_open后立即执行trigger_close,计算总等待时长为14.5+40+14=68.5s,到期后进入Closing状态,完全匹配实际门的行为 - Opening中途关闭:开门5秒后触发关闭,剩余开门时长9.5s,总等待时长
9.5+40+14=63.5s,到期后进入Closing,同步实际门的剩余开门→保持→关闭流程 - Open状态中途关闭:保持开启10秒后触发关闭,剩余保持时长30s,总等待时长
30+14=44s,到期后进入Closing,模拟实际门的剩余保持→关闭流程 - 自动关闭:Open状态保持40秒后,自动进入Closing状态,14秒后回到Closed,符合门的默认自动关闭逻辑
内容的提问来源于stack exchange,提问作者LuMa
相关产品推荐
相关产品推荐

