Files
yunmei f49c0920d4 feat: 完成 issue #3 边缘采集网关模板化封装
- 点位字典 CSV schema/加载/自动校验(缺失字段/量纲/重复点号,PRD 5.1)
- 协议可插拔只读驱动:OPC UA(S7-1200 适配)/S7/Modbus/称重/能源/模拟
- 周期采集引擎:只读+背压保护+健康度指标(丢失率/P99/可用性)
- Kafka 流式上行 + 本地 spool 断点续传(丢失率≤0.02% 保障)
- 模板配置外置(gateway.yaml + 点位字典 CSV),换行业零改码
- 18 个单元测试全绿;端到端运行 SLA 达标
2026-08-04 15:32:16 +08:00

60 lines
2.1 KiB
Python

# -*- coding: utf-8 -*-
"""采集驱动抽象基类 —— 模板化封装的协议插槽。
安全约束(PRD 9 章:边缘网关严格只读、零控制指令下发):
- 驱动仅暴露只读接口 `read_points()`,没有任何写/控制方法;
- 引擎只依赖本抽象,具体协议由子类实现,新增协议不改引擎代码。
"""
from __future__ import annotations
from abc import ABC, abstractmethod
from typing import Dict, List, Optional, Union
from point_dict.loader import Point
SampleValue = Union[float, int, bool, None]
class Driver(ABC):
"""只读采集驱动基类。"""
protocol: str = "base" # 协议名:opcua / s7 / modbus / weighing / energy / simulator
def __init__(self, config: Optional[dict] = None):
self.config = config or {}
@abstractmethod
def connect(self) -> None:
"""建立连接(幂等)。失败应抛出 ConnectionError 供引擎重试。"""
@abstractmethod
def read_points(self, points: List[Point]) -> Dict[str, SampleValue]:
"""批量读取测点值(只读)。
Args:
points: 本驱动负责的测点列表。
Returns:
{point_id: value};读失败的点可返回 None 或省略,
由引擎按“未读到”计入丢失率。
"""
@abstractmethod
def close(self) -> None:
"""关闭连接,释放资源。"""
# ------------------------------------------------------------------
# 模板化辅助
# ------------------------------------------------------------------
@classmethod
def from_template(cls, protocol: str, config: Optional[dict] = None) -> "Driver":
"""按模板配置实例化驱动(协议 → 实现类注册表)。"""
from . import _DRIVER_REGISTRY
if protocol not in _DRIVER_REGISTRY:
raise KeyError(
f"未注册的采集协议: '{protocol}',已注册: {sorted(_DRIVER_REGISTRY)}。"
f"如需支持新协议,实现 Driver 子类并注册。"
)
return _DRIVER_REGISTRY[protocol](config)