539 lines
19 KiB
Python
539 lines
19 KiB
Python
|
|
# -*- coding: utf-8 -*-
|
|||
|
|
"""
|
|||
|
|
装备模型抽象基类(核心)
|
|||
|
|
─────────────────────────────────────────────────────────────────
|
|||
|
|
BaseEquipmentModel 所有装备模型的统一抽象基类
|
|||
|
|
|
|||
|
|
职责:
|
|||
|
|
- 生命周期管理(start/stop/pause/resume/reset)
|
|||
|
|
- 仿真驱动(step/step_to)
|
|||
|
|
- 参数管理(set_params/update_param/get_param)
|
|||
|
|
- 参数版本快照(save_snapshot/restore_snapshot)
|
|||
|
|
- PyQt5 信号槽(state_updated/lifecycle_changed/
|
|||
|
|
params_changed/error_occurred)
|
|||
|
|
─────────────────────────────────────────────────────────────────
|
|||
|
|
"""
|
|||
|
|
|
|||
|
|
from __future__ import annotations
|
|||
|
|
|
|||
|
|
import asyncio
|
|||
|
|
import copy
|
|||
|
|
import logging
|
|||
|
|
from abc import abstractmethod
|
|||
|
|
from typing import Any, List, Optional, Type, Callable
|
|||
|
|
|
|||
|
|
from PyQt5.QtCore import QObject, pyqtSignal
|
|||
|
|
|
|||
|
|
from uas.comm import CommAdapterFactory
|
|||
|
|
from uas.comm.base import CommBaseAdapter
|
|||
|
|
from uas.comm.message import Message
|
|||
|
|
from uas.model.lifecycle import LifecycleFSM, LifecycleState
|
|||
|
|
from uas.model.params import EquipmentParams
|
|||
|
|
from uas.model.state import BaseState
|
|||
|
|
from uas.task.task_model import Task
|
|||
|
|
|
|||
|
|
logger = logging.getLogger(__name__)
|
|||
|
|
|
|||
|
|
|
|||
|
|
# ─────────────────────────────────────────────────────────────────
|
|||
|
|
# 装备模型抽象基类
|
|||
|
|
# ─────────────────────────────────────────────────────────────────
|
|||
|
|
|
|||
|
|
class BaseEquipmentModel(QObject):
|
|||
|
|
"""
|
|||
|
|
装备模型统一抽象基类
|
|||
|
|
|
|||
|
|
── 子类必须实现 ──────────────────────────────────────────────
|
|||
|
|
_do_step(dt) 核心仿真推进(更新 _state)
|
|||
|
|
_build_initial_state() 构建初始状态快照
|
|||
|
|
params_class 类属性:对应的 EquipmentParams 子类
|
|||
|
|
|
|||
|
|
── 子类可选覆盖 ──────────────────────────────────────────────
|
|||
|
|
_on_start() 启动时的额外初始化
|
|||
|
|
_on_stop() 停止时的清理
|
|||
|
|
_on_pause() 暂停时的处理
|
|||
|
|
_on_resume() 恢复时的处理
|
|||
|
|
_on_reset() 重置时的处理
|
|||
|
|
_on_params_changed(key, value) 参数变更时的响应
|
|||
|
|
_check_constraints() 约束检查(越界告警)
|
|||
|
|
"""
|
|||
|
|
|
|||
|
|
# ── PyQt5 信号 ────────────────────────────────────────────────
|
|||
|
|
state_updated = pyqtSignal(object) # BaseState 子类实例
|
|||
|
|
lifecycle_changed = pyqtSignal(str, str) # (old_state, new_state)
|
|||
|
|
params_changed = pyqtSignal(str, object) # (key, new_value)
|
|||
|
|
error_occurred = pyqtSignal(str) # 错误消息
|
|||
|
|
|
|||
|
|
# ── 子类须声明的类属性 ────────────────────────────────────────
|
|||
|
|
params_class: Type[EquipmentParams] = EquipmentParams
|
|||
|
|
|
|||
|
|
def __init__(
|
|||
|
|
self,
|
|||
|
|
params: Optional[EquipmentParams] = None,
|
|||
|
|
parent: QObject = None,
|
|||
|
|
):
|
|||
|
|
super().__init__(parent)
|
|||
|
|
|
|||
|
|
# 参数
|
|||
|
|
self._params: EquipmentParams = (
|
|||
|
|
params if params is not None
|
|||
|
|
else self.params_class()
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
# 状态
|
|||
|
|
self._state: Optional[BaseState] = None
|
|||
|
|
self._initial_state: Optional[BaseState] = None
|
|||
|
|
self._sub_models: List[BaseEquipmentModel] = []
|
|||
|
|
# 生命周期 FSM
|
|||
|
|
self._fsm = LifecycleFSM(
|
|||
|
|
initial = LifecycleState.CREATED,
|
|||
|
|
on_changed = self._on_fsm_changed,
|
|||
|
|
)
|
|||
|
|
self._comm = None
|
|||
|
|
# 仿真时钟
|
|||
|
|
self._sim_time: float = 0.0 # 仿真绝对时刻
|
|||
|
|
self._elapsed: float = 0.0 # 自启动累计时长
|
|||
|
|
|
|||
|
|
# 参数快照栈
|
|||
|
|
self._snapshots: List[EquipmentParams] = []
|
|||
|
|
|
|||
|
|
# 日志
|
|||
|
|
self.logger = logging.getLogger(
|
|||
|
|
f"{self.__class__.__name__}[{self._params.equipment_id}]"
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
# 初始化状态 → READY
|
|||
|
|
self.set_state(self._build_initial_state())
|
|||
|
|
self._fsm.to_ready(0.0)
|
|||
|
|
self._actions = {}
|
|||
|
|
|
|||
|
|
def action_is_available(self, action: str):
|
|||
|
|
return True
|
|||
|
|
|
|||
|
|
def register_action(self,
|
|||
|
|
object: BaseEquipmentModel,
|
|||
|
|
action: str,
|
|||
|
|
handler: Callable):
|
|||
|
|
if (object.equipment_id, action) not in self._actions:
|
|||
|
|
self._actions[(object.equipment_id, action) ].append((object, handler))
|
|||
|
|
|
|||
|
|
def dereigster_action(self, object: BaseEquipmentModel, action):
|
|||
|
|
if (object.equipment_id, action) in self._actions:
|
|||
|
|
del self._actions[(object.equipment_id, action)]
|
|||
|
|
|
|||
|
|
def call_action(self, object_id:str , action: str, **parameters):
|
|||
|
|
if (object_id, action) not in self._actions:
|
|||
|
|
raise ValueError()
|
|||
|
|
object, handler = self._actions[(object_id, action)]
|
|||
|
|
assert isinstance(object, BaseState)
|
|||
|
|
if object.action_is_available(action):
|
|||
|
|
return handler(**parameters)
|
|||
|
|
else:
|
|||
|
|
raise
|
|||
|
|
|
|||
|
|
def set_state(self, state: Optional[BaseState]):
|
|||
|
|
self._state = state.copy_with()
|
|||
|
|
self._initial_state = state.copy_with()
|
|||
|
|
self.state_updated.emit(self._state)
|
|||
|
|
|
|||
|
|
def add_sub_model(self, model: BaseEquipmentModel):
|
|||
|
|
if model not in self._sub_models:
|
|||
|
|
self._sub_models.append(model)
|
|||
|
|
|
|||
|
|
def add_sub_models(self, *models):
|
|||
|
|
for model in models:
|
|||
|
|
self.add_sub_model(model)
|
|||
|
|
|
|||
|
|
# ── 属性(只读)──────────────────────────────────────────────
|
|||
|
|
@property
|
|||
|
|
def actions(self):
|
|||
|
|
return self._actions
|
|||
|
|
|
|||
|
|
@property
|
|||
|
|
def sub_models(self) -> List[BaseEquipmentModel]:
|
|||
|
|
return self._sub_models
|
|||
|
|
|
|||
|
|
@property
|
|||
|
|
def params(self) -> EquipmentParams:
|
|||
|
|
return self._params
|
|||
|
|
|
|||
|
|
@property
|
|||
|
|
def state(self) -> Optional[BaseState]:
|
|||
|
|
return self._state
|
|||
|
|
|
|||
|
|
@property
|
|||
|
|
def lifecycle(self) -> LifecycleState:
|
|||
|
|
return self._fsm.state
|
|||
|
|
|
|||
|
|
@property
|
|||
|
|
def sim_time(self) -> float:
|
|||
|
|
return self._sim_time
|
|||
|
|
|
|||
|
|
@property
|
|||
|
|
def is_running(self) -> bool:
|
|||
|
|
return self._fsm.is_running
|
|||
|
|
|
|||
|
|
@property
|
|||
|
|
def equipment_id(self) -> str:
|
|||
|
|
return self._params.equipment_id
|
|||
|
|
|
|||
|
|
@property
|
|||
|
|
def name(self) -> str:
|
|||
|
|
return self._params.name
|
|||
|
|
|
|||
|
|
# ── 生命周期控制 ──────────────────────────────────────────────
|
|||
|
|
|
|||
|
|
def start(self) -> bool:
|
|||
|
|
"""
|
|||
|
|
启动模型(READY → RUNNING)
|
|||
|
|
:return: True=成功,False=当前状态不允许启动
|
|||
|
|
"""
|
|||
|
|
try:
|
|||
|
|
for model in self._sub_models:
|
|||
|
|
if not model.start():
|
|||
|
|
raise
|
|||
|
|
errors = self.validate_params()
|
|||
|
|
if errors:
|
|||
|
|
msg = f"参数校验失败,无法启动: {errors}"
|
|||
|
|
self.logger.error(msg)
|
|||
|
|
self.error_occurred.emit(msg)
|
|||
|
|
return False
|
|||
|
|
self._fsm.to_running(self._sim_time)
|
|||
|
|
self._on_start()
|
|||
|
|
self.logger.info(f"模型启动: {self.name}")
|
|||
|
|
return True
|
|||
|
|
except ValueError as e:
|
|||
|
|
self._handle_error(str(e))
|
|||
|
|
return False
|
|||
|
|
|
|||
|
|
def stop(self) -> bool:
|
|||
|
|
"""停止模型(RUNNING/PAUSED → STOPPED)"""
|
|||
|
|
try:
|
|||
|
|
for model in self._sub_models:
|
|||
|
|
if not model.stop():
|
|||
|
|
raise
|
|||
|
|
|
|||
|
|
self._fsm.to_stopped(self._sim_time)
|
|||
|
|
self._on_stop()
|
|||
|
|
self.logger.info(f"模型停止: {self.name}")
|
|||
|
|
return True
|
|||
|
|
except ValueError as e:
|
|||
|
|
self._handle_error(str(e))
|
|||
|
|
return False
|
|||
|
|
|
|||
|
|
def pause(self) -> bool:
|
|||
|
|
"""暂停模型(RUNNING → PAUSED)"""
|
|||
|
|
try:
|
|||
|
|
for model in self._sub_models:
|
|||
|
|
if not model.pause():
|
|||
|
|
raise
|
|||
|
|
self._fsm.to_paused(self._sim_time)
|
|||
|
|
self._on_pause()
|
|||
|
|
self.logger.info(f"模型暂停: {self.name}")
|
|||
|
|
return True
|
|||
|
|
except ValueError as e:
|
|||
|
|
self._handle_error(str(e))
|
|||
|
|
return False
|
|||
|
|
|
|||
|
|
def resume(self) -> bool:
|
|||
|
|
"""恢复模型(PAUSED → RUNNING)"""
|
|||
|
|
try:
|
|||
|
|
for model in self._sub_models:
|
|||
|
|
if not model.resume():
|
|||
|
|
raise
|
|||
|
|
self._fsm.to_running(self._sim_time)
|
|||
|
|
self._on_resume()
|
|||
|
|
self.logger.info(f"模型恢复: {self.name}")
|
|||
|
|
return True
|
|||
|
|
except ValueError as e:
|
|||
|
|
self._handle_error(str(e))
|
|||
|
|
return False
|
|||
|
|
|
|||
|
|
def reset(self) -> bool:
|
|||
|
|
"""
|
|||
|
|
重置模型(任意状态 → READY)
|
|||
|
|
恢复初始状态、清零仿真时钟
|
|||
|
|
"""
|
|||
|
|
try:
|
|||
|
|
for model in self._sub_models:
|
|||
|
|
if not model.reset():
|
|||
|
|
raise
|
|||
|
|
self._fsm.reset(0.0)
|
|||
|
|
self._sim_time = 0.0
|
|||
|
|
self._elapsed = 0.0
|
|||
|
|
self._state = copy.deepcopy(self._initial_state)
|
|||
|
|
self._on_reset()
|
|||
|
|
self.logger.info(f"模型重置: {self.name}")
|
|||
|
|
return True
|
|||
|
|
except Exception as e:
|
|||
|
|
self._handle_error(str(e))
|
|||
|
|
return False
|
|||
|
|
|
|||
|
|
def run_task(self, task: Task):
|
|||
|
|
pass
|
|||
|
|
|
|||
|
|
# ── 仿真驱动 ──────────────────────────────────────────────────
|
|||
|
|
|
|||
|
|
def step(self, dt: float) -> Optional[BaseState]:
|
|||
|
|
"""
|
|||
|
|
推进仿真 dt 秒(核心驱动方法)
|
|||
|
|
|
|||
|
|
内部执行顺序:
|
|||
|
|
① 检查生命周期(非 RUNNING 则跳过)
|
|||
|
|
② 调用 _do_step(dt)(子类实现运动/系统更新)
|
|||
|
|
③ 调用 _check_constraints()(约束检查)
|
|||
|
|
④ 更新 sim_time 和 elapsed_time
|
|||
|
|
⑤ 发射 state_updated 信号
|
|||
|
|
|
|||
|
|
:param dt: 时间步长(秒,必须 > 0)
|
|||
|
|
:return: 更新后的状态快照,或 None(未在运行中)
|
|||
|
|
"""
|
|||
|
|
if not self._fsm.can_step:
|
|||
|
|
return None
|
|||
|
|
if dt <= 0:
|
|||
|
|
raise ValueError(f"dt 必须大于 0,当前值: {dt}")
|
|||
|
|
|
|||
|
|
try:
|
|||
|
|
sub_states = []
|
|||
|
|
for model in self._sub_models:
|
|||
|
|
sub_state = model.step(dt)
|
|||
|
|
if not sub_state:
|
|||
|
|
raise
|
|||
|
|
sub_states.append(sub_state)
|
|||
|
|
# ② 子类核心更新
|
|||
|
|
self._do_step(dt)
|
|||
|
|
|
|||
|
|
# ③ 约束检查
|
|||
|
|
self._check_constraints()
|
|||
|
|
|
|||
|
|
# ④ 更新时钟
|
|||
|
|
self._sim_time += dt
|
|||
|
|
self._elapsed += dt
|
|||
|
|
|
|||
|
|
# 同步状态时间戳
|
|||
|
|
if self._state is not None:
|
|||
|
|
self._state.timestamp = self._sim_time
|
|||
|
|
self._state.elapsed_time = self._elapsed
|
|||
|
|
self._state.lifecycle = self._fsm.state.value
|
|||
|
|
|
|||
|
|
self._state.sub_states = sub_states
|
|||
|
|
# ⑤ 发射信号
|
|||
|
|
if self._state is not None:
|
|||
|
|
self.state_updated.emit(self._state)
|
|||
|
|
|
|||
|
|
return self._state
|
|||
|
|
|
|||
|
|
except Exception as e:
|
|||
|
|
self._handle_error(f"step 执行异常: {e}")
|
|||
|
|
return None
|
|||
|
|
|
|||
|
|
def step_to(self, t: float, dt: float = 0.1) -> Optional[BaseState]:
|
|||
|
|
"""
|
|||
|
|
推进到绝对时刻 t
|
|||
|
|
:param t: 目标时刻(秒)
|
|||
|
|
:param dt: 内部步长(秒)
|
|||
|
|
"""
|
|||
|
|
for model in self._sub_models:
|
|||
|
|
model.step_to(t, dt)
|
|||
|
|
if t <= self._sim_time:
|
|||
|
|
return self._state
|
|||
|
|
remaining = t - self._sim_time
|
|||
|
|
while remaining > 1e-9:
|
|||
|
|
step_dt = min(dt, remaining)
|
|||
|
|
self.step(step_dt)
|
|||
|
|
remaining -= step_dt
|
|||
|
|
return self._state
|
|||
|
|
|
|||
|
|
def get_state(self) -> Optional[BaseState]:
|
|||
|
|
"""获取当前状态快照(深拷贝)"""
|
|||
|
|
return self._state.copy_with() if self._state else None
|
|||
|
|
|
|||
|
|
# ── 参数管理 ──────────────────────────────────────────────────
|
|||
|
|
|
|||
|
|
def set_params(self, params: EquipmentParams) -> None:
|
|||
|
|
"""整体替换装备参数"""
|
|||
|
|
old = self._params
|
|||
|
|
self._params = params
|
|||
|
|
errors = self.validate_params()
|
|||
|
|
if errors:
|
|||
|
|
self._params = old
|
|||
|
|
raise ValueError(f"新参数校验失败: {errors}")
|
|||
|
|
self.logger.info(f"参数已整体替换: {params}")
|
|||
|
|
|
|||
|
|
def update_param(self, key: str, value: Any) -> None:
|
|||
|
|
"""
|
|||
|
|
动态更新单个参数
|
|||
|
|
自动触发 params_changed 信号和约束重校验
|
|||
|
|
"""
|
|||
|
|
old_value = self._params.get(key)
|
|||
|
|
self._params.set(key, value)
|
|||
|
|
|
|||
|
|
# 重新校验
|
|||
|
|
errors = self.validate_params()
|
|||
|
|
if errors:
|
|||
|
|
# 回滚
|
|||
|
|
self._params.set(key, old_value)
|
|||
|
|
raise ValueError(
|
|||
|
|
f"参数 {key}={value} 校验失败: {errors}"
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
self.logger.debug(f"参数更新: {key} = {value}")
|
|||
|
|
self.params_changed.emit(key, value)
|
|||
|
|
self._on_params_changed(key, value)
|
|||
|
|
|
|||
|
|
def get_param(self, key: str, default: Any = None) -> Any:
|
|||
|
|
"""读取单个参数值"""
|
|||
|
|
return self._params.get(key, default)
|
|||
|
|
|
|||
|
|
def validate_params(self) -> List[str]:
|
|||
|
|
"""校验当前参数合法性"""
|
|||
|
|
return self._params.validate()
|
|||
|
|
|
|||
|
|
# ── 参数快照 ──────────────────────────────────────────────────
|
|||
|
|
|
|||
|
|
def save_snapshot(self) -> int:
|
|||
|
|
"""
|
|||
|
|
保存当前参数快照
|
|||
|
|
:return: 快照索引
|
|||
|
|
"""
|
|||
|
|
snapshot = copy.deepcopy(self._params)
|
|||
|
|
self._snapshots.append(snapshot)
|
|||
|
|
idx = len(self._snapshots) - 1
|
|||
|
|
self.logger.debug(f"参数快照已保存: index={idx}")
|
|||
|
|
return idx
|
|||
|
|
|
|||
|
|
def restore_snapshot(self, index: int = -1) -> bool:
|
|||
|
|
"""
|
|||
|
|
恢复参数快照
|
|||
|
|
:param index: 快照索引(-1=最新)
|
|||
|
|
:return: True=成功
|
|||
|
|
"""
|
|||
|
|
if not self._snapshots:
|
|||
|
|
self.logger.warning("没有可用的参数快照")
|
|||
|
|
return False
|
|||
|
|
try:
|
|||
|
|
snapshot = self._snapshots[index]
|
|||
|
|
self._params = copy.deepcopy(snapshot)
|
|||
|
|
self.logger.info(f"参数快照已恢复: index={index}")
|
|||
|
|
return True
|
|||
|
|
except IndexError:
|
|||
|
|
self.logger.error(f"快照索引越界: {index}")
|
|||
|
|
return False
|
|||
|
|
|
|||
|
|
def clear_snapshots(self) -> None:
|
|||
|
|
"""清除所有参数快照"""
|
|||
|
|
self._snapshots.clear()
|
|||
|
|
|
|||
|
|
# ── 抽象方法(子类必须实现)──────────────────────────────────
|
|||
|
|
|
|||
|
|
@abstractmethod
|
|||
|
|
def _do_step(self, dt: float) -> None:
|
|||
|
|
"""
|
|||
|
|
核心仿真推进(子类实现)
|
|||
|
|
必须更新 self._state 的所有相关字段
|
|||
|
|
"""
|
|||
|
|
...
|
|||
|
|
|
|||
|
|
@abstractmethod
|
|||
|
|
def _build_initial_state(self) -> BaseState:
|
|||
|
|
"""
|
|||
|
|
构建初始状态快照(子类实现)
|
|||
|
|
在 __init__ 和 reset() 时调用
|
|||
|
|
"""
|
|||
|
|
...
|
|||
|
|
|
|||
|
|
# ── 可选覆盖钩子 ──────────────────────────────────────────────
|
|||
|
|
|
|||
|
|
def _on_start(self) -> None: pass
|
|||
|
|
def _on_stop(self) -> None: pass
|
|||
|
|
def _on_pause(self) -> None: pass
|
|||
|
|
def _on_resume(self) -> None: pass
|
|||
|
|
def _on_reset(self) -> None: pass
|
|||
|
|
|
|||
|
|
def _on_params_changed(self, key: str, value: Any) -> None:
|
|||
|
|
"""参数变更时的响应钩子(子类可覆盖)"""
|
|||
|
|
pass
|
|||
|
|
|
|||
|
|
def _check_constraints(self) -> None:
|
|||
|
|
"""
|
|||
|
|
约束检查钩子(子类可覆盖)
|
|||
|
|
检查速度/高度等是否越界,发射 error_occurred 告警
|
|||
|
|
"""
|
|||
|
|
pass
|
|||
|
|
|
|||
|
|
# ── 内部工具 ──────────────────────────────────────────────────
|
|||
|
|
|
|||
|
|
def _on_fsm_changed(self, old: str, new: str) -> None:
|
|||
|
|
"""FSM 状态变化回调 → 发射 lifecycle_changed 信号"""
|
|||
|
|
self.lifecycle_changed.emit(old, new)
|
|||
|
|
self.logger.debug(f"生命周期变化: {old} → {new}")
|
|||
|
|
|
|||
|
|
def _handle_error(self, msg: str) -> None:
|
|||
|
|
"""统一错误处理:记录日志 + 转 ERROR 状态 + 发射信号"""
|
|||
|
|
self.logger.error(msg)
|
|||
|
|
self._fsm.to_error(self._sim_time)
|
|||
|
|
self.error_occurred.emit(msg)
|
|||
|
|
|
|||
|
|
def set_initial_position(
|
|||
|
|
self,
|
|||
|
|
lat: float, lon: float, alt: float = 0.0,
|
|||
|
|
heading: float = 0.0,
|
|||
|
|
) -> None:
|
|||
|
|
"""
|
|||
|
|
设置初始位置(必须在 start() 之前调用)
|
|||
|
|
同时更新 _state 和 _initial_state
|
|||
|
|
"""
|
|||
|
|
for s in (self._state, self._initial_state):
|
|||
|
|
if s is not None:
|
|||
|
|
s.latitude = lat
|
|||
|
|
s.longitude = lon
|
|||
|
|
s.altitude = alt
|
|||
|
|
s.heading = heading
|
|||
|
|
|
|||
|
|
def __repr__(self) -> str:
|
|||
|
|
return (f"{self.__class__.__name__}("
|
|||
|
|
f"id={self.equipment_id}, "
|
|||
|
|
f"name={self.name}, "
|
|||
|
|
f"lc={self.lifecycle.value})")
|
|||
|
|
|
|||
|
|
|
|||
|
|
class NetworkModel:
|
|||
|
|
def __init__(self, network_id, url, model: BaseEquipmentModel):
|
|||
|
|
self.network_id = network_id
|
|||
|
|
self.url = url
|
|||
|
|
self.model = model
|
|||
|
|
|
|||
|
|
async def _publish_state(self, state):
|
|||
|
|
await self._comm_adapter.publish()
|
|||
|
|
|
|||
|
|
async def on_call(self, msg: Message):
|
|||
|
|
logger.warning(f"🚨 告警消息 | priority={msg.priority.name} | {msg.payload}")
|
|||
|
|
|
|||
|
|
async def subscribe_actions(self, adapter:CommBaseAdapter, model: BaseEquipmentModel):
|
|||
|
|
for action in model.actions:
|
|||
|
|
await adapter.subscribe(f"{self.network_id}/{model.equipment_id}/{action}", self.on_call)
|
|||
|
|
|
|||
|
|
async def register_network_actions(self, adapter:CommBaseAdapter, model: BaseEquipmentModel):
|
|||
|
|
for action in model.actions:
|
|||
|
|
await adapter.publish(Message(topic=f"{self.network_id}",
|
|||
|
|
payload={
|
|||
|
|
"model_id": model.equipment_id,
|
|||
|
|
"action": action,
|
|||
|
|
"description": ""
|
|||
|
|
}))
|
|||
|
|
|
|||
|
|
async def _process(self):
|
|||
|
|
async with CommAdapterFactory.create(self.url) as adapter:
|
|||
|
|
await self.register_network_actions(adapter, self.model)
|
|||
|
|
await adapter.subscribe(f"{self.network_id}/{self.model.equipment_id}")
|
|||
|
|
await self.subscribe_actions(adapter, self.model)
|
|||
|
|
for model in self.model.sub_models:
|
|||
|
|
await self.register_network_actions(adapter, model)
|
|||
|
|
await self.subscribe_actions(adapter, model)
|
|||
|
|
|
|||
|
|
def start(self):
|
|||
|
|
self.model.start()
|
|||
|
|
asyncio.run(self._process())
|
|||
|
|
|
|||
|
|
|