187 lines
7.3 KiB
Python
187 lines
7.3 KiB
Python
# -*- coding: utf-8 -*-
|
||
"""
|
||
装备模型生命周期状态机
|
||
─────────────────────────────────────────────────────────────────
|
||
LifecycleState 枚举:CREATED / READY / RUNNING / PAUSED /
|
||
STOPPED / ERROR
|
||
LifecycleFSM 有限状态机:管理合法状态转移,非法转移抛出异常
|
||
─────────────────────────────────────────────────────────────────
|
||
"""
|
||
|
||
from __future__ import annotations
|
||
|
||
from enum import Enum
|
||
from typing import Dict, Set, Callable, Optional
|
||
|
||
|
||
# ─────────────────────────────────────────────────────────────────
|
||
# 生命周期状态枚举
|
||
# ─────────────────────────────────────────────────────────────────
|
||
|
||
class LifecycleState(Enum):
|
||
CREATED = "CREATED" # 刚创建,参数未就绪
|
||
READY = "READY" # 参数就绪,可启动
|
||
RUNNING = "RUNNING" # 仿真运行中
|
||
PAUSED = "PAUSED" # 暂停(可恢复)
|
||
STOPPED = "STOPPED" # 已停止(不可恢复,需 reset)
|
||
ERROR = "ERROR" # 发生错误
|
||
|
||
|
||
# ─────────────────────────────────────────────────────────────────
|
||
# 合法状态转移表
|
||
# ─────────────────────────────────────────────────────────────────
|
||
|
||
# { 当前状态 → 可转移到的目标状态集合 }
|
||
_TRANSITIONS: Dict[LifecycleState, Set[LifecycleState]] = {
|
||
LifecycleState.CREATED: {
|
||
LifecycleState.READY,
|
||
LifecycleState.ERROR,
|
||
},
|
||
LifecycleState.READY: {
|
||
LifecycleState.RUNNING,
|
||
LifecycleState.ERROR,
|
||
},
|
||
LifecycleState.RUNNING: {
|
||
LifecycleState.PAUSED,
|
||
LifecycleState.STOPPED,
|
||
LifecycleState.ERROR,
|
||
LifecycleState.READY, # reset 时
|
||
},
|
||
LifecycleState.PAUSED: {
|
||
LifecycleState.RUNNING,
|
||
LifecycleState.STOPPED,
|
||
LifecycleState.ERROR,
|
||
LifecycleState.READY, # reset 时
|
||
},
|
||
LifecycleState.STOPPED: {
|
||
LifecycleState.READY, # reset 后可重新启动
|
||
LifecycleState.ERROR,
|
||
},
|
||
LifecycleState.ERROR: {
|
||
LifecycleState.READY, # 错误恢复后 reset
|
||
},
|
||
}
|
||
|
||
|
||
# ─────────────────────────────────────────────────────────────────
|
||
# 生命周期有限状态机
|
||
# ─────────────────────────────────────────────────────────────────
|
||
|
||
class LifecycleFSM:
|
||
"""
|
||
装备模型生命周期有限状态机
|
||
|
||
职责:
|
||
- 维护当前状态
|
||
- 校验状态转移合法性
|
||
- 触发转移回调(on_enter / on_exit)
|
||
- 记录状态历史
|
||
"""
|
||
|
||
def __init__(
|
||
self,
|
||
initial: LifecycleState = LifecycleState.CREATED,
|
||
on_changed: Optional[Callable[[str, str], None]] = None,
|
||
):
|
||
self._state: LifecycleState = initial
|
||
self._history: list = [(initial, 0.0)]
|
||
self._on_changed = on_changed # (old, new) 回调
|
||
|
||
# ── 属性 ──────────────────────────────────────────────────────
|
||
|
||
@property
|
||
def state(self) -> LifecycleState:
|
||
return self._state
|
||
|
||
@property
|
||
def history(self) -> list:
|
||
return list(self._history)
|
||
|
||
# ── 状态查询 ──────────────────────────────────────────────────
|
||
|
||
@property
|
||
def is_running(self) -> bool:
|
||
return self._state == LifecycleState.RUNNING
|
||
|
||
@property
|
||
def is_paused(self) -> bool:
|
||
return self._state == LifecycleState.PAUSED
|
||
|
||
@property
|
||
def is_stopped(self) -> bool:
|
||
return self._state == LifecycleState.STOPPED
|
||
|
||
@property
|
||
def is_ready(self) -> bool:
|
||
return self._state == LifecycleState.READY
|
||
|
||
@property
|
||
def is_error(self) -> bool:
|
||
return self._state == LifecycleState.ERROR
|
||
|
||
@property
|
||
def can_step(self) -> bool:
|
||
"""是否可以执行 step()"""
|
||
return self._state == LifecycleState.RUNNING
|
||
|
||
# ── 状态转移 ──────────────────────────────────────────────────
|
||
|
||
def transition(
|
||
self,
|
||
target: LifecycleState,
|
||
timestamp: float = 0.0,
|
||
force: bool = False,
|
||
) -> bool:
|
||
"""
|
||
执行状态转移
|
||
:param target: 目标状态
|
||
:param timestamp: 当前仿真时刻(用于历史记录)
|
||
:param force: True=强制转移(跳过合法性检查,仅内部使用)
|
||
:return: True=转移成功,False=已在目标状态
|
||
:raises ValueError: 非法状态转移
|
||
"""
|
||
if self._state == target:
|
||
return False
|
||
|
||
if not force:
|
||
allowed = _TRANSITIONS.get(self._state, set())
|
||
if target not in allowed:
|
||
raise ValueError(
|
||
f"非法状态转移: {self._state.value} → {target.value} "
|
||
f"(允许: {[s.value for s in allowed]})"
|
||
)
|
||
|
||
old_state = self._state
|
||
self._state = target
|
||
self._history.append((target, timestamp))
|
||
|
||
if self._on_changed:
|
||
self._on_changed(old_state.value, target.value)
|
||
|
||
return True
|
||
|
||
# ── 快捷转移方法 ──────────────────────────────────────────────
|
||
|
||
def to_ready(self, t: float = 0.0) -> bool:
|
||
return self.transition(LifecycleState.READY, t)
|
||
|
||
def to_running(self, t: float = 0.0) -> bool:
|
||
return self.transition(LifecycleState.RUNNING, t)
|
||
|
||
def to_paused(self, t: float = 0.0) -> bool:
|
||
return self.transition(LifecycleState.PAUSED, t)
|
||
|
||
def to_stopped(self, t: float = 0.0) -> bool:
|
||
return self.transition(LifecycleState.STOPPED, t)
|
||
|
||
def to_error(self, t: float = 0.0) -> bool:
|
||
return self.transition(LifecycleState.ERROR, t, force=True)
|
||
|
||
# ── 工具 ──────────────────────────────────────────────────────
|
||
|
||
def reset(self, t: float = 0.0) -> bool:
|
||
"""强制重置到 READY(任意状态均可)"""
|
||
return self.transition(LifecycleState.READY, t, force=True)
|
||
|
||
def __repr__(self) -> str:
|
||
return f"LifecycleFSM(state={self._state.value})" |